diff --git a/.hgtags b/.hgtags index e7144757c53..3e4fe714491 100644 --- a/.hgtags +++ b/.hgtags @@ -257,3 +257,5 @@ efe7dbc6088691757404e0c8745f894e3ca9c022 jdk9-b09 0d1f816217dce5e72187f167cc1816080cbeb453 jdk9-b12 1a30593dcb9802faec3b6edb24d86ca088594e4e jdk9-b13 97932f6ad950ae5a73a9da5c96e6e58503ff646b jdk9-b14 +74eb0778e4f2dbff6628e718378449fba27c4265 jdk9-b15 +4a09f5d30be844ac6f714bdb0f63d8c3c08b9a98 jdk9-b16 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index b370baabdcc..210ff9faef9 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -257,3 +257,5 @@ ab55a18a95e1990a588929d5d29db3eb9985fea0 jdk9-b11 59f6350295f9681fe5956d8bc889bf341914c6cb jdk9-b12 5800456add07e1a68170a229fb5e27376f8875e5 jdk9-b13 4e3aa9723e9972623e3dafc321b368e7db7e9b3b jdk9-b14 +b114474fb25af4e73cb7219f7c04bd8994da03a5 jdk9-b15 +cf22a728521f91a4692b433d39d730a0a1b23155 jdk9-b16 diff --git a/common/autoconf/configure b/common/autoconf/configure index 636f6e8efdd..b49e03e7fad 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -49,7 +49,7 @@ fi ### run_autogen_or_fail() { - if test "x`which autoconf 2> /dev/null`" = x; then + if test "x`which autoconf 2> /dev/null | grep -v '^no autoconf in'`" = x; then echo "Cannot locate autoconf, unable to correct situation." echo "Please install autoconf and run 'bash autogen.sh' to update the generated files." echo "Error: Cannot continue" 1>&2 @@ -80,7 +80,7 @@ check_autoconf_timestamps() { } check_hg_updates() { - if test "x`which hg 2> /dev/null`" != x; then + if test "x`which hg 2> /dev/null | grep -v '^no hg in'`" != x; then conf_updated_autoconf_files=`cd $conf_script_dir && hg status -mard 2> /dev/null | grep autoconf` if test "x$conf_updated_autoconf_files" != x; then echo "Configure source code has been updated, checking time stamps" diff --git a/corba/.hgtags b/corba/.hgtags index 3f510f7c8a2..a021d932579 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -257,3 +257,5 @@ a4bf701ac316946c2e5e83138ad8e687da6a4b30 jdk9-b06 e212cdcc8c11f0ba5acf6f5ddb596c4c545a93f9 jdk9-b12 088eec4c36f4d7f250fcd19c4969bf698e3d2cdc jdk9-b13 a2b82f863ba95a596da555a4c1b871c404863e7e jdk9-b14 +e54022d0dd92106fff7f7fe670010cd7e6517ee3 jdk9-b15 +422ef9d29d84f571453f015c4cb8713c3af70ee4 jdk9-b16 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 00898012217..43e10fc2ccd 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -417,3 +417,5 @@ ebc44d040cd149d2120d69fe183a3dae7840f4b4 jdk9-b10 1c383bb39e2849ca62cb763f4e182a29b421d60a jdk9-b12 456ad9c99133803d4e1433124c85a6fd141b9ac9 jdk9-b13 bd333491bb6c012d7b606939406d0fa9a5ac7ffd jdk9-b14 +170f6d733d7aec062f743a6b8c1cce940a7a984a jdk9-b15 +b14e7c0b7d3ec04127f565cda1d84122e205680c jdk9-b16 diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 6f6d4c30e13..4c6f0de0010 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -1221,10 +1221,8 @@ void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { bool is_obj = (type == T_ARRAY || type == T_OBJECT); LIR_Opr offset = off.result(); - if (data != dst) { - __ move(data, dst); - data = dst; - } + // Because we want a 2-arg form of xchg + __ move(data, dst); assert (!x->is_add() && (type == T_INT || (is_obj LP64_ONLY(&& UseCompressedOops))), "unexpected type"); LIR_Address* addr; @@ -1254,7 +1252,7 @@ void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { pre_barrier(ptr, LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ xchg(LIR_OprFact::address(addr), data, dst, tmp); + __ xchg(LIR_OprFact::address(addr), dst, dst, tmp); if (is_obj) { // Seems to be a precise address post_barrier(ptr, data); diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index 13829b1da23..3d8fb0e5d5a 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -184,7 +184,7 @@ static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation"); if (value == 0 && UseBlockZeroing && - (count > (BlockZeroingLowLimit >> LogHeapWordSize))) { + (count > (size_t)(BlockZeroingLowLimit >> LogHeapWordSize))) { // Call it only when block zeroing is used ((_zero_Fn)StubRoutines::zero_aligned_words())(tohw, count); } else { diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java index faef0ce00ec..1aa3edbc35a 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java @@ -231,6 +231,9 @@ public class CallSite { // identical call sites with the same method name/bci are // possible so we have to try them all until we find the late // inline call site that has a matching inline id. + if (calls == null) { + return null; + } CallSite site = sites.pop(); for (CallSite c : calls) { if (c.matches(site)) { @@ -250,6 +253,27 @@ public class CallSite { return null; } + public ArrayDeque findCallSite2(CallSite site) { + if (calls == null) { + return null; + } + + for (CallSite c : calls) { + if (c.matches(site)) { + ArrayDeque stack = new ArrayDeque(); + stack.push(c); + return stack; + } else { + ArrayDeque stack = c.findCallSite2(site); + if (stack != null) { + stack.push(c); + return stack; + } + } + } + return null; + } + public long getInlineId() { return inlineId; } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java index 861fe443753..e6617da628d 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java @@ -49,6 +49,12 @@ public class Compilation implements LogEvent { this.id = id; } + void reset() { + call = new CallSite(); + lateInlineCall = new CallSite(); + phases = new ArrayList(4); + } + Phase getPhase(String s) { for (Phase p : getPhases()) { if (p.getName().equals(s)) { @@ -212,10 +218,6 @@ public class Compilation implements LogEvent { return phases; } - public void setPhases(ArrayList phases) { - this.setPhases(phases); - } - public String getFailureReason() { return failureReason; } @@ -240,10 +242,6 @@ public class Compilation implements LogEvent { return call; } - public void setCall(CallSite call) { - this.call = call; - } - public CallSite getLateInlineCall() { return lateInlineCall; } diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java index 077c1d20ab6..50704c3512e 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java @@ -395,6 +395,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants compile.setEnd(Double.parseDouble(search(atts, "stamp"))); if (Integer.parseInt(search(atts, "success")) == 0) { compile.setFailureReason(failureReason); + failureReason = null; } } else if (qname.equals("make_not_entrant")) { String id = makeId(atts); @@ -451,6 +452,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants nmethods.put(id, nm); events.add(nm); } else if (qname.equals("parse")) { + if (failureReason != null && scopes.size() == 0 && !lateInlining) { + failureReason = null; + compile.reset(); + site = compile.getCall(); + } + if (methodHandleSite != null) { throw new InternalError("method handle site should have been replaced"); } @@ -529,6 +536,18 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants site = compile.getCall().findCallSite(thisCallScopes); if (site == null) { + System.out.println("call scopes:"); + for (CallSite c : thisCallScopes) { + System.out.println(c.getMethod() + " " + c.getBci() + " " + c.getInlineId()); + } + CallSite c = thisCallScopes.getLast(); + if (c.getInlineId() != 0) { + System.out.println("Looking for call site in entire tree:"); + ArrayDeque stack = compile.getCall().findCallSite2(c); + for (CallSite c2 : stack) { + System.out.println(c2.getMethod() + " " + c2.getBci() + " " + c2.getInlineId()); + } + } System.out.println(caller.getMethod() + " bci: " + bci); throw new InternalError("couldn't find call site"); } diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index fc176943ee8..f60190ae6c3 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -1083,7 +1083,7 @@ void LIR_OpLabel::emit_code(LIR_Assembler* masm) { void LIR_OpArrayCopy::emit_code(LIR_Assembler* masm) { masm->emit_arraycopy(this); - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } void LIR_OpUpdateCRC32::emit_code(LIR_Assembler* masm) { @@ -1100,20 +1100,20 @@ void LIR_Op1::emit_code(LIR_Assembler* masm) { void LIR_OpAllocObj::emit_code(LIR_Assembler* masm) { masm->emit_alloc_obj(this); - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } void LIR_OpBranch::emit_code(LIR_Assembler* masm) { masm->emit_opBranch(this); if (stub()) { - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } } void LIR_OpConvert::emit_code(LIR_Assembler* masm) { masm->emit_opConvert(this); if (stub() != NULL) { - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } } @@ -1123,13 +1123,13 @@ void LIR_Op2::emit_code(LIR_Assembler* masm) { void LIR_OpAllocArray::emit_code(LIR_Assembler* masm) { masm->emit_alloc_array(this); - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } void LIR_OpTypeCheck::emit_code(LIR_Assembler* masm) { masm->emit_opTypeCheck(this); if (stub()) { - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } } @@ -1144,7 +1144,7 @@ void LIR_Op3::emit_code(LIR_Assembler* masm) { void LIR_OpLock::emit_code(LIR_Assembler* masm) { masm->emit_lock(this); if (stub()) { - masm->emit_code_stub(stub()); + masm->append_code_stub(stub()); } } diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index a339af5098f..e26c280c38a 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -1127,6 +1127,7 @@ class LIR_Op: public CompilationResourceObj { virtual void print_instr(outputStream* out) const = 0; virtual void print_on(outputStream* st) const PRODUCT_RETURN; + virtual bool is_patching() { return false; } virtual LIR_OpCall* as_OpCall() { return NULL; } virtual LIR_OpJavaCall* as_OpJavaCall() { return NULL; } virtual LIR_OpLabel* as_OpLabel() { return NULL; } @@ -1387,6 +1388,7 @@ class LIR_Op1: public LIR_Op { return (LIR_MoveKind)_flags; } + virtual bool is_patching() { return _patch != lir_patch_none; } virtual void emit_code(LIR_Assembler* masm); virtual LIR_Op1* as_Op1() { return this; } virtual const char * name() const PRODUCT_RETURN0; @@ -1619,6 +1621,7 @@ public: int profiled_bci() const { return _profiled_bci; } bool should_profile() const { return _should_profile; } + virtual bool is_patching() { return _info_for_patch != NULL; } virtual void emit_code(LIR_Assembler* masm); virtual LIR_OpTypeCheck* as_OpTypeCheck() { return this; } void print_instr(outputStream* out) const PRODUCT_RETURN; diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index 826cf70080a..ef2b10623a4 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -58,7 +58,7 @@ void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_cod _masm->nop(); } patch->install(_masm, patch_code, obj, info); - append_patching_stub(patch); + append_code_stub(patch); #ifdef ASSERT Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci()); @@ -131,11 +131,6 @@ LIR_Assembler::~LIR_Assembler() { } -void LIR_Assembler::append_patching_stub(PatchingStub* stub) { - _slow_case_stubs->append(stub); -} - - void LIR_Assembler::check_codespace() { CodeSection* cs = _masm->code_section(); if (cs->remaining() < (int)(NOT_LP64(1*K)LP64_ONLY(2*K))) { @@ -144,7 +139,7 @@ void LIR_Assembler::check_codespace() { } -void LIR_Assembler::emit_code_stub(CodeStub* stub) { +void LIR_Assembler::append_code_stub(CodeStub* stub) { _slow_case_stubs->append(stub); } @@ -442,7 +437,7 @@ void LIR_Assembler::add_debug_info_for_null_check_here(CodeEmitInfo* cinfo) { void LIR_Assembler::add_debug_info_for_null_check(int pc_offset, CodeEmitInfo* cinfo) { ImplicitNullCheckStub* stub = new ImplicitNullCheckStub(pc_offset, cinfo); - emit_code_stub(stub); + append_code_stub(stub); } void LIR_Assembler::add_debug_info_for_div0_here(CodeEmitInfo* info) { @@ -451,7 +446,7 @@ void LIR_Assembler::add_debug_info_for_div0_here(CodeEmitInfo* info) { void LIR_Assembler::add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo) { DivByZeroStub* stub = new DivByZeroStub(pc_offset, cinfo); - emit_code_stub(stub); + append_code_stub(stub); } void LIR_Assembler::emit_rtcall(LIR_OpRTCall* op) { diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 0d4c64823eb..2211b0cc32c 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -144,7 +144,7 @@ class LIR_Assembler: public CompilationResourceObj { // stubs void emit_slow_case_stubs(); void emit_static_call_stub(); - void emit_code_stub(CodeStub* op); + void append_code_stub(CodeStub* op); void add_call_info_here(CodeEmitInfo* info) { add_call_info(code_offset(), info); } // code patterns diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp index 74e04f85dda..91bef59ef17 100644 --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp @@ -2382,16 +2382,6 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo int arg_count = frame_map()->oop_map_arg_count(); OopMap* map = new OopMap(frame_size, arg_count); - // Check if this is a patch site. - bool is_patch_info = false; - if (op->code() == lir_move) { - assert(!is_call_site, "move must not be a call site"); - assert(op->as_Op1() != NULL, "move must be LIR_Op1"); - LIR_Op1* move = (LIR_Op1*)op; - - is_patch_info = move->patch_code() != lir_patch_none; - } - // Iterate through active intervals for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) { int assigned_reg = interval->assigned_reg(); @@ -2406,7 +2396,7 @@ OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo // moves, any intervals which end at this instruction are included // in the oop map since we may safepoint while doing the patch // before we've consumed the inputs. - if (is_patch_info || op->id() < interval->current_to()) { + if (op->is_patching() || op->id() < interval->current_to()) { // caller-save registers must not be included into oop-maps at calls assert(!is_call_site || assigned_reg >= nof_regs || !is_caller_save(assigned_reg), "interval is in a caller-save register at a call -> register will be overwritten"); diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index 54f2225d3fe..bc88beb4343 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -274,6 +274,8 @@ void ClassLoaderData::add_class(Klass* k) { MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); Klass* old_value = _klasses; k->set_next_link(old_value); + // Make sure linked class is stable, since the class list is walked without a lock + OrderAccess::storestore(); // link the new item into the list _klasses = k; diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 923a6f70d2c..c7eca2d011b 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -2036,7 +2036,7 @@ void ClassVerifier::verify_switch( while ((bcp + padding_offset) < aligned_bcp) { if(*(bcp + padding_offset) != 0) { verify_error(ErrorContext::bad_code(bci), - "Nonzero padding byte in lookswitch or tableswitch"); + "Nonzero padding byte in lookupswitch or tableswitch"); return; } padding_offset++; diff --git a/hotspot/src/share/vm/compiler/compilerOracle.cpp b/hotspot/src/share/vm/compiler/compilerOracle.cpp index c58fb169309..b646158af28 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp @@ -307,6 +307,9 @@ bool CompilerOracle::should_print(methodHandle method) { return (check_predicate(PrintCommand, method)); } +bool CompilerOracle::should_print_methods() { + return lists[PrintCommand] != NULL; +} bool CompilerOracle::should_log(methodHandle method) { if (!LogCompilation) return false; diff --git a/hotspot/src/share/vm/compiler/compilerOracle.hpp b/hotspot/src/share/vm/compiler/compilerOracle.hpp index f736a4eebfc..df025f76be5 100644 --- a/hotspot/src/share/vm/compiler/compilerOracle.hpp +++ b/hotspot/src/share/vm/compiler/compilerOracle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -73,6 +73,9 @@ class CompilerOracle : AllStatic { // For updating the oracle file static void append_comment_to_file(const char* message); static void append_exclude_to_file(methodHandle method); + + // Tells whether there are any methods to print for print_method_statistics() + static bool should_print_methods(); }; #endif // SHARE_VM_COMPILER_COMPILERORACLE_HPP diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index ca4f3e3e1b4..0f79ab5072f 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1267,8 +1267,10 @@ IRT_END // This is a support of the JVMTI PopFrame interface. // Make sure it is an invokestatic of a polymorphic intrinsic that has a member_name argument // and return it as a vm_result so that it can be reloaded in the list of invokestatic parameters. -// The dmh argument is a reference to a DirectMethoHandle that has a member name field. -IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address dmh, +// The member_name argument is a saved reference (in local#0) to the member_name. +// For backward compatibility with some JDK versions (7, 8) it can also be a direct method handle. +// FIXME: remove DMH case after j.l.i.InvokerBytecodeGenerator code shape is updated. +IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, address member_name, Method* method, address bcp)) Bytecodes::Code code = Bytecodes::code_at(method, bcp); if (code != Bytecodes::_invokestatic) { @@ -1280,8 +1282,12 @@ IRT_ENTRY(void, InterpreterRuntime::member_name_arg_or_null(JavaThread* thread, Symbol* mname = cpool->name_ref_at(cp_index); if (MethodHandles::has_member_arg(cname, mname)) { - oop member_name = java_lang_invoke_DirectMethodHandle::member((oop)dmh); - thread->set_vm_result(member_name); + oop member_name_oop = (oop) member_name; + if (java_lang_invoke_DirectMethodHandle::is_instance(member_name_oop)) { + // FIXME: remove after j.l.i.InvokerBytecodeGenerator code shape is updated. + member_name_oop = java_lang_invoke_DirectMethodHandle::member(member_name_oop); + } + thread->set_vm_result(member_name_oop); } IRT_END #endif // INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 11e72d4ed27..cd5fceff2d0 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -3095,7 +3095,7 @@ void Metaspace::ergo_initialize() { void Metaspace::global_initialize() { // Initialize the alignment for shared spaces. - int max_alignment = os::vm_page_size(); + int max_alignment = os::vm_allocation_granularity(); size_t cds_total = 0; MetaspaceShared::set_max_alignment(max_alignment); diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 9c4c9b8fbf5..34907dd55a5 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1273,6 +1273,12 @@ bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDesc void InstanceKlass::methods_do(void f(Method* method)) { + // Methods aren't stable until they are loaded. This can be read outside + // a lock through the ClassLoaderData for profiling + if (!is_loaded()) { + return; + } + int len = methods()->length(); for (int index = 0; index < len; index++) { Method* m = methods()->at(index); diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index 10b69ceb17c..dced2e00f34 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -155,6 +155,9 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { } } + // print inlining for last compilation only + C.dump_print_inlining(); + // No retry; just break the loop. break; } diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 3a00ae2f829..9c05d1da889 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -672,6 +672,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _print_inlining_list(NULL), _print_inlining_stream(NULL), _print_inlining_idx(0), + _print_inlining_output(NULL), _preserve_jvm_state(0), _interpreter_frame_size(0) { C = this; @@ -978,6 +979,7 @@ Compile::Compile( ciEnv* ci_env, _print_inlining_list(NULL), _print_inlining_stream(NULL), _print_inlining_idx(0), + _print_inlining_output(NULL), _preserve_jvm_state(0), _allowed_reasons(0), _interpreter_frame_size(0) { @@ -2207,7 +2209,7 @@ void Compile::Optimize() { } // (End scope of igvn; run destructor if necessary for asserts.) - dump_inlining(); + process_print_inlining(); // A method with only infinite loops has no edges entering loops from root { NOT_PRODUCT( TracePhase t2("graphReshape", &_t_graphReshaping, TimeCompiler); ) @@ -3868,7 +3870,7 @@ void Compile::print_inlining_assert_ready() { assert(!_print_inlining || _print_inlining_stream->size() == 0, "loosing data"); } -void Compile::dump_inlining() { +void Compile::process_print_inlining() { bool do_print_inlining = print_inlining() || print_intrinsics(); if (do_print_inlining || log() != NULL) { // Print inlining message for candidates that we couldn't inline @@ -3885,9 +3887,21 @@ void Compile::dump_inlining() { } } if (do_print_inlining) { + ResourceMark rm; + stringStream ss; for (int i = 0; i < _print_inlining_list->length(); i++) { - tty->print("%s", _print_inlining_list->adr_at(i)->ss()->as_string()); + ss.print("%s", _print_inlining_list->adr_at(i)->ss()->as_string()); } + size_t end = ss.size(); + _print_inlining_output = NEW_ARENA_ARRAY(comp_arena(), char, end+1); + strncpy(_print_inlining_output, ss.base(), end+1); + _print_inlining_output[end] = 0; + } +} + +void Compile::dump_print_inlining() { + if (_print_inlining_output != NULL) { + tty->print_raw(_print_inlining_output); } } diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 739f30434c4..36ff03906f1 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -420,6 +420,7 @@ class Compile : public Phase { stringStream* _print_inlining_stream; GrowableArray* _print_inlining_list; int _print_inlining_idx; + char* _print_inlining_output; // Only keep nodes in the expensive node list that need to be optimized void cleanup_expensive_nodes(PhaseIterGVN &igvn); @@ -917,7 +918,8 @@ class Compile : public Phase { void remove_useless_late_inlines(GrowableArray* inlines, Unique_Node_List &useful); - void dump_inlining(); + void process_print_inlining(); + void dump_print_inlining(); bool over_inlining_cutoff() const { if (!inlining_incrementally()) { diff --git a/hotspot/src/share/vm/prims/jvmtiEnv.cpp b/hotspot/src/share/vm/prims/jvmtiEnv.cpp index 6dcf2e1bf95..765cbcd6290 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp @@ -307,9 +307,9 @@ JvmtiEnv::GetObjectSize(jobject object, jlong* size_ptr) { !java_lang_Class::is_primitive(mirror)) { Klass* k = java_lang_Class::as_Klass(mirror); assert(k != NULL, "class for non-primitive mirror must exist"); - *size_ptr = k->size() * wordSize; + *size_ptr = (jlong)k->size() * wordSize; } else { - *size_ptr = mirror->size() * wordSize; + *size_ptr = (jlong)mirror->size() * wordSize; } return JVMTI_ERROR_NONE; } /* end GetObjectSize */ diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 67a16978d3b..a68ed456899 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -33,9 +33,11 @@ #include "prims/whitebox.hpp" #include "prims/wbtestmethods/parserTests.hpp" +#include "runtime/thread.hpp" #include "runtime/arguments.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" + #include "utilities/debug.hpp" #include "utilities/macros.hpp" #include "utilities/exceptions.hpp" @@ -576,6 +578,15 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo WB_END +WB_ENTRY(jlong, WB_GetThreadStackSize(JNIEnv* env, jobject o)) + return (jlong) Thread::current()->stack_size(); +WB_END + +WB_ENTRY(jlong, WB_GetThreadRemainingStackSize(JNIEnv* env, jobject o)) + JavaThread* t = JavaThread::current(); + return (jlong) t->stack_available(os::current_stack_pointer()) - (jlong) StackShadowPages * os::vm_page_size(); +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -690,6 +701,8 @@ static JNINativeMethod methods[] = { {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", (void*)&WB_GetNMethod }, + {CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize }, + {CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize }, }; #undef CC diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 5ebe1cf251c..91e485e7aed 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1449,7 +1449,7 @@ bool verify_object_alignment() { return true; } -uintx Arguments::max_heap_for_compressed_oops() { +size_t Arguments::max_heap_for_compressed_oops() { // Avoid sign flip. assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size"); // We need to fit both the NULL page and the heap into the memory budget, while diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 7ba83996f46..e852b56ef54 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -120,7 +120,8 @@ void collect_profiled_methods(Method* m) { } void print_method_profiling_data() { - if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) { + if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData) && + (PrintMethodData || CompilerOracle::should_print_methods())) { ResourceMark rm; HandleMark hm; collected_profiled_methods = new GrowableArray(1024); diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp new file mode 100644 index 00000000000..4259227c3b3 --- /dev/null +++ b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP +#define SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP + +#include + +// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles +// [jk] this is not 100% correct because the float word order may different +// from the byte order (e.g. on ARM FPA) +#ifdef VM_LITTLE_ENDIAN +# define __HI(x) *(1+(int*)&x) +# define __LO(x) *(int*)&x +#else +# define __HI(x) *(int*)&x +# define __LO(x) *(1+(int*)&x) +#endif + +static double copysignA(double x, double y) { + __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); + return x; +} + +/* + * ==================================================== + * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * scalbn (double x, int n) + * scalbn(x,n) returns x* 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +hugeX = 1.0e+300, +tiny = 1.0e-300; + +static double scalbnA (double x, int n) { + int k,hx,lx; + hx = __HI(x); + lx = __LO(x); + k = (hx&0x7ff00000)>>20; /* extract exponent */ + if (k==0) { /* 0 or subnormal x */ + if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ + x *= two54; + hx = __HI(x); + k = ((hx&0x7ff00000)>>20) - 54; + if (n< -50000) return tiny*x; /*underflow*/ + } + if (k==0x7ff) return x+x; /* NaN or Inf */ + k = k+n; + if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ + if (k > 0) /* normal result */ + {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return hugeX*copysignA(hugeX,x); /*overflow*/ + else return tiny*copysignA(tiny,x); /*underflow*/ + } + k += 54; /* subnormal result */ + __HI(x) = (hx&0x800fffff)|(k<<20); + return x*twom54; +} + +#endif // SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp index c5fb4e2e3e4..69feb28bdfb 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -43,78 +43,7 @@ # pragma optimize ( "", off ) #endif -#include - -// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles -// [jk] this is not 100% correct because the float word order may different -// from the byte order (e.g. on ARM) -#ifdef VM_LITTLE_ENDIAN -# define __HI(x) *(1+(int*)&x) -# define __LO(x) *(int*)&x -#else -# define __HI(x) *(int*)&x -# define __LO(x) *(1+(int*)&x) -#endif - -#if !defined(AIX) -double copysign(double x, double y) { - __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); - return x; -} -#endif - -/* - * ==================================================== - * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - -/* - * scalbn (double x, int n) - * scalbn(x,n) returns x* 2**n computed by exponent - * manipulation rather than by actually performing an - * exponentiation or a multiplication. - */ - -static const double -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ - twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ - hugeX = 1.0e+300, - tiny = 1.0e-300; - -#if !defined(AIX) -double scalbn (double x, int n) { - int k,hx,lx; - hx = __HI(x); - lx = __LO(x); - k = (hx&0x7ff00000)>>20; /* extract exponent */ - if (k==0) { /* 0 or subnormal x */ - if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ - x *= two54; - hx = __HI(x); - k = ((hx&0x7ff00000)>>20) - 54; - if (n< -50000) return tiny*x; /*underflow*/ - } - if (k==0x7ff) return x+x; /* NaN or Inf */ - k = k+n; - if (k > 0x7fe) return hugeX*copysign(hugeX,x); /* overflow */ - if (k > 0) /* normal result */ - {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return hugeX*copysign(hugeX,x); /*overflow*/ - else return tiny*copysign(tiny,x); /*underflow*/ - } - k += 54; /* subnormal result */ - __HI(x) = (hx&0x800fffff)|(k<<20); - return x*twom54; -} -#endif +#include "runtime/sharedRuntimeMath.hpp" /* __ieee754_log(x) * Return the logarithm of x @@ -719,7 +648,7 @@ double __ieee754_pow(double x, double y) { z = one-(r-z); j = __HI(z); j += (n<<20); - if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ + if((j>>20)<=0) z = scalbnA(z,n); /* subnormal output */ else __HI(z) += (n<<20); return s*z; } diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp index 7c499d84165..1691bdf7690 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -63,63 +63,7 @@ #define SAFEBUF #endif -#include - -// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles -// [jk] this is not 100% correct because the float word order may different -// from the byte order (e.g. on ARM) -#ifdef VM_LITTLE_ENDIAN -# define __HI(x) *(1+(int*)&x) -# define __LO(x) *(int*)&x -#else -# define __HI(x) *(int*)&x -# define __LO(x) *(1+(int*)&x) -#endif - -static double copysignA(double x, double y) { - __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); - return x; -} - -/* - * scalbn (double x, int n) - * scalbn(x,n) returns x* 2**n computed by exponent - * manipulation rather than by actually performing an - * exponentiation or a multiplication. - */ - -static const double -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ -hugeX = 1.0e+300, -tiny = 1.0e-300; - -static double scalbnA (double x, int n) { - int k,hx,lx; - hx = __HI(x); - lx = __LO(x); - k = (hx&0x7ff00000)>>20; /* extract exponent */ - if (k==0) { /* 0 or subnormal x */ - if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ - x *= two54; - hx = __HI(x); - k = ((hx&0x7ff00000)>>20) - 54; - if (n< -50000) return tiny*x; /*underflow*/ - } - if (k==0x7ff) return x+x; /* NaN or Inf */ - k = k+n; - if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ - if (k > 0) /* normal result */ - {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} - if (k <= -54) { - if (n > 50000) /* in case integer overflow in n+k */ - return hugeX*copysignA(hugeX,x); /*overflow*/ - else return tiny*copysignA(tiny,x); /*underflow*/ - } - k += 54; /* subnormal result */ - __HI(x) = (hx&0x800fffff)|(k<<20); - return x*twom54; -} +#include "runtime/sharedRuntimeMath.hpp" /* * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index e470171dc21..8c2db990110 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -83,6 +83,7 @@ needs_jdk = \ runtime/RedefineObject/TestRedefineObject.java \ runtime/XCheckJniJsig/XCheckJSig.java \ serviceability/attach/AttachWithStalePidFile.java \ + serviceability/jvmti/8036666/GetObjectLockCount.java \ serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java \ serviceability/dcmd/DynLibDcmdTest.java @@ -134,9 +135,12 @@ needs_compact3 = \ gc/parallelScavenge/TestDynShrinkHeap.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ + serviceability/jvmti/GetObjectSizeOverflow.java \ + serviceability/jvmti/TestRedefineWithUnresolvedClass.java \ compiler/tiered/NonTieredLevelsTest.java \ compiler/tiered/TieredLevelsTest.java \ - compiler/intrinsics/bmi/verifycode + compiler/intrinsics/bmi/verifycode \ + runtime/whitebox/WBStackSize.java # Compact 2 adds full VM tests compact2 = \ diff --git a/hotspot/test/compiler/5091921/Test7005594.java b/hotspot/test/compiler/5091921/Test7005594.java index 4a23be13702..32e8bae93a4 100644 --- a/hotspot/test/compiler/5091921/Test7005594.java +++ b/hotspot/test/compiler/5091921/Test7005594.java @@ -25,7 +25,6 @@ /** * @test * @bug 7005594 - * @ignore 7117034 * @summary Array overflow not handled correctly with loop optimzations * * @run shell Test7005594.sh diff --git a/hotspot/test/compiler/5091921/Test7005594.sh b/hotspot/test/compiler/5091921/Test7005594.sh index 8d9fc36ead7..2ca434ae876 100644 --- a/hotspot/test/compiler/5091921/Test7005594.sh +++ b/hotspot/test/compiler/5091921/Test7005594.sh @@ -78,7 +78,7 @@ cp ${TESTSRC}/Test7005594.sh . ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTVMOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 result=$? @@ -97,7 +97,7 @@ then fi # The test should pass when no enough space for object heap -grep "Could not reserve enough space for object heap" test.out +grep "Could not reserve enough space for .*object heap" test.out if [ $? = 0 ] then echo "Passed" diff --git a/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java b/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java index 6d4fa400dda..ec27615fba3 100644 --- a/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java +++ b/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java @@ -25,6 +25,12 @@ import com.oracle.java.testlibrary.cli.*; /** * Base class for all X86 bit manipulation related command line options. + * + * Note that this test intended to verify that VM could be launched with + * specific options and that values of these options processed correctly. + * In order to do that test launch a new VM with tested options, the same + * flavor-specific flag as one that was used for parent VM (-client, -server, + * -minimal, -graal) and '-version'. */ public abstract class BMICommandLineOptionTestBase extends CPUSpecificCommandLineOptionTest { @@ -58,10 +64,11 @@ public abstract class BMICommandLineOptionTestBase String supportedCPUFeatures[], String unsupportedCPUFeatures[]) { super(".*", supportedCPUFeatures, unsupportedCPUFeatures); - this.optionName = optionName; - this.warningMessage = warningMessage; - this.errorMessage = CommandLineOptionTest. - UNRECOGNIZED_OPTION_ERROR_FORMAT.format(optionName); + this.optionName = optionName; + this.warningMessage = warningMessage; + this.errorMessage = String.format( + CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT, + optionName); } } diff --git a/hotspot/test/compiler/arguments/BMISupportedCPUTest.java b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java index c0af31fd766..df6e1540918 100644 --- a/hotspot/test/compiler/arguments/BMISupportedCPUTest.java +++ b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java @@ -28,6 +28,12 @@ import com.oracle.java.testlibrary.cli.*; * Test on bit manipulation related command line options, * that should be executed on CPU that supports all required * features. + * + * Note that this test intended to verify that VM could be launched with + * specific options and that values of these options processed correctly. + * In order to do that test launch a new VM with tested options, the same + * flavor-specific flag as one that was used for parent VM (-client, -server, + * -minimal, -graal) and '-version'. */ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { @@ -49,24 +55,38 @@ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { @Override public void runTestCases() throws Throwable { - // verify that VM will succesfully start up whithout warnings - CommandLineOptionTest. - verifyJVMStartup("-XX:+" + optionName, - null, new String[] { warningMessage }, - ExitCode.OK); + /* + Verify that VM will successfully start up without warnings. + VM will be launched with following flags: + -XX:+ -version + */ + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); - // verify that VM will succesfully start up whithout warnings - CommandLineOptionTest. - verifyJVMStartup("-XX:-" + optionName, - null, new String[] { warningMessage }, - ExitCode.OK); + /* + Verify that VM will successfully start up without warnings. + VM will be launched with following flags: + -XX:- -version + */ + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage }, ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(optionName, false)); - // verify that on appropriate CPU option in on by default - CommandLineOptionTest.verifyOptionValue(optionName, "true"); + /* + Verify that on appropriate CPU option in on by default. + VM will be launched with following flags: + -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true"); - // verify that option could be explicitly turned off - CommandLineOptionTest.verifyOptionValue(optionName, "false", - "-XX:-" + optionName); + /* + Verify that option could be explicitly turned off. + VM will be launched with following flags: + -XX:- -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } } diff --git a/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java index 7a78c74e579..93fbcb29687 100644 --- a/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java +++ b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java @@ -28,6 +28,12 @@ import com.oracle.java.testlibrary.cli.*; * Test on bit manipulation related command line options, * that should be executed on CPU that does not support * required features. + * + * Note that this test intended to verify that VM could be launched with + * specific options and that values of these options processed correctly. + * In order to do that test launch a new VM with tested options, the same + * flavor-specific flag as one that was used for parent VM (-client, -server, + * -minimal, -graal) and '-version'. */ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { @@ -64,28 +70,38 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { */ public void unsupportedX86CPUTestCases() throws Throwable { - // verify that VM will succesfully start up, but output will - // contain a warning - CommandLineOptionTest. - verifyJVMStartup("-XX:+" + optionName, - new String[] { warningMessage }, - new String[] { errorMessage }, - ExitCode.OK); + /* + Verify that VM will successfully start up, but output will contain a + warning. VM will be launched with following options: + -XX:+ -version + */ + CommandLineOptionTest.verifySameJVMStartup( + new String[] { warningMessage }, new String[] { errorMessage }, + ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag( + optionName, true)); - // verify that VM will succesfully startup without any warnings - CommandLineOptionTest. - verifyJVMStartup("-XX:-" + optionName, - null, - new String[] { warningMessage, errorMessage }, - ExitCode.OK); + /* + Verify that VM will successfully startup without any warnings. + VM will be launched with following options: + -XX:- -version + */ + CommandLineOptionTest.verifySameJVMStartup(null, + new String[] { warningMessage, errorMessage }, ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(optionName, false)); - // verify that on unsupported CPUs option is off by default - CommandLineOptionTest.verifyOptionValue(optionName, "false"); + /* + Verify that on unsupported CPUs option is off by default. + VM will be launched with following options: -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false"); - // verify that on unsupported CPUs option will be off even if - // it was explicitly turned on by uset - CommandLineOptionTest.verifyOptionValue(optionName, "false", - "-XX:+" + optionName); + /* + Verify that on unsupported CPUs option will be off even if + it was explicitly turned on by user. VM will be launched with + following options: -XX:+ -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } @@ -97,18 +113,17 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { */ public void unsupportedNonX86CPUTestCases() throws Throwable { - // verify that VM known nothing about tested option - CommandLineOptionTest. - verifyJVMStartup("-XX:+" + optionName, - new String[] { errorMessage }, - null, - ExitCode.FAIL); + /* + Verify that VM known nothing about tested option. VM will be launched + with following options: -XX:[+-] -version + */ + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); - CommandLineOptionTest. - verifyJVMStartup("-XX:-" + optionName, - new String[] { errorMessage }, - null, - ExitCode.FAIL); + CommandLineOptionTest.verifySameJVMStartup( + new String[] { errorMessage }, null, ExitCode.FAIL, + CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } } diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java index 995d450e365..d6628b1ed0c 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java @@ -40,7 +40,8 @@ import com.oracle.java.testlibrary.*; import com.oracle.java.testlibrary.cli.*; public class TestUseCountTrailingZerosInstructionOnSupportedCPU - extends BMISupportedCPUTest { + extends BMISupportedCPUTest { + private static final String DISABLE_BMI = "-XX:-UseBMI1Instructions"; public TestUseCountTrailingZerosInstructionOnSupportedCPU() { super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1"); @@ -51,18 +52,23 @@ public class TestUseCountTrailingZerosInstructionOnSupportedCPU super.runTestCases(); - // verify that option will be disabled if all BMI1 instuctions - // are explicitly disabled - CommandLineOptionTest. - verifyOptionValue("UseCountTrailingZerosInstruction", "false", - "-XX:-UseBMI1Instructions"); + /* + Verify that option will be disabled if all BMI1 instructions + are explicitly disabled. VM will be launched with following options: + -XX:-UseBMI1Instructions -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + TestUseCountTrailingZerosInstructionOnSupportedCPU.DISABLE_BMI); - // verify that option could be turned on even if other BMI1 - // instructions were turned off - CommandLineOptionTest. - verifyOptionValue("UseCountTrailingZerosInstruction", "true", - "-XX:-UseBMI1Instructions", - "-XX:+UseCountTrailingZerosInstruction"); + /* + Verify that option could be turned on even if other BMI1 + instructions were turned off. VM will be launched with following + options: -XX:-UseBMI1Instructions + -XX:+UseCountTrailingZerosInstruction -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + TestUseCountTrailingZerosInstructionOnSupportedCPU.DISABLE_BMI, + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java index 86853aab0c5..67b6ea318ca 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8031321 * @summary Verify processing of UseCountTrailingZerosInstruction option - * on CPU without TZCNT instuction (BMI1 feature) support. + * on CPU without TZCNT instruction (BMI1 feature) support. * @library /testlibrary /testlibrary/whitebox * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU * BMIUnsupportedCPUTest @@ -40,7 +40,8 @@ import com.oracle.java.testlibrary.*; import com.oracle.java.testlibrary.cli.*; public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU - extends BMIUnsupportedCPUTest { + extends BMIUnsupportedCPUTest { + private static final String ENABLE_BMI = "-XX:+UseBMI1Instructions"; public TestUseCountTrailingZerosInstructionOnUnsupportedCPU() { super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1"); @@ -51,16 +52,24 @@ public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU super.unsupportedX86CPUTestCases(); - // verify that option will not be turned on during - // UseBMI1Instuctions processing - CommandLineOptionTest. - verifyOptionValue("UseCountTrailingZerosInstruction", "false", - "-XX:+UseBMI1Instructions"); + /* + Verify that option will not be turned on during UseBMI1Instructions + processing. VM will be launched with following options: + -XX:+UseBMI1Instructions -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + TestUseCountTrailingZerosInstructionOnUnsupportedCPU. + ENABLE_BMI); - CommandLineOptionTest. - verifyOptionValue("UseCountTrailingZerosInstruction", "false", - "-XX:+UseCountTrailingZerosInstruction", - "-XX:+UseBMI1Instructions"); + /* + VM will be launched with following options: + -XX:+UseCountTrailingZerosInstruction -XX:+UseBMI1Instructions + -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + CommandLineOptionTest.prepareBooleanFlag(optionName, true), + TestUseCountTrailingZerosInstructionOnUnsupportedCPU. + ENABLE_BMI); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java b/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java index fcdd592263d..ae700981216 100644 --- a/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java +++ b/hotspot/test/compiler/uncommontrap/TestSpecTrapClassUnloading.java @@ -25,7 +25,7 @@ * @test * @bug 8031752 * @summary speculative traps need to be cleaned up at GC - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx1M TestSpecTrapClassUnloading + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UseTypeSpeculation -XX:TypeProfileLevel=222 -XX:CompileCommand=exclude,java.lang.reflect.Method::invoke -XX:CompileCommand=exclude,sun.reflect.DelegatingMethodAccessorImpl::invoke -Xmx512M TestSpecTrapClassUnloading * */ @@ -45,7 +45,7 @@ public class TestSpecTrapClassUnloading { MemoryChunk other; long[] array; MemoryChunk(MemoryChunk other) { - other = other; + this.other = other; array = new long[1024 * 1024 * 1024]; } } diff --git a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java index 944efcc3956..6f9b02de270 100644 --- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java +++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java @@ -26,7 +26,7 @@ * @bug 8016479 * @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags * @library /testlibrary - * @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -verbose:gc TestDynShrinkHeap + * @run main/othervm -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseParallelGC -XX:MinHeapFreeRatio=0 -XX:MaxHeapFreeRatio=100 -Xmx1g -verbose:gc TestDynShrinkHeap */ import com.oracle.java.testlibrary.DynamicVMOption; import java.lang.management.ManagementFactory; @@ -41,7 +41,7 @@ public class TestDynShrinkHeap { public static final String MAX_FREE_RATIO_FLAG_NAME = "MaxHeapFreeRatio"; private static ArrayList list = new ArrayList<>(0); - private static final int M = 1024 * 1024; // to make heap more manageable by test code + private static final int LEN = 512 * 1024 + 1; public TestDynShrinkHeap() { } @@ -69,12 +69,12 @@ public class TestDynShrinkHeap { } private void eat() { - for (int i = 0; i < M; i++) { + for (int i = 0; i < LEN; i++) { list.add(new byte[1024]); } - MemoryUsagePrinter.printMemoryUsage("allocated " + M + " arrays"); + MemoryUsagePrinter.printMemoryUsage("allocated " + LEN + " arrays"); - list.subList(0, M / 2).clear(); + list.subList(0, LEN / 2).clear(); System.gc(); MemoryUsagePrinter.printMemoryUsage("array halved"); } diff --git a/hotspot/test/runtime/6929067/T.java b/hotspot/test/runtime/6929067/T.java deleted file mode 100644 index 48c48857b95..00000000000 --- a/hotspot/test/runtime/6929067/T.java +++ /dev/null @@ -1,12 +0,0 @@ -public class T -{ - public static boolean foo(boolean bar) - { - return bar; - } - - public static void printIt() - { - System.out.println("Hello"); - } -} diff --git a/hotspot/test/runtime/6929067/invoke.c b/hotspot/test/runtime/6929067/invoke.c deleted file mode 100644 index 8dde2cd671b..00000000000 --- a/hotspot/test/runtime/6929067/invoke.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -#include - -union env_union -{ - void *void_env; - JNIEnv *jni_env; -}; - -union env_union tmp; -JNIEnv* env; -JavaVM* jvm; -JavaVMInitArgs vm_args; -JavaVMOption options[1]; -jclass class_id; -jmethodID method_id; -jint result; - -long product(unsigned long n, unsigned long m) { - if (m == 1) { - return n; - } else { - int *p = alloca(sizeof (int)); - *p = n; - return product (n, m-1) + *p; - } -} - -void * -floobydust (void *p) -{ - (*jvm)->AttachCurrentThread(jvm, &tmp.void_env, NULL); - env = tmp.jni_env; - - class_id = (*env)->FindClass (env, "T"); - assert (class_id); - - method_id = (*env)->GetStaticMethodID (env, class_id, "printIt", "()V"); - assert (method_id); - - (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL); - - (*jvm)->DetachCurrentThread(jvm); - - printf("%ld\n", product(5000,5000)); - - (*jvm)->AttachCurrentThread(jvm, &tmp.void_env, NULL); - env = tmp.jni_env; - - class_id = (*env)->FindClass (env, "T"); - assert (class_id); - - method_id = (*env)->GetStaticMethodID (env, class_id, "printIt", "()V"); - assert (method_id); - - (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL); - - (*jvm)->DetachCurrentThread(jvm); - - printf("%ld\n", product(5000,5000)); - - return NULL; -} - -int -main (int argc, const char** argv) -{ - options[0].optionString = "-Xss320k"; - - vm_args.version = JNI_VERSION_1_2; - vm_args.ignoreUnrecognized = JNI_TRUE; - vm_args.options = options; - vm_args.nOptions = 1; - - result = JNI_CreateJavaVM (&jvm, &tmp.void_env, &vm_args); - assert (result >= 0); - - env = tmp.jni_env; - - floobydust (NULL); - - pthread_t thr; - pthread_create (&thr, NULL, floobydust, NULL); - pthread_join (thr, NULL); - - return 0; -} diff --git a/hotspot/test/runtime/InitialThreadOverflow/invoke.c b/hotspot/test/runtime/InitialThreadOverflow/invoke.c deleted file mode 100644 index 84f0e405003..00000000000 --- a/hotspot/test/runtime/InitialThreadOverflow/invoke.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include - -#include - -JavaVM* jvm; - -void * -floobydust (void *p) { - JNIEnv *env; - jclass class_id; - jmethodID method_id; - - (*jvm)->AttachCurrentThread(jvm, (void**)&env, NULL); - - class_id = (*env)->FindClass (env, "DoOverflow"); - assert (class_id); - - method_id = (*env)->GetStaticMethodID(env, class_id, "printIt", "()V"); - assert (method_id); - - (*env)->CallStaticVoidMethod(env, class_id, method_id, NULL); - - (*jvm)->DetachCurrentThread(jvm); -} - -int -main (int argc, const char** argv) { - JavaVMOption options[1]; - options[0].optionString = (char*) "-Xss320k"; - - JavaVMInitArgs vm_args; - vm_args.version = JNI_VERSION_1_2; - vm_args.ignoreUnrecognized = JNI_TRUE; - vm_args.options = options; - vm_args.nOptions = 1; - - JNIEnv* env; - jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); - assert(result >= 0); - - pthread_t thr; - pthread_create(&thr, NULL, floobydust, NULL); - pthread_join(thr, NULL); - - floobydust(NULL); - - return 0; -} diff --git a/hotspot/test/runtime/InitialThreadOverflow/testme.sh b/hotspot/test/runtime/InitialThreadOverflow/testme.sh deleted file mode 100644 index d5d0eb223ff..00000000000 --- a/hotspot/test/runtime/InitialThreadOverflow/testme.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. - -# @test testme.sh -# @bug 8009062 -# @summary Poor performance of JNI AttachCurrentThread after fix for 7017193 -# @compile DoOverflow.java -# @run shell testme.sh - -set -x -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" -fi -echo "TESTSRC=${TESTSRC}" -## Adding common setup Variables for running shell tests. -. ${TESTSRC}/../../test_env.sh - -if [ "${VM_OS}" != "linux" ] -then - echo "Test only valid for Linux" - exit 0 -fi - -gcc_cmd=`which gcc` -if [ "x$gcc_cmd" = "x" ]; then - echo "WARNING: gcc not found. Cannot execute test." 2>&1 - exit 0; -fi - -CFLAGS="-m${VM_BITS}" - -LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH -export LD_LIBRARY_PATH - -cp ${TESTSRC}/invoke.c . - -# Copy the result of our @compile action: -cp ${TESTCLASSES}/DoOverflow.class . - -echo "Architecture: ${VM_CPU}" -echo "Compilation flag: ${CFLAGS}" -echo "VM type: ${VM_TYPE}" -echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}" - -# Note pthread may not be found thus invoke creation will fail to be created. -# Check to ensure you have a /usr/lib/libpthread.so if you don't please look -# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. - -$gcc_cmd -DLINUX ${CFLAGS} -o invoke \ - -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \ - -L${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ - -ljvm -lpthread invoke.c - -./invoke -exit $? diff --git a/hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java b/hotspot/test/runtime/StackGuardPages/DoOverflow.java similarity index 87% rename from hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java rename to hotspot/test/runtime/StackGuardPages/DoOverflow.java index 958285ca915..4b9c45b62e8 100644 --- a/hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java +++ b/hotspot/test/runtime/StackGuardPages/DoOverflow.java @@ -30,12 +30,16 @@ public class DoOverflow { overflow(); } + public static void printAlive() { + System.out.println("Java thread is alive."); + } + public static void printIt() { System.out.println("Going to overflow stack"); try { new DoOverflow().overflow(); } catch(java.lang.StackOverflowError e) { - System.out.println("Overflow OK " + count); + System.out.println("Test PASSED. Got StackOverflowError at " + count + " iteration"); } } } diff --git a/hotspot/test/runtime/StackGuardPages/invoke.c b/hotspot/test/runtime/StackGuardPages/invoke.c new file mode 100644 index 00000000000..483ac0b98e7 --- /dev/null +++ b/hotspot/test/runtime/StackGuardPages/invoke.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2010, 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. + * + */ + +/* This code tests the fact that we actually remove stack guard page when calling + * JavaThread::exit() i.e. when detaching from current thread. + * We overflow the stack and check that we get access error because of a guard page. + * Than we detach from vm thread and overflow stack once again. This time we shouldn't + * get access error because stack guard page is removed + * + * Notice: due a complicated interaction of signal handlers, the test may crash. + * It's OK - don't file a bug. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +JavaVM* _jvm; + +static jmp_buf context; + +static int _last_si_code = -1; +static int _failures = 0; +static int _rec_count = 0; +static int _kp_rec_count = 0; + +pid_t gettid() { + return (pid_t) syscall(SYS_gettid); +} + +static void handler(int sig, siginfo_t *si, void *unused) { + _last_si_code = si->si_code; + printf("Got SIGSEGV(%d) at address: 0x%lx\n",si->si_code, (long) si->si_addr); + longjmp(context, 1); +} + +void set_signal_handler() { + static char altstack[SIGSTKSZ]; + + stack_t ss = { + .ss_size = SIGSTKSZ, + .ss_flags = 0, + .ss_sp = altstack + }; + + struct sigaction sa = { + .sa_sigaction = handler, + .sa_flags = SA_ONSTACK | SA_SIGINFO | SA_RESETHAND + }; + + _last_si_code = -1; + + sigaltstack(&ss, 0); + sigemptyset(&sa.sa_mask); + if (sigaction(SIGSEGV, &sa, NULL) == -1) { + fprintf(stderr, "Test ERROR. Can't set sigaction (%d)\n", errno); + exit(7); + } +} + +void *run_java_overflow (void *p) { + JNIEnv *env; + jclass class_id; + jmethodID method_id; + int res; + + res = (*_jvm)->AttachCurrentThread(_jvm, (void**)&env, NULL); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't attach to current thread\n"); + exit(7); + } + + class_id = (*env)->FindClass (env, "DoOverflow"); + if (class_id == NULL) { + fprintf(stderr, "Test ERROR. Can't load class DoOverflow\n"); + exit(7); + } + + method_id = (*env)->GetStaticMethodID(env, class_id, "printIt", "()V"); + if (method_id == NULL) { + fprintf(stderr, "Test ERROR. Can't find method DoOverflow.printIt\n"); + exit(7); + } + + (*env)->CallStaticVoidMethod(env, class_id, method_id, NULL); + + res = (*_jvm)->DetachCurrentThread(_jvm); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't call detach from current thread\n"); + exit(7); + } +} + +void do_overflow(){ + int *p = alloca(sizeof(int)); + if (_kp_rec_count == 0 || _rec_count < _kp_rec_count) { + _rec_count ++; + do_overflow(); + } +} + +void *run_native_overflow(void *p) { + // Test that stack guard page is correctly set for initial and non initial thread + // and correctly removed for the initial thread + JNIEnv *env; + jclass class_id; + jmethodID method_id; + int res; + + printf("run_native_overflow %ld\n", (long) gettid()); + + res = (*_jvm)->AttachCurrentThread(_jvm, (void **)&env, NULL); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't attach to current thread\n"); + exit(7); + } + + class_id = (*env)->FindClass (env, "DoOverflow"); + if (class_id == NULL) { + fprintf(stderr, "Test ERROR. Can't load class DoOverflow\n"); + exit(7); + } + + method_id = (*env)->GetStaticMethodID (env, class_id, "printAlive", "()V"); + if (method_id == NULL) { + fprintf(stderr, "Test ERROR. Can't find method DoOverflow.printAlive\n"); + exit(7); + } + + (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL); + + set_signal_handler(); + if (! setjmp(context)) { + do_overflow(); + } + + if (_last_si_code == SEGV_ACCERR) { + printf("Test PASSED. Got access violation accessing guard page at %d\n", _rec_count); + } + + res = (*_jvm)->DetachCurrentThread(_jvm); + if (res != JNI_OK) { + fprintf(stderr, "Test ERROR. Can't call detach from current thread\n"); + exit(7); + } + + if (getpid() != gettid()) { + // For non-initial thread we don't unmap the region but call os::uncommit_memory and keep PROT_NONE + // so if host has enough swap space we will get the same SEGV with code SEGV_ACCERR(2) trying + // to access it as if the guard page is present. + // We have no way to check this, so bail out, marking test as succeeded + printf("Test PASSED. Not initial thread\n"); + return NULL; + } + + // Limit depth of recursion for second run. It can't exceed one for first run. + _kp_rec_count = _rec_count; + _rec_count = 0; + + set_signal_handler(); + if (! setjmp(context)) { + do_overflow(); + } + + if (_last_si_code == SEGV_ACCERR) { + ++ _failures; + fprintf(stderr,"Test FAILED. Stack guard page is still there at %d\n", _rec_count); + } else if (_last_si_code == -1) { + printf("Test PASSED. No stack guard page is present. Maximum recursion level reached at %d\n", _rec_count); + } + else{ + printf("Test PASSED. No stack guard page is present. SIGSEGV(%d) at %d\n", _last_si_code, _rec_count); + } + + return NULL; +} + +void usage() { + fprintf(stderr, "Usage: invoke test_java_overflow\n"); + fprintf(stderr, " invoke test_native_overflow\n"); + exit(7); +} + + +int main (int argc, const char** argv) { + JavaVMInitArgs vm_args; + JavaVMOption options[2]; + JNIEnv* env; + + printf("Test started with pid: %ld\n", (long) getpid()); + + options[0].optionString = "-Xint"; + options[1].optionString = "-Xss320k"; + + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + vm_args.options = options; + vm_args.nOptions = 2; + + if (JNI_CreateJavaVM (&_jvm, (void **)&env, &vm_args) < 0 ) { + fprintf(stderr, "Test ERROR. Can't create JavaVM\n"); + exit(7); + } + + pthread_t thr; + + if (argc > 1 && strcmp(argv[1], "test_java_overflow") == 0) { + printf("\nTesting JAVA_OVERFLOW\n"); + + printf("Testing stack guard page behaviour for other thread\n"); + pthread_create (&thr, NULL, run_java_overflow, NULL); + pthread_join (thr, NULL); + + printf("Testing stack guard page behaviour for initial thread\n"); + run_java_overflow(NULL); + // This test crash on error + exit(0); + } + + if (argc > 1 && strcmp(argv[1], "test_native_overflow") == 0) { + printf("\nTesting NATIVE_OVERFLOW\n"); + + printf("Testing stack guard page behaviour for other thread\n"); + pthread_create (&thr, NULL, run_native_overflow, NULL); + pthread_join (thr, NULL); + + printf("Testing stack guard page behaviour for initial thread\n"); + run_native_overflow(NULL); + + exit((_failures > 0) ? 1 : 0); + } + + fprintf(stderr, "Test ERROR. Unknown parameter %s\n", ((argc > 1) ? argv[1] : "none")); + usage(); +} diff --git a/hotspot/test/runtime/6929067/Test6929067.sh b/hotspot/test/runtime/StackGuardPages/testme.sh similarity index 62% rename from hotspot/test/runtime/6929067/Test6929067.sh rename to hotspot/test/runtime/StackGuardPages/testme.sh index e1fd6b78237..7f6a24a3d31 100644 --- a/hotspot/test/runtime/6929067/Test6929067.sh +++ b/hotspot/test/runtime/StackGuardPages/testme.sh @@ -1,13 +1,10 @@ #!/bin/sh -## -## @test Test6929067.sh -## @bug 6929067 -## @bug 8021296 -## @bug 8025519 -## @summary Stack guard pages should be removed when thread is detached -## @run shell Test6929067.sh -## +# +# @test testme.sh +# @summary Stack guard pages should be installed correctly and removed when thread is detached +# @run shell testme.sh +# if [ "${TESTSRC}" = "" ] then @@ -32,12 +29,9 @@ fi CFLAGS=-m${VM_BITS} -LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH +LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:${TESTJAVA}/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH -cp ${TESTSRC}/*.java ${THIS_DIR} -${COMPILEJAVA}/bin/javac *.java - echo "Architecture: ${VM_CPU}" echo "Compilation flag: ${CFLAGS}" echo "VM type: ${VM_TYPE}" @@ -47,10 +41,20 @@ echo "LD_LIBRARY_PATH: ${LD_LIBRARY_PATH}" # Check to ensure you have a /usr/lib/libpthread.so if you don't please look # for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. -$gcc_cmd -DLINUX ${CFLAGS} -o invoke \ +cp ${TESTSRC}/DoOverflow.java . +${COMPILEJAVA}/bin/javac DoOverflow.java + +$gcc_cmd -DLINUX -g3 ${CFLAGS} -o invoke \ -I${TESTJAVA}/include -I${TESTJAVA}/include/linux \ -L${TESTJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ + -L${TESTJAVA}/lib/${VM_CPU}/${VM_TYPE} \ ${TESTSRC}/invoke.c -ljvm -lpthread -./invoke +if [ $? -ne 0 ] ; then + echo "Compile failed, Ignoring failed compilation and forcing the test to pass" + exit 0 +fi + +./invoke test_java_overflow +./invoke test_native_overflow exit $? diff --git a/hotspot/test/runtime/whitebox/WBStackSize.java b/hotspot/test/runtime/whitebox/WBStackSize.java new file mode 100644 index 00000000000..2a0216082d7 --- /dev/null +++ b/hotspot/test/runtime/whitebox/WBStackSize.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test WBStackSize + * @summary verify that whitebox functions getThreadFullStackSize() and getThreadRemainingStackSize are working + * @library /testlibrary /testlibrary/whitebox + * @build WBStackSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k WBStackSize + */ + +/* + * The test may product a false failure if too big StackYellowPages/StackRedPages/ShackShadowPages + * VM options are specified. The proper test would retrieve the page size from VM and account for these options + * instead of check below: + * Math.abs(actualStackSize - configStackSize) > configStackSize * 0.1 + * + * Please file a test bug, if this is a problem. + */ + +import com.sun.management.HotSpotDiagnosticMXBean; +import sun.hotspot.WhiteBox; + +public class WBStackSize { + + static final long K = 1024; + + static final long MIN_STACK_SIZE = 8 * K; + static final long MAX_STACK_SIZE_ALLOCATED_IN_MAIN = 200 * K; // current value is about 130k on 64-bit platforms + + static final WhiteBox wb = WhiteBox.getWhiteBox(); + + static long stackSizeOnOverflow = -1; + + static int eatAllStack() { + return eatAllStack() * 2; + } + + static void testStackOverflow() { + + stackSizeOnOverflow = wb.getThreadRemainingStackSize(); + + if (stackSizeOnOverflow > MIN_STACK_SIZE) { + + try { + testStackOverflow(); + } catch (StackOverflowError e) { + // We caught SOE too early. The error will be reported in main() + } + + } else { + + try { + eatAllStack(); + throw new RuntimeException("Haven't caught StackOverflowError at all"); + } catch (StackOverflowError e) { + // OK: we caught the anticipated error + } + } + } + + public static void main(String[] args) { + HotSpotDiagnosticMXBean bean = sun.management.ManagementFactoryHelper.getDiagnosticMXBean(); + long configStackSize = Long.valueOf(bean.getVMOption("ThreadStackSize").getValue()) * K; + + System.out.println("ThreadStackSize VM option: " + configStackSize); + + long actualStackSize = wb.getThreadStackSize(); + System.out.println("Full stack size: " + actualStackSize); + + if (Math.abs(actualStackSize - configStackSize) > configStackSize * 0.1) { + throw new RuntimeException("getThreadFullStackSize value [" + actualStackSize + + "] should be within 90%..110% of the value returned by HotSpotDiagnosticMXBean"); + } + + long remainingStackSize = wb.getThreadRemainingStackSize(); + System.out.println("Remaining stack size in main(): " + remainingStackSize); + + // Up to 200k can be already allocated by VM + if (remainingStackSize > configStackSize + || (configStackSize > MAX_STACK_SIZE_ALLOCATED_IN_MAIN + && remainingStackSize < configStackSize - MAX_STACK_SIZE_ALLOCATED_IN_MAIN)) { + + throw new RuntimeException("getThreadRemainingStackSize value [" + remainingStackSize + + "] should be at least ThreadStackSize value [" + configStackSize + "] minus [" + + MAX_STACK_SIZE_ALLOCATED_IN_MAIN + "]"); + } + + testStackOverflow(); + + if (stackSizeOnOverflow > MIN_STACK_SIZE) { + throw new RuntimeException("Caught StackOverflowError too early: when there were " + + stackSizeOnOverflow + " bytes in stack"); + } else if (stackSizeOnOverflow < 0) { + throw new RuntimeException("Internal test error: stackRemainingSize < 0"); + } else { + System.out.println("Caught StackOverflowError as expected"); + } + } +} diff --git a/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java new file mode 100644 index 00000000000..ec33d813541 --- /dev/null +++ b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflow.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.PrintWriter; +import com.oracle.java.testlibrary.*; + +/* + * Test to verify GetObjectSize does not overflow on a 600M element int[] + * + * @test + * @bug 8027230 + * @library /testlibrary + * @build GetObjectSizeOverflowAgent + * @run main ClassFileInstaller GetObjectSizeOverflowAgent + * @run main GetObjectSizeOverflow + */ +public class GetObjectSizeOverflow { + public static void main(String[] args) throws Exception { + + if (!Platform.is64bit()) { + System.out.println("Test needs a 4GB heap and can only be run as a 64bit process, skipping."); + return; + } + + PrintWriter pw = new PrintWriter("MANIFEST.MF"); + pw.println("Premain-Class: GetObjectSizeOverflowAgent"); + pw.close(); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "GetObjectSizeOverflowAgent.class"}); + pb.start().waitFor(); + + ProcessBuilder pt = ProcessTools.createJavaProcessBuilder(true, "-Xmx4000m", "-javaagent:agent.jar", "GetObjectSizeOverflowAgent"); + OutputAnalyzer output = new OutputAnalyzer(pt.start()); + + if (output.getStdout().contains("Could not reserve enough space") || output.getStderr().contains("java.lang.OutOfMemoryError")) { + System.out.println("stdout: " + output.getStdout()); + System.out.println("stderr: " + output.getStderr()); + System.out.println("Test could not reserve or allocate enough space, skipping"); + return; + } + + output.stdoutShouldContain("GetObjectSizeOverflow passed"); + } +} diff --git a/hotspot/test/serviceability/jvmti/GetObjectSizeOverflowAgent.java b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflowAgent.java new file mode 100644 index 00000000000..8f7c2162364 --- /dev/null +++ b/hotspot/test/serviceability/jvmti/GetObjectSizeOverflowAgent.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.instrument.*; + +public class GetObjectSizeOverflowAgent { + + static Instrumentation instrumentation; + + public static void premain(String agentArgs, Instrumentation instrumentation) { + GetObjectSizeOverflowAgent.instrumentation = instrumentation; + } + + public static void main(String[] args) throws Exception { + int[] a = new int[600_000_000]; + long size = instrumentation.getObjectSize(a); + + if (size < 2_400_000_000L) { + throw new RuntimeException("Invalid size of array, expected >= 2400000000, got " + size); + } + + System.out.println("GetObjectSizeOverflow passed"); + } +} diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java index e35260c6d2f..a959900459a 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java @@ -150,6 +150,8 @@ public class WhiteBox { public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations); public native void runMemoryUnitTests(); public native void readFromNoaccessArea(); + public native long getThreadStackSize(); + public native long getThreadRemainingStackSize(); // CPU features public native String getCPUFeatures(); diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7cda4470598..e7c3b4c5d14 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -257,3 +257,5 @@ f93a792fe37279d4d37aea86a99f3abbdc6fe79b jdk9-b09 e88cecf5a21b760ff7d7761c2db6bb8c82bc9f0c jdk9-b12 5eaf717f6e36037a6d3744ffeee0e4c88e64a0d2 jdk9-b13 32b3fc4bc7374a34d52b7f4e2391b4b4b0c084e8 jdk9-b14 +6bad71866c7598587860e0981b0b0e51ec8c0476 jdk9-b15 +a1461221b05d4620e4d7d1907e2a0282aaedf31c jdk9-b16 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index c7dda23a67d..b6167002ea2 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -260,3 +260,5 @@ c9e8bb8c1144a966ca7b481142c6b5e55d14a29c jdk9-b09 779f8b21c75f83e3918dac8499e4d0ecb3a54ed7 jdk9-b12 3d42204854c9f703e3ccdc8891248e73057713ab jdk9-b13 02e58850b7062825308413d420f2b02c1f25a724 jdk9-b14 +e9780330017a6b464a385356d77e5136f9de8d09 jdk9-b15 +1e1a3b2215b7551d88e89d1ca8c1e1ebe3d3c0ab jdk9-b16 diff --git a/jdk/.hgtags b/jdk/.hgtags index fdf62aef521..1d0fd47c313 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -257,3 +257,5 @@ ab06ba2894313a47e4969ca37792ff119c49e711 jdk9-b10 83d9bc20973de232cae45b139fdff8a4549c130f jdk9-b12 c7c8002d02721e02131d104549ebeb8b379fb8d2 jdk9-b13 5c7a17a81afd0906b53ee31d95a3211c96ff6b25 jdk9-b14 +4537360f09fe23ab339ee588747b657feb12d0c8 jdk9-b15 +ab7d2c565b0de5bee1361d282d4029371327fc9e jdk9-b16 diff --git a/jdk/make/Bundles.gmk b/jdk/make/Bundles.gmk index 15538f0a11a..f6139ab6932 100644 --- a/jdk/make/Bundles.gmk +++ b/jdk/make/Bundles.gmk @@ -74,19 +74,16 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) JDK_TARGET_LIST := $(subst $(JDK_IMAGE_DIR)/,$(JDK_BUNDLE_DIR)/Home/,$(JDK_FILE_LIST)) JRE_TARGET_LIST := $(subst $(JRE_IMAGE_DIR)/,$(JRE_BUNDLE_DIR)/Home/,$(JRE_FILE_LIST)) - # The old builds implementation of this did not preserve symlinks so - # make sure they are followed and the contents copied instead. - # To fix this, remove -L # Copy empty directories (jre/lib/applet). $(JDK_BUNDLE_DIR)/Home/%: $(JDK_IMAGE_DIR)/% $(ECHO) Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(MKDIR) -p $(@D) - if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -L '$<' '$@'; fi + if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi $(JRE_BUNDLE_DIR)/Home/%: $(JRE_IMAGE_DIR)/% $(ECHO) Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(MKDIR) -p $(@D) - if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -L '$<' '$@'; fi + if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi $(JDK_BUNDLE_DIR)/MacOS/libjli.dylib: $(ECHO) Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@) diff --git a/jdk/make/CompileJavaClasses.gmk b/jdk/make/CompileJavaClasses.gmk index 6d2acb6708f..67e8b6d4812 100644 --- a/jdk/make/CompileJavaClasses.gmk +++ b/jdk/make/CompileJavaClasses.gmk @@ -373,7 +373,7 @@ ifndef OPENJDK JAVAC_FLAGS := -cp $(JDK_OUTPUTDIR)/classes, \ SRC := $(JDK_OUTPUTDIR)/gensrc_ab/32bit, \ BIN := $(JDK_OUTPUTDIR)/classes_ab/32bit, \ - HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers)) + HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers_ab/32)) $(BUILD_ACCESSBRIDGE_32): $(BUILD_JDK) @@ -382,7 +382,7 @@ ifndef OPENJDK JAVAC_FLAGS := -cp $(JDK_OUTPUTDIR)/classes, \ SRC := $(JDK_OUTPUTDIR)/gensrc_ab/legacy, \ BIN := $(JDK_OUTPUTDIR)/classes_ab/legacy, \ - HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers)) + HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers_ab/legacy)) $(BUILD_ACCESSBRIDGE_LEGACY): $(BUILD_JDK) @@ -393,7 +393,7 @@ ifndef OPENJDK JAVAC_FLAGS := -cp $(JDK_OUTPUTDIR)/classes, \ SRC := $(JDK_OUTPUTDIR)/gensrc_ab/64bit, \ BIN := $(JDK_OUTPUTDIR)/classes_ab/64bit, \ - HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers)) + HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers_ab/64)) $(BUILD_ACCESSBRIDGE_64): $(BUILD_JDK) diff --git a/jdk/make/CompileLaunchers.gmk b/jdk/make/CompileLaunchers.gmk index 68786a0a5b3..bb995d8a6ab 100644 --- a/jdk/make/CompileLaunchers.gmk +++ b/jdk/make/CompileLaunchers.gmk @@ -428,7 +428,7 @@ ifeq ($(USE_EXTERNAL_LIBZ), true) UNPACKEXE_CFLAGS := -DSYSTEM_ZLIB UNPACKEXE_ZIPOBJS := -lz else - UNPACKEXE_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.5 + UNPACKEXE_CFLAGS := -I$(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.8 UNPACKEXE_ZIPOBJS := $(JDK_OUTPUTDIR)/objs/libzip/zcrc32$(OBJ_SUFFIX) \ $(JDK_OUTPUTDIR)/objs/libzip/deflate$(OBJ_SUFFIX) \ $(JDK_OUTPUTDIR)/objs/libzip/trees$(OBJ_SUFFIX) \ @@ -442,11 +442,6 @@ else endif -ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc) - UNPACKEXE_CFLAGS += -xregs=no%appl - UNPACKEXE_LDFLAGS_solaris += -xmemalign=4s -endif - UNPACKEXE_LANG := C ifeq ($(OPENJDK_TARGET_OS), solaris) UNPACKEXE_LANG := C++ diff --git a/jdk/make/CopyIntoClasses.gmk b/jdk/make/CopyIntoClasses.gmk index b3a216fb90e..fdf2a173aca 100644 --- a/jdk/make/CopyIntoClasses.gmk +++ b/jdk/make/CopyIntoClasses.gmk @@ -30,7 +30,6 @@ COPY_PATTERNS := .icu _dict .dat _options .js aliasmap .spp .wav .css \ # These directories should not be copied at all EXCLUDES += \ - com/sun/org/apache/xml/internal/security/resource/schema \ java/awt/doc-files \ java/lang/doc-files \ javax/swing/doc-files \ diff --git a/jdk/make/CreateJars.gmk b/jdk/make/CreateJars.gmk index eebdcf666f0..9d79394539c 100644 --- a/jdk/make/CreateJars.gmk +++ b/jdk/make/CreateJars.gmk @@ -552,40 +552,53 @@ $(eval $(call SetupArchive,BUILD_CT_SYM, $(IMAGES_OUTPUTDIR)/symbols/_the.symbol ########################################################################################## -SRC_ZIP_INCLUDES = \ - com/sun/corba \ - com/sun/image/codec/jpeg \ - com/sun/imageio \ - com/sun/java_cup \ - com/sun/javadoc \ - com/sun/java/swing \ - com/sun/jmx \ - com/sun/naming \ - com/sun/org/apache \ - com/sun/security/auth \ - com/sun/security/jgss \ - com/sun/source \ - java \ - javax/accessibility \ - javax/annotation \ - javax/imageio \ - javax/lang \ - javax/management \ - javax/naming \ - javax/print \ - javax/rmi \ - javax/script \ - javax/security \ - javax/sound \ - javax/sql \ - javax/swing \ - javax/tools \ - javax/xml \ - org/ietf \ - org/omg \ - org/w3c/dom \ - org/xml/sax \ - # +ifdef OPENJDK + SRC_ZIP_INCLUDES = \ + com \ + java \ + javax \ + jdk \ + org \ + sun \ + # + SRC_ZIP_EXCLUDES = +else + SRC_ZIP_INCLUDES = \ + com/sun/corba \ + com/sun/image/codec/jpeg \ + com/sun/imageio \ + com/sun/java_cup \ + com/sun/javadoc \ + com/sun/java/swing \ + com/sun/jmx \ + com/sun/naming \ + com/sun/org/apache \ + com/sun/security/auth \ + com/sun/security/jgss \ + com/sun/source \ + java \ + javax/accessibility \ + javax/annotation \ + javax/imageio \ + javax/lang \ + javax/management \ + javax/naming \ + javax/print \ + javax/rmi \ + javax/script \ + javax/security \ + javax/sound \ + javax/sql \ + javax/swing \ + javax/tools \ + javax/xml \ + org/ietf \ + org/omg \ + org/w3c/dom \ + org/xml/sax \ + # + SRC_ZIP_EXCLUDES = javax/swing/beaninfo +endif SRC_ZIP_SRCS = $(JDK_TOPDIR)/src/share/classes $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes SRC_ZIP_SRCS += $(JDK_OUTPUTDIR)/gensrc @@ -616,7 +629,7 @@ $(eval $(call MakeDir, $(IMAGES_OUTPUTDIR)/src)) $(eval $(call SetupZipArchive,BUILD_SRC_ZIP, \ SRC := $(SRC_ZIP_SRCS) $(IMAGES_OUTPUTDIR)/src, \ INCLUDES := $(SRC_ZIP_INCLUDES) launcher, \ - EXCLUDES := javax/swing/beaninfo, \ + EXCLUDES := $(SRC_ZIP_EXCLUDES), \ SUFFIXES := .java .c .h, \ ZIP := $(IMAGES_OUTPUTDIR)/src.zip, \ EXTRA_DEPS := $(LAUNCHER_ZIP_SRC))) diff --git a/jdk/make/Setup.gmk b/jdk/make/Setup.gmk index aab0adec464..123a03e2c17 100644 --- a/jdk/make/Setup.gmk +++ b/jdk/make/Setup.gmk @@ -27,7 +27,7 @@ DISABLE_WARNINGS := -Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,- # To build with all warnings enabled, do the following: # make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000" -JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,cast,classfile,dep-ann,divzero,empty,overloads,serial,static,try,varargs -Werror +JAVAC_WARNINGS := -Xlint:-unchecked,-deprecation,-overrides,auxiliaryclass,cast,classfile,dep-ann,divzero,empty,fallthrough,overloads,serial,static,try,varargs -Werror # Any java code executed during a JDK build to build other parts of the JDK must be # executed by the bootstrap JDK (probably with -Xbootclasspath/p: ) and for this diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index 06a5672d00a..a689e52f03a 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -1251,7 +1251,7 @@ ifndef BUILD_HEADLESS_ONLY LIBSPLASHSCREEN_LDFLAGS_SUFFIX := ifneq ($(USE_EXTERNAL_LIBZ), true) - LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.5 + LIBSPLASHSCREEN_DIRS += $(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.8 LIBSPLASHSCREEN_CFLAGS += $(ZLIB_CPPFLAGS) endif diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 2241d5d8d86..66ef38ec94f 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -231,9 +231,9 @@ $(BUILD_LIBJAVA): $(BUILD_LIBFDLIBM) BUILD_LIBZIP_EXCLUDES := ifeq ($(USE_EXTERNAL_LIBZ), true) LIBZ := -lz - LIBZIP_EXCLUDES += zlib-1.2.5 + LIBZIP_EXCLUDES += zlib-1.2.8 else - ZLIB_CPPFLAGS := -I$(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.5 + ZLIB_CPPFLAGS := -I$(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.8 endif BUILD_LIBZIP_REORDER := @@ -410,7 +410,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) endif ifneq ($(USE_EXTERNAL_LIBZ), true) - BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.5 + BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/share/native/java/util/zip/zlib-1.2.8 LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS) BUILD_LIBJLI_FILES += \ inflate.c \ diff --git a/jdk/make/lib/PlatformLibraries.gmk b/jdk/make/lib/PlatformLibraries.gmk index 336e4b1b3e4..e78a9833dd5 100644 --- a/jdk/make/lib/PlatformLibraries.gmk +++ b/jdk/make/lib/PlatformLibraries.gmk @@ -143,7 +143,8 @@ ifndef OPENJDK define SetupAccessBridge # Parameter 1 Suffix # Parameter 2 Machine - # Parameter 3 ACCESSBRIDGE_ARCH_ suffix + # Parameter 3 ACCESSBRIDGE_ARCH_ suffix and name of directory where gensrc headers + # are found. $(call SetupNativeCompilation,BUILD_JAWTACCESSBRIDGE$1, \ LIBRARY = JAWTAccessBridge$1, \ @@ -153,7 +154,8 @@ ifndef OPENJDK LANG := C++, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -DACCESSBRIDGE_ARCH_$3, \ + -DACCESSBRIDGE_ARCH_$3 \ + -I$(JDK_OUTPUTDIR)/gensrc_headers_ab/$3, \ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \ winspool.lib jawt.lib comdlg32.lib advapi32.lib shell32.lib \ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \ @@ -179,7 +181,8 @@ ifndef OPENJDK LANG := C++, \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) \ - -DACCESSBRIDGE_ARCH_$3, \ + -DACCESSBRIDGE_ARCH_$3 \ + -I$(JDK_OUTPUTDIR)/gensrc_headers_ab/$3, \ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \ winspool.lib comdlg32.lib advapi32.lib shell32.lib \ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \ @@ -204,7 +207,8 @@ ifndef OPENJDK LANG := C++, \ OPTIMIZATION := LOW, \ CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT \ - -DACCESSBRIDGE_ARCH_$3, \ + -DACCESSBRIDGE_ARCH_$3 \ + -I$(JDK_OUTPUTDIR)/gensrc_headers_ab/$3, \ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \ winspool.lib comdlg32.lib advapi32.lib shell32.lib \ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \ @@ -225,7 +229,7 @@ ifndef OPENJDK ifeq ($(OPENJDK_TARGET_CPU_BITS), 32) $(eval $(call SetupAccessBridge,-32,I386,32)) - $(eval $(call SetupAccessBridge,,I386,LEGACY)) + $(eval $(call SetupAccessBridge,,I386,legacy)) else $(eval $(call SetupAccessBridge,-64,X64,64)) endif diff --git a/jdk/make/profile-rtjar-includes.txt b/jdk/make/profile-rtjar-includes.txt index b20031a017e..1e954ad625c 100644 --- a/jdk/make/profile-rtjar-includes.txt +++ b/jdk/make/profile-rtjar-includes.txt @@ -88,7 +88,7 @@ PROFILE_2_RTJAR_INCLUDE_PACKAGES := \ java/sql \ javax/rmi/ssl \ javax/sql \ - javax/transaction \ + javax/transaction/xa \ javax/xml \ org/w3c \ org/xml/sax \ @@ -223,7 +223,8 @@ FULL_JRE_RTJAR_INCLUDE_TYPES := \ javax/management/remote/rmi/_RMIConnection_Stub.class \ javax/management/remote/rmi/_RMIServerImpl_Tie.class \ javax/management/remote/rmi/_RMIServer_Stub.class \ - javax/rmi/*.class + javax/rmi/*.class \ + javax/transaction/*.class FULL_JRE_RTJAR_EXCLUDE_TYPES := diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java index 4f64ef41b7a..aeb6b7736bb 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/ConstantPool.java @@ -512,7 +512,7 @@ class ConstantPool { } static String qualifiedStringValue(String s1, String s234) { // Qualification by dot must decompose uniquely. Second string might already be qualified. - assert(s1.indexOf(".") < 0); + assert(s1.indexOf('.') < 0); return s1+"."+s234; } diff --git a/jdk/src/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java b/jdk/src/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java index f24f87c947e..6b32bb17aa0 100644 --- a/jdk/src/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java +++ b/jdk/src/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java @@ -102,7 +102,7 @@ public final class CorbanameUrl { } location = url.substring(addrStart, addrEnd); - int keyStart = location.indexOf("/"); + int keyStart = location.indexOf('/'); if (keyStart >= 0) { // Has key string if (keyStart == (location.length() -1)) { diff --git a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java index 2990ed8b549..a6de4af5cd8 100644 --- a/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java +++ b/jdk/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java @@ -336,7 +336,7 @@ public class RegistryContext implements Context, Referenceable { String url = "rmi://"; // Enclose IPv6 literal address in '[' and ']' - url = (host.indexOf(":") > -1) ? url + "[" + host + "]" : + url = (host.indexOf(':') > -1) ? url + "[" + host + "]" : url + host; if (port > 0) { url += ":" + Integer.toString(port); diff --git a/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java b/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java index 3e90b27bcce..cb5255d0a7b 100644 --- a/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java +++ b/jdk/src/share/classes/com/sun/jndi/toolkit/url/GenericURLContext.java @@ -149,7 +149,7 @@ abstract public class GenericURLContext implements Context { * foo:rest/of/name foo: */ protected String getURLPrefix(String url) throws NamingException { - int start = url.indexOf(":"); + int start = url.indexOf(':'); if (start < 0) { throw new OperationNotSupportedException("Invalid URL: " + url); @@ -160,7 +160,7 @@ abstract public class GenericURLContext implements Context { start += 2; // skip double slash // find last slash - int posn = url.indexOf("/", start); + int posn = url.indexOf('/', start); if (posn >= 0) { start = posn; } else { diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/etsi.xsd b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/etsi.xsd deleted file mode 100644 index d69852ff842..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/etsi.xsd +++ /dev/null @@ -1,347 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.rng b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.rng deleted file mode 100644 index 895e033a626..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.rng +++ /dev/null @@ -1,219 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.xsd b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.xsd deleted file mode 100644 index 85af68b5518..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xenc-schema.xsd +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - ]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.dtd b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.dtd deleted file mode 100644 index b2cc19f63a1..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.dtd +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.rng b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.rng deleted file mode 100644 index 03330fb1fee..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.rng +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.xsd b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.xsd deleted file mode 100644 index e8288a526c3..00000000000 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/resource/schema/xmldsig-core-schema.xsd +++ /dev/null @@ -1,318 +0,0 @@ - - - - - - ]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jdk/src/share/classes/com/sun/rmi/rmid/ExecOptionPermission.java b/jdk/src/share/classes/com/sun/rmi/rmid/ExecOptionPermission.java index 616922429b4..28119ef169f 100644 --- a/jdk/src/share/classes/com/sun/rmi/rmid/ExecOptionPermission.java +++ b/jdk/src/share/classes/com/sun/rmi/rmid/ExecOptionPermission.java @@ -303,7 +303,7 @@ public final class ExecOptionPermission extends Permission offset = pname.length() - 1; - while ((last = pname.lastIndexOf(".", offset)) != -1) { + while ((last = pname.lastIndexOf('.', offset)) != -1) { pname = pname.substring(0, last+1) + "*"; x = permissions.get(pname); @@ -318,7 +318,7 @@ public final class ExecOptionPermission extends Permission pname = p.getName(); offset = pname.length() - 1; - while ((last = pname.lastIndexOf("=", offset)) != -1) { + while ((last = pname.lastIndexOf('=', offset)) != -1) { pname = pname.substring(0, last+1) + "*"; x = permissions.get(pname); diff --git a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java index cfb728e9910..2d7cc6bf73c 100644 --- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java +++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java @@ -6831,7 +6831,7 @@ public class CachedRowSetImpl extends BaseRowSet implements RowSet, RowSetIntern // table name else isolate table name. indexFrom = command.toLowerCase().indexOf("from"); - indexComma = command.indexOf(",", indexFrom); + indexComma = command.indexOf(',', indexFrom); if(indexComma == -1) { // implies only one table diff --git a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java index 46637217d1f..ef281db9b10 100644 --- a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java +++ b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java @@ -910,7 +910,7 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet { // now remove the last "," strWhereClause = strWhereClause.substring - (0, strWhereClause.lastIndexOf(",")); + (0, strWhereClause.lastIndexOf(',')); // Add from clause strWhereClause = strWhereClause.concat(" from "); @@ -920,7 +920,7 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet { //Remove the last "," strWhereClause = strWhereClause.substring - (0, strWhereClause.lastIndexOf(",")); + (0, strWhereClause.lastIndexOf(',')); // Add the where clause strWhereClause = strWhereClause.concat(" where "); diff --git a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java index 3b04d1c748c..d3c22eaf128 100644 --- a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java +++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java @@ -240,7 +240,7 @@ public class WebRowSetXmlWriter implements XmlWriter, Serializable { // Remove the string after "@xxxx" // before writing it to the xml file. String strProviderInstance = (caller.getSyncProvider()).toString(); - String strProvider = strProviderInstance.substring(0, (caller.getSyncProvider()).toString().indexOf("@")); + String strProvider = strProviderInstance.substring(0, (caller.getSyncProvider()).toString().indexOf('@')); propString("sync-provider-name", strProvider); propString("sync-provider-vendor", "Oracle Corporation"); diff --git a/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java b/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java index 31d714187aa..45aeecc2341 100644 --- a/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java +++ b/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java @@ -1147,7 +1147,7 @@ public class XmlReaderContentHandler extends DefaultHandler { if (nullValue) { rs.setSyncProvider(null); } else { - String str = s.substring(0,s.indexOf("@")+1); + String str = s.substring(0,s.indexOf('@')+1); rs.setSyncProvider(str); } break; diff --git a/jdk/src/share/classes/com/sun/rowset/internal/XmlResolver.java b/jdk/src/share/classes/com/sun/rowset/internal/XmlResolver.java index a51df227d51..a3fa6afc9a2 100644 --- a/jdk/src/share/classes/com/sun/rowset/internal/XmlResolver.java +++ b/jdk/src/share/classes/com/sun/rowset/internal/XmlResolver.java @@ -39,7 +39,7 @@ import org.xml.sax.InputSource; public class XmlResolver implements EntityResolver { public InputSource resolveEntity(String publicId, String systemId) { - String schemaName = systemId.substring(systemId.lastIndexOf("/")); + String schemaName = systemId.substring(systemId.lastIndexOf('/')); if(systemId.startsWith("http://java.sun.com/xml/ns/jdbc")) { return new InputSource(this.getClass().getResourceAsStream(schemaName)); diff --git a/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java index 6bce9361380..e287f858804 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java @@ -694,7 +694,7 @@ public class JndiLoginModule implements LoginModule { throw new LoginException("Error: no CallbackHandler available " + "to garner authentication information from the user"); - String protocol = userProvider.substring(0, userProvider.indexOf(":")); + String protocol = userProvider.substring(0, userProvider.indexOf(':')); Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback(protocol + " " diff --git a/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java index e161b0ee8de..1de82aa98b6 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java @@ -400,7 +400,7 @@ public class LdapLoginModule implements LoginModule { // Add any JNDI properties to the environment for (String key : options.keySet()) { - if (key.indexOf(".") > -1) { + if (key.indexOf('.') > -1) { ldapEnvironment.put(key, options.get(key)); } } diff --git a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java index 034a986eac2..8b7e88facac 100644 --- a/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java +++ b/jdk/src/share/classes/com/sun/tools/example/debug/gui/CommandInterpreter.java @@ -857,7 +857,7 @@ public class CommandInterpreter { bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber); } else { // Try stripping method from class.method token. - int idot = token.lastIndexOf("."); + int idot = token.lastIndexOf('.'); if ( (idot <= 0) || /* No dot or dot in first char */ (idot >= token.length() - 1) ) { /* dot in last char */ return null; diff --git a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java index 640a8c53ed9..33f6e3ddf7f 100644 --- a/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java +++ b/jdk/src/share/classes/com/sun/tools/example/debug/tty/Commands.java @@ -1079,7 +1079,7 @@ class Commands { } } else { // Try stripping method from class.method token. - int idot = token.lastIndexOf("."); + int idot = token.lastIndexOf('.'); if ( (idot <= 0) || /* No dot or dot in first char */ (idot >= token.length() - 1) ) { /* dot in last char */ printBreakpointCommandUsage(atForm, inForm); diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java index 64d5abe848a..d453d82c38c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java @@ -67,7 +67,7 @@ class AllClassesQuery extends QueryHandler { continue; } String name = clazz.getName(); - int pos = name.lastIndexOf("."); + int pos = name.lastIndexOf('.'); String pkg; if (name.startsWith("[")) { // Only in ancient heap dumps pkg = ""; diff --git a/jdk/src/share/classes/java/applet/Applet.java b/jdk/src/share/classes/java/applet/Applet.java index 889e618a55e..9dccb7c9a7e 100644 --- a/jdk/src/share/classes/java/applet/Applet.java +++ b/jdk/src/share/classes/java/applet/Applet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -86,6 +86,7 @@ public class Applet extends Panel { /** * Read an applet from an object input stream. + * @param s an object input stream. * @exception HeadlessException if * GraphicsEnvironment.isHeadless() returns * true diff --git a/jdk/src/share/classes/java/applet/AppletContext.java b/jdk/src/share/classes/java/applet/AppletContext.java index c031686acc0..47fec71cb5b 100644 --- a/jdk/src/share/classes/java/applet/AppletContext.java +++ b/jdk/src/share/classes/java/applet/AppletContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -152,7 +152,7 @@ public interface AppletContext { * For security reasons, mapping of streams and keys exists for each * codebase. In other words, applet from one codebase cannot access * the streams created by an applet from a different codebase - *

+ * * @param key key with which the specified value is to be associated. * @param stream stream to be associated with the specified key. If this * parameter is null, the specified key is removed @@ -172,7 +172,7 @@ public interface AppletContext { * For security reasons, mapping of streams and keys exists for each * codebase. In other words, applet from one codebase cannot access * the streams created by an applet from a different codebase - *

+ * * @return the stream to which this applet context maps the key * @param key key whose associated stream is to be returned. * @since 1.4 @@ -185,7 +185,7 @@ public interface AppletContext { * For security reasons, mapping of streams and keys exists for each * codebase. In other words, applet from one codebase cannot access * the streams created by an applet from a different codebase - *

+ * * @return an Iterator of all the names of the streams in this applet * context. * @since 1.4 diff --git a/jdk/src/share/classes/java/awt/geom/Path2D.java b/jdk/src/share/classes/java/awt/geom/Path2D.java index 9f7df213546..7a401d36cf4 100644 --- a/jdk/src/share/classes/java/awt/geom/Path2D.java +++ b/jdk/src/share/classes/java/awt/geom/Path2D.java @@ -1926,9 +1926,9 @@ public abstract class Path2D implements Shape, Cloneable { * maintains, but it may contain no more precision either. * If the tradeoff of precision vs. storage size in the result is * important then the convenience constructors in the - * {@link Path2D.Float#Path2D.Float(Shape, AffineTransform) Path2D.Float} + * {@link Path2D.Float#Float(Shape, AffineTransform) Path2D.Float} * and - * {@link Path2D.Double#Path2D.Double(Shape, AffineTransform) Path2D.Double} + * {@link Path2D.Double#Double(Shape, AffineTransform) Path2D.Double} * subclasses should be used to make the choice explicit. * * @param at the {@code AffineTransform} used to transform a diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index a8aee7ffe62..262a126fafc 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -1296,7 +1296,7 @@ public final class Class implements java.io.Serializable, String simpleName = getSimpleBinaryName(); if (simpleName == null) { // top level class simpleName = getName(); - return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name + return simpleName.substring(simpleName.lastIndexOf('.')+1); // strip the package name } // According to JLS3 "Binary Compatibility" (13.1) the binary // name of non-package classes (not top level) is the binary diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java index 078c1502176..876b1855012 100644 --- a/jdk/src/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/share/classes/java/lang/ClassLoader.java @@ -2133,7 +2133,7 @@ public abstract class ClassLoader { return result.booleanValue(); // Check for most specific package entry - int dotIndex = className.lastIndexOf("."); + int dotIndex = className.lastIndexOf('.'); if (dotIndex < 0) { // default package result = packageAssertionStatus.get(null); if (result != null) @@ -2144,7 +2144,7 @@ public abstract class ClassLoader { result = packageAssertionStatus.get(className); if (result != null) return result.booleanValue(); - dotIndex = className.lastIndexOf(".", dotIndex-1); + dotIndex = className.lastIndexOf('.', dotIndex-1); } // Return the classloader default diff --git a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 7bcdfaf5e89..d881fe5d18d 100644 --- a/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -85,7 +85,7 @@ class InvokerBytecodeGenerator { private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, String className, String invokerName, MethodType invokerType) { if (invokerName.contains(".")) { - int p = invokerName.indexOf("."); + int p = invokerName.indexOf('.'); className = invokerName.substring(0, p); invokerName = invokerName.substring(p+1); } diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java index 36630459b88..0676b7b3ab0 100644 --- a/jdk/src/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/share/classes/java/lang/invoke/LambdaForm.java @@ -607,7 +607,7 @@ class LambdaForm { assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_')))); LambdaForm form = new LambdaForm(sig); form.vmentry = m; - mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form); + form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form); // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only forms.put(sig, form); } diff --git a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java index 5bea02055ef..b6ef976c515 100644 --- a/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java +++ b/jdk/src/share/classes/java/lang/invoke/LambdaMetafactory.java @@ -313,7 +313,8 @@ public class LambdaMetafactory { * reference expression features of the Java Programming Language. * *

This is the general, more flexible metafactory; a streamlined version - * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}. + * is provided by {@link #metafactory(java.lang.invoke.MethodHandles.Lookup, + * String, MethodType, MethodType, MethodHandle, MethodType)}. * A general description of the behavior of this method is provided * {@link LambdaMetafactory above}. * diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java index 6abceb5ad19..abd8999aeaa 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -692,8 +692,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names); - basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform); - return lform; + return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform); } static diff --git a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java index ee5e6221b11..d34a2998cab 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java @@ -91,8 +91,10 @@ final class MethodTypeForm { return lambdaForms[which]; } - public LambdaForm setCachedLambdaForm(int which, LambdaForm form) { - // Should we perform some sort of CAS, to avoid racy duplication? + synchronized public LambdaForm setCachedLambdaForm(int which, LambdaForm form) { + // Simulate a CAS, to avoid racy duplication of results. + LambdaForm prev = lambdaForms[which]; + if (prev != null) return prev; return lambdaForms[which] = form; } diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 60e059e8e77..8493d10eaa4 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -633,7 +633,7 @@ public abstract class Executable extends AccessibleObject getConstantPool(getDeclaringClass()), this, getDeclaringClass(), - getParameterTypes(), + getGenericParameterTypes(), TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER); } diff --git a/jdk/src/share/classes/java/net/CookieManager.java b/jdk/src/share/classes/java/net/CookieManager.java index f2d29cda82b..15d4cc33e08 100644 --- a/jdk/src/share/classes/java/net/CookieManager.java +++ b/jdk/src/share/classes/java/net/CookieManager.java @@ -294,7 +294,7 @@ public class CookieManager extends CookieHandler // the path is the directory of the page/doc String path = uri.getPath(); if (!path.endsWith("/")) { - int i = path.lastIndexOf("/"); + int i = path.lastIndexOf('/'); if (i > 0) { path = path.substring(0, i + 1); } else { @@ -364,7 +364,7 @@ public class CookieManager extends CookieHandler static private boolean isInPortList(String lst, int port) { - int i = lst.indexOf(","); + int i = lst.indexOf(','); int val = -1; while (i > 0) { try { @@ -375,7 +375,7 @@ public class CookieManager extends CookieHandler } catch (NumberFormatException numberFormatException) { } lst = lst.substring(i+1); - i = lst.indexOf(","); + i = lst.indexOf(','); } if (!lst.isEmpty()) { try { diff --git a/jdk/src/share/classes/java/net/InetAddress.java b/jdk/src/share/classes/java/net/InetAddress.java index 77c6a1f6c57..5bbdf0fd187 100644 --- a/jdk/src/share/classes/java/net/InetAddress.java +++ b/jdk/src/share/classes/java/net/InetAddress.java @@ -1138,7 +1138,7 @@ class InetAddress implements java.io.Serializable { // This is supposed to be an IPv6 literal // Check if a numeric or string zone id is present int pos; - if ((pos=host.indexOf ("%")) != -1) { + if ((pos=host.indexOf ('%')) != -1) { numericZone = checkNumericZone (host); if (numericZone == -1) { /* remainder of string must be an ifname */ ifname = host.substring (pos+1); diff --git a/jdk/src/share/classes/java/net/Socket.java b/jdk/src/share/classes/java/net/Socket.java index d4b7656ce5e..43fe4bfd940 100644 --- a/jdk/src/share/classes/java/net/Socket.java +++ b/jdk/src/share/classes/java/net/Socket.java @@ -1017,7 +1017,7 @@ class Socket implements java.io.Closeable { if (isClosed()) throw new SocketException("Socket is closed"); if (!on) { - getImpl().setOption(SocketOptions.SO_LINGER, new Boolean(on)); + getImpl().setOption(SocketOptions.SO_LINGER, on); } else { if (linger < 0) { throw new IllegalArgumentException("invalid value for SO_LINGER"); diff --git a/jdk/src/share/classes/java/net/SocketPermission.java b/jdk/src/share/classes/java/net/SocketPermission.java index 51777d90385..d44c8471613 100644 --- a/jdk/src/share/classes/java/net/SocketPermission.java +++ b/jdk/src/share/classes/java/net/SocketPermission.java @@ -777,7 +777,7 @@ public final class SocketPermission extends Permission // Literal IPv6 address host = getName().substring(1, getName().indexOf(']')); } else { - int i = getName().indexOf(":"); + int i = getName().indexOf(':'); if (i == -1) host = getName(); else { diff --git a/jdk/src/share/classes/java/net/SocksSocketImpl.java b/jdk/src/share/classes/java/net/SocksSocketImpl.java index b05a4d4c853..7c0f899b8e6 100644 --- a/jdk/src/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java @@ -368,7 +368,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { String host = epoint.getHostString(); // IPv6 litteral? if (epoint.getAddress() instanceof Inet6Address && - (!host.startsWith("[")) && (host.indexOf(":") >= 0)) { + (!host.startsWith("[")) && (host.indexOf(':') >= 0)) { host = "[" + host + "]"; } try { @@ -688,7 +688,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { String host = saddr.getHostString(); // IPv6 litteral? if (saddr.getAddress() instanceof Inet6Address && - (!host.startsWith("[")) && (host.indexOf(":") >= 0)) { + (!host.startsWith("[")) && (host.indexOf(':') >= 0)) { host = "[" + host + "]"; } try { diff --git a/jdk/src/share/classes/java/net/URI.java b/jdk/src/share/classes/java/net/URI.java index 0a05793b9a9..0035d00ead7 100644 --- a/jdk/src/share/classes/java/net/URI.java +++ b/jdk/src/share/classes/java/net/URI.java @@ -1851,9 +1851,9 @@ public final class URI sb.append("//"); if (authority.startsWith("[")) { // authority should (but may not) contain an embedded IPv6 address - int end = authority.indexOf("]"); + int end = authority.indexOf(']'); String doquote = authority, dontquote = ""; - if (end != -1 && authority.indexOf(":") != -1) { + if (end != -1 && authority.indexOf(':') != -1) { // the authority contains an IPv6 address if (end == authority.length()) { dontquote = authority; @@ -1889,8 +1889,8 @@ public final class URI * because we must not quote a literal IPv6 address */ if (opaquePart.startsWith("//[")) { - int end = opaquePart.indexOf("]"); - if (end != -1 && opaquePart.indexOf(":")!=-1) { + int end = opaquePart.indexOf(']'); + if (end != -1 && opaquePart.indexOf(':')!=-1) { String doquote, dontquote; if (end == opaquePart.length()) { dontquote = opaquePart; diff --git a/jdk/src/share/classes/java/security/AccessController.java b/jdk/src/share/classes/java/security/AccessController.java index 36408a8d633..e2b8e584560 100644 --- a/jdk/src/share/classes/java/security/AccessController.java +++ b/jdk/src/share/classes/java/security/AccessController.java @@ -592,14 +592,24 @@ public final class AccessController { System.getSecurityManager() != null && !callerPD.impliesCreateAccessControlContext()) { - ProtectionDomain nullPD = new ProtectionDomain(null, null); - return new AccessControlContext(new ProtectionDomain[] { nullPD }); + return getInnocuousAcc(); } else { return new AccessControlContext(callerPD, combiner, parent, context, perms); } } + private static class AccHolder { + // An AccessControlContext with no granted permissions. + // Only initialized on demand when getInnocuousAcc() is called. + static final AccessControlContext innocuousAcc = + new AccessControlContext(new ProtectionDomain[] { + new ProtectionDomain(null, null) }); + } + private static AccessControlContext getInnocuousAcc() { + return AccHolder.innocuousAcc; + } + private static ProtectionDomain getCallerPD(final Class caller) { ProtectionDomain callerPd = doPrivileged (new PrivilegedAction() { diff --git a/jdk/src/share/classes/java/security/BasicPermission.java b/jdk/src/share/classes/java/security/BasicPermission.java index 89cc2f92152..0abbfa7c047 100644 --- a/jdk/src/share/classes/java/security/BasicPermission.java +++ b/jdk/src/share/classes/java/security/BasicPermission.java @@ -430,7 +430,7 @@ final class BasicPermissionCollection offset = path.length()-1; - while ((last = path.lastIndexOf(".", offset)) != -1) { + while ((last = path.lastIndexOf('.', offset)) != -1) { path = path.substring(0, last+1) + "*"; //System.out.println("check "+path); diff --git a/jdk/src/share/classes/java/security/Provider.java b/jdk/src/share/classes/java/security/Provider.java index e8c7a081b5a..346aca9474c 100644 --- a/jdk/src/share/classes/java/security/Provider.java +++ b/jdk/src/share/classes/java/security/Provider.java @@ -931,7 +931,7 @@ public abstract class Provider extends Properties { } private String[] getTypeAndAlgorithm(String key) { - int i = key.indexOf("."); + int i = key.indexOf('.'); if (i < 1) { if (debug != null) { debug.println("Ignoring invalid entry in provider " diff --git a/jdk/src/share/classes/java/security/Security.java b/jdk/src/share/classes/java/security/Security.java index 0db09da7061..e24c0023f77 100644 --- a/jdk/src/share/classes/java/security/Security.java +++ b/jdk/src/share/classes/java/security/Security.java @@ -1114,7 +1114,7 @@ public final class Security { // implementation of an algorithm. We are only interested // in entries which lead to the implementation // classes. - if (currentKey.indexOf(" ") < 0) { + if (currentKey.indexOf(' ') < 0) { result.add(currentKey.substring( serviceName.length() + 1)); } diff --git a/jdk/src/share/classes/java/util/PropertyPermission.java b/jdk/src/share/classes/java/util/PropertyPermission.java index b772e1b12f8..d532bddabf6 100644 --- a/jdk/src/share/classes/java/util/PropertyPermission.java +++ b/jdk/src/share/classes/java/util/PropertyPermission.java @@ -546,7 +546,7 @@ final class PropertyPermissionCollection extends PermissionCollection offset = name.length()-1; - while ((last = name.lastIndexOf(".", offset)) != -1) { + while ((last = name.lastIndexOf('.', offset)) != -1) { name = name.substring(0, last+1) + "*"; //System.out.println("check "+name); diff --git a/jdk/src/share/classes/java/util/jar/JarVerifier.java b/jdk/src/share/classes/java/util/jar/JarVerifier.java index 0c24af26f28..c1468a1be1c 100644 --- a/jdk/src/share/classes/java/util/jar/JarVerifier.java +++ b/jdk/src/share/classes/java/util/jar/JarVerifier.java @@ -276,7 +276,7 @@ class JarVerifier { // now we are parsing a signature block file - String key = uname.substring(0, uname.lastIndexOf(".")); + String key = uname.substring(0, uname.lastIndexOf('.')); if (signerCache == null) signerCache = new ArrayList<>(); diff --git a/jdk/src/share/classes/java/util/logging/LogManager.java b/jdk/src/share/classes/java/util/logging/LogManager.java index d2f7004bb27..ffd9d96300d 100644 --- a/jdk/src/share/classes/java/util/logging/LogManager.java +++ b/jdk/src/share/classes/java/util/logging/LogManager.java @@ -779,7 +779,7 @@ public class LogManager { int ix = 1; for (;;) { - int ix2 = name.indexOf(".", ix); + int ix2 = name.indexOf('.', ix); if (ix2 < 0) { break; } @@ -802,7 +802,7 @@ public class LogManager { } LogNode node = root; while (name.length() > 0) { - int ix = name.indexOf("."); + int ix = name.indexOf('.'); String head; if (ix > 0) { head = name.substring(0, ix); diff --git a/jdk/src/share/classes/java/util/logging/XMLFormatter.java b/jdk/src/share/classes/java/util/logging/XMLFormatter.java index 541c73fafff..075da9a3681 100644 --- a/jdk/src/share/classes/java/util/logging/XMLFormatter.java +++ b/jdk/src/share/classes/java/util/logging/XMLFormatter.java @@ -174,7 +174,7 @@ public class XMLFormatter extends Formatter { // Check to see if the parameter was not a messagetext format // or was not null or empty if (parameters != null && parameters.length != 0 - && record.getMessage().indexOf("{") == -1 ) { + && record.getMessage().indexOf('{') == -1 ) { for (Object parameter : parameters) { sb.append(" "); try { diff --git a/jdk/src/share/classes/java/util/zip/ZipInputStream.java b/jdk/src/share/classes/java/util/zip/ZipInputStream.java index 77a598df818..7b4ccc86c76 100644 --- a/jdk/src/share/classes/java/util/zip/ZipInputStream.java +++ b/jdk/src/share/classes/java/util/zip/ZipInputStream.java @@ -319,7 +319,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants { if (len > 0) { byte[] extra = new byte[len]; readFully(extra, 0, len); - e.setExtra0(extra, true); + e.setExtra0(extra, + e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL); } return e; } diff --git a/jdk/src/share/classes/javax/management/MBeanPermission.java b/jdk/src/share/classes/javax/management/MBeanPermission.java index 3c998e4ea01..4a3442511a3 100644 --- a/jdk/src/share/classes/javax/management/MBeanPermission.java +++ b/jdk/src/share/classes/javax/management/MBeanPermission.java @@ -290,7 +290,7 @@ public class MBeanPermission extends Permission { // Parse ObjectName - int openingBracket = name.indexOf("["); + int openingBracket = name.indexOf('['); if (openingBracket == -1) { // If "[on]" missing then ObjectName("*:*") // @@ -329,7 +329,7 @@ public class MBeanPermission extends Permission { // Parse member - int poundSign = name.indexOf("#"); + int poundSign = name.indexOf('#'); if (poundSign == -1) setMember("*"); diff --git a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java index 0605713bf7a..f2534a62269 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -329,7 +329,7 @@ public class DescriptorSupport inFld = false; } else if (inFld && inDesc) { // want kw=value, eg, name="myname" value="myvalue" - int eq_separator = tok.indexOf("="); + int eq_separator = tok.indexOf('='); if (eq_separator > 0) { String kwPart = tok.substring(0,eq_separator); String valPart = tok.substring(eq_separator+1); @@ -458,7 +458,7 @@ public class DescriptorSupport if ((fields[i] == null) || (fields[i].equals(""))) { continue; } - int eq_separator = fields[i].indexOf("="); + int eq_separator = fields[i].indexOf('='); if (eq_separator < 0) { // illegal if no = or is first character if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index d19aa48fde6..7483ab13188 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -934,7 +934,7 @@ public class RequiredModelMBean String opMethodName; // Parse for class name and method - int opSplitter = opName.lastIndexOf("."); + int opSplitter = opName.lastIndexOf('.'); if (opSplitter > 0) { opClassName = opName.substring(0,opSplitter); opMethodName = opName.substring(opSplitter+1); @@ -943,7 +943,7 @@ public class RequiredModelMBean /* Ignore anything after a left paren. We keep this for compatibility but it isn't specified. */ - opSplitter = opMethodName.indexOf("("); + opSplitter = opMethodName.indexOf('('); if (opSplitter > 0) opMethodName = opMethodName.substring(0,opSplitter); diff --git a/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java b/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java index 37a2660cb03..9aa0e6352a2 100644 --- a/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java +++ b/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java @@ -495,7 +495,7 @@ public final class PrivateCredentialPermission extends Permission { // perform new initialization from the permission name - if (getName().indexOf(" ") == -1 && getName().indexOf("\"") == -1) { + if (getName().indexOf(' ') == -1 && getName().indexOf('"') == -1) { // name only has a credential class specified credentialClass = getName(); diff --git a/jdk/src/share/classes/javax/security/sasl/Sasl.java b/jdk/src/share/classes/javax/security/sasl/Sasl.java index 1ce36c74311..74f21c1b215 100644 --- a/jdk/src/share/classes/javax/security/sasl/Sasl.java +++ b/jdk/src/share/classes/javax/security/sasl/Sasl.java @@ -600,7 +600,7 @@ public class Sasl { // implementation of an algorithm. We are only interested // in entries which lead to the implementation // classes. - if (currentKey.indexOf(" ") < 0) { + if (currentKey.indexOf(' ') < 0) { String className = providers[i].getProperty(currentKey); if (!classes.contains(className)) { classes.add(className); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java index 66e8e7e3f11..f5b24254ece 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/ClassWriter.java @@ -785,11 +785,29 @@ public class ClassWriter extends ClassVisitor { if (innerClasses == null) { innerClasses = new ByteVector(); } - ++innerClassesCount; - innerClasses.putShort(name == null ? 0 : newClass(name)); - innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); - innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); - innerClasses.putShort(access); + // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the + // constant_pool table which represents a class or interface C that is + // not a package member must have exactly one corresponding entry in the + // classes array". To avoid duplicates we keep track in the intVal field + // of the Item of each CONSTANT_Class_info entry C whether an inner + // class entry has already been added for C (this field is unused for + // class entries, and changing its value does not change the hashcode + // and equality tests). If so we store the index of this inner class + // entry (plus one) in intVal. This hack allows duplicate detection in + // O(1) time. + Item nameItem = newClassItem(name); + if (nameItem.intVal == 0) { + ++innerClassesCount; + innerClasses.putShort(nameItem.index); + innerClasses.putShort(outerName == null ? 0 : newClass(outerName)); + innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName)); + innerClasses.putShort(access); + nameItem.intVal = innerClassesCount; + } else { + // Compare the inner classes entry nameItem.intVal - 1 with the + // arguments of this method and throw an exception if there is a + // difference? + } } @Override diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java index e32a13af942..811b74c7242 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Frame.java @@ -1455,16 +1455,20 @@ final class Frame { | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE); } else { // if u and t are array types, but not with the same element - // type, merge(u,t)=java/lang/Object - v = OBJECT | cw.addType("java/lang/Object"); + // type, merge(u,t) = dim(u) - 1 | java/lang/Object + int vdim = ELEMENT_OF + (u & DIM); + v = vdim | OBJECT | cw.addType("java/lang/Object"); } } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) { // if t is any other reference or array type, the merged type - // is Object, or min(dim(u), dim(t)) | java/lang/Object is u - // and t have different array dimensions - int tdim = t & DIM; - int udim = u & DIM; - v = (udim != tdim ? Math.min(tdim, udim) : 0) | OBJECT + // is min(udim, tdim) | java/lang/Object, where udim is the + // array dimension of u, minus 1 if u is an array type with a + // primitive element type (and similarly for tdim). + int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0 + : ELEMENT_OF) + (t & DIM); + int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0 + : ELEMENT_OF) + (u & DIM); + v = Math.min(tdim, udim) | OBJECT | cw.addType("java/lang/Object"); } else { // if t is any other type, merge(u,t)=TOP diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Item.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Item.java index 90ff74377ff..25ed37718dd 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Item.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Item.java @@ -230,6 +230,7 @@ final class Item { * @param strVal3 * third part of the value of this item. */ + @SuppressWarnings("fallthrough") void set(final int type, final String strVal1, final String strVal2, final String strVal3) { this.type = type; @@ -237,9 +238,10 @@ final class Item { this.strVal2 = strVal2; this.strVal3 = strVal3; switch (type) { + case ClassWriter.CLASS: + this.intVal = 0; // intVal of a class must be zero, see visitInnerClass case ClassWriter.UTF8: case ClassWriter.STR: - case ClassWriter.CLASS: case ClassWriter.MTYPE: case ClassWriter.TYPE_NORMAL: hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Label.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Label.java index f4bc30df4bd..bbea0001235 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Label.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Label.java @@ -502,7 +502,7 @@ public class Label { void addToSubroutine(final long id, final int nbSubroutines) { if ((status & VISITED) == 0) { status |= VISITED; - srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1]; + srcAndRefPositions = new int[nbSubroutines / 32 + 1]; } srcAndRefPositions[(int) (id >>> 32)] |= (int) id; } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java index 81a82804d6e..e02fad465d9 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/MethodWriter.java @@ -1430,6 +1430,14 @@ class MethodWriter extends MethodVisitor { @Override public void visitMaxs(final int maxStack, final int maxLocals) { + if (resize) { + // replaces the temporary jump opcodes introduced by Label.resolve. + if (ClassReader.RESIZE) { + resizeInstructions(); + } else { + throw new RuntimeException("Method code too large!"); + } + } if (ClassReader.FRAMES && compute == FRAMES) { // completes the control flow graph with exception handler blocks Handler handler = firstHandler; @@ -1987,43 +1995,43 @@ class MethodWriter extends MethodVisitor { stackMap.putByte(v); } } else { - StringBuffer buf = new StringBuffer(); + StringBuilder sb = new StringBuilder(); d >>= 28; while (d-- > 0) { - buf.append('['); + sb.append('['); } if ((t & Frame.BASE_KIND) == Frame.OBJECT) { - buf.append('L'); - buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); - buf.append(';'); + sb.append('L'); + sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1); + sb.append(';'); } else { switch (t & 0xF) { case 1: - buf.append('I'); + sb.append('I'); break; case 2: - buf.append('F'); + sb.append('F'); break; case 3: - buf.append('D'); + sb.append('D'); break; case 9: - buf.append('Z'); + sb.append('Z'); break; case 10: - buf.append('B'); + sb.append('B'); break; case 11: - buf.append('C'); + sb.append('C'); break; case 12: - buf.append('S'); + sb.append('S'); break; default: - buf.append('J'); + sb.append('J'); } } - stackMap.putByte(7).putShort(cw.newClass(buf.toString())); + stackMap.putByte(7).putShort(cw.newClass(sb.toString())); } } } @@ -2051,14 +2059,6 @@ class MethodWriter extends MethodVisitor { if (classReaderOffset != 0) { return 6 + classReaderLength; } - if (resize) { - // replaces the temporary jump opcodes introduced by Label.resolve. - if (ClassReader.RESIZE) { - resizeInstructions(); - } else { - throw new RuntimeException("Method code too large!"); - } - } int size = 8; if (code.length > 0) { if (code.length > 65536) { @@ -2715,49 +2715,50 @@ class MethodWriter extends MethodVisitor { } } - // recomputes the stack map frames - if (frameCount > 0) { - if (compute == FRAMES) { - frameCount = 0; - stackMap = null; - previousFrame = null; - frame = null; - Frame f = new Frame(); - f.owner = labels; - Type[] args = Type.getArgumentTypes(descriptor); - f.initInputFrame(cw, access, args, maxLocals); - visitFrame(f); - Label l = labels; - while (l != null) { - /* - * here we need the original label position. getNewOffset - * must therefore never have been called for this label. - */ - u = l.position - 3; - if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u])) { - getNewOffset(allIndexes, allSizes, l); - // TODO update offsets in UNINITIALIZED values - visitFrame(l.frame); - } - l = l.successor; - } - } else { + // updates the stack map frame labels + if (compute == FRAMES) { + Label l = labels; + while (l != null) { /* - * Resizing an existing stack map frame table is really hard. - * Not only the table must be parsed to update the offets, but - * new frames may be needed for jump instructions that were - * inserted by this method. And updating the offsets or - * inserting frames can change the format of the following - * frames, in case of packed frames. In practice the whole table - * must be recomputed. For this the frames are marked as - * potentially invalid. This will cause the whole class to be - * reread and rewritten with the COMPUTE_FRAMES option (see the - * ClassWriter.toByteArray method). This is not very efficient - * but is much easier and requires much less code than any other - * method I can think of. + * Detects the labels that are just after an IF instruction that + * has been resized with the IFNOT GOTO_W pattern. These labels + * are now the target of a jump instruction (the IFNOT + * instruction). Note that we need the original label position + * here. getNewOffset must therefore never have been called for + * this label. */ - cw.invalidFrames = true; + u = l.position - 3; + if (u >= 0 && resize[u]) { + l.status |= Label.TARGET; + } + getNewOffset(allIndexes, allSizes, l); + l = l.successor; } + // Update the offsets in the uninitialized types + for (i = 0; i < cw.typeTable.length; ++i) { + Item item = cw.typeTable[i]; + if (item != null && item.type == ClassWriter.TYPE_UNINIT) { + item.intVal = getNewOffset(allIndexes, allSizes, 0, + item.intVal); + } + } + // The stack map frames are not serialized yet, so we don't need + // to update them. They will be serialized in visitMaxs. + } else if (frameCount > 0) { + /* + * Resizing an existing stack map frame table is really hard. Not + * only the table must be parsed to update the offets, but new + * frames may be needed for jump instructions that were inserted by + * this method. And updating the offsets or inserting frames can + * change the format of the following frames, in case of packed + * frames. In practice the whole table must be recomputed. For this + * the frames are marked as potentially invalid. This will cause the + * whole class to be reread and rewritten with the COMPUTE_FRAMES + * option (see the ClassWriter.toByteArray method). This is not very + * efficient but is much easier and requires much less code than any + * other method I can think of. + */ + cw.invalidFrames = true; } // updates the exception handler block labels Handler h = firstHandler; diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Type.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Type.java index e385f9f6491..633a4a024ea 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Type.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/Type.java @@ -585,11 +585,11 @@ public class Type { case DOUBLE: return "double"; case ARRAY: - StringBuffer b = new StringBuffer(getElementType().getClassName()); + StringBuilder sb = new StringBuilder(getElementType().getClassName()); for (int i = getDimensions(); i > 0; --i) { - b.append("[]"); + sb.append("[]"); } - return b.toString(); + return sb.toString(); case OBJECT: return new String(buf, off, len).replace('/', '.'); default: diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java index 4ece2dba90d..2c54ea475fd 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/InstructionAdapter.java @@ -1089,7 +1089,7 @@ public class InstructionAdapter extends MethodVisitor { @Deprecated public void invokestatic(final String owner, final String name, final String desc) { - if (api < Opcodes.ASM5) { + if (api >= Opcodes.ASM5) { invokestatic(owner, name, desc, false); return; } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java index df97a36575f..92a83ff8ecc 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Method.java @@ -205,7 +205,7 @@ public class Method { } String returnType = method.substring(0, space); String methodName = method.substring(space + 1, start - 1).trim(); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append('('); int p; do { @@ -229,7 +229,7 @@ public class Method { return type; } - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); int index = 0; while ((index = type.indexOf("[]", index) + 1) > 0) { sb.append('['); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java index 2b4f7201d69..d5edd06363f 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/Remapper.java @@ -147,17 +147,17 @@ public abstract class Remapper { } Type[] args = Type.getArgumentTypes(desc); - StringBuffer s = new StringBuffer("("); + StringBuilder sb = new StringBuilder("("); for (int i = 0; i < args.length; i++) { - s.append(mapDesc(args[i].getDescriptor())); + sb.append(mapDesc(args[i].getDescriptor())); } Type returnType = Type.getReturnType(desc); if (returnType == Type.VOID_TYPE) { - s.append(")V"); - return s.toString(); + sb.append(")V"); + return sb.toString(); } - s.append(')').append(mapDesc(returnType.getDescriptor())); - return s.toString(); + sb.append(')').append(mapDesc(returnType.getDescriptor())); + return sb.toString(); } public Object mapValue(Object value) { diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java index de8915125ff..51fcb4c46f6 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/commons/SerialVersionUIDAdder.java @@ -239,7 +239,9 @@ public class SerialVersionUIDAdder extends ClassVisitor { if (computeSVUID) { this.name = name; this.access = access; - this.interfaces = Arrays.copyOf(interfaces, interfaces.length); + this.interfaces = new String[interfaces.length]; + System.arraycopy(interfaces, 0, this.interfaces, 0, + interfaces.length); } super.visit(version, access, name, signature, superName, interfaces); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java index b6e2075de8b..bb01f7a7a3d 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/MethodNode.java @@ -351,7 +351,7 @@ public class MethodNode extends MethodVisitor { } @Override - @SuppressWarnings("serial") // Anonymous class + @SuppressWarnings("serial") public AnnotationVisitor visitAnnotationDefault() { return new AnnotationNode(new ArrayList(0) { @Override diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java index 92b570b17f0..fc22dc3200a 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/AnalyzerException.java @@ -66,7 +66,7 @@ import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; * @author Bing Ran * @author Eric Bruneton */ -@SuppressWarnings("serial") // implementation class +@SuppressWarnings("serial") public class AnalyzerException extends Exception { public final AbstractInsnNode node; diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java index f6b8db3ddfb..cbb5f86f534 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java @@ -754,14 +754,14 @@ public class Frame { */ @Override public String toString() { - StringBuffer b = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < getLocals(); ++i) { - b.append(getLocal(i)); + sb.append(getLocal(i)); } - b.append(' '); + sb.append(' '); for (int i = 0; i < getStackSize(); ++i) { - b.append(getStack(i).toString()); + sb.append(getStack(i).toString()); } - return b.toString(); + return sb.toString(); } } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java index a9487e16f5e..26e208a4cef 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/ASMifier.java @@ -206,7 +206,6 @@ public class ASMifier extends Printer { } text.add("import java.util.*;\n"); text.add("import jdk.internal.org.objectweb.asm.*;\n"); - text.add("import jdk.internal.org.objectweb.asm.attrs.*;\n"); text.add("public class " + simpleName + "Dump implements Opcodes {\n\n"); text.add("public static byte[] dump () throws Exception {\n\n"); text.add("ClassWriter cw = new ClassWriter(0);\n"); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java index 5105db7f9c2..22dddf2d5e1 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/CheckClassAdapter.java @@ -298,26 +298,26 @@ public class CheckClassAdapter extends ClassVisitor { for (int j = 0; j < method.instructions.size(); ++j) { method.instructions.get(j).accept(mv); - StringBuffer s = new StringBuffer(); + StringBuilder sb = new StringBuilder(); Frame f = frames[j]; if (f == null) { - s.append('?'); + sb.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { - s.append(getShortName(f.getLocal(k).toString())) + sb.append(getShortName(f.getLocal(k).toString())) .append(' '); } - s.append(" : "); + sb.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { - s.append(getShortName(f.getStack(k).toString())) + sb.append(getShortName(f.getStack(k).toString())) .append(' '); } } - while (s.length() < method.maxStack + method.maxLocals + 1) { - s.append(' '); + while (sb.length() < method.maxStack + method.maxLocals + 1) { + sb.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); - pw.print(" " + s + " : " + t.text.get(t.text.size() - 1)); + pw.print(" " + sb + " : " + t.text.get(t.text.size() - 1)); } for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { method.tryCatchBlocks.get(j).accept(mv); diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java index 5c2c8bf4776..c210e2c4033 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/util/Textifier.java @@ -443,7 +443,7 @@ public class Textifier extends Printer { } buf.append(tab); - appendAccess(access); + appendAccess(access & ~Opcodes.ACC_VOLATILE); if ((access & Opcodes.ACC_NATIVE) != 0) { buf.append("native "); } diff --git a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt index c6f8ad648af..b1d916092e5 100644 --- a/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt +++ b/jdk/src/share/classes/jdk/internal/org/objectweb/asm/version.txt @@ -1,12 +1,12 @@ Path: . -Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/asm-svn-2014-03-12 +Working Copy Root Path: /hudson/jobs/objectweb-pull/workspace/asm-svn-2014-05-27 URL: file:///svnroot/asm/trunk/asm Repository Root: file:///svnroot/asm Repository UUID: 271bd773-ee82-43a6-9b2b-1890ed8ce7f9 -Revision: 1721 +Revision: 1748 Node Kind: directory Schedule: normal Last Changed Author: ebruneton -Last Changed Rev: 1721 -Last Changed Date: 2014-03-02 17:25:35 +0100 (Sun, 02 Mar 2014) +Last Changed Rev: 1747 +Last Changed Date: 2014-05-24 10:22:13 +0200 (Sat, 24 May 2014) diff --git a/jdk/src/share/classes/jdk/internal/util/xml/impl/Parser.java b/jdk/src/share/classes/jdk/internal/util/xml/impl/Parser.java index 7eb918d7b7b..6db4d4fdb6d 100644 --- a/jdk/src/share/classes/jdk/internal/util/xml/impl/Parser.java +++ b/jdk/src/share/classes/jdk/internal/util/xml/impl/Parser.java @@ -2860,14 +2860,25 @@ public abstract class Parser { } else { // Get encoding from BOM or the xml text decl. reader = bom(is.getByteStream(), ' '); + /** + * [#4.3.3] requires BOM for UTF-16, however, it's not uncommon + * that it may be missing. A mature technique exists in Xerces + * to further check for possible UTF-16 encoding + */ + if (reader == null) { + reader = utf16(is.getByteStream()); + } + if (reader == null) { // Encoding is defined by the xml text decl. reader = enc("UTF-8", is.getByteStream()); expenc = xml(reader); - if (expenc.startsWith("UTF-16")) { - panic(FAULT); // UTF-16 must have BOM [#4.3.3] + if (!expenc.equals("UTF-8")) { + if (expenc.startsWith("UTF-16")) { + panic(FAULT); // UTF-16 must have BOM [#4.3.3] + } + reader = enc(expenc, is.getByteStream()); } - reader = enc(expenc, is.getByteStream()); } else { // Encoding is defined by the BOM. xml(reader); @@ -2956,6 +2967,49 @@ public abstract class Parser { } } + + /** + * Using a mature technique from Xerces, this method checks further after + * the bom method above to see if the encoding is UTF-16 + * + * @param is A byte stream of the entity. + * @return a reader, may be null + * @exception Exception is parser specific exception form panic method. + * @exception IOException + */ + private Reader utf16(InputStream is) + throws Exception { + if (mChIdx != 0) { + //The bom method has read ONE byte into the buffer. + byte b0 = (byte)mChars[0]; + if (b0 == 0x00 || b0 == 0x3C) { + int b1 = is.read(); + int b2 = is.read(); + int b3 = is.read(); + if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) { + // UTF-16, big-endian, no BOM + mChars[0] = (char)(b1); + mChars[mChIdx++] = (char)(b3); + return new ReaderUTF16(is, 'b'); + } else if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) { + // UTF-16, little-endian, no BOM + mChars[0] = (char)(b0); + mChars[mChIdx++] = (char)(b2); + return new ReaderUTF16(is, 'l'); + } else { + /**not every InputStream supports reset, so we have to remember + * the state for further parsing + **/ + mChars[0] = (char)(b0); + mChars[mChIdx++] = (char)(b1); + mChars[mChIdx++] = (char)(b2); + mChars[mChIdx++] = (char)(b3); + } + + } + } + return null; + } /** * Parses the xml text declaration. * @@ -2974,17 +3028,17 @@ public abstract class Parser { String enc = "UTF-8"; char ch; int val; - short st; - // Read the xml text declaration into the buffer - if (mChIdx != 0) { - // The bom method have read ONE char into the buffer. - st = (short) ((mChars[0] == '<') ? 1 : -1); - } else { - st = 0; - } + short st = 0; + int byteRead = mChIdx; //number of bytes read prior to entering this method + while (st >= 0 && mChIdx < mChars.length) { - ch = ((val = reader.read()) >= 0) ? (char) val : EOS; - mChars[mChIdx++] = ch; + if (st < byteRead) { + ch = mChars[st]; + } else { + ch = ((val = reader.read()) >= 0) ? (char) val : EOS; + mChars[mChIdx++] = ch; + } + switch (st) { case 0: // read '<' of xml declaration switch (ch) { diff --git a/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java b/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java index 8be1fe6a5dc..a44560b4597 100644 --- a/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java +++ b/jdk/src/share/classes/jdk/net/ExtendedSocketOptions.java @@ -32,7 +32,7 @@ import java.net.SocketOption; * {@link java.net.StandardSocketOptions}. These options may be platform * specific. * - * @since 1.9 + * @since 1.8 */ @jdk.Exported public final class ExtendedSocketOptions { diff --git a/jdk/src/share/classes/jdk/net/NetworkPermission.java b/jdk/src/share/classes/jdk/net/NetworkPermission.java index 0e853f0d527..01aa1a89653 100644 --- a/jdk/src/share/classes/jdk/net/NetworkPermission.java +++ b/jdk/src/share/classes/jdk/net/NetworkPermission.java @@ -58,7 +58,7 @@ import java.security.BasicPermission; * * @see jdk.net.ExtendedSocketOptions * - * @since 1.9 + * @since 1.8 */ @jdk.Exported diff --git a/jdk/src/share/classes/jdk/net/SocketFlow.java b/jdk/src/share/classes/jdk/net/SocketFlow.java index a102a3f35a0..3d673d1fc44 100644 --- a/jdk/src/share/classes/jdk/net/SocketFlow.java +++ b/jdk/src/share/classes/jdk/net/SocketFlow.java @@ -43,7 +43,7 @@ import java.lang.annotation.Native; * When a security manager is installed, a {@link NetworkPermission} * is required to set or get this option. * - * @since 1.9 + * @since 1.8 */ @jdk.Exported public class SocketFlow { @@ -66,7 +66,7 @@ public class SocketFlow { * one of these statuses, which reflect the state of socket's * flow. * - * @since 1.9 + * @since 1.8 */ @jdk.Exported public enum Status { diff --git a/jdk/src/share/classes/jdk/net/Sockets.java b/jdk/src/share/classes/jdk/net/Sockets.java index 9f7d94a0323..2f2da459e45 100644 --- a/jdk/src/share/classes/jdk/net/Sockets.java +++ b/jdk/src/share/classes/jdk/net/Sockets.java @@ -51,7 +51,7 @@ import sun.net.ExtendedOptionsImpl; * When a security manager is installed, some non-standard socket options * may require a security permission before being set or get. * The details are specified in {@link ExtendedSocketOptions}. No permission - * is required for {@link java.net.StandardSocketOption}s. + * is required for {@link java.net.StandardSocketOptions}. * * @see java.nio.channels.NetworkChannel */ diff --git a/jdk/src/share/classes/jdk/net/package-info.java b/jdk/src/share/classes/jdk/net/package-info.java index 236d640dbfa..fd824f6fd1d 100644 --- a/jdk/src/share/classes/jdk/net/package-info.java +++ b/jdk/src/share/classes/jdk/net/package-info.java @@ -27,7 +27,7 @@ * Platform specific socket options for the {@code java.net} and {@code java.nio.channels} * socket classes. * - * @since 1.9 + * @since 1.8 */ @jdk.Exported diff --git a/jdk/src/share/classes/sun/jvmstat/monitor/AbstractMonitor.java b/jdk/src/share/classes/sun/jvmstat/monitor/AbstractMonitor.java index 80789de60c5..c615df26eb5 100644 --- a/jdk/src/share/classes/sun/jvmstat/monitor/AbstractMonitor.java +++ b/jdk/src/share/classes/sun/jvmstat/monitor/AbstractMonitor.java @@ -84,7 +84,7 @@ public abstract class AbstractMonitor implements Monitor { * {@inheritDoc} */ public String getBaseName() { - int baseIndex = name.lastIndexOf(".")+1; + int baseIndex = name.lastIndexOf('.') + 1; return name.substring(baseIndex); } diff --git a/jdk/src/share/classes/sun/jvmstat/monitor/HostIdentifier.java b/jdk/src/share/classes/sun/jvmstat/monitor/HostIdentifier.java index 4ac28a1034a..470de36e64a 100644 --- a/jdk/src/share/classes/sun/jvmstat/monitor/HostIdentifier.java +++ b/jdk/src/share/classes/sun/jvmstat/monitor/HostIdentifier.java @@ -138,8 +138,8 @@ public class HostIdentifier { String frag = u.getFragment(); URI u2 = null; - int c1index = uriString.indexOf(":"); - int c2index = uriString.lastIndexOf(":"); + int c1index = uriString.indexOf(':'); + int c2index = uriString.lastIndexOf(':'); if (c2index != c1index) { /* * this is the scheme:hostname:port case. Attempt to diff --git a/jdk/src/share/classes/sun/management/StackTraceElementCompositeData.java b/jdk/src/share/classes/sun/management/StackTraceElementCompositeData.java index 27eed847dac..cb863fe27ba 100644 --- a/jdk/src/share/classes/sun/management/StackTraceElementCompositeData.java +++ b/jdk/src/share/classes/sun/management/StackTraceElementCompositeData.java @@ -68,7 +68,7 @@ public class StackTraceElementCompositeData extends LazyCompositeData { ste.getMethodName(), ste.getFileName(), new Integer(ste.getLineNumber()), - new Boolean(ste.isNativeMethod()), + ste.isNativeMethod(), }; try { return new CompositeDataSupport(stackTraceElementCompositeType, diff --git a/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java b/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java index 2e12104dced..cef28271e7e 100644 --- a/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java +++ b/jdk/src/share/classes/sun/management/ThreadInfoCompositeData.java @@ -120,8 +120,8 @@ public class ThreadInfoCompositeData extends LazyCompositeData { new Long(threadInfo.getLockOwnerId()), threadInfo.getLockOwnerName(), stackTraceData, - new Boolean(threadInfo.isSuspended()), - new Boolean(threadInfo.isInNative()), + threadInfo.isSuspended(), + threadInfo.isInNative(), lockedMonitorsData, lockedSyncsData, }; diff --git a/jdk/src/share/classes/sun/management/VMOptionCompositeData.java b/jdk/src/share/classes/sun/management/VMOptionCompositeData.java index 51d8181451a..6eeac787000 100644 --- a/jdk/src/share/classes/sun/management/VMOptionCompositeData.java +++ b/jdk/src/share/classes/sun/management/VMOptionCompositeData.java @@ -59,7 +59,7 @@ public class VMOptionCompositeData extends LazyCompositeData { final Object[] vmOptionItemValues = { option.getName(), option.getValue(), - new Boolean(option.isWriteable()), + option.isWriteable(), option.getOrigin().toString(), }; diff --git a/jdk/src/share/classes/sun/management/snmp/jvminstr/NotificationTargetImpl.java b/jdk/src/share/classes/sun/management/snmp/jvminstr/NotificationTargetImpl.java index 9e080001ad0..d6574e3ebf9 100644 --- a/jdk/src/share/classes/sun/management/snmp/jvminstr/NotificationTargetImpl.java +++ b/jdk/src/share/classes/sun/management/snmp/jvminstr/NotificationTargetImpl.java @@ -70,8 +70,8 @@ public class NotificationTargetImpl implements NotificationTarget { String addrStr; if (target.startsWith("[")) { - final int index = target.indexOf("]"); - final int index2 = target.lastIndexOf(":"); + final int index = target.indexOf(']'); + final int index2 = target.lastIndexOf(':'); if(index == -1) throw new IllegalArgumentException("Host starts with [ but " + "does not end with ]"); @@ -85,8 +85,8 @@ public class NotificationTargetImpl implements NotificationTarget { if (addrStr.startsWith("[")) throw new IllegalArgumentException("More than one [[...]]"); } else { - final int index = target.indexOf(":"); - final int index2 = target.lastIndexOf(":"); + final int index = target.indexOf(':'); + final int index2 = target.lastIndexOf(':'); if(index == -1) throw new IllegalArgumentException("Missing port separator \":\""); addrStr = target.substring(0, index); @@ -98,7 +98,7 @@ public class NotificationTargetImpl implements NotificationTarget { address = InetAddress.getByName(addrStr); //THE CHECK SHOULD BE STRONGER!!! - final int index = target.lastIndexOf(":"); + final int index = target.lastIndexOf(':'); community = target.substring(index + 1, target.length()); diff --git a/jdk/src/share/classes/sun/misc/ExtensionInfo.java b/jdk/src/share/classes/sun/misc/ExtensionInfo.java index 8b536379558..3fc17bf7339 100644 --- a/jdk/src/share/classes/sun/misc/ExtensionInfo.java +++ b/jdk/src/share/classes/sun/misc/ExtensionInfo.java @@ -273,8 +273,8 @@ public class ExtensionInfo { else { // Look for index of "." in the string - int sIdx = source.indexOf("."); - int tIdx = target.indexOf("."); + int sIdx = source.indexOf('.'); + int tIdx = target.indexOf('.'); if (sIdx == -1) sIdx = source.length() - 1; @@ -304,10 +304,10 @@ public class ExtensionInfo { String versionError = mf.format(args); // Look for "-" for pre-release - int prIndex = token.indexOf("-"); + int prIndex = token.indexOf('-'); // Look for "_" for patch release - int patchIndex = token.indexOf("_"); + int patchIndex = token.indexOf('_'); if (prIndex == -1 && patchIndex == -1) { diff --git a/jdk/src/share/classes/sun/misc/JarIndex.java b/jdk/src/share/classes/sun/misc/JarIndex.java index e43b9ee7f2e..d459751186b 100644 --- a/jdk/src/share/classes/sun/misc/JarIndex.java +++ b/jdk/src/share/classes/sun/misc/JarIndex.java @@ -172,7 +172,7 @@ public class JarIndex { if ((jarFiles = indexMap.get(fileName)) == null) { /* try the package name again */ int pos; - if((pos = fileName.lastIndexOf("/")) != -1) { + if((pos = fileName.lastIndexOf('/')) != -1) { jarFiles = indexMap.get(fileName.substring(0, pos)); } } @@ -195,7 +195,7 @@ public class JarIndex { public void add(String fileName, String jarName) { String packageName; int pos; - if((pos = fileName.lastIndexOf("/")) != -1) { + if((pos = fileName.lastIndexOf('/')) != -1) { packageName = fileName.substring(0, pos); } else { packageName = fileName; diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java index 11dae819751..dca817148a5 100644 --- a/jdk/src/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java @@ -793,7 +793,7 @@ public class URLClassPath { boolean validIndex(final String name) { String packageName = name; int pos; - if((pos = name.lastIndexOf("/")) != -1) { + if((pos = name.lastIndexOf('/')) != -1) { packageName = name.substring(0, pos); } @@ -803,7 +803,7 @@ public class URLClassPath { while (enum_.hasMoreElements()) { entry = enum_.nextElement(); entryName = entry.getName(); - if((pos = entryName.lastIndexOf("/")) != -1) + if((pos = entryName.lastIndexOf('/')) != -1) entryName = entryName.substring(0, pos); if (entryName.equals(packageName)) { return true; @@ -900,7 +900,7 @@ public class URLClassPath { */ JarIndex newIndex = newLoader.getIndex(); if(newIndex != null) { - int pos = jarName.lastIndexOf("/"); + int pos = jarName.lastIndexOf('/'); newIndex.merge(this.index, (pos == -1 ? null : jarName.substring(0, pos + 1))); } diff --git a/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java b/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java index 9c3fb964f0a..b490caa8f5e 100644 --- a/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java @@ -258,7 +258,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { d = null; } if (d != null && time != null) { - int c = time.indexOf(":"); + int c = time.indexOf(':'); now.setTime(d); now.set(Calendar.HOUR, Integer.parseInt(time.substring(0, c))); now.set(Calendar.MINUTE, Integer.parseInt(time.substring(c + 1))); @@ -294,7 +294,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { public FtpDirEntry parseLine(String line) { String name = null; - int i = line.lastIndexOf(";"); + int i = line.lastIndexOf(';'); if (i > 0) { name = line.substring(i + 1).trim(); line = line.substring(0, i); @@ -305,7 +305,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { FtpDirEntry file = new FtpDirEntry(name); while (!line.isEmpty()) { String s; - i = line.indexOf(";"); + i = line.indexOf(';'); if (i > 0) { s = line.substring(0, i); line = line.substring(i + 1); @@ -313,7 +313,7 @@ public class FtpClient extends sun.net.ftp.FtpClient { s = line; line = ""; } - i = s.indexOf("="); + i = s.indexOf('='); if (i > 0) { String fact = s.substring(0, i); String value = s.substring(i + 1); diff --git a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java index aa28e556adf..2abeddc5d88 100644 --- a/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java +++ b/jdk/src/share/classes/sun/net/spi/nameservice/dns/DNSNameService.java @@ -325,7 +325,7 @@ public final class DNSNameService implements NameService { while (i.hasNext()) { String parentDomain = i.next(); int start = 0; - while ((start = parentDomain.indexOf(".")) != -1 + while ((start = parentDomain.indexOf('.')) != -1 && start < parentDomain.length() -1) { try { results = resolve(ctx, host+"."+parentDomain, ids, 0); diff --git a/jdk/src/share/classes/sun/net/util/IPAddressUtil.java b/jdk/src/share/classes/sun/net/util/IPAddressUtil.java index 4dafa8a1d0b..a4cc9842a2b 100644 --- a/jdk/src/share/classes/sun/net/util/IPAddressUtil.java +++ b/jdk/src/share/classes/sun/net/util/IPAddressUtil.java @@ -132,7 +132,7 @@ public class IPAddressUtil { byte[] dst = new byte[INADDR16SZ]; int srcb_length = srcb.length; - int pc = src.indexOf ("%"); + int pc = src.indexOf ('%'); if (pc == srcb_length -1) { return null; } diff --git a/jdk/src/share/classes/sun/net/www/ParseUtil.java b/jdk/src/share/classes/sun/net/www/ParseUtil.java index d671c077291..cb8311996b1 100644 --- a/jdk/src/share/classes/sun/net/www/ParseUtil.java +++ b/jdk/src/share/classes/sun/net/www/ParseUtil.java @@ -356,8 +356,8 @@ public class ParseUtil { * because we must not quote a literal IPv6 address */ if (opaquePart.startsWith("//[")) { - int end = opaquePart.indexOf("]"); - if (end != -1 && opaquePart.indexOf(":")!=-1) { + int end = opaquePart.indexOf(']'); + if (end != -1 && opaquePart.indexOf(':')!=-1) { String doquote, dontquote; if (end == opaquePart.length()) { dontquote = opaquePart; @@ -408,8 +408,8 @@ public class ParseUtil { } else if (authority != null) { sb.append("//"); if (authority.startsWith("[")) { - int end = authority.indexOf("]"); - if (end != -1 && authority.indexOf(":")!=-1) { + int end = authority.indexOf(']'); + if (end != -1 && authority.indexOf(':')!=-1) { String doquote, dontquote; if (end == authority.length()) { dontquote = authority; diff --git a/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java b/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java index 4357ffc4e73..e7a2cbb73be 100644 --- a/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java +++ b/jdk/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java @@ -93,9 +93,9 @@ public class ServerSocketAdaptor // package-private public Socket accept() throws IOException { synchronized (ssc.blockingLock()) { - if (!ssc.isBound()) - throw new IllegalBlockingModeException(); try { + if (!ssc.isBound()) + throw new NotYetBoundException(); if (timeout == 0) { SocketChannel sc = ssc.accept(); if (sc == null && !ssc.isBlocking()) diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index 482f6b5ca2a..aa41880319b 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -341,6 +341,6 @@ public final class ReflectUtil { * (not to be confused with a Java Language anonymous inner class). */ public static boolean isVMAnonymousClass(Class cls) { - return cls.getName().indexOf("/") > -1; + return cls.getName().indexOf('/') > -1; } } diff --git a/jdk/src/share/classes/sun/rmi/runtime/Log.java b/jdk/src/share/classes/sun/rmi/runtime/Log.java index 507622a3acd..9a152b69e2c 100644 --- a/jdk/src/share/classes/sun/rmi/runtime/Log.java +++ b/jdk/src/share/classes/sun/rmi/runtime/Log.java @@ -426,7 +426,7 @@ public abstract class Log { * Mimic old log messages that only contain unqualified names. */ private static String unqualifiedName(String name) { - int lastDot = name.lastIndexOf("."); + int lastDot = name.lastIndexOf('.'); if (lastDot >= 0) { name = name.substring(lastDot + 1); } diff --git a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java index c561216b985..343810da8ae 100644 --- a/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java +++ b/jdk/src/share/classes/sun/rmi/transport/proxy/CGIHandler.java @@ -141,7 +141,7 @@ public final class CGIHandler { { try { String command, param; - int delim = QueryString.indexOf("="); + int delim = QueryString.indexOf('='); if (delim == -1) { command = QueryString; param = ""; diff --git a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java index 602f1807d05..736ef98fcd8 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSManagerImpl.java @@ -50,8 +50,8 @@ public class GSSManagerImpl extends GSSManager { if (osname.startsWith("SunOS") || osname.contains("OS X") || osname.startsWith("Linux")) { - return new Boolean(System.getProperty - (USE_NATIVE_PROP)); + return Boolean.valueOf(System.getProperty + (USE_NATIVE_PROP)); } return Boolean.FALSE; } diff --git a/jdk/src/share/classes/sun/security/jgss/wrapper/Krb5Util.java b/jdk/src/share/classes/sun/security/jgss/wrapper/Krb5Util.java index 730c6fa17fa..77d5a3598e8 100644 --- a/jdk/src/share/classes/sun/security/jgss/wrapper/Krb5Util.java +++ b/jdk/src/share/classes/sun/security/jgss/wrapper/Krb5Util.java @@ -39,7 +39,7 @@ class Krb5Util { static String getTGSName(GSSNameElement name) throws GSSException { String krbPrinc = name.getKrbName(); - int atIndex = krbPrinc.indexOf("@"); + int atIndex = krbPrinc.indexOf('@'); String realm = krbPrinc.substring(atIndex + 1); StringBuffer buf = new StringBuffer("krbtgt/"); buf.append(realm).append('@').append(realm); diff --git a/jdk/src/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/share/classes/sun/security/krb5/KdcComm.java index caaf20a86f8..721c105d345 100644 --- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -144,7 +144,8 @@ public final class KdcComm { try { Config cfg = Config.getInstance(); String temp = cfg.get("libdefaults", "kdc_timeout"); - timeout = parsePositiveIntString(temp); + timeout = parseTimeString(temp); + temp = cfg.get("libdefaults", "max_retries"); max_retries = parsePositiveIntString(temp); temp = cfg.get("libdefaults", "udp_preference_limit"); @@ -425,6 +426,25 @@ public final class KdcComm { } } + /** + * Parses a time value string. If it ends with "s", parses as seconds. + * Otherwise, parses as milliseconds. + * @param s the time string + * @return the integer value in milliseconds, or -1 if input is null or + * has an invalid format + */ + private static int parseTimeString(String s) { + if (s == null) { + return -1; + } + if (s.endsWith("s")) { + int seconds = parsePositiveIntString(s.substring(0, s.length()-1)); + return (seconds < 0) ? -1 : (seconds*1000); + } else { + return parsePositiveIntString(s); + } + } + /** * Returns krb5.conf setting of {@code key} for a specific realm, * which can be: @@ -446,7 +466,11 @@ public final class KdcComm { try { String value = Config.getInstance().get("realms", realm, key); - temp = parsePositiveIntString(value); + if (key.equals("kdc_timeout")) { + temp = parseTimeString(value); + } else { + temp = parsePositiveIntString(value); + } } catch (Exception exc) { // Ignored, defValue will be picked up } diff --git a/jdk/src/share/classes/sun/security/provider/PolicyFile.java b/jdk/src/share/classes/sun/security/provider/PolicyFile.java index ec3b54c2dcb..70fae4361fa 100644 --- a/jdk/src/share/classes/sun/security/provider/PolicyFile.java +++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java @@ -1271,7 +1271,7 @@ public class PolicyFile extends java.security.Policy { Boolean imp = AccessController.doPrivileged (new PrivilegedAction() { public Boolean run() { - return new Boolean(entry.getCodeSource().implies(cs)); + return entry.getCodeSource().implies(cs); } }); if (!imp.booleanValue()) { @@ -1856,7 +1856,7 @@ public class PolicyFile extends java.security.Policy { int colonIndex; String prefix = value; String suffix; - if ((colonIndex = value.indexOf(":")) != -1) { + if ((colonIndex = value.indexOf(':')) != -1) { prefix = value.substring(0, colonIndex); } diff --git a/jdk/src/share/classes/sun/security/smartcardio/CardImpl.java b/jdk/src/share/classes/sun/security/smartcardio/CardImpl.java index 40cc25596fa..322726f9c35 100644 --- a/jdk/src/share/classes/sun/security/smartcardio/CardImpl.java +++ b/jdk/src/share/classes/sun/security/smartcardio/CardImpl.java @@ -246,7 +246,7 @@ final class CardImpl extends Card { } checkExclusive(); try { - SCardDisconnect(cardId, (reset ? SCARD_LEAVE_CARD : SCARD_RESET_CARD)); + SCardDisconnect(cardId, (reset ? SCARD_RESET_CARD : SCARD_LEAVE_CARD)); } catch (PCSCException e) { throw new CardException("disconnect() failed", e); } finally { diff --git a/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java b/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java index 46e0678fb0c..7cdffffecf9 100644 --- a/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java @@ -338,7 +338,7 @@ final class SunX509KeyManagerImpl extends X509ExtendedKeyManager { } String sigType; if (keyType.contains("_")) { - int k = keyType.indexOf("_"); + int k = keyType.indexOf('_'); sigType = keyType.substring(k + 1); keyType = keyType.substring(0, k); } else { diff --git a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java index b6a5034cad8..b817cde7fd7 100644 --- a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java @@ -302,7 +302,7 @@ final class X509KeyManagerImpl extends X509ExtendedKeyManager final String sigKeyAlgorithm; KeyType(String algorithm) { - int k = algorithm.indexOf("_"); + int k = algorithm.indexOf('_'); if (k == -1) { keyAlgorithm = algorithm; sigKeyAlgorithm = null; diff --git a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java index ec2247d81b6..63afd87af31 100644 --- a/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java +++ b/jdk/src/share/classes/sun/security/tools/jarsigner/Main.java @@ -1560,8 +1560,7 @@ public class Main { first = false; } try { - CertPath cp = certificateFactory.generateCertPath(certs); - validator.validate(cp, pkixParameters); + validateCertChain(certs); } catch (Exception e) { if (debug) { e.printStackTrace(); @@ -1871,8 +1870,7 @@ public class Main { printCert("", certChain[0], true, null, true); try { - CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain)); - validator.validate(cp, pkixParameters); + validateCertChain(Arrays.asList(certChain)); } catch (Exception e) { if (debug) { e.printStackTrace(); @@ -1937,6 +1935,22 @@ public class Main { System.exit(1); } + void validateCertChain(List certs) throws Exception { + int cpLen = 0; + out: for (; cpLen 0) { + CertPath cp = certificateFactory.generateCertPath( + (cpLen == certs.size())? certs: certs.subList(0, cpLen)); + validator.validate(cp, pkixParameters); + } + } + char[] getPass(String prompt) { System.err.print(prompt); diff --git a/jdk/src/share/classes/sun/security/util/HostnameChecker.java b/jdk/src/share/classes/sun/security/util/HostnameChecker.java index 77f17f71a10..1a6f3c2a446 100644 --- a/jdk/src/share/classes/sun/security/util/HostnameChecker.java +++ b/jdk/src/share/classes/sun/security/util/HostnameChecker.java @@ -300,8 +300,8 @@ public class HostnameChecker { template = template.toLowerCase(Locale.ENGLISH); // Retreive leftmost component - int templateIdx = template.indexOf("."); - int nameIdx = name.indexOf("."); + int templateIdx = template.indexOf('.'); + int nameIdx = name.indexOf('.'); if (templateIdx == -1) templateIdx = template.length(); @@ -326,7 +326,7 @@ public class HostnameChecker { */ private static boolean matchWildCards(String name, String template) { - int wildcardIdx = template.indexOf("*"); + int wildcardIdx = template.indexOf('*'); if (wildcardIdx == -1) return name.equals(template); @@ -349,7 +349,7 @@ public class HostnameChecker { // update the match scope name = name.substring(beforeStartIdx + beforeWildcard.length()); - wildcardIdx = afterWildcard.indexOf("*"); + wildcardIdx = afterWildcard.indexOf('*'); } return name.endsWith(afterWildcard); } diff --git a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java index 083e23a3700..5222e8a04c5 100644 --- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java @@ -98,7 +98,7 @@ public class SignatureFileVerifier { } finally { Providers.stopJarVerification(obj); } - this.name = name.substring(0, name.lastIndexOf(".")) + this.name = name.substring(0, name.lastIndexOf('.')) .toUpperCase(Locale.ENGLISH); this.md = md; this.signerCache = signerCache; diff --git a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java index d11e44e9077..f3e71a793b3 100644 --- a/jdk/src/share/classes/sun/security/validator/PKIXValidator.java +++ b/jdk/src/share/classes/sun/security/validator/PKIXValidator.java @@ -86,12 +86,12 @@ public final class PKIXValidator extends Validator { factory = CertificateFactory.getInstance("X.509"); } catch (InvalidAlgorithmParameterException e) { throw new RuntimeException("Unexpected error: " + e.toString(), e); - } catch (CertificateException e) { - throw new RuntimeException("Internal error", e); - } + } catch (CertificateException e) { + throw new RuntimeException("Internal error", e); + } setDefaultParameters(variant); - plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING); + plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING); trustedSubjects = setTrustedSubjects(); } @@ -107,13 +107,13 @@ public final class PKIXValidator extends Validator { } parameterTemplate = params; - try { - factory = CertificateFactory.getInstance("X.509"); - } catch (CertificateException e) { - throw new RuntimeException("Internal error", e); - } + try { + factory = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + throw new RuntimeException("Internal error", e); + } - plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING); + plugin = variant.equals(VAR_PLUGIN_CODE_SIGNING); trustedSubjects = setTrustedSubjects(); } @@ -133,10 +133,10 @@ public final class PKIXValidator extends Validator { List keys; if (subjectMap.containsKey(dn)) { keys = subjectMap.get(dn); - } else { + } else { keys = new ArrayList(); subjectMap.put(dn, keys); - } + } keys.add(cert.getPublicKey()); } @@ -202,75 +202,74 @@ public final class PKIXValidator extends Validator { pkixParameters.addCertPathChecker(algorithmChecker); } - // check that chain is in correct order and check if chain contains - // trust anchor - X500Principal prevIssuer = null; - for (int i = 0; i < chain.length; i++) { - X509Certificate cert = chain[i]; - X500Principal dn = cert.getSubjectX500Principal(); - if (i != 0 && - !dn.equals(prevIssuer)) { - // chain is not ordered correctly, call builder instead - return doBuild(chain, otherCerts, pkixParameters); - } - - // Check if chain[i] is already trusted. It may be inside - // trustedCerts, or has the same dn and public key as a cert - // inside trustedCerts. The latter happens when a CA has - // updated its cert with a stronger signature algorithm in JRE - // but the weak one is still in circulation. - - if (trustedCerts.contains(cert) || // trusted cert - (trustedSubjects.containsKey(dn) && // replacing ... - trustedSubjects.get(dn).contains( // ... weak cert - cert.getPublicKey()))) { - if (i == 0) { - return new X509Certificate[] {chain[0]}; - } - // Remove and call validator on partial chain [0 .. i-1] - X509Certificate[] newChain = new X509Certificate[i]; - System.arraycopy(chain, 0, newChain, 0, i); - return doValidate(newChain, pkixParameters); - } - prevIssuer = cert.getIssuerX500Principal(); + // check that chain is in correct order and check if chain contains + // trust anchor + X500Principal prevIssuer = null; + for (int i = 0; i < chain.length; i++) { + X509Certificate cert = chain[i]; + X500Principal dn = cert.getSubjectX500Principal(); + if (i != 0 && !dn.equals(prevIssuer)) { + // chain is not ordered correctly, call builder instead + return doBuild(chain, otherCerts, pkixParameters); } - // apparently issued by trust anchor? - X509Certificate last = chain[chain.length - 1]; - X500Principal issuer = last.getIssuerX500Principal(); - X500Principal subject = last.getSubjectX500Principal(); - if (trustedSubjects.containsKey(issuer) && - isSignatureValid(trustedSubjects.get(issuer), last)) { - return doValidate(chain, pkixParameters); - } + // Check if chain[i] is already trusted. It may be inside + // trustedCerts, or has the same dn and public key as a cert + // inside trustedCerts. The latter happens when a CA has + // updated its cert with a stronger signature algorithm in JRE + // but the weak one is still in circulation. - // don't fallback to builder if called from plugin/webstart - if (plugin) { - // Validate chain even if no trust anchor is found. This - // allows plugin/webstart to make sure the chain is - // otherwise valid - if (chain.length > 1) { - X509Certificate[] newChain = - new X509Certificate[chain.length-1]; - System.arraycopy(chain, 0, newChain, 0, newChain.length); - - // temporarily set last cert as sole trust anchor - try { - pkixParameters.setTrustAnchors - (Collections.singleton(new TrustAnchor - (chain[chain.length-1], null))); - } catch (InvalidAlgorithmParameterException iape) { - // should never occur, but ... - throw new CertificateException(iape); - } - doValidate(newChain, pkixParameters); + if (trustedCerts.contains(cert) || // trusted cert + (trustedSubjects.containsKey(dn) && // replacing ... + trustedSubjects.get(dn).contains( // ... weak cert + cert.getPublicKey()))) { + if (i == 0) { + return new X509Certificate[] {chain[0]}; } - // if the rest of the chain is valid, throw exception - // indicating no trust anchor was found - throw new ValidatorException - (ValidatorException.T_NO_TRUST_ANCHOR); + // Remove and call validator on partial chain [0 .. i-1] + X509Certificate[] newChain = new X509Certificate[i]; + System.arraycopy(chain, 0, newChain, 0, i); + return doValidate(newChain, pkixParameters); } - // otherwise, fall back to builder + prevIssuer = cert.getIssuerX500Principal(); + } + + // apparently issued by trust anchor? + X509Certificate last = chain[chain.length - 1]; + X500Principal issuer = last.getIssuerX500Principal(); + X500Principal subject = last.getSubjectX500Principal(); + if (trustedSubjects.containsKey(issuer) && + isSignatureValid(trustedSubjects.get(issuer), last)) { + return doValidate(chain, pkixParameters); + } + + // don't fallback to builder if called from plugin/webstart + if (plugin) { + // Validate chain even if no trust anchor is found. This + // allows plugin/webstart to make sure the chain is + // otherwise valid + if (chain.length > 1) { + X509Certificate[] newChain = + new X509Certificate[chain.length-1]; + System.arraycopy(chain, 0, newChain, 0, newChain.length); + + // temporarily set last cert as sole trust anchor + try { + pkixParameters.setTrustAnchors + (Collections.singleton(new TrustAnchor + (chain[chain.length-1], null))); + } catch (InvalidAlgorithmParameterException iape) { + // should never occur, but ... + throw new CertificateException(iape); + } + doValidate(newChain, pkixParameters); + } + // if the rest of the chain is valid, throw exception + // indicating no trust anchor was found + throw new ValidatorException + (ValidatorException.T_NO_TRUST_ANCHOR); + } + // otherwise, fall back to builder return doBuild(chain, otherCerts, pkixParameters); } diff --git a/jdk/src/share/classes/sun/security/x509/CRLExtensions.java b/jdk/src/share/classes/sun/security/x509/CRLExtensions.java index 628e1125add..834f78fa642 100644 --- a/jdk/src/share/classes/sun/security/x509/CRLExtensions.java +++ b/jdk/src/share/classes/sun/security/x509/CRLExtensions.java @@ -185,7 +185,7 @@ public class CRLExtensions { String name; String id = attr.getPrefix(); if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified - int index = alias.lastIndexOf("."); + int index = alias.lastIndexOf('.'); name = alias.substring(index + 1); } else name = alias; diff --git a/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java b/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java index 3198fd6cd6a..70125a07b2d 100644 --- a/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java +++ b/jdk/src/share/classes/sun/tools/jconsole/ConnectDialog.java @@ -325,7 +325,7 @@ public class ConnectDialog extends InternalDialog } else { String host = remoteTF.getText().trim(); String port = "0"; - int index = host.lastIndexOf(":"); + int index = host.lastIndexOf(':'); if (index >= 0) { port = host.substring(index + 1); host = host.substring(0, index); diff --git a/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java b/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java index ebdda0bbdbc..eb1f6b1be80 100644 --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/Utils.java @@ -210,7 +210,7 @@ public class Utils { public static String getArrayClassName(String name) { String className = null; if (name.startsWith("[")) { - int index = name.lastIndexOf("["); + int index = name.lastIndexOf('['); className = name.substring(index, name.length()); if (className.startsWith("[L")) { className = className.substring(2, className.length() - 1); @@ -241,7 +241,7 @@ public class Utils { if (className == null) { return name; } - int index = name.lastIndexOf("["); + int index = name.lastIndexOf('['); StringBuilder brackets = new StringBuilder(className); for (int i = 0; i <= index; i++) { brackets.append("[]"); diff --git a/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java b/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java index c29be4b9f0e..45538a28bc3 100644 --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XOperations.java @@ -113,7 +113,7 @@ public abstract class XOperations extends JPanel implements ActionListener { if (methodLabel.getText().length() > 20) { methodLabel.setText(methodLabel.getText(). substring(methodLabel.getText(). - lastIndexOf(".") + 1, + lastIndexOf('.') + 1, methodLabel.getText().length())); } diff --git a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java index 26d968fa506..ed5658cc9ae 100644 --- a/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java +++ b/jdk/src/share/classes/sun/tools/jconsole/inspector/XTree.java @@ -475,7 +475,7 @@ public class XTree extends JTree { private static Map extractKeyValuePairs( String props, ObjectName mbean) { Map map = new LinkedHashMap(); - int eq = props.indexOf("="); + int eq = props.indexOf('='); while (eq != -1) { String key = props.substring(0, eq); String value = mbean.getKeyProperty(key); @@ -484,7 +484,7 @@ public class XTree extends JTree { if (props.startsWith(",")) { props = props.substring(1); } - eq = props.indexOf("="); + eq = props.indexOf('='); } return map; } @@ -821,7 +821,7 @@ public class XTree extends JTree { } private void buildKeyValue() { - int index = tokenValue.indexOf("="); + int index = tokenValue.indexOf('='); if (index < 0) { key = tokenValue; value = tokenValue; diff --git a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg index 74096efea5f..c120c5e3242 100644 --- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg +++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg @@ -18,18 +18,5 @@ attributes = compatibility disabledMechanisms = { CKM_DSA_KEY_PAIR_GEN -# the following mechanisms are disabled due to performance issues -# (Solaris bug 6337157) - CKM_DSA_SHA1 - CKM_MD5_RSA_PKCS - CKM_SHA1_RSA_PKCS - CKM_SHA256_RSA_PKCS - CKM_SHA384_RSA_PKCS - CKM_SHA512_RSA_PKCS -# the following mechanisms are disabled to ensure backward compatibility -# (Solaris bug 6545046) - CKM_DES_CBC_PAD - CKM_DES3_CBC_PAD - CKM_AES_CBC_PAD } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/ChangeLog b/jdk/src/share/native/java/util/zip/zlib-1.2.8/ChangeLog similarity index 81% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/ChangeLog rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/ChangeLog index f310bb0fcdb..f22aabaef53 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/ChangeLog +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/ChangeLog @@ -1,12 +1,276 @@ ChangeLog file for zlib +Changes in 1.2.8 (28 Apr 2013) +- Update contrib/minizip/iowin32.c for Windows RT [Vollant] +- Do not force Z_CONST for C++ +- Clean up contrib/vstudio [Ro§] +- Correct spelling error in zlib.h +- Fix mixed line endings in contrib/vstudio + +Changes in 1.2.7.3 (13 Apr 2013) +- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc + +Changes in 1.2.7.2 (13 Apr 2013) +- Change check for a four-byte type back to hexadecimal +- Fix typo in win32/Makefile.msc +- Add casts in gzwrite.c for pointer differences + +Changes in 1.2.7.1 (24 Mar 2013) +- Replace use of unsafe string functions with snprintf if available +- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] +- Fix gzgetc undefine when Z_PREFIX set [Turk] +- Eliminate use of mktemp in Makefile (not always available) +- Fix bug in 'F' mode for gzopen() +- Add inflateGetDictionary() function +- Correct comment in deflate.h +- Use _snprintf for snprintf in Microsoft C +- On Darwin, only use /usr/bin/libtool if libtool is not Apple +- Delete "--version" file if created by "ar --version" [Richard G.] +- Fix configure check for veracity of compiler error return codes +- Fix CMake compilation of static lib for MSVC2010 x64 +- Remove unused variable in infback9.c +- Fix argument checks in gzlog_compress() and gzlog_write() +- Clean up the usage of z_const and respect const usage within zlib +- Clean up examples/gzlog.[ch] comparisons of different types +- Avoid shift equal to bits in type (caused endless loop) +- Fix unintialized value bug in gzputc() introduced by const patches +- Fix memory allocation error in examples/zran.c [Nor] +- Fix bug where gzopen(), gzclose() would write an empty file +- Fix bug in gzclose() when gzwrite() runs out of memory +- Check for input buffer malloc failure in examples/gzappend.c +- Add note to contrib/blast to use binary mode in stdio +- Fix comparisons of differently signed integers in contrib/blast +- Check for invalid code length codes in contrib/puff +- Fix serious but very rare decompression bug in inftrees.c +- Update inflateBack() comments, since inflate() can be faster +- Use underscored I/O function names for WINAPI_FAMILY +- Add _tr_flush_bits to the external symbols prefixed by --zprefix +- Add contrib/vstudio/vc10 pre-build step for static only +- Quote --version-script argument in CMakeLists.txt +- Don't specify --version-script on Apple platforms in CMakeLists.txt +- Fix casting error in contrib/testzlib/testzlib.c +- Fix types in contrib/minizip to match result of get_crc_table() +- Simplify contrib/vstudio/vc10 with 'd' suffix +- Add TOP support to win32/Makefile.msc +- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h +- Add vc11 and vc12 build files to contrib/vstudio +- Add gzvprintf() as an undocumented function in zlib +- Fix configure for Sun shell +- Remove runtime check in configure for four-byte integer type +- Add casts and consts to ease user conversion to C++ +- Add man pages for minizip and miniunzip +- In Makefile uninstall, don't rm if preceding cd fails +- Do not return Z_BUF_ERROR if deflateParam() has nothing to write + +Changes in 1.2.7 (2 May 2012) +- Replace use of memmove() with a simple copy for portability +- Test for existence of strerror +- Restore gzgetc_ for backward compatibility with 1.2.6 +- Fix build with non-GNU make on Solaris +- Require gcc 4.0 or later on Mac OS X to use the hidden attribute +- Include unistd.h for Watcom C +- Use __WATCOMC__ instead of __WATCOM__ +- Do not use the visibility attribute if NO_VIZ defined +- Improve the detection of no hidden visibility attribute +- Avoid using __int64 for gcc or solo compilation +- Cast to char * in gzprintf to avoid warnings [Zinser] +- Fix make_vms.com for VAX [Zinser] +- Don't use library or built-in byte swaps +- Simplify test and use of gcc hidden attribute +- Fix bug in gzclose_w() when gzwrite() fails to allocate memory +- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() +- Fix bug in test/minigzip.c for configure --solo +- Fix contrib/vstudio project link errors [Mohanathas] +- Add ability to choose the builder in make_vms.com [Schweda] +- Add DESTDIR support to mingw32 win32/Makefile.gcc +- Fix comments in win32/Makefile.gcc for proper usage +- Allow overriding the default install locations for cmake +- Generate and install the pkg-config file with cmake +- Build both a static and a shared version of zlib with cmake +- Include version symbols for cmake builds +- If using cmake with MSVC, add the source directory to the includes +- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] +- Move obsolete emx makefile to old [Truta] +- Allow the use of -Wundef when compiling or using zlib +- Avoid the use of the -u option with mktemp +- Improve inflate() documentation on the use of Z_FINISH +- Recognize clang as gcc +- Add gzopen_w() in Windows for wide character path names +- Rename zconf.h in CMakeLists.txt to move it out of the way +- Add source directory in CMakeLists.txt for building examples +- Look in build directory for zlib.pc in CMakeLists.txt +- Remove gzflags from zlibvc.def in vc9 and vc10 +- Fix contrib/minizip compilation in the MinGW environment +- Update ./configure for Solaris, support --64 [Mooney] +- Remove -R. from Solaris shared build (possible security issue) +- Avoid race condition for parallel make (-j) running example +- Fix type mismatch between get_crc_table() and crc_table +- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] +- Fix the path to zlib.map in CMakeLists.txt +- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] +- Add instructions to win32/Makefile.gcc for shared install [Torri] + +Changes in 1.2.6.1 (12 Feb 2012) +- Avoid the use of the Objective-C reserved name "id" +- Include io.h in gzguts.h for Microsoft compilers +- Fix problem with ./configure --prefix and gzgetc macro +- Include gz_header definition when compiling zlib solo +- Put gzflags() functionality back in zutil.c +- Avoid library header include in crc32.c for Z_SOLO +- Use name in GCC_CLASSIC as C compiler for coverage testing, if set +- Minor cleanup in contrib/minizip/zip.c [Vollant] +- Update make_vms.com [Zinser] +- Remove unnecessary gzgetc_ function +- Use optimized byte swap operations for Microsoft and GNU [Snyder] +- Fix minor typo in zlib.h comments [Rzesniowiecki] + +Changes in 1.2.6 (29 Jan 2012) +- Update the Pascal interface in contrib/pascal +- Fix function numbers for gzgetc_ in zlibvc.def files +- Fix configure.ac for contrib/minizip [Schiffer] +- Fix large-entry detection in minizip on 64-bit systems [Schiffer] +- Have ./configure use the compiler return code for error indication +- Fix CMakeLists.txt for cross compilation [McClure] +- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] +- Fix compilation of contrib/minizip on FreeBSD [Marquez] +- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] +- Include io.h for Turbo C / Borland C on all platforms [Truta] +- Make version explicit in contrib/minizip/configure.ac [Bosmans] +- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] +- Minor cleanup up contrib/minizip/unzip.c [Vollant] +- Fix bug when compiling minizip with C++ [Vollant] +- Protect for long name and extra fields in contrib/minizip [Vollant] +- Avoid some warnings in contrib/minizip [Vollant] +- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip +- Add missing libs to minizip linker command +- Add support for VPATH builds in contrib/minizip +- Add an --enable-demos option to contrib/minizip/configure +- Add the generation of configure.log by ./configure +- Exit when required parameters not provided to win32/Makefile.gcc +- Have gzputc return the character written instead of the argument +- Use the -m option on ldconfig for BSD systems [Tobias] +- Correct in zlib.map when deflateResetKeep was added + +Changes in 1.2.5.3 (15 Jan 2012) +- Restore gzgetc function for binary compatibility +- Do not use _lseeki64 under Borland C++ [Truta] +- Update win32/Makefile.msc to build test/*.c [Truta] +- Remove old/visualc6 given CMakefile and other alternatives +- Update AS400 build files and documentation [Monnerat] +- Update win32/Makefile.gcc to build test/*.c [Truta] +- Permit stronger flushes after Z_BLOCK flushes +- Avoid extraneous empty blocks when doing empty flushes +- Permit Z_NULL arguments to deflatePending +- Allow deflatePrime() to insert bits in the middle of a stream +- Remove second empty static block for Z_PARTIAL_FLUSH +- Write out all of the available bits when using Z_BLOCK +- Insert the first two strings in the hash table after a flush + +Changes in 1.2.5.2 (17 Dec 2011) +- fix ld error: unable to find version dependency 'ZLIB_1.2.5' +- use relative symlinks for shared libs +- Avoid searching past window for Z_RLE strategy +- Assure that high-water mark initialization is always applied in deflate +- Add assertions to fill_window() in deflate.c to match comments +- Update python link in README +- Correct spelling error in gzread.c +- Fix bug in gzgets() for a concatenated empty gzip stream +- Correct error in comment for gz_make() +- Change gzread() and related to ignore junk after gzip streams +- Allow gzread() and related to continue after gzclearerr() +- Allow gzrewind() and gzseek() after a premature end-of-file +- Simplify gzseek() now that raw after gzip is ignored +- Change gzgetc() to a macro for speed (~40% speedup in testing) +- Fix gzclose() to return the actual error last encountered +- Always add large file support for windows +- Include zconf.h for windows large file support +- Include zconf.h.cmakein for windows large file support +- Update zconf.h.cmakein on make distclean +- Merge vestigial vsnprintf determination from zutil.h to gzguts.h +- Clarify how gzopen() appends in zlib.h comments +- Correct documentation of gzdirect() since junk at end now ignored +- Add a transparent write mode to gzopen() when 'T' is in the mode +- Update python link in zlib man page +- Get inffixed.h and MAKEFIXED result to match +- Add a ./config --solo option to make zlib subset with no libary use +- Add undocumented inflateResetKeep() function for CAB file decoding +- Add --cover option to ./configure for gcc coverage testing +- Add #define ZLIB_CONST option to use const in the z_stream interface +- Add comment to gzdopen() in zlib.h to use dup() when using fileno() +- Note behavior of uncompress() to provide as much data as it can +- Add files in contrib/minizip to aid in building libminizip +- Split off AR options in Makefile.in and configure +- Change ON macro to Z_ARG to avoid application conflicts +- Facilitate compilation with Borland C++ for pragmas and vsnprintf +- Include io.h for Turbo C / Borland C++ +- Move example.c and minigzip.c to test/ +- Simplify incomplete code table filling in inflate_table() +- Remove code from inflate.c and infback.c that is impossible to execute +- Test the inflate code with full coverage +- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) +- Add deflateResetKeep and fix inflateResetKeep to retain dictionary +- Fix gzwrite.c to accommodate reduced memory zlib compilation +- Have inflate() with Z_FINISH avoid the allocation of a window +- Do not set strm->adler when doing raw inflate +- Fix gzeof() to behave just like feof() when read is not past end of file +- Fix bug in gzread.c when end-of-file is reached +- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF +- Document gzread() capability to read concurrently written files +- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] + +Changes in 1.2.5.1 (10 Sep 2011) +- Update FAQ entry on shared builds (#13) +- Avoid symbolic argument to chmod in Makefile.in +- Fix bug and add consts in contrib/puff [Oberhumer] +- Update contrib/puff/zeros.raw test file to have all block types +- Add full coverage test for puff in contrib/puff/Makefile +- Fix static-only-build install in Makefile.in +- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] +- Add libz.a dependency to shared in Makefile.in for parallel builds +- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out +- Replace $(...) with `...` in configure for non-bash sh [Bowler] +- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] +- Add solaris* to Linux* in configure to allow gcc use [Groffen] +- Add *bsd* to Linux* case in configure [Bar-Lev] +- Add inffast.obj to dependencies in win32/Makefile.msc +- Correct spelling error in deflate.h [Kohler] +- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc +- Add test to configure for GNU C looking for gcc in output of $cc -v +- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] +- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not +- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense +- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) +- Make stronger test in zconf.h to include unistd.h for LFS +- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] +- Fix zlib.h LFS support when Z_PREFIX used +- Add updated as400 support (removed from old) [Monnerat] +- Avoid deflate sensitivity to volatile input data +- Avoid division in adler32_combine for NO_DIVIDE +- Clarify the use of Z_FINISH with deflateBound() amount of space +- Set binary for output file in puff.c +- Use u4 type for crc_table to avoid conversion warnings +- Apply casts in zlib.h to avoid conversion warnings +- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] +- Improve inflateSync() documentation to note indeterminancy +- Add deflatePending() function to return the amount of pending output +- Correct the spelling of "specification" in FAQ [Randers-Pehrson] +- Add a check in configure for stdarg.h, use for gzprintf() +- Check that pointers fit in ints when gzprint() compiled old style +- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] +- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] +- Add debug records in assmebler code [Londer] +- Update RFC references to use http://tools.ietf.org/html/... [Li] +- Add --archs option, use of libtool to configure for Mac OS X [Borstel] + Changes in 1.2.5 (19 Apr 2010) - Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] - Default to libdir as sharedlibdir in configure [Nieder] - Update copyright dates on modified source files - Update trees.c to be able to generate modified trees.h - Exit configure for MinGW, suggesting win32/Makefile.gcc +- Check for NULL path in gz_open [Homurlu] Changes in 1.2.4.5 (18 Apr 2010) - Set sharedlibdir in configure [Torok] @@ -261,7 +525,7 @@ Changes in 1.2.3.4 (21 Dec 2009) - Clear bytes after deflate lookahead to avoid use of uninitialized data - Change a limit in inftrees.c to be more transparent to Coverity Prevent - Update win32/zlib.def with exported symbols from zlib.h -- Correct spelling error in zlib.h [Willem] +- Correct spelling errors in zlib.h [Willem, Sobrado] - Allow Z_BLOCK for deflate() to force a new block - Allow negative bits in inflatePrime() to delete existing bit buffer - Add Z_TREES flush option to inflate() to return at end of trees diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/README b/jdk/src/share/native/java/util/zip/zlib-1.2.8/README similarity index 87% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/README rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/README index d4219bf889f..5ca9d127eda 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/README +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/README @@ -1,22 +1,22 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.5 is a general purpose data compression library. All the code is +zlib 1.2.8 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). All functions of the compression library are documented in the file zlib.h (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file example.c which also tests that the library -is working correctly. Another example is given in the file minigzip.c. The -compression library itself is composed of all source files except example.c and -minigzip.c. +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. To compile all files and run the test program, follow the instructions given at the top of Makefile.in. In short "./configure; make test", and if that goes -well, "make install" should work for most flavors of Unix. For Windows, use one -of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use make_vms.com. Questions about zlib should be sent to , or to Gilles Vollant @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . -The changes made in version 1.2.5 are documented in the file ChangeLog. +The changes made in version 1.2.8 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -44,7 +44,7 @@ http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . A Python interface to zlib written by A.M. Kuchling is available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html . +http://docs.python.org/library/zlib.html . zlib is built into tcl: http://wiki.tcl.tk/4610 . @@ -84,7 +84,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2010 Jean-loup Gailly and Mark Adler + (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/compress.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/compress.c similarity index 98% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/compress.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/compress.c index 9d8713f9446..cdc51e08172 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/compress.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/compress.c @@ -53,7 +53,7 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) z_stream stream; int err; - stream.next_in = (Bytef*)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; #ifdef MAXSEG_64K /* Check for source > 64K on 16-bit machine: */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h similarity index 99% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h index 2383bdc847d..94df2aaf287 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h @@ -26,7 +26,7 @@ * Generated automatically by crc32.c */ -local const unsigned long FAR crc_table[TBLS][256] = +local const z_crc_t FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.c similarity index 91% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.c index 1dce5b0d055..5cc66c5e537 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.c @@ -23,7 +23,7 @@ */ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -61,7 +61,7 @@ * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt + * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -76,7 +76,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -179,6 +179,9 @@ local const config configuration_table[10] = { struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ #endif +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) + /* =========================================================================== * Update a hash value with the given input byte * IN assertion: all calls to to UPDATE_HASH are made with consecutive @@ -259,10 +262,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, strm->msg = Z_NULL; if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif #ifdef FASTEST if (level != 0) level = 1; @@ -317,7 +329,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } @@ -338,43 +350,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) uInt dictLength; { deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) return Z_STREAM_ERROR; - s = strm->state; - if (s->wrap) + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ - if (length < MIN_MATCH) return Z_OK; - if (length > s->w_size) { - length = s->w_size; - dictionary += dictLength - length; /* use the tail of the dictionary */ + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); } - if (hash_head) hash_head = 0; /* to make compiler happy */ + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; return Z_OK; } /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; @@ -404,11 +443,22 @@ int ZEXPORT deflateReset (strm) s->last_flush = Z_NO_FLUSH; _tr_init(s); - lm_init(s); return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + /* ========================================================================= */ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; @@ -420,15 +470,43 @@ int ZEXPORT deflateSetHeader (strm, head) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflatePrime (strm, bits, value) z_streamp strm; int bits; int value; { + deflate_state *s; + int put; + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); return Z_OK; } @@ -459,6 +537,8 @@ int ZEXPORT deflateParams(strm, level, strategy) strm->total_in != 0) { /* Flush the last buffer: */ err = deflate(strm, Z_BLOCK); + if (err == Z_BUF_ERROR && s->pending == 0) + err = Z_OK; } if (s->level != level) { s->level = level; @@ -586,19 +666,22 @@ local void putShortMSB (s, b) local void flush_pending(strm) z_streamp strm; { - unsigned len = strm->state->pending; + unsigned len; + deflate_state *s = strm->state; + _tr_flush_bits(s); + len = s->pending; if (len > strm->avail_out) len = strm->avail_out; if (len == 0) return; - zmemcpy(strm->next_out, strm->state->pending_out, len); + zmemcpy(strm->next_out, s->pending_out, len); strm->next_out += len; - strm->state->pending_out += len; + s->pending_out += len; strm->total_out += len; strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; } } @@ -825,7 +908,7 @@ int ZEXPORT deflate (strm, flush) * flushes. For repeated and useless calls with Z_FINISH, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ - } else if (strm->avail_in == 0 && flush <= old_flush && + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && flush != Z_FINISH) { ERR_RETURN(strm, Z_BUF_ERROR); } @@ -874,6 +957,7 @@ int ZEXPORT deflate (strm, flush) if (s->lookahead == 0) { s->strstart = 0; s->block_start = 0L; + s->insert = 0; } } } @@ -969,12 +1053,12 @@ int ZEXPORT deflateCopy (dest, source) ss = source->state; - zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); if (ds == Z_NULL) return Z_MEM_ERROR; dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); ds->strm = dest; ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); @@ -990,8 +1074,8 @@ int ZEXPORT deflateCopy (dest, source) } /* following zmemcpy do not work for 16-bit MSDOS */ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); @@ -1025,15 +1109,15 @@ local int read_buf(strm, buf, size) strm->avail_in -= len; + zmemcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); + strm->adler = adler32(strm->adler, buf, len); } #ifdef GZIP else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); + strm->adler = crc32(strm->adler, buf, len); } #endif - zmemcpy(buf, strm->next_in, len); strm->next_in += len; strm->total_in += len; @@ -1060,6 +1144,7 @@ local void lm_init (s) s->strstart = 0; s->block_start = 0L; s->lookahead = 0; + s->insert = 0; s->match_length = s->prev_length = MIN_MATCH-1; s->match_available = 0; s->ins_h = 0; @@ -1334,6 +1419,8 @@ local void fill_window(s) unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + do { more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); @@ -1386,7 +1473,7 @@ local void fill_window(s) #endif more += wsize; } - if (s->strm->avail_in == 0) return; + if (s->strm->avail_in == 0) break; /* If there was no sliding: * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && @@ -1405,12 +1492,24 @@ local void fill_window(s) s->lookahead += n; /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); #if MIN_MATCH != 3 Call UPDATE_HASH() MIN_MATCH-3 more times #endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } } /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. @@ -1451,6 +1550,9 @@ local void fill_window(s) s->high_water += init; } } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); } /* =========================================================================== @@ -1530,8 +1632,14 @@ local block_state deflate_stored(s, flush) FLUSH_BLOCK(s, 0); } } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if ((long)s->strstart > s->block_start) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1627,8 +1735,14 @@ local block_state deflate_fast(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #ifndef FASTEST @@ -1752,8 +1866,14 @@ local block_state deflate_slow(s, flush) _tr_tally_lit(s, s->window[s->strstart-1], bflush); s->match_available = 0; } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } #endif /* FASTEST */ @@ -1773,11 +1893,11 @@ local block_state deflate_rle(s, flush) for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. + * for the longest run, plus one for the unrolled loop. */ - if (s->lookahead < MAX_MATCH) { + if (s->lookahead <= MAX_MATCH) { fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { return need_more; } if (s->lookahead == 0) break; /* flush the current block */ @@ -1800,6 +1920,7 @@ local block_state deflate_rle(s, flush) if (s->match_length > s->lookahead) s->match_length = s->lookahead; } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); } /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -1820,8 +1941,14 @@ local block_state deflate_rle(s, flush) } if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } /* =========================================================================== @@ -1853,6 +1980,12 @@ local block_state deflate_huff(s, flush) s->strstart++; if (bflush) FLUSH_BLOCK(s, 0); } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.h similarity index 97% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.h index 652be480efd..8be47fa013b 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/deflate.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/deflate.h @@ -23,7 +23,7 @@ */ /* deflate.h -- internal compression state - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -72,6 +72,9 @@ #define MAX_BITS 15 /* All codes must not exceed MAX_BITS bits */ +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + #define INIT_STATE 42 #define EXTRA_STATE 69 #define NAME_STATE 73 @@ -125,7 +128,7 @@ typedef struct internal_state { int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ + Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ @@ -212,7 +215,7 @@ typedef struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ + /* Didn't use ct_data typedef below to suppress compiler warning */ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ @@ -268,7 +271,7 @@ typedef struct internal_state { ulg opt_len; /* bit length of current block with optimal trees */ ulg static_len; /* bit length of current block with static trees */ uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ + uInt insert; /* bytes at end of window left to insert */ #ifdef DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ @@ -318,6 +321,7 @@ void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, int last)); diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzclose.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzclose.c similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/gzclose.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/gzclose.c diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzguts.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzguts.h similarity index 68% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/gzguts.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/gzguts.h index d8fbf1e4c4b..5889f45c784 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzguts.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzguts.h @@ -23,7 +23,7 @@ */ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,7 +36,7 @@ # endif #endif -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL @@ -51,13 +51,80 @@ #endif #include +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99, yet still not supported by + Microsoft more than a decade later!), _snprintf does not guarantee null + termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ #ifdef _MSC_VER -# include -# define vsnprintf _vsnprintf +# define snprintf _snprintf #endif #ifndef local @@ -76,7 +143,7 @@ # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else -# ifdef STDC +# ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else @@ -92,7 +159,15 @@ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); #endif -/* default i/o buffer size -- double this for output when reading */ +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ @@ -108,23 +183,25 @@ /* internal gzip file state data structure */ typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ /* used for both reading and writing */ int mode; /* see gzip modes above */ int fd; /* file descriptor */ char *path; /* path or fd for error messages */ - z_off64_t pos; /* current position in uncompressed data */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ unsigned char *in; /* input buffer */ unsigned char *out; /* output buffer (double-sized when reading) */ - unsigned char *next; /* next output data to deliver or write */ + int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ - unsigned have; /* amount of output data unused at next */ - int eof; /* true if end of input file reached */ - z_off64_t start; /* where the gzip data started, for rewinding */ - z_off64_t raw; /* where the raw data started, for seeking */ int how; /* 0: get header, 1: copy, 2: decompress */ - int direct; /* true if last read direct, false if gzip */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ /* just for writing */ int level; /* compression level */ int strategy; /* compression strategy */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzlib.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzlib.c similarity index 74% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/gzlib.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/gzlib.c index 9a3db2efe0c..4dce9b96ef7 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzlib.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzlib.c @@ -22,22 +22,26 @@ * questions. */ -/* - * Copyright (C) 2004, 2010 Mark Adler +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" +#if defined(_WIN32) && !defined(__BORLANDC__) +# define LSEEK _lseeki64 +#else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 # define LSEEK lseek64 #else # define LSEEK lseek #endif +#endif /* Local functions */ local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const char *, int, const char *)); +local gzFile gz_open OF((const void *, int, const char *)); #if defined UNDER_CE @@ -95,28 +99,40 @@ char ZLIB_INTERNAL *gz_strwinerror (error) local void gz_reset(state) gz_statep state; { + state->x.have = 0; /* no output data available */ if (state->mode == GZ_READ) { /* for reading ... */ - state->have = 0; /* no output data available */ state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ state->how = LOOK; /* look for gzip header */ - state->direct = 1; /* default for empty file */ } state->seek = 0; /* no seek request pending */ gz_error(state, Z_OK, NULL); /* clear error */ - state->pos = 0; /* no uncompressed data yet */ + state->x.pos = 0; /* no uncompressed data yet */ state->strm.avail_in = 0; /* no input data yet */ } /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(path, fd, mode) - const char *path; + const void *path; int fd; const char *mode; { gz_statep state; + size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL) + return NULL; /* allocate gzFile structure to return */ - state = malloc(sizeof(gz_state)); + state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ @@ -127,6 +143,7 @@ local gzFile gz_open(path, fd, mode) state->mode = GZ_NONE; state->level = Z_DEFAULT_COMPRESSION; state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; while (*mode) { if (*mode >= '0' && *mode <= '9') state->level = *mode - '0'; @@ -148,6 +165,16 @@ local gzFile gz_open(path, fd, mode) return NULL; case 'b': /* ignore -- will request binary anyway */ break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif case 'f': state->strategy = Z_FILTERED; break; @@ -159,6 +186,10 @@ local gzFile gz_open(path, fd, mode) break; case 'F': state->strategy = Z_FIXED; + break; + case 'T': + state->direct = 1; + break; default: /* could consider as an error, but just ignore */ ; } @@ -171,30 +202,71 @@ local gzFile gz_open(path, fd, mode) return NULL; } + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + /* save the path name for error messages */ - state->path = malloc(strlen(path) + 1); +#ifdef _WIN32 + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (size_t)-1) + len = 0; + } + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } - strcpy(state->path, path); +#ifdef _WIN32 + if (fd == -2) + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + else +#endif +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(state->path, len + 1, "%s", (const char *)path); +#else + strcpy(state->path, path); +#endif - /* open the file with the appropriate mode (or just use fd) */ - state->fd = fd != -1 ? fd : - open(path, + /* compute the flags for open() */ + oflag = #ifdef O_LARGEFILE - O_LARGEFILE | + O_LARGEFILE | #endif #ifdef O_BINARY - O_BINARY | + O_BINARY | #endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | ( - state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))), - 0666); +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef _WIN32 + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); @@ -240,14 +312,28 @@ gzFile ZEXPORT gzdopen(fd, mode) char *path; /* identifier for error messages */ gzFile gz; - if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ +#else sprintf(path, "", fd); /* for debugging */ +#endif gz = gz_open(path, fd, mode); free(path); return gz; } +/* -- see zlib.h -- */ +#ifdef _WIN32 +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + /* -- see zlib.h -- */ int ZEXPORT gzbuffer(file, size) gzFile file; @@ -267,8 +353,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ - if (size == 0) - return -1; + if (size < 2) + size = 2; /* need two bytes to check magic header */ state->want = size; return 0; } @@ -285,7 +371,8 @@ int ZEXPORT gzrewind(file) state = (gz_statep)file; /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* back up and start over */ @@ -313,7 +400,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) return -1; /* check that there's no error */ - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; /* can only seek from start or relative to current position */ @@ -322,31 +409,32 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* normalize offset to a SEEK_CUR specification */ if (whence == SEEK_SET) - offset -= state->pos; + offset -= state->x.pos; else if (state->seek) offset += state->skip; state->seek = 0; /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && - state->pos + offset >= state->raw) { - ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); if (ret == -1) return -1; - state->have = 0; + state->x.have = 0; state->eof = 0; + state->past = 0; state->seek = 0; gz_error(state, Z_OK, NULL); state->strm.avail_in = 0; - state->pos += offset; - return state->pos; + state->x.pos += offset; + return state->x.pos; } /* calculate skip amount, rewinding if needed for back seek when reading */ if (offset < 0) { if (state->mode != GZ_READ) /* writing -- can't go backwards */ return -1; - offset += state->pos; + offset += state->x.pos; if (offset < 0) /* before start of file! */ return -1; if (gzrewind(file) == -1) /* rewind, then skip to offset */ @@ -355,11 +443,11 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* if reading, skip what's in output buffer (one less gzgetc() check) */ if (state->mode == GZ_READ) { - n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? - (unsigned)offset : state->have; - state->have -= n; - state->next += n; - state->pos += n; + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; offset -= n; } @@ -368,7 +456,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) state->seek = 1; state->skip = offset; } - return state->pos + offset; + return state->x.pos + offset; } /* -- see zlib.h -- */ @@ -397,7 +485,7 @@ z_off64_t ZEXPORT gztell64(file) return -1; /* return position */ - return state->pos + (state->seek ? state->skip : 0); + return state->x.pos + (state->seek ? state->skip : 0); } /* -- see zlib.h -- */ @@ -457,8 +545,7 @@ int ZEXPORT gzeof(file) return 0; /* return end-of-file state */ - return state->mode == GZ_READ ? - (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; + return state->mode == GZ_READ ? state->past : 0; } /* -- see zlib.h -- */ @@ -478,7 +565,8 @@ const char * ZEXPORT gzerror(file, errnum) /* return error information */ if (errnum != NULL) *errnum = state->err; - return state->msg == NULL ? "" : state->msg; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ @@ -495,8 +583,10 @@ void ZEXPORT gzclearerr(file) return; /* clear error and end-of-file */ - if (state->mode == GZ_READ) + if (state->mode == GZ_READ) { state->eof = 0; + state->past = 0; + } gz_error(state, Z_OK, NULL); } @@ -518,26 +608,33 @@ void ZLIB_INTERNAL gz_error(state, err, msg) state->msg = NULL; } + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + /* set error code, and if no message, then done */ state->err = err; if (msg == NULL) return; - /* for an out of memory error, save as static string */ - if (err == Z_MEM_ERROR) { - state->msg = (char *)msg; + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) return; - } /* construct error message with path */ - if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { state->err = Z_MEM_ERROR; - state->msg = (char *)"out of memory"; return; } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); +#endif return; } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzread.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzread.c similarity index 54% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/gzread.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/gzread.c index 15e85028cfd..cd87098b95a 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzread.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzread.c @@ -23,7 +23,7 @@ */ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -32,10 +32,9 @@ /* Local functions */ local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); local int gz_avail OF((gz_statep)); -local int gz_next4 OF((gz_statep, unsigned long *)); -local int gz_head OF((gz_statep)); +local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); -local int gz_make OF((gz_statep)); +local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from @@ -70,73 +69,54 @@ local int gz_load(state, buf, len, have) error, 0 otherwise. Note that the eof flag is set when the end of the input file is reached, even though there may be unused data in the buffer. Once that data has been used, no more attempts will be made to read the file. - gz_avail() assumes that strm->avail_in == 0. */ + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ local int gz_avail(state) gz_statep state; { + unsigned got; z_streamp strm = &(state->strm); - if (state->err != Z_OK) + if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { - if (gz_load(state, state->in, state->size, - (unsigned *)&(strm->avail_in)) == -1) + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) return -1; + strm->avail_in += got; strm->next_in = state->in; } return 0; } -/* Get next byte from input, or -1 if end or error. */ -#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \ - (strm->avail_in == 0 ? -1 : \ - (strm->avail_in--, *(strm->next_in)++))) - -/* Get a four-byte little-endian integer and return 0 on success and the value - in *ret. Otherwise -1 is returned and *ret is not modified. */ -local int gz_next4(state, ret) - gz_statep state; - unsigned long *ret; -{ - int ch; - unsigned long val; - z_streamp strm = &(state->strm); - - val = NEXT(); - val += (unsigned)NEXT() << 8; - val += (unsigned long)NEXT() << 16; - ch = NEXT(); - if (ch == -1) - return -1; - val += (unsigned long)ch << 24; - *ret = val; - return 0; -} - -/* Look for gzip header, set up for inflate or copy. state->have must be zero. +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. If this is the first time in, allocate required memory. state->how will be left unchanged if there is no more input data available, will be set to COPY if there is no gzip header and direct copying will be performed, or it will - be set to GZIP for decompression, and the gzip header will be skipped so - that the next available input data is the raw deflate stream. If direct - copying, then leftover input data from the input buffer will be copied to - the output buffer. In that case, all further file reads will be directly to - either the output buffer or a user buffer. If decompressing, the inflate - state and the check value will be initialized. gz_head() will return 0 on - success or -1 on failure. Failures may include read errors or gzip header - errors. */ -local int gz_head(state) + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(state) gz_statep state; { z_streamp strm = &(state->strm); - int flags; - unsigned len; /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ - state->in = malloc(state->want); - state->out = malloc(state->want << 1); + state->in = (unsigned char *)malloc(state->want); + state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { if (state->out != NULL) free(state->out); @@ -153,7 +133,7 @@ local int gz_head(state) state->strm.opaque = Z_NULL; state->strm.avail_in = 0; state->strm.next_in = Z_NULL; - if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */ + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ free(state->out); free(state->in); state->size = 0; @@ -162,83 +142,45 @@ local int gz_head(state) } } - /* get some data in the input buffer */ - if (strm->avail_in == 0) { + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { if (gz_avail(state) == -1) return -1; if (strm->avail_in == 0) return 0; } - /* look for the gzip magic header bytes 31 and 139 */ - if (strm->next_in[0] == 31) { - strm->avail_in--; - strm->next_in++; - if (strm->avail_in == 0 && gz_avail(state) == -1) - return -1; - if (strm->avail_in && strm->next_in[0] == 139) { - /* we have a gzip header, woo hoo! */ - strm->avail_in--; - strm->next_in++; - - /* skip rest of header */ - if (NEXT() != 8) { /* compression method */ - gz_error(state, Z_DATA_ERROR, "unknown compression method"); - return -1; - } - flags = NEXT(); - if (flags & 0xe0) { /* reserved flag bits */ - gz_error(state, Z_DATA_ERROR, "unknown header flags set"); - return -1; - } - NEXT(); /* modification time */ - NEXT(); - NEXT(); - NEXT(); - NEXT(); /* extra flags */ - NEXT(); /* operating system */ - if (flags & 4) { /* extra field */ - len = (unsigned)NEXT(); - len += (unsigned)NEXT() << 8; - while (len--) - if (NEXT() < 0) - break; - } - if (flags & 8) /* file name */ - while (NEXT() > 0) - ; - if (flags & 16) /* comment */ - while (NEXT() > 0) - ; - if (flags & 2) { /* header crc */ - NEXT(); - NEXT(); - } - /* an unexpected end of file is not checked for here -- it will be - noticed on the first request for uncompressed data */ - - /* set up for decompression */ - inflateReset(strm); - strm->adler = crc32(0L, Z_NULL, 0); - state->how = GZIP; - state->direct = 0; - return 0; - } - else { - /* not a gzip file -- save first byte (31) and fall to raw i/o */ - state->out[0] = 31; - state->have = 1; - } + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; } - /* doing raw i/o, save start of raw data for seeking, copy any leftover - input to output -- this assumes that the output buffer is larger than - the input buffer, which also assures space for gzungetc() */ - state->raw = state->pos; - state->next = state->out; + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; if (strm->avail_in) { - memcpy(state->next + state->have, strm->next_in, strm->avail_in); - state->have += strm->avail_in; + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; strm->avail_in = 0; } state->how = COPY; @@ -247,19 +189,15 @@ local int gz_head(state) } /* Decompress from input to the provided next_out and avail_out in the state. - If the end of the compressed data is reached, then verify the gzip trailer - check value and length (modulo 2^32). state->have and state->next are set - to point to the just decompressed data, and the crc is updated. If the - trailer is verified, state->how is reset to LOOK to look for the next gzip - stream or raw data, once state->have is depleted. Returns 0 on success, -1 - on failure. Failures may include invalid compressed data or a failed gzip - trailer verification. */ + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ local int gz_decomp(state) gz_statep state; { - int ret; + int ret = Z_OK; unsigned had; - unsigned long crc, len; z_streamp strm = &(state->strm); /* fill output buffer up to end of deflate stream */ @@ -269,15 +207,15 @@ local int gz_decomp(state) if (strm->avail_in == 0 && gz_avail(state) == -1) return -1; if (strm->avail_in == 0) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; } /* decompress and handle errors */ ret = inflate(strm, Z_NO_FLUSH); if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { gz_error(state, Z_STREAM_ERROR, - "internal error: inflate stream corrupt"); + "internal error: inflate stream corrupt"); return -1; } if (ret == Z_MEM_ERROR) { @@ -286,67 +224,55 @@ local int gz_decomp(state) } if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ gz_error(state, Z_DATA_ERROR, - strm->msg == NULL ? "compressed data error" : strm->msg); + strm->msg == NULL ? "compressed data error" : strm->msg); return -1; } } while (strm->avail_out && ret != Z_STREAM_END); - /* update available output and crc check value */ - state->have = had - strm->avail_out; - state->next = strm->next_out - state->have; - strm->adler = crc32(strm->adler, state->next, state->have); + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; - /* check gzip trailer if at end of deflate stream */ - if (ret == Z_STREAM_END) { - if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) { - gz_error(state, Z_DATA_ERROR, "unexpected end of file"); - return -1; - } - if (crc != strm->adler) { - gz_error(state, Z_DATA_ERROR, "incorrect data check"); - return -1; - } - if (len != (strm->total_out & 0xffffffffL)) { - gz_error(state, Z_DATA_ERROR, "incorrect length check"); - return -1; - } - state->how = LOOK; /* ready for next stream, once have is 0 (leave - state->direct unchanged to remember how) */ - } + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; /* good decompression */ return 0; } -/* Make data and put in the output buffer. Assumes that state->have == 0. +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. Data is either copied from the input file or decompressed from the input file depending on state->how. If state->how is LOOK, then a gzip header is - looked for (and skipped if found) to determine wither to copy or decompress. - Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY - or GZIP unless the end of the input file has been reached and all data has - been processed. */ -local int gz_make(state) + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(state) gz_statep state; { z_streamp strm = &(state->strm); - if (state->how == LOOK) { /* look for gzip header */ - if (gz_head(state) == -1) - return -1; - if (state->have) /* got some data from gz_head() */ + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; return 0; - } - if (state->how == COPY) { /* straight copy */ - if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1) - return -1; - state->next = state->out; - } - else if (state->how == GZIP) { /* decompress */ - strm->avail_out = state->size << 1; - strm->next_out = state->out; - if (gz_decomp(state) == -1) - return -1; - } + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); return 0; } @@ -360,12 +286,12 @@ local int gz_skip(state, len) /* skip over len bytes or reach end-of-file, whichever comes first */ while (len) /* skip over whatever is in output buffer */ - if (state->have) { - n = GT_OFF(state->have) || (z_off64_t)state->have > len ? - (unsigned)len : state->have; - state->have -= n; - state->next += n; - state->pos += n; + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; len -= n; } @@ -376,7 +302,7 @@ local int gz_skip(state, len) /* need more data to skip -- load up output buffer */ else { /* get more output, looking for header if required */ - if (gz_make(state) == -1) + if (gz_fetch(state) == -1) return -1; } return 0; @@ -398,14 +324,15 @@ int ZEXPORT gzread(file, buf, len) state = (gz_statep)file; strm = &(state->strm); - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return -1; } @@ -424,49 +351,51 @@ int ZEXPORT gzread(file, buf, len) got = 0; do { /* first just try copying data from the output buffer */ - if (state->have) { - n = state->have > len ? len : state->have; - memcpy(buf, state->next, n); - state->next += n; - state->have -= n; + if (state->x.have) { + n = state->x.have > len ? len : state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) + else if (state->eof && strm->avail_in == 0) { + state->past = 1; /* tried to read past end */ break; + } /* need output data -- for small len or new stream load up our output buffer */ else if (state->how == LOOK || len < (state->size << 1)) { /* get more output, looking for header if required */ - if (gz_make(state) == -1) + if (gz_fetch(state) == -1) return -1; - continue; /* no progress yet -- go back to memcpy() above */ + continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ - if (gz_load(state, buf, len, &n) == -1) + if (gz_load(state, (unsigned char *)buf, len, &n) == -1) return -1; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ strm->avail_out = len; - strm->next_out = buf; + strm->next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) return -1; - n = state->have; - state->have = 0; + n = state->x.have; + state->x.have = 0; } /* update progress */ len -= n; buf = (char *)buf + n; got += n; - state->pos += n; + state->x.pos += n; } while (len); /* return number of bytes read into user buffer (will fit in int) */ @@ -474,6 +403,11 @@ int ZEXPORT gzread(file, buf, len) } /* -- see zlib.h -- */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif int ZEXPORT gzgetc(file) gzFile file; { @@ -486,15 +420,16 @@ int ZEXPORT gzgetc(file) return -1; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* try output buffer (no need to check for skip request) */ - if (state->have) { - state->have--; - state->pos++; - return *(state->next)++; + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; } /* nothing there -- try gzread() */ @@ -502,6 +437,12 @@ int ZEXPORT gzgetc(file) return ret < 1 ? -1 : buf[0]; } +int ZEXPORT gzgetc_(file) +gzFile file; +{ + return gzgetc(file); +} + /* -- see zlib.h -- */ int ZEXPORT gzungetc(c, file) int c; @@ -514,8 +455,9 @@ int ZEXPORT gzungetc(c, file) return -1; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; /* process a skip request */ @@ -530,32 +472,34 @@ int ZEXPORT gzungetc(c, file) return -1; /* if output buffer empty, put byte at end (allows more pushing) */ - if (state->have == 0) { - state->have = 1; - state->next = state->out + (state->size << 1) - 1; - state->next[0] = c; - state->pos--; + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; return c; } /* if no room, give up (must have already done a gzungetc()) */ - if (state->have == (state->size << 1)) { - gz_error(state, Z_BUF_ERROR, "out of room to push characters"); + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); return -1; } /* slide output data if needed and insert byte before existing data */ - if (state->next == state->out) { - unsigned char *src = state->out + state->have; + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; unsigned char *dest = state->out + (state->size << 1); while (src > state->out) *--dest = *--src; - state->next = dest; + state->x.next = dest; } - state->have++; - state->next--; - state->next[0] = c; - state->pos--; + state->x.have++; + state->x.next--; + state->x.next[0] = c; + state->x.pos--; + state->past = 0; return c; } @@ -575,8 +519,9 @@ char * ZEXPORT gzgets(file, buf, len) return NULL; state = (gz_statep)file; - /* check that we're reading and that there's no error */ - if (state->mode != GZ_READ || state->err != Z_OK) + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) return NULL; /* process a skip request */ @@ -593,32 +538,31 @@ char * ZEXPORT gzgets(file, buf, len) left = (unsigned)len - 1; if (left) do { /* assure that something is in the output buffer */ - if (state->have == 0) { - if (gz_make(state) == -1) - return NULL; /* error */ - if (state->have == 0) { /* end of file */ - if (buf == str) /* got bupkus */ - return NULL; - break; /* got something -- return it */ - } + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ } /* look for end-of-line in current output buffer */ - n = state->have > left ? left : state->have; - eol = memchr(state->next, '\n', n); + n = state->x.have > left ? left : state->x.have; + eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) - n = (unsigned)(eol - state->next) + 1; + n = (unsigned)(eol - state->x.next) + 1; /* copy through end-of-line, or remainder if not found */ - memcpy(buf, state->next, n); - state->have -= n; - state->next += n; - state->pos += n; + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; left -= n; buf += n; } while (left && eol == NULL); - /* found end-of-line or out of space -- terminate string and return it */ + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; buf[0] = 0; return str; } @@ -634,16 +578,12 @@ int ZEXPORT gzdirect(file) return 0; state = (gz_statep)file; - /* check that we're reading */ - if (state->mode != GZ_READ) - return 0; - /* if the state is not known, but we can find out, then do so (this is mainly for right after a gzopen() or gzdopen()) */ - if (state->how == LOOK && state->have == 0) - (void)gz_head(state); + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); - /* return 1 if reading direct, 0 if decompressing a gzip stream */ + /* return 1 if transparent, 0 if processing a gzip stream */ return state->direct; } @@ -651,7 +591,7 @@ int ZEXPORT gzdirect(file) int ZEXPORT gzclose_r(file) gzFile file; { - int ret; + int ret, err; gz_statep state; /* get internal structure */ @@ -669,9 +609,10 @@ int ZEXPORT gzclose_r(file) free(state->out); free(state->in); } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; gz_error(state, Z_OK, NULL); free(state->path); ret = close(state->fd); free(state); - return ret ? Z_ERRNO : Z_OK; + return ret ? Z_ERRNO : err; } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzwrite.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzwrite.c similarity index 75% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/gzwrite.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/gzwrite.c index bff643e0667..1955cf763b4 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/gzwrite.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/gzwrite.c @@ -23,7 +23,7 @@ */ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -42,44 +42,55 @@ local int gz_init(state) int ret; z_streamp strm = &(state->strm); - /* allocate input and output buffers */ - state->in = malloc(state->want); - state->out = malloc(state->want); - if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + /* allocate input buffer */ + state->in = (unsigned char *)malloc(state->want); + if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } - /* allocate deflate memory, set up for gzip compression */ - strm->zalloc = Z_NULL; - strm->zfree = Z_NULL; - strm->opaque = Z_NULL; - ret = deflateInit2(strm, state->level, Z_DEFLATED, - 15 + 16, 8, state->strategy); - if (ret != Z_OK) { - free(state->in); - gz_error(state, Z_MEM_ERROR, "out of memory"); - return -1; + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = (unsigned char *)malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } } /* mark state as initialized */ state->size = state->want; - /* initialize write buffer */ - strm->avail_out = state->size; - strm->next_out = state->out; - state->next = strm->next_out; + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } return 0; } /* Compress whatever is at avail_in and next_in and write to the output file. Return -1 if there is an error writing to the output file, otherwise 0. flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. */ + then the deflate() state is reset to start a new gzip stream. If gz->direct + is true, then simply write to the output file without compressing, and + ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; @@ -92,6 +103,17 @@ local int gz_comp(state, flush) if (state->size == 0 && gz_init(state) == -1) return -1; + /* write directly if requested */ + if (state->direct) { + got = write(state->fd, strm->next_in, strm->avail_in); + if (got < 0 || (unsigned)got != strm->avail_in) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in = 0; + return 0; + } + /* run deflate() on provided input until it produces no more output */ ret = Z_OK; do { @@ -99,8 +121,8 @@ local int gz_comp(state, flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->next); - if (have && ((got = write(state->fd, state->next, have)) < 0 || + have = (unsigned)(strm->next_out - state->x.next); + if (have && ((got = write(state->fd, state->x.next, have)) < 0 || (unsigned)got != have)) { gz_error(state, Z_ERRNO, zstrerror()); return -1; @@ -109,7 +131,7 @@ local int gz_comp(state, flush) strm->avail_out = state->size; strm->next_out = state->out; } - state->next = strm->next_out; + state->x.next = strm->next_out; } /* compress */ @@ -155,7 +177,7 @@ local int gz_zero(state, len) } strm->avail_in = n; strm->next_in = state->in; - state->pos += n; + state->x.pos += n; if (gz_comp(state, Z_NO_FLUSH) == -1) return -1; len -= n; @@ -170,7 +192,6 @@ int ZEXPORT gzwrite(file, buf, len) unsigned len; { unsigned put = len; - unsigned n; gz_statep state; z_streamp strm; @@ -187,7 +208,7 @@ int ZEXPORT gzwrite(file, buf, len) /* since an int is returned, make sure len fits in one, otherwise return with an error (this avoids the flaw in the interface) */ if ((int)len < 0) { - gz_error(state, Z_BUF_ERROR, "requested length does not fit in int"); + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); return 0; } @@ -210,16 +231,19 @@ int ZEXPORT gzwrite(file, buf, len) if (len < state->size) { /* copy to input buffer, compress when full */ do { + unsigned have, copy; + if (strm->avail_in == 0) strm->next_in = state->in; - n = state->size - strm->avail_in; - if (n > len) - n = len; - memcpy(strm->next_in + strm->avail_in, buf, n); - strm->avail_in += n; - state->pos += n; - buf = (char *)buf + n; - len -= n; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + copy = state->size - have; + if (copy > len) + copy = len; + memcpy(state->in + have, buf, copy); + strm->avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); @@ -231,8 +255,8 @@ int ZEXPORT gzwrite(file, buf, len) /* directly compress user buffer to file */ strm->avail_in = len; - strm->next_in = (voidp)buf; - state->pos += len; + strm->next_in = (z_const Bytef *)buf; + state->x.pos += len; if (gz_comp(state, Z_NO_FLUSH) == -1) return 0; } @@ -246,6 +270,7 @@ int ZEXPORT gzputc(file, c) gzFile file; int c; { + unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; @@ -269,19 +294,23 @@ int ZEXPORT gzputc(file, c) /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ - if (strm->avail_in < state->size) { + if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; - strm->next_in[strm->avail_in++] = c; - state->pos++; - return c; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } } /* no room in buffer or not initialized, use gz_write() */ buf[0] = c; if (gzwrite(file, buf, 1) != 1) return -1; - return c; + return c & 0xff; } /* -- see zlib.h -- */ @@ -298,16 +327,15 @@ int ZEXPORT gzputs(file, str) return ret == 0 && len != 0 ? -1 : ret; } -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { int size, len; gz_statep state; z_streamp strm; - va_list va; /* get internal structure */ if (file == NULL) @@ -337,25 +365,20 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) /* do the printf() into the input buffer, put length in len */ size = (int)(state->size); state->in[size - 1] = 0; - va_start(va, format); #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf(state->in, format, va); - va_end(va); + (void)vsprintf((char *)(state->in), format, va); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else - len = vsprintf(state->in, format, va); - va_end(va); + len = vsprintf((char *)(state->in), format, va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf(state->in, size, format, va); - va_end(va); - len = strlen(state->in); + (void)vsnprintf((char *)(state->in), size, format, va); + len = strlen((char *)(state->in)); # else len = vsnprintf((char *)(state->in), size, format, va); - va_end(va); # endif #endif @@ -366,11 +389,22 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; - state->pos += len; + state->x.pos += len; return len; } -#else /* !STDC */ +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) +{ + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + +#else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, @@ -390,6 +424,10 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, state = (gz_statep)file; strm = &(state->strm); + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return 0; + /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) return 0; @@ -414,22 +452,23 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, state->in[size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, + sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) if (state->in[len] == 0) break; # else - len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, + snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(state->in); + len = strlen((char *)(state->in)); # else - len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, + a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, + a19, a20); # endif #endif @@ -440,7 +479,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, /* update buffer and position, defer compression until needed */ strm->avail_in = (unsigned)len; strm->next_in = state->in; - state->pos += len; + state->x.pos += len; return len; } @@ -524,7 +563,7 @@ int ZEXPORT gzsetparams(file, level, strategy) int ZEXPORT gzclose_w(file) gzFile file; { - int ret = 0; + int ret = Z_OK; gz_statep state; /* get internal structure */ @@ -539,17 +578,24 @@ int ZEXPORT gzclose_w(file) /* check for seek request */ if (state->seek) { state->seek = 0; - ret += gz_zero(state, state->skip); + if (gz_zero(state, state->skip) == -1) + ret = state->err; } /* flush, free memory, and close file */ - ret += gz_comp(state, Z_FINISH); - (void)deflateEnd(&(state->strm)); - free(state->out); - free(state->in); + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (state->size) { + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + } gz_error(state, Z_OK, NULL); free(state->path); - ret += close(state->fd); + if (close(state->fd) == -1) + ret = Z_ERRNO; free(state); - return ret ? Z_ERRNO : Z_OK; + return ret; } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/infback.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/infback.c similarity index 98% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/infback.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/infback.c index 783274e4c26..7001b4bfe62 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/infback.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/infback.c @@ -23,7 +23,7 @@ */ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -66,10 +66,19 @@ int stream_size; return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *)ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -270,7 +279,7 @@ out_func out; void FAR *out_desc; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -418,7 +427,6 @@ void FAR *out_desc; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inffast.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inffast.c similarity index 98% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inffast.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inffast.c index e6a05723be4..4b9cddd7040 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inffast.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inffast.c @@ -23,7 +23,7 @@ */ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010 Mark Adler + * Copyright (C) 1995-2008, 2010, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -93,8 +93,8 @@ z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inffast.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inffast.h similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inffast.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inffast.h diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inffixed.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inffixed.h similarity index 97% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inffixed.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inffixed.h index f44fee25112..f0a4ef1c4e8 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inffixed.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inffixed.h @@ -26,9 +26,9 @@ * Generated automatically by makefixed(). */ - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. */ static const code lenfix[512] = { diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inflate.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inflate.c similarity index 94% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inflate.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inflate.c index 6e172217b3f..b159c1543a6 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inflate.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inflate.c @@ -23,7 +23,7 @@ */ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -117,14 +117,15 @@ /* function prototypes */ local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); -int ZEXPORT inflateReset(strm) +int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; @@ -133,15 +134,13 @@ z_streamp strm; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; state->mode = HEAD; state->last = 0; state->havedict = 0; state->dmax = 32768U; state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -151,6 +150,19 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + int ZEXPORT inflateReset2(strm, windowBits) z_streamp strm; int windowBits; @@ -204,10 +216,19 @@ int stream_size; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else strm->zalloc = zcalloc; strm->opaque = (voidpf)0; +#endif } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif state = (struct inflate_state FAR *) ZALLOC(strm, 1, sizeof(struct inflate_state)); if (state == Z_NULL) return Z_MEM_ERROR; @@ -345,8 +366,8 @@ void makefixed() low = 0; for (;;) { if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); if (++low == size) break; putchar(','); } @@ -379,12 +400,13 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, out) +local int updatewindow(strm, end, copy) z_streamp strm; -unsigned out; +const Bytef *end; +unsigned copy; { struct inflate_state FAR *state; - unsigned copy, dist; + unsigned dist; state = (struct inflate_state FAR *)strm->state; @@ -404,19 +426,18 @@ unsigned out; } /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); + zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } @@ -523,11 +544,6 @@ unsigned out; bits -= bits & 7; \ } while (0) -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is @@ -615,7 +631,7 @@ z_streamp strm; int flush; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -821,7 +837,7 @@ int flush; #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); + strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: @@ -929,7 +945,7 @@ int flush; while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); @@ -949,7 +965,6 @@ int flush; PULLBYTE(); } if (here.val < 16) { - NEEDBITS(here.bits); DROPBITS(here.bits); state->lens[state->have++] = here.val; } @@ -1004,7 +1019,7 @@ int flush; values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); @@ -1013,7 +1028,7 @@ int flush; state->mode = BAD; break; } - state->distcode = (code const FAR *)(state->next); + state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); @@ -1194,7 +1209,7 @@ int flush; #ifdef GUNZIP state->flags ? hold : #endif - REVERSE(hold)) != state->check) { + ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; @@ -1238,8 +1253,9 @@ int flush; */ inf_leave: RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1273,13 +1289,37 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; - unsigned long id; + unsigned long dictid; + int ret; /* check state */ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; @@ -1287,29 +1327,21 @@ uInt dictLength; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; - /* check for correct dictionary id */ + /* check for correct dictionary identifier */ if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) return Z_DATA_ERROR; } - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { state->mode = MEM; return Z_MEM_ERROR; } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; @@ -1345,7 +1377,7 @@ gz_headerp head; */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; -unsigned char FAR *buf; +const unsigned char FAR *buf; unsigned len; { unsigned got; @@ -1457,8 +1489,8 @@ z_streamp source; } /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inflate.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inflate.h similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inflate.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inflate.h diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inftrees.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inftrees.c similarity index 89% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inftrees.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inftrees.c index 9842631ccdf..c4b0bf2dd4a 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inftrees.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inftrees.c @@ -23,7 +23,7 @@ */ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2010 Mark Adler + * Copyright (C) 1995-2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -33,7 +33,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; + " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -86,7 +86,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -232,8 +232,8 @@ unsigned short FAR *work; mask = used - 1; /* mask for comparing low */ /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ @@ -301,8 +301,8 @@ unsigned short FAR *work; /* check for enough space */ used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ @@ -313,38 +313,14 @@ unsigned short FAR *work; } } - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - here.op = (unsigned char)64; /* invalid code marker */ - here.bits = (unsigned char)(len - drop); - here.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - here.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = here; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; } /* set return parameters */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/inftrees.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/inftrees.h similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/inftrees.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/inftrees.h diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/patches/ChangeLog_java b/jdk/src/share/native/java/util/zip/zlib-1.2.8/patches/ChangeLog_java similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/patches/ChangeLog_java rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/patches/ChangeLog_java diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/trees.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/trees.c similarity index 96% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/trees.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/trees.c index 04da4d709f3..e4ecffea093 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/trees.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/trees.c @@ -23,7 +23,7 @@ */ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2010 Jean-loup Gailly + * Copyright (C) 1995-2012 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -98,11 +98,6 @@ local const uch bl_order[BL_CODES] * probability, to avoid transmitting the lengths for unused bit length codes. */ -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - /* =========================================================================== * Local data. These are initialized only once. */ @@ -175,8 +170,8 @@ local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); local int build_bl_tree OF((deflate_state *s)); local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); @@ -423,7 +418,6 @@ void ZLIB_INTERNAL _tr_init(s) s->bi_buf = 0; s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ #ifdef DEBUG s->compressed_len = 0L; s->bits_sent = 0L; @@ -906,16 +900,18 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + /* =========================================================================== * Send one empty static block to give enough lookahead for inflate. * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. */ void ZLIB_INTERNAL _tr_align(s) deflate_state *s; @@ -926,20 +922,6 @@ void ZLIB_INTERNAL _tr_align(s) s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; } /* =========================================================================== @@ -1014,7 +996,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { #endif send_bits(s, (STATIC_TREES<<1)+last, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); #ifdef DEBUG s->compressed_len += 3 + s->static_len; #endif @@ -1022,7 +1005,8 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif @@ -1099,8 +1083,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc) */ local void compress_block(s, ltree, dtree) deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ @@ -1142,7 +1126,6 @@ local void compress_block(s, ltree, dtree) } while (lx < s->last_lit); send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; } /* =========================================================================== @@ -1250,7 +1233,6 @@ local void copy_block(s, buf, len, header) int header; /* true if block header must be written */ { bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ if (header) { put_short(s, (ush)len); diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/trees.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/trees.h similarity index 100% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/trees.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/trees.h diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/uncompr.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/uncompr.c similarity index 97% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/uncompr.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/uncompr.c index e71d018f8d0..1bcf06feeb0 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/uncompr.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/uncompr.c @@ -54,7 +54,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen) z_stream stream; int err; - stream.next_in = (Bytef*)source; + stream.next_in = (z_const Bytef *)source; stream.avail_in = (uInt)sourceLen; /* Check for source > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; @@ -76,7 +76,7 @@ int ZEXPORT uncompress (dest, destLen, source, sourceLen) return Z_DATA_ERROR; return err; } - *destLen = (uLong)stream.total_out; + *destLen = stream.total_out; err = inflateEnd(&stream); return err; diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zadler32.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zadler32.c similarity index 78% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zadler32.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zadler32.c index c4465e1d6ed..a3108315221 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zadler32.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zadler32.c @@ -23,7 +23,7 @@ */ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2007 Mark Adler + * Copyright (C) 1995-2011 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -33,9 +33,9 @@ #define local static -local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521UL /* largest prime smaller than 65536 */ +#define BASE 65521 /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -45,39 +45,44 @@ local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO16(buf) DO8(buf,0); DO8(buf,8); -/* use NO_DIVIDE if your processor does not do division in hardware */ +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ #ifdef NO_DIVIDE -# define MOD(a) \ +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ if (a >= BASE) a -= BASE; \ } while (0) -# define MOD4(a) \ +# define MOD(a) \ do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ if (a >= BASE) a -= BASE; \ } while (0) #else # define MOD(a) a %= BASE -# define MOD4(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE #endif /* ========================================================================= */ @@ -116,7 +121,7 @@ uLong ZEXPORT adler32(adler, buf, len) } if (adler >= BASE) adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ + MOD28(sum2); /* only added so many BASE's */ return adler | (sum2 << 16); } @@ -161,8 +166,13 @@ local uLong adler32_combine_(adler1, adler2, len2) unsigned long sum2; unsigned rem; + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; sum1 = adler1 & 0xffff; sum2 = rem * sum1; MOD(sum2); diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zconf.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zconf.h similarity index 74% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zconf.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zconf.h index 78f162cfd6a..c7edbed7d12 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zconf.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zconf.h @@ -23,7 +23,7 @@ */ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -42,11 +42,13 @@ * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET /* all linked symbols */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block @@ -54,9 +56,11 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 @@ -67,44 +71,53 @@ # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzvprintf z_gzvprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd @@ -119,16 +132,22 @@ # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateSetDictionary z_inflateSetDictionary +# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine +# define inflateResetKeep z_inflateResetKeep # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table -# define uncompress z_uncompress +# ifndef Z_SOLO +# define uncompress z_uncompress +# endif # define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion @@ -138,7 +157,9 @@ # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func -# define gzFile z_gzFile +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func @@ -224,6 +245,12 @@ # endif #endif +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + /* Some Mac compilers merge all .h files incorrectly: */ #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) # define NO_DUMMY_DECL @@ -270,6 +297,14 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have @@ -360,6 +395,7 @@ typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ + #ifdef _LP64 typedef unsigned int uLong; /* 32 bits or more */ #else @@ -387,12 +423,47 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + #ifdef STDC -# include /* for off_t */ +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and @@ -401,21 +472,38 @@ typedef uLong FAR uLongf; * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ -#if -_LARGEFILE64_SOURCE - -1 == 1 +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif # endif #endif -#ifndef SEEK_SET +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ @@ -425,18 +513,14 @@ typedef uLong FAR uLongf; # define z_off_t long #endif -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif #endif /* MVS linker does not support external names larger than 8 bytes */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zcrc32.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zcrc32.c similarity index 87% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zcrc32.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zcrc32.c index 0eb5b64f110..0fe90df9799 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zcrc32.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zcrc32.c @@ -23,7 +23,7 @@ */ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -41,6 +41,8 @@ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should first call get_crc_table() to initialize the tables before allowing more than one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. */ #ifdef MAKECRCH @@ -54,31 +56,11 @@ #define local static -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - /* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif #ifdef BYFOUR -# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, const unsigned char FAR *, unsigned)); local unsigned long crc32_big OF((unsigned long, @@ -92,16 +74,16 @@ local unsigned long gf2_matrix_times OF((unsigned long *mat, unsigned long vec)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); -local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; +local z_crc_t FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); + local void write_table OF((FILE *, const z_crc_t FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: @@ -131,9 +113,9 @@ local void make_crc_table OF((void)); */ local void make_crc_table() { - unsigned long c; + z_crc_t c; int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ + z_crc_t poly; /* polynomial exclusive-or pattern */ /* terms of polynomial defining this crc (except x^32): */ static volatile int first = 1; /* flag to limit concurrent making */ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; @@ -145,13 +127,13 @@ local void make_crc_table() first = 0; /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { - c = (unsigned long)n; + c = (z_crc_t)n; for (k = 0; k < 8; k++) c = c & 1 ? poly ^ (c >> 1) : c >> 1; crc_table[0][n] = c; @@ -162,11 +144,11 @@ local void make_crc_table() and then the byte reversal of those as well as the first table */ for (n = 0; n < 256; n++) { c = crc_table[0][n]; - crc_table[4][n] = REV(c); + crc_table[4][n] = ZSWAP32(c); for (k = 1; k < 4; k++) { c = crc_table[0][c & 0xff] ^ (c >> 8); crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); + crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ @@ -188,7 +170,7 @@ local void make_crc_table() if (out == NULL) return; fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); + fprintf(out, "local const z_crc_t FAR "); fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); write_table(out, crc_table[0]); # ifdef BYFOUR @@ -208,12 +190,13 @@ local void make_crc_table() #ifdef MAKECRCH local void write_table(out, table) FILE *out; - const unsigned long FAR *table; + const z_crc_t FAR *table; { int n; for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); } #endif /* MAKECRCH */ @@ -228,13 +211,13 @@ local void write_table(out, table) /* ========================================================================= * This function can be used by asm versions of crc32() */ -const unsigned long FAR * ZEXPORT get_crc_table() +const z_crc_t FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const z_crc_t FAR *)crc_table; } /* ========================================================================= */ @@ -256,7 +239,7 @@ uLong ZEXPORT crc32(crc, buf, len) #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) @@ -290,17 +273,17 @@ local unsigned long crc32_little(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = (u4)crc; + c = (z_crc_t)crc; c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; @@ -330,17 +313,17 @@ local unsigned long crc32_big(crc, buf, len) const unsigned char FAR *buf; unsigned len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = REV((u4)crc); + c = ZSWAP32((z_crc_t)crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } - buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; buf4--; while (len >= 32) { DOBIG32; @@ -357,7 +340,7 @@ local unsigned long crc32_big(crc, buf, len) c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); } while (--len); c = ~c; - return (unsigned long)(REV(c)); + return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zlib.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zlib.h similarity index 84% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zlib.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zlib.h index b3617e58bc7..8779cadf207 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zlib.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zlib.h @@ -23,9 +23,9 @@ */ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 + version 1.2.8, April 28th, 2013 - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -48,8 +48,8 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H @@ -61,11 +61,11 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 +#define ZLIB_VERSION "1.2.8" +#define ZLIB_VERNUM 0x1280 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_REVISION 8 #define ZLIB_VER_SUBREVISION 0 /* @@ -107,15 +107,15 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ + z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ + uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte should be put there */ uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ + uLong total_out; /* total number of bytes output so far */ - char *msg; /* last error message, NULL if no error */ + z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ @@ -351,8 +351,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); Z_FINISH can be used immediately after deflateInit if all the compression is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. + value returned by deflateBound (see below). Then deflate is guaranteed to + return Z_STREAM_END. If not enough output space is provided, deflate will + not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the adler32 checksum of all input read so far (that is, total_in bytes). @@ -475,23 +476,29 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, + strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed adler32 checksum is equal to that saved by the compressor and returns Z_STREAM_END @@ -502,7 +509,9 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); initializing with inflateInit2(). Any information contained in the gzip header is not retained, so applications that need that information should instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. + perform their own processing of the gzip header and trailer. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + producted so far. The CRC-32 is checked against the gzip trailer. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has @@ -604,10 +613,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly @@ -634,8 +648,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, @@ -712,9 +726,29 @@ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. */ +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); @@ -727,8 +761,9 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, than or equal to 16, and that many of the least significant bits of value will be inserted in the output. - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, @@ -814,10 +849,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the adler32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -827,19 +863,38 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflate(). */ +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, @@ -986,12 +1041,13 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, @@ -999,11 +1055,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. @@ -1112,6 +1169,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 27-31: 0 (reserved) */ +#ifndef Z_SOLO /* utility functions */ @@ -1173,10 +1231,11 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. */ - /* gzip file access functions */ /* @@ -1186,7 +1245,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, wrapper, documented in RFC 1952, wrapped around a deflate stream. */ -typedef voidp gzFile; /* opaque gzip file descriptor */ +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); @@ -1196,13 +1255,28 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was @@ -1221,7 +1295,11 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not @@ -1259,14 +1337,26 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. @@ -1280,7 +1370,7 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of @@ -1325,7 +1415,10 @@ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); @@ -1421,9 +1514,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. + (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. @@ -1432,6 +1523,13 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); @@ -1443,7 +1541,8 @@ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); @@ -1481,6 +1580,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); file that is being written concurrently. */ +#endif /* !Z_SOLO */ /* checksum functions */ @@ -1516,16 +1616,17 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. Usage example: @@ -1568,17 +1669,42 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); #define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) #define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) #define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) + ZLIB_VERSION, (int)sizeof(z_stream)) + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) +#endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if @@ -1586,7 +1712,7 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +#ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); @@ -1595,14 +1721,23 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); #endif -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); @@ -1619,6 +1754,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); #endif +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + /* hack for buggy compilers */ #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; @@ -1627,8 +1769,21 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const unsigned long FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if defined(_WIN32) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif #ifdef __cplusplus } diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.c b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.c similarity index 95% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.c rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.c index 041aa973179..e54347610c8 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.c +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.c @@ -23,19 +23,22 @@ */ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif #ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ #endif -const char * const z_errmsg[10] = { +z_const char * const z_errmsg[10] = { "need dictionary", /* Z_NEED_DICT 2 */ "stream end", /* Z_STREAM_END 1 */ "", /* Z_OK 0 */ @@ -109,27 +112,27 @@ uLong ZEXPORT zlibCompileFlags() #ifdef FASTEST flags += 1L << 21; #endif -#ifdef STDC +#if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifdef NO_vsnprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_vsprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_vsnprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #else - flags += 1L << 24; + flags += 1L << 24; # ifdef NO_snprintf - flags += 1L << 25; + flags += 1L << 25; # ifdef HAS_sprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # else # ifdef HAS_snprintf_void - flags += 1L << 26; + flags += 1L << 26; # endif # endif #endif @@ -205,6 +208,7 @@ void ZLIB_INTERNAL zmemzero(dest, len) } #endif +#ifndef Z_SOLO #ifdef SYS16BIT @@ -340,3 +344,5 @@ void ZLIB_INTERNAL zcfree (opaque, ptr) } #endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.h b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.h similarity index 76% rename from jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.h rename to jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.h index 1c4e8d38fe5..b82b14d4a5e 100644 --- a/jdk/src/share/native/java/util/zip/zlib-1.2.5/zutil.h +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.8/zutil.h @@ -23,7 +23,7 @@ */ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. + * Copyright (C) 1995-2013 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -37,7 +37,7 @@ #ifndef ZUTIL_H #define ZUTIL_H -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL @@ -45,7 +45,7 @@ #include "zlib.h" -#ifdef STDC +#if defined(STDC) && !defined(Z_SOLO) # if !(defined(_WIN32_WCE) && defined(_MSC_VER)) # include # endif @@ -53,6 +53,10 @@ # include #endif +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + #ifndef local # define local static #endif @@ -64,13 +68,13 @@ typedef unsigned short ush; typedef ush FAR ushf; typedef unsigned long ulg; -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* (size given to avoid silly warnings with Visual C++) */ #define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] #define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) + return (strm->msg = ERR_MSG(err), (err)) /* To be used only when the state is known to be valid */ /* common constants */ @@ -102,16 +106,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) # define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include # endif -# else /* MSC or DJGPP */ -# include # endif #endif @@ -131,18 +137,20 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #ifdef OS2 # define OS_CODE 0x06 -# ifdef M_I86 +# if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) # define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif # endif # endif #endif @@ -177,14 +185,15 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#if defined(__BORLANDC__) +#if defined(__BORLANDC__) && !defined(MSDOS) #pragma warn -8004 #pragma warn -8008 #pragma warn -8066 #endif /* provide prototypes for these when building zlib without LFS */ -#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); #endif @@ -201,42 +210,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* functions */ -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) -# define vsnprintf _vsnprintf -# endif -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) +#if defined(pyr) || defined(Z_SOLO) # define NO_MEMCPY #endif #if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) @@ -285,14 +259,19 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # define Tracecv(c,x) #endif - -voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, - unsigned size)); -void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif #define ZALLOC(strm, items, size) \ (*((strm)->zalloc))((strm)->opaque, (items), (size)) #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + #endif /* ZUTIL_H */ diff --git a/jdk/src/share/native/sun/security/smartcardio/pcsc.c b/jdk/src/share/native/sun/security/smartcardio/pcsc.c index ab30e138120..b837234761d 100644 --- a/jdk/src/share/native/sun/security/smartcardio/pcsc.c +++ b/jdk/src/share/native/sun/security/smartcardio/pcsc.c @@ -125,7 +125,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardEstablishContext jobjectArray pcsc_multi2jstring(JNIEnv *env, char *spec) { jobjectArray result; jclass stringClass; - char *cp, **tab; + char *cp, **tab = NULL; jstring js; int cnt = 0; @@ -179,7 +179,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReade { SCARDCONTEXT context = (SCARDCONTEXT)jContext; LONG rv; - LPTSTR mszReaders; + LPTSTR mszReaders = NULL; DWORD size = 0; jobjectArray result; @@ -190,18 +190,20 @@ JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReade } dprintf1("-size: %d\n", size); - mszReaders = malloc(size); - if (mszReaders == NULL) { - throwOutOfMemoryError(env, NULL); - return NULL; - } + if (size) { + mszReaders = malloc(size); + if (mszReaders == NULL) { + throwOutOfMemoryError(env, NULL); + return NULL; + } - rv = CALL_SCardListReaders(context, NULL, mszReaders, &size); - if (handleRV(env, rv)) { - free(mszReaders); - return NULL; + rv = CALL_SCardListReaders(context, NULL, mszReaders, &size); + if (handleRV(env, rv)) { + free(mszReaders); + return NULL; + } + dprintf1("-String: %s\n", mszReaders); } - dprintf1("-String: %s\n", mszReaders); result = pcsc_multi2jstring(env, mszReaders); free(mszReaders); @@ -336,7 +338,7 @@ JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusCha const char *readerName; readerState = calloc(readers, sizeof(SCARD_READERSTATE)); - if (readerState == NULL) { + if (readerState == NULL && readers > 0) { throwOutOfMemoryError(env, NULL); return NULL; } @@ -347,6 +349,10 @@ JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusCha return NULL; } + for (i = 0; i < readers; i++) { + readerState[i].szReader = NULL; + } + for (i = 0; i < readers; i++) { jobject jReaderName = (*env)->GetObjectArrayElement(env, jReaderNames, i); if ((*env)->ExceptionCheck(env)) { @@ -369,9 +375,11 @@ JNIEXPORT jintArray JNICALL Java_sun_security_smartcardio_PCSC_SCardGetStatusCha (*env)->DeleteLocalRef(env, jReaderName); } - rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers); - if (handleRV(env, rv)) { - goto cleanup; + if (readers > 0) { + rv = CALL_SCardGetStatusChange(context, (DWORD)jTimeout, readerState, readers); + if (handleRV(env, rv)) { + goto cleanup; + } } jEventState = (*env)->NewIntArray(env, readers); diff --git a/jdk/src/solaris/classes/java/lang/UNIXProcess.java b/jdk/src/solaris/classes/java/lang/UNIXProcess.java index 56ba83f036f..85f15407c8f 100644 --- a/jdk/src/solaris/classes/java/lang/UNIXProcess.java +++ b/jdk/src/solaris/classes/java/lang/UNIXProcess.java @@ -97,6 +97,7 @@ final class UNIXProcess extends Process { EnumSet.copyOf(Arrays.asList(launchMechanisms)); } + @SuppressWarnings("fallthrough") private String helperPath(String javahome, String osArch) { switch (this) { case SOLARIS: diff --git a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c index dfe9c421c19..f344f4a00d9 100644 --- a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c +++ b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c @@ -136,5 +136,9 @@ JNIEXPORT void JNICALL Java_sun_security_smartcardio_PlatformPCSC_initialize if ((*env)->ExceptionCheck(env)) { return; } +#ifndef __APPLE__ scardControl = (FPTR_SCardControl) findFunction(env, hModule, "SCardControl"); +#else + scardControl = (FPTR_SCardControl) findFunction(env, hModule, "SCardControl132"); +#endif // __APPLE__ } diff --git a/jdk/src/windows/transport/shmem/shmem_md.c b/jdk/src/windows/transport/shmem/shmem_md.c index 056dce648f7..2574bc3933b 100644 --- a/jdk/src/windows/transport/shmem/shmem_md.c +++ b/jdk/src/windows/transport/shmem/shmem_md.c @@ -200,6 +200,17 @@ sysIPMutexEnter(sys_ipmutex_t mutex, sys_event_t event) rc = WaitForMultipleObjects(count, handles, FALSE, /* wait for either, not both */ INFINITE); /* infinite timeout */ + + /* If the mutex is abandoned we will consider this a fatal error + * and abort with appropriate message. + * + * Note that only mutexes can be abandoned and that our mutex is + * always at position 0 in the handles array. Thus we only need + * to check WAIT_ABANDONED_0 (not WAIT_ABANDONED_0 + x). + */ + if (rc == WAIT_ABANDONED_0) { + exitTransportWithError("Observed abandoned IP mutex. Aborting.",THIS_FILE, __DATE__, __LINE__); + } return (rc == WAIT_OBJECT_0) ? SYS_OK : SYS_ERR; } diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index dd045badca7..64c5ba9036a 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -261,6 +261,10 @@ com/sun/jdi/JdbMethodExitTest.sh generic-all # 8041934 com/sun/jdi/RepStep.java generic-all +# 8044419 +com/sun/jdi/JdbReadTwiceTest.sh generic-all + + ############################################################################ # jdk_util diff --git a/jdk/test/demo/jvmti/mtrace/JFrameCreateTime.java b/jdk/test/demo/jvmti/mtrace/JFrameCreateTime.java deleted file mode 100644 index b08206ef3e9..00000000000 --- a/jdk/test/demo/jvmti/mtrace/JFrameCreateTime.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* JFrameCreateTime: - * - * Example swing application that just creates a JFrame object. - * - */ - -/* Early in 1.5 it was reported that doing a step into the first JFrame - * was very slow (VisualMust debugger people reported this). - */ - -import java.awt.GraphicsEnvironment; -import javax.swing.*; - -public class JFrameCreateTime { - public static void main(String[] args) { - JFrame f; - long start, end; - if (GraphicsEnvironment.isHeadless()) { - System.out.println("JFrameCreateTime test was skipped due to headless mode"); - } else { - start = System.currentTimeMillis(); - f = new JFrame("JFrame"); - end = System.currentTimeMillis(); - - System.out.println("JFrame first creation took " + (end - start) + " ms"); - - start = System.currentTimeMillis(); - f = new JFrame("JFrame"); - end = System.currentTimeMillis(); - - System.out.println("JFrame second creation took " + (end - start) + " ms"); - System.exit(0); - } - } -} diff --git a/jdk/test/demo/jvmti/mtrace/TraceJFrame.java b/jdk/test/demo/jvmti/mtrace/TraceJFrame.java deleted file mode 100644 index c0dbe0ba960..00000000000 --- a/jdk/test/demo/jvmti/mtrace/TraceJFrame.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* @test - * @bug 5000000 6299047 - * @summary Test jvmti demo mtrace - * - * @compile ../DemoRun.java - * @compile JFrameCreateTime.java - * @build TraceJFrame - * @run main TraceJFrame JFrameCreateTime - */ - -import java.awt.GraphicsEnvironment; - -public class TraceJFrame { - public static void main(String args[]) throws Exception { - if (GraphicsEnvironment.isHeadless()) { - System.out.println("TraceJFrame test was skipped due to headless mode"); - } else { - DemoRun demo; - - /* Run demo that uses JVMTI mtrace agent (no options) */ - demo = new DemoRun("mtrace", "" /* options to mtrace */ ); - demo.runit(args[0]); - - /* Make sure patterns in output look ok */ - if (demo.output_contains("ERROR")) { - throw new RuntimeException("Test failed - ERROR seen in output"); - } - - /* Must be a pass. */ - System.out.println("Test passed - cleanly terminated"); - } - } -} diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index 039feb16404..d59688e9d7d 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -937,18 +937,13 @@ public class Basic { equal(pb.redirectError(), Redirect.to(efile)); THROWS(IllegalArgumentException.class, - new Fun(){void f() { - pb.redirectInput(Redirect.to(ofile)); }}, - new Fun(){void f() { - pb.redirectInput(Redirect.appendTo(ofile)); }}, - new Fun(){void f() { - pb.redirectOutput(Redirect.from(ifile)); }}, - new Fun(){void f() { - pb.redirectError(Redirect.from(ifile)); }}); + () -> pb.redirectInput(Redirect.to(ofile)), + () -> pb.redirectOutput(Redirect.from(ifile)), + () -> pb.redirectError(Redirect.from(ifile))); THROWS(IOException.class, // Input file does not exist - new Fun(){void f() throws Throwable { pb.start(); }}); + () -> pb.start()); setFileContents(ifile, "standard input"); //---------------------------------------------------------------- @@ -1084,18 +1079,15 @@ public class Basic { = new FilePermission("<>", "read,write,execute"); THROWS(SecurityException.class, - new Fun() { void f() throws IOException { - policy.setPermissions(xPermission); - redirectIO(pb, from(tmpFile), PIPE, PIPE); - pb.start();}}, - new Fun() { void f() throws IOException { - policy.setPermissions(rxPermission); - redirectIO(pb, PIPE, to(ofile), PIPE); - pb.start();}}, - new Fun() { void f() throws IOException { - policy.setPermissions(rxPermission); - redirectIO(pb, PIPE, PIPE, to(efile)); - pb.start();}}); + () -> { policy.setPermissions(xPermission); + redirectIO(pb, from(tmpFile), PIPE, PIPE); + pb.start();}, + () -> { policy.setPermissions(rxPermission); + redirectIO(pb, PIPE, to(ofile), PIPE); + pb.start();}, + () -> { policy.setPermissions(rxPermission); + redirectIO(pb, PIPE, PIPE, to(efile)); + pb.start();}); { policy.setPermissions(rxPermission); @@ -1258,10 +1250,10 @@ public class Basic { // System.getenv() is read-only. //---------------------------------------------------------------- THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ getenv().put("FOO","BAR");}}, - new Fun(){void f(){ getenv().remove("PATH");}}, - new Fun(){void f(){ getenv().keySet().remove("PATH");}}, - new Fun(){void f(){ getenv().values().remove("someValue");}}); + () -> getenv().put("FOO","BAR"), + () -> getenv().remove("PATH"), + () -> getenv().keySet().remove("PATH"), + () -> getenv().values().remove("someValue")); try { Collection> c = getenv().entrySet(); @@ -1286,19 +1278,17 @@ public class Basic { { final Map m = new ProcessBuilder().environment(); THROWS(IllegalArgumentException.class, - new Fun(){void f(){ m.put("FOO=","BAR");}}, - new Fun(){void f(){ m.put("FOO\u0000","BAR");}}, - new Fun(){void f(){ m.put("FOO","BAR\u0000");}}); + () -> m.put("FOO=","BAR"), + () -> m.put("FOO\u0000","BAR"), + () -> m.put("FOO","BAR\u0000")); } //---------------------------------------------------------------- // Commands must never be null. //---------------------------------------------------------------- THROWS(NullPointerException.class, - new Fun(){void f(){ - new ProcessBuilder((List)null);}}, - new Fun(){void f(){ - new ProcessBuilder().command((List)null);}}); + () -> new ProcessBuilder((List)null), + () -> new ProcessBuilder().command((List)null)); //---------------------------------------------------------------- // Put in a command; get the same one back out. @@ -1323,25 +1313,18 @@ public class Basic { // Commands must contain at least one element. //---------------------------------------------------------------- THROWS(IndexOutOfBoundsException.class, - new Fun() { void f() throws IOException { - new ProcessBuilder().start();}}, - new Fun() { void f() throws IOException { - new ProcessBuilder(new ArrayList()).start();}}, - new Fun() { void f() throws IOException { - Runtime.getRuntime().exec(new String[]{});}}); + () -> new ProcessBuilder().start(), + () -> new ProcessBuilder(new ArrayList()).start(), + () -> Runtime.getRuntime().exec(new String[]{})); //---------------------------------------------------------------- // Commands must not contain null elements at start() time. //---------------------------------------------------------------- THROWS(NullPointerException.class, - new Fun() { void f() throws IOException { - new ProcessBuilder("foo",null,"bar").start();}}, - new Fun() { void f() throws IOException { - new ProcessBuilder((String)null).start();}}, - new Fun() { void f() throws IOException { - new ProcessBuilder(new String[]{null}).start();}}, - new Fun() { void f() throws IOException { - new ProcessBuilder(new String[]{"foo",null,"bar"}).start();}}); + () -> new ProcessBuilder("foo",null,"bar").start(), + () -> new ProcessBuilder((String)null).start(), + () -> new ProcessBuilder(new String[]{null}).start(), + () -> new ProcessBuilder(new String[]{"foo",null,"bar"}).start()); //---------------------------------------------------------------- // Command lists are growable. @@ -1358,15 +1341,13 @@ public class Basic { try { final Map env = new ProcessBuilder().environment(); THROWS(NullPointerException.class, - new Fun(){void f(){ env.put("foo",null);}}, - new Fun(){void f(){ env.put(null,"foo");}}, - new Fun(){void f(){ env.remove(null);}}, - new Fun(){void f(){ - for (Map.Entry e : env.entrySet()) - e.setValue(null);}}, - new Fun() { void f() throws IOException { - Runtime.getRuntime().exec(new String[]{"foo"}, - new String[]{null});}}); + () -> env.put("foo",null), + () -> env.put(null,"foo"), + () -> env.remove(null), + () -> { for (Map.Entry e : env.entrySet()) + e.setValue(null);}, + () -> Runtime.getRuntime().exec(new String[]{"foo"}, + new String[]{null})); } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- @@ -1375,10 +1356,10 @@ public class Basic { try { final Map env = new ProcessBuilder().environment(); THROWS(ClassCastException.class, - new Fun(){void f(){ env.remove(TRUE);}}, - new Fun(){void f(){ env.keySet().remove(TRUE);}}, - new Fun(){void f(){ env.values().remove(TRUE);}}, - new Fun(){void f(){ env.entrySet().remove(TRUE);}}); + () -> env.remove(TRUE), + () -> env.keySet().remove(TRUE), + () -> env.values().remove(TRUE), + () -> env.entrySet().remove(TRUE)); } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- @@ -1394,22 +1375,22 @@ public class Basic { // Nulls in environment queries are forbidden. //---------------------------------------------------------------- THROWS(NullPointerException.class, - new Fun(){void f(){ getenv(null);}}, - new Fun(){void f(){ env.get(null);}}, - new Fun(){void f(){ env.containsKey(null);}}, - new Fun(){void f(){ env.containsValue(null);}}, - new Fun(){void f(){ env.keySet().contains(null);}}, - new Fun(){void f(){ env.values().contains(null);}}); + () -> getenv(null), + () -> env.get(null), + () -> env.containsKey(null), + () -> env.containsValue(null), + () -> env.keySet().contains(null), + () -> env.values().contains(null)); //---------------------------------------------------------------- // Non-String types in environment queries are forbidden. //---------------------------------------------------------------- THROWS(ClassCastException.class, - new Fun(){void f(){ env.get(TRUE);}}, - new Fun(){void f(){ env.containsKey(TRUE);}}, - new Fun(){void f(){ env.containsValue(TRUE);}}, - new Fun(){void f(){ env.keySet().contains(TRUE);}}, - new Fun(){void f(){ env.values().contains(TRUE);}}); + () -> env.get(TRUE), + () -> env.containsKey(TRUE), + () -> env.containsValue(TRUE), + () -> env.keySet().contains(TRUE), + () -> env.values().contains(TRUE)); //---------------------------------------------------------------- // Illegal String values in environment queries are (grumble) OK @@ -1427,12 +1408,11 @@ public class Basic { final Set> entrySet = new ProcessBuilder().environment().entrySet(); THROWS(NullPointerException.class, - new Fun(){void f(){ entrySet.contains(null);}}); + () -> entrySet.contains(null)); THROWS(ClassCastException.class, - new Fun(){void f(){ entrySet.contains(TRUE);}}, - new Fun(){void f(){ - entrySet.contains( - new SimpleImmutableEntry(TRUE,""));}}); + () -> entrySet.contains(TRUE), + () -> entrySet.contains( + new SimpleImmutableEntry(TRUE,""))); check(! entrySet.contains (new SimpleImmutableEntry("", ""))); @@ -1902,8 +1882,7 @@ public class Basic { final ProcessBuilder pb = new ProcessBuilder(new String[]{"unliKely"}); pb.environment().put("PATH", "suBdiR"); - THROWS(IOException.class, - new Fun() {void f() throws Throwable {pb.start();}}); + THROWS(IOException.class, () -> pb.start()); } catch (Throwable t) { unexpected(t); } finally { new File("suBdiR/unliKely").delete(); @@ -1976,10 +1955,8 @@ public class Basic { equal(SIZE, p.getInputStream().available()); equal(SIZE, p.getErrorStream().available()); THROWS(IOException.class, - new Fun(){void f() throws IOException { - p.getOutputStream().write((byte) '!'); - p.getOutputStream().flush(); - }}); + () -> { p.getOutputStream().write((byte) '!'); + p.getOutputStream().flush();}); final byte[] bytes = new byte[SIZE + 1]; equal(SIZE, p.getInputStream().read(bytes)); @@ -2006,12 +1983,9 @@ public class Basic { InputStream[] streams = { p.getInputStream(), p.getErrorStream() }; for (final InputStream in : streams) { Fun[] ops = { - new Fun(){void f() throws IOException { - in.read(); }}, - new Fun(){void f() throws IOException { - in.read(bytes); }}, - new Fun(){void f() throws IOException { - in.available(); }} + () -> in.read(), + () -> in.read(bytes), + () -> in.available() }; for (Fun op : ops) { try { @@ -2215,21 +2189,17 @@ public class Basic { } catch (Throwable t) { unexpected(t); } THROWS(SecurityException.class, - new Fun() { void f() throws IOException { - policy.setPermissions(/* Nothing */); - System.getenv("foo");}}, - new Fun() { void f() throws IOException { - policy.setPermissions(/* Nothing */); - System.getenv();}}, - new Fun() { void f() throws IOException { - policy.setPermissions(/* Nothing */); - new ProcessBuilder("echo").start();}}, - new Fun() { void f() throws IOException { - policy.setPermissions(/* Nothing */); - Runtime.getRuntime().exec("echo");}}, - new Fun() { void f() throws IOException { - policy.setPermissions(new RuntimePermission("getenv.bar")); - System.getenv("foo");}}); + () -> { policy.setPermissions(/* Nothing */); + System.getenv("foo");}, + () -> { policy.setPermissions(/* Nothing */); + System.getenv();}, + () -> { policy.setPermissions(/* Nothing */); + new ProcessBuilder("echo").start();}, + () -> { policy.setPermissions(/* Nothing */); + Runtime.getRuntime().exec("echo");}, + () -> { policy.setPermissions( + new RuntimePermission("getenv.bar")); + System.getenv("foo");}); try { policy.setPermissions(new RuntimePermission("getenv.foo")); @@ -2246,18 +2216,16 @@ public class Basic { = new FilePermission("<>", "execute"); THROWS(SecurityException.class, - new Fun() { void f() throws IOException { - // environment permission by itself insufficient - policy.setPermissions(new RuntimePermission("getenv.*")); - ProcessBuilder pb = new ProcessBuilder("env"); - pb.environment().put("foo","bar"); - pb.start();}}, - new Fun() { void f() throws IOException { - // exec permission by itself insufficient - policy.setPermissions(execPermission); - ProcessBuilder pb = new ProcessBuilder("env"); - pb.environment().put("foo","bar"); - pb.start();}}); + () -> { // environment permission by itself insufficient + policy.setPermissions(new RuntimePermission("getenv.*")); + ProcessBuilder pb = new ProcessBuilder("env"); + pb.environment().put("foo","bar"); + pb.start();}, + () -> { // exec permission by itself insufficient + policy.setPermissions(execPermission); + ProcessBuilder pb = new ProcessBuilder("env"); + pb.environment().put("foo","bar"); + pb.start();}); try { // Both permissions? OK. @@ -2585,7 +2553,7 @@ public class Basic { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private static abstract class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/lang/annotation/typeAnnotations/TestExecutableGetAnnotatedType.java b/jdk/test/java/lang/annotation/typeAnnotations/TestExecutableGetAnnotatedType.java new file mode 100644 index 00000000000..ad8a87a13d3 --- /dev/null +++ b/jdk/test/java/lang/annotation/typeAnnotations/TestExecutableGetAnnotatedType.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8039916 + * @summary Test that a call to getType() on an AnnotatedType returned from an + * Executable.getAnnotated* returns the same type as the corresponding + * Executable.getGeneric* call. + * @run testng TestExecutableGetAnnotatedType + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.testng.Assert.*; + +public class TestExecutableGetAnnotatedType { + @Test(dataProvider = "genericExecutableData") + public void testGenericMethodExceptions(Executable e) throws Exception { + testExceptions(e); + } + + @Test(dataProvider = "executableData") + public void testMethodExceptions(Executable e) throws Exception { + testExceptions(e); + } + + @Test(dataProvider = "genericExecutableData") + public void testGenericMethodParameterTypes(Executable e) throws Exception { + testMethodParameters(e); + } + + @Test(dataProvider = "executableData") + public void testMethodParameterTypes(Executable e) throws Exception { + testMethodParameters(e); + } + + @Test(dataProvider = "genericExecutableData") + public void testGenericParameterTypes(Executable e) throws Exception { + testParameters(e.getParameters()); + } + + @Test(dataProvider = "executableData") + public void testParameterTypes(Executable e) throws Exception { + testParameters(e.getParameters()); + } + + // should test constructors as well, see JDK-8044629 + @Test(dataProvider = "genericMethodData") + public void testGenericReceiverType(Executable e) throws Exception { + testReceiverType0(e); + } + + // should test constructors as well, see JDK-8044629 + @Test(dataProvider = "methodData") + public void testReceiverType(Executable e) throws Exception { + testReceiverType0(e); + } + + @Test(dataProvider = "genericMethodData") + public void testGenericMethodReturnType(Object o) throws Exception { + // testng gets confused if the param to this method has type Method + Method m = (Method)o; + testReturnType(m); + } + + @Test(dataProvider = "methodData") + public void testMethodReturnType(Object o) throws Exception { + // testng gets confused if the param to this method has type Method + Method m = (Method)o; + testReturnType(m); + } + + private void testExceptions(Executable e) { + Type[] ts = e.getGenericExceptionTypes(); + AnnotatedType[] ats = e.getAnnotatedExceptionTypes(); + assertEquals(ts.length, ats.length); + + for (int i = 0; i < ts.length; i++) { + Type t = ts[i]; + AnnotatedType at = ats[i]; + assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); + } + } + + private void testMethodParameters(Executable e) { + Type[] ts = e.getGenericParameterTypes(); + AnnotatedType[] ats = e.getAnnotatedParameterTypes(); + assertEquals(ts.length, ats.length); + + for (int i = 0; i < ts.length; i++) { + Type t = ts[i]; + AnnotatedType at = ats[i]; + assertSame(at.getType(), t, e.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); + } + } + + private void testParameters(Parameter[] params) { + for (Parameter p : params) { + Type t = p.getParameterizedType(); + AnnotatedType at = p.getAnnotatedType(); + assertSame(at.getType(), t, p.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); + } + } + + private void testReceiverType0(Executable e) { + if (Modifier.isStatic(e.getModifiers())) + assertNull(e.getAnnotatedReceiverType()); + else + assertSame(e.getAnnotatedReceiverType().getType(), e.getDeclaringClass()); + } + + private void testReturnType(Method m) { + Type t = m.getGenericReturnType(); + AnnotatedType at = m.getAnnotatedReturnType(); + assertSame(at.getType(), t, m.toString() + ": T: " + t + ", AT: " + at + ", AT.getType(): " + at.getType() + "\n"); + } + + @DataProvider + public Object[][] methodData() throws Exception { + return filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class) + .toArray(new Object[0][0]); + } + + @DataProvider + public Object[][] genericMethodData() throws Exception { + return filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class) + .toArray(new Object[0][0]); + } + + @DataProvider + public Object[][] executableData() throws Exception { + @SuppressWarnings("raw") + List l = filterData(Arrays.stream(Methods1.class.getMethods()), Methods1.class); + l.addAll(filterData(Arrays.stream(Methods1.class.getConstructors()), Methods1.class)); + l.addAll(filterData(Arrays.stream(Ctors1.class.getConstructors()), Ctors1.class)); + return ((List)l).toArray(new Object[0][0]); + } + + @DataProvider + public Object[][] genericExecutableData() throws Exception { + @SuppressWarnings("raw") + List l = filterData(Arrays.stream(GenericMethods1.class.getMethods()), GenericMethods1.class); + l.addAll(filterData(Arrays.stream(GenericMethods1.class.getConstructors()), GenericMethods1.class)); + l.addAll(filterData(Arrays.stream(GenericCtors1.class.getConstructors()), GenericCtors1.class)); + return ((List)l).toArray(new Object[0][0]); + } + + private List filterData(Stream l, Class c) { + return l.filter(m -> (m.getDeclaringClass() == c)) // remove object methods + .map(m -> { Object[] o = new Object[1]; o[0] = m; return o; }) + .collect(Collectors.toList()); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + public @interface TA {} + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + public @interface TB {} + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + public @interface TC {} + + public static class Methods1 { + public static void m1() throws Error, RuntimeException {;} + public static long m2(int a, double b) throws Error, RuntimeException { return 0L; } + public static Object m3(String s, List l) throws Error, RuntimeException { return null; } + public static Object m4(String s, List l) { return null; } + public static Object m4(String s, List l, boolean ... b){ return null; } + + public static void m10() throws @TA Error, @TB @TC RuntimeException {;} + public static @TB long m20(@TC int a, @TA double b) throws @TA Error, @TB @TC RuntimeException { return 0L; } + public static @TC Object m30(@TA String s, @TB List l) throws @TA Error, @TB @TC RuntimeException { return null; } + public static @TA Object m40(@TB String s, @TC List<@TA String> l) { return null; } + public static @TA Object m40(@TB String s, @TC List<@TA String> l, @TB boolean ... b) { return null; } + + public Methods1(int a, double b) {} + public Methods1(String s, List l, boolean ... b) {} + public Methods1(@TC long a, @TA float b) {} + public Methods1(@TA int i, @TB String s, @TC List<@TA String> l, @TB boolean ... b) {} + } + + // test default ctor + public static class Ctors1 { + } + + public static class GenericMethods1 { + public E m1(E e, Object o) throws Error, RuntimeException { return null; } + public E m2(List e, int i) throws Error, RuntimeException { return null; } + public E m3(double d, List e) throws Error, RuntimeException { return null; } + public E m4(byte[] b, GenericMethods1 e) { return null; } + public E m5(GenericMethods1 e) { return null; } + public E m6(char c, E e) { return null; } + public E m7(char c, E e, byte ... b) { return null; } + + public static M n1(M e) { return null; } + public static M n2(List e) { return null; } + public static M n3(List e) throws Error, M { return null; } + public static M n4(GenericMethods1 e) throws Error, RuntimeException { return null; } + public static M n5(GenericMethods1 e) { return null; } + public static M n6(M e) { return null; } + + public E o1(E e) { return null; } + public E o2(List e) { return null; } + public E o3(GenericMethods1 this, List e) throws M, N { return null; } + public E o4(GenericMethods1 e) throws Error, RuntimeException { return null; } + public E o5(GenericMethods1 e) { return null; } + public E o6(E e) { return null; } + + + // with annotations + public @TA E m10(E e, @TC Object o) throws @TA Error, @TB @TC RuntimeException { return null; } + public @TB E m20(@TA List<@TA ? extends @TA List> e, @TC int i) throws @TA Error, @TB @TC RuntimeException { return null; } + public @TB E m30(@TC double d, List e) throws @TA Error, @TB @TC RuntimeException { return null; } + public <@TA E extends @TA List> @TA E m40(@TA byte @TB [] b, GenericMethods1<@TA ? extends E> e) { return null; } + public <@TB E extends @TB List> E m50(@TA GenericMethods1 e) { return null; } + public <@TB E extends @TA List & Cloneable> E m60(@TC char c, E e) { return null; } + public <@TB E extends @TA List & Cloneable> E m70(@TC char c, E e, @TA @TB byte ... b) { return null; } + + public static <@TA M> @TA M n10(M e) { return null; } + public static <@TA @TB @TC M> M n20(List<@TA ? extends List> e) { return null; } + @TA @TB @TC public static M n30(List<@TB M> e) throws @TA Error, @TB @TC M { return null; } + public static <@TC M extends Number> M n40(GenericMethods1 e) throws @TA Error, @TB @TC RuntimeException { return null; } + @TA public static M n50(GenericMethods1 e) { return null; } + public static <@TA M extends @TB List & @TC @TB Cloneable> M n60(M e) { return null; } + + public <@TC M> E o10(@TA E e) { return null; } + public @TA E o20(@TB List<@TB ? extends @TB List> e) { return null; } + @TC public @TB E o30(@TA @TB @TC GenericMethods1 this, List e) throws @TA M, @TB @TC N { return null; } + public <@TA M extends Number> E o40(GenericMethods1 e) throws @TA Error, @TB @TC RuntimeException { return null; } + public E o50(GenericMethods1<@TA ? super Number> e) { return null; } + public <@TA M extends @TB List & @TC Cloneable> E o60(@TA E e) { return null; } + + + // ctors + public GenericMethods1(List e, int i) throws Error, RuntimeException { } + public GenericMethods1(char c, E e, byte ... b) { } + @TC public GenericMethods1(List<@TC E> e) throws @TA M, @TB @TC N { } + public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m) throws @TA Exception { } + public <@TA M extends @TB List & @TC Cloneable> GenericMethods1(@TA E e, @TB M m, @TC byte ... b) throws Exception { } + } + + // test default ctor + public static class GenericCtors1 { + } +} diff --git a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java index dc34bba24b9..33acc50d667 100644 --- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java +++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java @@ -33,11 +33,9 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.nio.file.Files; -import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.PosixFileAttributeView; -import java.util.stream.Stream; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -163,34 +161,66 @@ public class LogGeneratedClassesTest extends LUtils { tr.assertZero("Should still return 0"); } + private static boolean isWriteableDirectory(Path p) { + if (!Files.isDirectory(p)) { + return false; + } + Path test = p.resolve(Paths.get("test")); + try { + Files.createFile(test); + assertTrue(Files.exists(test)); + return true; + } catch (IOException e) { + assertFalse(Files.exists(test)); + return false; + } finally { + if (Files.exists(test)) { + try { + Files.delete(test); + } catch (IOException e) { + throw new Error(e); + } + } + } + } + @Test public void testDumpDirNotWritable() throws IOException { - if (! Files.getFileStore(Paths.get(".")) - .supportsFileAttributeView(PosixFileAttributeView.class)) { + if (!Files.getFileStore(Paths.get(".")) + .supportsFileAttributeView(PosixFileAttributeView.class)) { // No easy way to setup readonly directory without POSIX // We would like to skip the test with a cause with // throw new SkipException("Posix not supported"); // but jtreg will report failure so we just pass the test // which we can look at if jtreg changed its behavior + System.out.println("WARNING: POSIX is not supported. Skipping testDumpDirNotWritable test."); return; } Files.createDirectory(Paths.get("readOnly"), asFileAttribute(fromString("r-xr-xr-x"))); + try { + if (isWriteableDirectory(Paths.get("readOnly"))) { + // Skipping the test: it's allowed to write into read-only directory + // (e.g. current user is super user). + System.out.println("WARNING: readOnly directory is writeable. Skipping testDumpDirNotWritable test."); + return; + } - TestResult tr = doExec(JAVA_CMD.getAbsolutePath(), - "-cp", ".", - "-Djdk.internal.lambda.dumpProxyClasses=readOnly", - "-Djava.security.manager", - "com.example.TestLambda"); - assertEquals(tr.testOutput.stream() - .filter(s -> s.startsWith("WARNING")) - .peek(s -> assertTrue(s.contains("not writable"))) - .count(), - 1, "only show error once"); - tr.assertZero("Should still return 0"); - - TestUtil.removeAll(Paths.get("readOnly")); + TestResult tr = doExec(JAVA_CMD.getAbsolutePath(), + "-cp", ".", + "-Djdk.internal.lambda.dumpProxyClasses=readOnly", + "-Djava.security.manager", + "com.example.TestLambda"); + assertEquals(tr.testOutput.stream() + .filter(s -> s.startsWith("WARNING")) + .peek(s -> assertTrue(s.contains("not writable"))) + .count(), + 1, "only show error once"); + tr.assertZero("Should still return 0"); + } finally { + TestUtil.removeAll(Paths.get("readOnly")); + } } @Test diff --git a/jdk/test/java/nio/charset/StandardCharsets/Standard.java b/jdk/test/java/nio/charset/StandardCharsets/Standard.java index 66d1b112a1b..c570a955857 100644 --- a/jdk/test/java/nio/charset/StandardCharsets/Standard.java +++ b/jdk/test/java/nio/charset/StandardCharsets/Standard.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -99,13 +99,6 @@ public class Standard { System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); } - private static abstract class Fun {abstract void f() throws Throwable;} - private static void THROWS(Class k, Fun... fs) { - for (Fun f : fs) - try { f.f(); fail("Expected " + k.getName() + " not thrown"); } - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} static byte[] serializedForm(Object obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/jdk/test/java/util/Collection/BiggernYours.java b/jdk/test/java/util/Collection/BiggernYours.java index 24ce930e713..37bbe072c7a 100644 --- a/jdk/test/java/util/Collection/BiggernYours.java +++ b/jdk/test/java/util/Collection/BiggernYours.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -236,13 +236,6 @@ public class BiggernYours { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private static abstract class Fun {abstract void f() throws Throwable;} - static void THROWS(Class k, Fun... fs) { - for (Fun f : fs) - try { f.f(); fail("Expected " + k.getName() + " not thrown"); } - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} private static abstract class CheckedThread extends Thread { abstract void realRun() throws Throwable; public void run() { diff --git a/jdk/test/java/util/Collection/IteratorAtEnd.java b/jdk/test/java/util/Collection/IteratorAtEnd.java index fffc7f70fa1..be3a7e116cc 100644 --- a/jdk/test/java/util/Collection/IteratorAtEnd.java +++ b/jdk/test/java/util/Collection/IteratorAtEnd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -84,9 +84,9 @@ public class IteratorAtEnd { try { final Iterator it = c.iterator(); THROWS(NoSuchElementException.class, - new Fun() {void f() { while (true) it.next(); }}); + () -> { while (true) it.next(); }); try { it.remove(); } - catch (UnsupportedOperationException _) { return; } + catch (UnsupportedOperationException exc) { return; } pass(); } catch (Throwable t) { unexpected(t); } @@ -96,10 +96,9 @@ public class IteratorAtEnd { final ListIterator it = list.listIterator(0); it.next(); final Object x = it.previous(); - THROWS(NoSuchElementException.class, - new Fun() {void f() { it.previous(); }}); + THROWS(NoSuchElementException.class, () -> it.previous()); try { it.remove(); } - catch (UnsupportedOperationException _) { return; } + catch (UnsupportedOperationException exc) { return; } pass(); check(! list.get(0).equals(x)); } catch (Throwable t) { unexpected(t); } @@ -108,10 +107,9 @@ public class IteratorAtEnd { final ListIterator it = list.listIterator(list.size()); it.previous(); final Object x = it.next(); - THROWS(NoSuchElementException.class, - new Fun() {void f() { it.next(); }}); + THROWS(NoSuchElementException.class, () -> it.next()); try { it.remove(); } - catch (UnsupportedOperationException _) { return; } + catch (UnsupportedOperationException exc) { return; } pass(); check(! list.get(list.size()-1).equals(x)); } catch (Throwable t) { unexpected(t); } @@ -132,7 +130,7 @@ public class IteratorAtEnd { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private static abstract class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/Collection/MOAT.java b/jdk/test/java/util/Collection/MOAT.java index f50682fea24..f55a1e87745 100644 --- a/jdk/test/java/util/Collection/MOAT.java +++ b/jdk/test/java/util/Collection/MOAT.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -117,10 +117,8 @@ public class MOAT { final List emptyArray = Arrays.asList(new Integer[]{}); testCollection(emptyArray); testEmptyList(emptyArray); - THROWS(IndexOutOfBoundsException.class, - new Fun(){void f(){ emptyArray.set(0,1); }}); - THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ emptyArray.add(0,1); }}); + THROWS(IndexOutOfBoundsException.class, () -> emptyArray.set(0,1)); + THROWS(UnsupportedOperationException.class, () -> emptyArray.add(0,1)); List noOne = nCopies(0,1); testCollection(noOne); @@ -204,8 +202,7 @@ public class MOAT { if (rnd.nextBoolean()) check(! it.hasNext()); - THROWS(NoSuchElementException.class, - new Fun(){void f(){ it.next(); }}); + THROWS(NoSuchElementException.class, () -> it.next()); try { it.remove(); } catch (IllegalStateException ignored) { pass(); } @@ -232,16 +229,15 @@ public class MOAT { private static void testImmutableCollection(final Collection c) { THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ c.add(99); }}, - new Fun(){void f(){ c.addAll(singleton(99)); }}); + () -> c.add(99), + () -> c.addAll(singleton(99))); if (! c.isEmpty()) { final Integer first = c.iterator().next(); THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ c.clear(); }}, - new Fun(){void f(){ c.remove(first); }}, - new Fun(){void f(){ c.removeAll(singleton(first)); }}, - new Fun(){void f(){ c.retainAll(emptyList()); }} - ); + () -> c.clear(), + () -> c.remove(first), + () -> c.removeAll(singleton(first)), + () -> c.retainAll(emptyList())); } } @@ -253,17 +249,17 @@ public class MOAT { testList(c); testImmutableCollection(c); THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ c.set(0,42); }}, - new Fun(){void f(){ c.add(0,42); }}, - new Fun(){void f(){ c.addAll(0,singleton(86)); }}); + () -> c.set(0,42), + () -> c.add(0,42), + () -> c.addAll(0,singleton(86))); if (! c.isEmpty()) THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ - Iterator it = c.iterator(); - it.next(); it.remove();}}, - new Fun(){void f(){ - ListIterator it = c.listIterator(); - it.next(); it.remove();}}); + () -> { Iterator it = c.iterator(); + it.next(); + it.remove(); }, + () -> { ListIterator it = c.listIterator(); + it.next(); + it.remove(); }); } private static void clear(Collection c) { @@ -290,19 +286,19 @@ public class MOAT { private static void testImmutableMap(final Map m) { THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ m.put(1,1); }}, - new Fun(){void f(){ m.putAll(singletonMap(1,1)); }}); + () -> m.put(1,1), + () -> m.putAll(singletonMap(1,1))); if (! m.isEmpty()) { final Integer first = m.keySet().iterator().next(); THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ m.remove(first); }}, - new Fun(){void f(){ m.clear(); }}); + () -> m.remove(first), + () -> m.clear()); final Map.Entry me = m.entrySet().iterator().next(); Integer key = me.getKey(); Integer val = me.getValue(); THROWS(UnsupportedOperationException.class, - new Fun(){void f(){ me.setValue(3); }}); + () -> me.setValue(3)); equal(key, me.getKey()); equal(val, me.getValue()); } @@ -492,9 +488,9 @@ public class MOAT { // insert, query, remove element at head if (isEmpty) { THROWS(NoSuchElementException.class, - new Fun(){void f(){ deq.getFirst(); }}, - new Fun(){void f(){ deq.element(); }}, - new Fun(){void f(){ deq.iterator().next(); }}); + () -> deq.getFirst(), + () -> deq.element(), + () -> deq.iterator().next()); check(deq.peekFirst() == null); check(deq.peek() == null); } else { @@ -546,9 +542,9 @@ public class MOAT { } if (isEmpty) { THROWS(NoSuchElementException.class, - new Fun(){void f(){ deq.getFirst(); }}, - new Fun(){void f(){ deq.element(); }}, - new Fun(){void f(){ deq.iterator().next(); }}); + () -> deq.getFirst(), + () -> deq.element(), + () -> deq.iterator().next()); check(deq.peekFirst() == null); check(deq.peek() == null); } else { @@ -571,8 +567,7 @@ public class MOAT { // insert, query, remove element at tail if (isEmpty) { check(deq.peekLast() == null); - THROWS(NoSuchElementException.class, - new Fun(){void f(){ deq.getLast(); }}); + THROWS(NoSuchElementException.class, () -> deq.getLast()); } else { check(deq.peekLast() != e); check(deq.getLast() != e); @@ -615,8 +610,7 @@ public class MOAT { } if (isEmpty) { check(deq.peekLast() == null); - THROWS(NoSuchElementException.class, - new Fun(){void f(){ deq.getLast(); }}); + THROWS(NoSuchElementException.class, () -> deq.getLast()); } else { check(deq.peekLast() != e); check(deq.getLast() != e); @@ -649,17 +643,17 @@ public class MOAT { if (isList) { check(!asList.listIterator().hasPrevious()); THROWS(NoSuchElementException.class, - new Fun(){void f(){ asList.listIterator().previous(); }}); + () -> asList.listIterator().previous()); } THROWS(NoSuchElementException.class, - new Fun(){void f(){ deq.iterator().next(); }}, - new Fun(){void f(){ deq.element(); }}, - new Fun(){void f(){ deq.getFirst(); }}, - new Fun(){void f(){ deq.getLast(); }}, - new Fun(){void f(){ deq.pop(); }}, - new Fun(){void f(){ deq.remove(); }}, - new Fun(){void f(){ deq.removeFirst(); }}, - new Fun(){void f(){ deq.removeLast(); }}); + () -> deq.iterator().next(), + () -> deq.element(), + () -> deq.getFirst(), + () -> deq.getLast(), + () -> deq.pop(), + () -> deq.remove(), + () -> deq.removeFirst(), + () -> deq.removeLast()); check(deq.poll() == null); check(deq.pollFirst() == null); @@ -728,8 +722,8 @@ public class MOAT { l.listIterator(0); l.listIterator(l.size()); THROWS(IndexOutOfBoundsException.class, - new Fun(){void f(){l.listIterator(-1);}}, - new Fun(){void f(){l.listIterator(l.size() + 1);}}); + () -> l.listIterator(-1), + () -> l.listIterator(l.size() + 1)); if (l instanceof AbstractList) { try { @@ -1004,22 +998,22 @@ public class MOAT { ? (ConcurrentMap) m : null; List fs = new ArrayList(); - fs.add(new Fun(){void f(){ check(! m.containsKey(null));}}); - fs.add(new Fun(){void f(){ equal(m.remove(null), null);}}); - fs.add(new Fun(){void f(){ equal(m.get(null), null);}}); - if (cm != null) { - fs.add(new Fun(){void f(){ check(! cm.remove(null,null));}});} + fs.add(() -> check(! m.containsKey(null))); + fs.add(() -> equal(m.remove(null), null)); + fs.add(() -> equal(m.get(null), null)); + if (cm != null) + fs.add(() -> check(! cm.remove(null,null))); throwsConsistently(NullPointerException.class, fs); fs.clear(); final Map sm = singletonMap(null,1); - fs.add(new Fun(){void f(){ equal(m.put(null,1), null); m.clear();}}); - fs.add(new Fun(){void f(){ m.putAll(sm); m.clear();}}); + fs.add(() -> { equal(m.put(null,1), null); m.clear();}); + fs.add(() -> { m.putAll(sm); m.clear();}); if (cm != null) { - fs.add(new Fun(){void f(){ check(! cm.remove(null,null));}}); - fs.add(new Fun(){void f(){ equal(cm.putIfAbsent(null,1), 1);}}); - fs.add(new Fun(){void f(){ equal(cm.replace(null,1), null);}}); - fs.add(new Fun(){void f(){ equal(cm.replace(null,1, 1), 1);}}); + fs.add(() -> check(! cm.remove(null,null))); + fs.add(() -> equal(cm.putIfAbsent(null,1), 1)); + fs.add(() -> equal(cm.replace(null,1), null)); + fs.add(() -> equal(cm.replace(null,1, 1), 1)); } throwsConsistently(NullPointerException.class, fs); } @@ -1180,8 +1174,7 @@ public class MOAT { equalNext(it, 3); equalNext(it, 1); check(! it.hasNext()); - THROWS(NoSuchElementException.class, - new Fun(){void f(){it.next();}}); + THROWS(NoSuchElementException.class, () -> it.next()); } { @@ -1191,8 +1184,7 @@ public class MOAT { check(it.hasNext()); equal(it.next().getKey(), 3); check(it.hasNext()); equal(it.next().getKey(), 1); check(! it.hasNext()); - THROWS(NoSuchElementException.class, - new Fun(){void f(){it.next();}}); + THROWS(NoSuchElementException.class, () -> it.next()); } prepMapForDescItrTests(m); @@ -1262,8 +1254,7 @@ public class MOAT { equalNext(it, 3); equalNext(it, 1); check(! it.hasNext()); - THROWS(NoSuchElementException.class, - new Fun(){void f(){it.next();}}); + THROWS(NoSuchElementException.class, () -> it.next()); } prepSetForDescItrTests(s); @@ -1365,7 +1356,7 @@ public class MOAT { System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); } - private static abstract class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} private static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/Collections/AsLifoQueue.java b/jdk/test/java/util/Collections/AsLifoQueue.java index ddb98a74517..59c08e85c75 100644 --- a/jdk/test/java/util/Collections/AsLifoQueue.java +++ b/jdk/test/java/util/Collections/AsLifoQueue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -56,8 +56,7 @@ public class AsLifoQueue { equal(q.size(), 3); check(! q.offer("d")); equal(q.size(), 3); - THROWS(IllegalStateException.class, - new Fun(){void f(){ q.add("d"); }}); + THROWS(IllegalStateException.class, () -> q.add("d")); equal(q.size(), 3); equal(q.toString(), "[c, b, a]"); equal(q.peek(), "c"); @@ -66,8 +65,7 @@ public class AsLifoQueue { equal(q.poll(), "b"); equal(q.peek(), "a"); equal(q.remove(), "a"); - THROWS(NoSuchElementException.class, - new Fun(){void f(){ q.remove(); }}); + THROWS(NoSuchElementException.class, () -> q.remove()); equal(q.poll(), null); check(q.isEmpty()); equal(q.size(), 0); @@ -88,7 +86,7 @@ public class AsLifoQueue { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - static abstract class Fun { abstract void f() throws Throwable; } + interface Fun {void f() throws Throwable;} private static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/NavigableMap/LockStep.java b/jdk/test/java/util/NavigableMap/LockStep.java index adb8b1978c9..62ffc72877d 100644 --- a/jdk/test/java/util/NavigableMap/LockStep.java +++ b/jdk/test/java/util/NavigableMap/LockStep.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -236,8 +236,8 @@ public class LockStep { Comparator cmp = comparator(s); if (s.isEmpty()) { THROWS(NoSuchElementException.class, - new Fun(){void f(){ s.first(); }}, - new Fun(){void f(){ s.last(); }}); + () -> s.first(), + () -> s.last()); equal(null, s.lower(1)); equal(null, s.floor(1)); equal(null, s.ceiling(1)); @@ -265,8 +265,7 @@ public class LockStep { }; for (final Iterator it : its) if (maybe(4)) - THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + THROWS(IllegalStateException.class, () -> it.remove()); Object prev = null; for (Object e : s) { check(s.contains(e)); @@ -284,7 +283,7 @@ public class LockStep { for (final Iterator it : its) { if (maybe(2)) check(! it.hasNext()); - Fun fun = new Fun(){void f(){ it.next(); }}; + Fun fun = () -> it.next(); THROWS(NoSuchElementException.class, fun, fun, fun); } } @@ -380,8 +379,8 @@ public class LockStep { Comparator cmp = comparator(m); if (m.isEmpty()) { THROWS(NoSuchElementException.class, - new Fun(){void f(){ m.firstKey(); }}, - new Fun(){void f(){ m.lastKey(); }}); + () -> m.firstKey(), + () -> m.lastKey()); equal(null, m.firstEntry()); equal(null, m.lastEntry()); equal(null, m.pollFirstEntry()); @@ -430,8 +429,7 @@ public class LockStep { Iterator[] its = concat(kits, vits, eits); for (final Iterator it : its) if (maybe(4)) - THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + THROWS(IllegalStateException.class, () -> it.remove()); Map.Entry prev = null; for (Map.Entry e : (Set) m.entrySet()) { Object k = e.getKey(); @@ -459,7 +457,7 @@ public class LockStep { for (final Iterator it : its) { if (maybe(2)) check(! it.hasNext()); - Fun fun = new Fun(){void f(){ it.next(); }}; + Fun fun = () -> it.next(); THROWS(NoSuchElementException.class, fun, fun, fun); } } @@ -633,7 +631,7 @@ public class LockStep { } static Fun remover(final Iterator it) { - return new Fun(){void f(){ it.remove(); }}; + return () -> it.remove(); } static MapFrobber randomRemover(NavigableMap m) { @@ -663,7 +661,7 @@ public class LockStep { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + () -> it.remove()); } checkUnusedKey(m, k);}}, new MapFrobber() {void frob(NavigableMap m) { @@ -673,7 +671,7 @@ public class LockStep { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + () -> it.remove()); } checkUnusedKey(m, k);}}, new MapFrobber() {void frob(NavigableMap m) { @@ -718,7 +716,7 @@ public class LockStep { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + () -> it.remove()); } checkUnusedElt(s, e);}}, new SetFrobber() {void frob(NavigableSet s) { @@ -728,7 +726,7 @@ public class LockStep { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + () -> it.remove()); } checkUnusedElt(s, e);}}, new SetFrobber() {void frob(NavigableSet s) { @@ -738,7 +736,7 @@ public class LockStep { it.remove(); if (maybe(2)) THROWS(IllegalStateException.class, - new Fun(){void f(){ it.remove(); }}); + () -> it.remove()); } checkUnusedElt(s, e);}} }; @@ -769,12 +767,12 @@ public class LockStep { for (final NavigableMap m : maps) { final Object e = usedKey(m); THROWS(IllegalArgumentException.class, - new Fun(){void f(){m.subMap(e,true,e,false) - .subMap(e,true,e,true);}}, - new Fun(){void f(){m.subMap(e,false,e,true) - .subMap(e,true,e,true);}}, - new Fun(){void f(){m.tailMap(e,false).tailMap(e,true);}}, - new Fun(){void f(){m.headMap(e,false).headMap(e,true);}}); + () -> {m.subMap(e,true,e,false) + .subMap(e,true,e,true);}, + () -> {m.subMap(e,false,e,true) + .subMap(e,true,e,true);}, + () -> m.tailMap(e,false).tailMap(e,true), + () -> m.headMap(e,false).headMap(e,true)); } //System.out.printf("%s%n", m1); for (int i = size; i > 0; i--) { @@ -811,12 +809,12 @@ public class LockStep { for (final NavigableSet s : sets) { final Object e = usedElt(s); THROWS(IllegalArgumentException.class, - new Fun(){void f(){s.subSet(e,true,e,false) - .subSet(e,true,e,true);}}, - new Fun(){void f(){s.subSet(e,false,e,true) - .subSet(e,true,e,true);}}, - new Fun(){void f(){s.tailSet(e,false).tailSet(e,true);}}, - new Fun(){void f(){s.headSet(e,false).headSet(e,true);}}); + () -> {s.subSet(e,true,e,false) + .subSet(e,true,e,true);}, + () -> {s.subSet(e,false,e,true) + .subSet(e,true,e,true);}, + () -> s.tailSet(e,false).tailSet(e,true), + () -> s.headSet(e,false).headSet(e,true)); } //System.out.printf("%s%n", s1); for (int i = size; i > 0; i--) { @@ -847,7 +845,7 @@ public class LockStep { System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); } - static abstract class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/PriorityQueue/ForgetMeNot.java b/jdk/test/java/util/PriorityQueue/ForgetMeNot.java index f6970fa73f7..7778d1d793d 100644 --- a/jdk/test/java/util/PriorityQueue/ForgetMeNot.java +++ b/jdk/test/java/util/PriorityQueue/ForgetMeNot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -37,16 +37,14 @@ public class ForgetMeNot { private static void noMoreElements(final Iterator it) { for (int j = 0; j < 2; j++) { - THROWS(NoSuchElementException.class, - new Fun() { void f() { it.next(); }}); + THROWS(NoSuchElementException.class, () -> it.next()); check(! it.hasNext()); } } private static void removeIsCurrentlyIllegal(final Iterator it) { for (int j = 0; j < 2; j++) { - THROWS(IllegalStateException.class, - new Fun() { void f() { it.remove(); }}); + THROWS(IllegalStateException.class, () -> it.remove()); } } @@ -146,7 +144,7 @@ public class ForgetMeNot { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private static abstract class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/Properties/LoadAndStoreXML.java b/jdk/test/java/util/Properties/LoadAndStoreXML.java index 5353c645b81..241a783053f 100644 --- a/jdk/test/java/util/Properties/LoadAndStoreXML.java +++ b/jdk/test/java/util/Properties/LoadAndStoreXML.java @@ -32,6 +32,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; @@ -47,6 +48,7 @@ import java.util.Properties; import java.util.PropertyPermission; public class LoadAndStoreXML { + static final String bomChar = "\uFEFF"; /** * Simple policy implementation that grants a set of permissions to @@ -125,13 +127,14 @@ public class LoadAndStoreXML { * Sanity test that properties saved with Properties#storeToXML can be * read with Properties#loadFromXML. */ - static void testLoadAndStore(String encoding) throws IOException { + static void testLoadAndStore(String encoding, boolean appendBOM) throws IOException { System.out.println("testLoadAndStore, encoding=" + encoding); Properties props = new Properties(); + props.put("k0", "\u6C34"); props.put("k1", "foo"); props.put("k2", "bar"); - props.put("k3", "\\u0020\\u0391\\u0392\\u0393\\u0394\\u0395\\u0396\\u0397"); + props.put("k3", "\u0020\u0391\u0392\u0393\u0394\u0395\u0396\u0397"); props.put("k4", "\u7532\u9aa8\u6587"); props.put("k5", "/lib/jaxp.properties"); @@ -141,7 +144,17 @@ public class LoadAndStoreXML { throw new RuntimeException("OutputStream closed by storeToXML"); Properties p = new Properties(); - TestInputStream in = new TestInputStream(out.toByteArray()); + TestInputStream in; + if (appendBOM) { + byte[] byteOrderMark = bomChar.getBytes(Charset.forName(encoding)); + byte[] outArray = out.toByteArray(); + byte[] inputArray = new byte[byteOrderMark.length + outArray.length]; + System.arraycopy(byteOrderMark, 0, inputArray, 0, byteOrderMark.length); + System.arraycopy(outArray, 0, inputArray, byteOrderMark.length, outArray.length); + in = new TestInputStream(inputArray); + } else { + in = new TestInputStream(out.toByteArray()); + } p.loadFromXML(in); if (in.isOpen()) throw new RuntimeException("InputStream not closed by loadFromXML"); @@ -231,8 +244,12 @@ public class LoadAndStoreXML { public static void main(String[] args) throws IOException { - testLoadAndStore("UTF-8"); - testLoadAndStore("UTF-16"); + testLoadAndStore("UTF-8", false); + testLoadAndStore("UTF-16", false); + testLoadAndStore("UTF-16BE", false); + testLoadAndStore("UTF-16LE", false); + testLoadAndStore("UTF-16BE", true); + testLoadAndStore("UTF-16LE", true); testLoadWithoutEncoding(); testLoadWithBadEncoding(); testStoreWithBadEncoding(); @@ -250,7 +267,7 @@ public class LoadAndStoreXML { Policy.setPolicy(p); System.setSecurityManager(new SecurityManager()); try { - testLoadAndStore("UTF-8"); + testLoadAndStore("UTF-8", false); } finally { // turn off security manager and restore policy System.setSecurityManager(null); diff --git a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java index cdfd9e88bdb..94ad2a172bb 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -69,19 +69,13 @@ public class Interrupt { (BlockingDeque) q : null; q.clear(); List fs = new ArrayList(); - fs.add(new Fun() { void f() throws Throwable - { q.take(); }}); - fs.add(new Fun() { void f() throws Throwable - { q.poll(60, SECONDS); }}); + fs.add(() -> q.take()); + fs.add(() -> q.poll(60, SECONDS)); if (deq != null) { - fs.add(new Fun() { void f() throws Throwable - { deq.takeFirst(); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.takeLast(); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.pollFirst(7, SECONDS); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.pollLast(7, SECONDS); }}); + fs.add(() -> deq.takeFirst()); + fs.add(() -> deq.takeLast()); + fs.add(() -> deq.pollFirst(7, SECONDS)); + fs.add(() -> deq.pollLast(7, SECONDS)); } checkInterrupted(fs); @@ -92,19 +86,13 @@ public class Interrupt { catch (Throwable t) { unexpected(t); } fs.clear(); - fs.add(new Fun() { void f() throws Throwable - { q.put(1); }}); - fs.add(new Fun() { void f() throws Throwable - { q.offer(1, 7, SECONDS); }}); + fs.add(() -> q.put(1)); + fs.add(() -> q.offer(1, 7, SECONDS)); if (deq != null) { - fs.add(new Fun() { void f() throws Throwable - { deq.putFirst(1); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.putLast(1); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.offerFirst(1, 7, SECONDS); }}); - fs.add(new Fun() { void f() throws Throwable - { deq.offerLast(1, 7, SECONDS); }}); + fs.add(() -> deq.putFirst(1)); + fs.add(() -> deq.putLast(1)); + fs.add(() -> deq.offerFirst(1, 7, SECONDS)); + fs.add(() -> deq.offerLast(1, 7, SECONDS)); } checkInterrupted(fs); } catch (Throwable t) { @@ -135,5 +123,5 @@ public class Interrupt { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private abstract static class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} } diff --git a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java index 123481985b2..b6b8d637b2f 100644 --- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java +++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -40,10 +40,8 @@ public class Basic { equal(barrier.getNumberWaiting(), 0); THROWS(BrokenBarrierException.class, - new Fun() { public void f() throws Throwable { - barrier.await(); }}, - new Fun() { public void f() throws Throwable { - barrier.await(100, MILLISECONDS); }}); + () -> barrier.await(), + () -> barrier.await(100, MILLISECONDS)); } private static void reset(CyclicBarrier barrier) { @@ -417,7 +415,7 @@ public class Basic { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - abstract static class Fun { abstract void f() throws Throwable; } + interface Fun {void f() throws Throwable;} private static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/concurrent/Executors/Throws.java b/jdk/test/java/util/concurrent/Executors/Throws.java index 424b60d6d72..402472df366 100644 --- a/jdk/test/java/util/concurrent/Executors/Throws.java +++ b/jdk/test/java/util/concurrent/Executors/Throws.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -45,33 +45,31 @@ public class Throws { ThreadPoolExecutor executor) {}}; final RejectedExecutionHandler nullHandler = null; - THROWS( - NullPointerException.class, - new Fun(){void f(){ newFixedThreadPool(3, null); }}, - new Fun(){void f(){ newCachedThreadPool(null); }}, - new Fun(){void f(){ newSingleThreadScheduledExecutor(null); }}, - new Fun(){void f(){ newScheduledThreadPool(0, null); }}, - new Fun(){void f(){ unconfigurableExecutorService(null); }}, - new Fun(){void f(){ unconfigurableScheduledExecutorService(null); }}, - new Fun(){void f(){ callable(null, "foo"); }}, - new Fun(){void f(){ callable((Runnable) null); }}, - new Fun(){void f(){ callable((PrivilegedAction) null); }}, - new Fun(){void f(){ callable((PrivilegedExceptionAction) null); }}, - new Fun(){void f(){ privilegedCallable((Callable) null); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(0, nullFactory); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(0, nullFactory, reh); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(0, fac, nullHandler); }}); + THROWS(NullPointerException.class, + () -> newFixedThreadPool(3, null), + () -> newCachedThreadPool(null), + () -> newSingleThreadScheduledExecutor(null), + () -> newScheduledThreadPool(0, null), + () -> unconfigurableExecutorService(null), + () -> unconfigurableScheduledExecutorService(null), + () -> callable(null, "foo"), + () -> callable((Runnable) null), + () -> callable((PrivilegedAction) null), + () -> callable((PrivilegedExceptionAction) null), + () -> privilegedCallable((Callable) null), + () -> new ScheduledThreadPoolExecutor(0, nullFactory), + () -> new ScheduledThreadPoolExecutor(0, nullFactory, reh), + () -> new ScheduledThreadPoolExecutor(0, fac, nullHandler)); - THROWS( - IllegalArgumentException.class, - new Fun(){void f(){ newFixedThreadPool(-42); }}, - new Fun(){void f(){ newFixedThreadPool(0) ; }}, - new Fun(){void f(){ newFixedThreadPool(-42, fac); }}, - new Fun(){void f(){ newFixedThreadPool(0, fac); }}, - new Fun(){void f(){ newScheduledThreadPool(-42); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(-42); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(-42, reh); }}, - new Fun(){void f(){ new ScheduledThreadPoolExecutor(-42, fac, reh); }}); + THROWS(IllegalArgumentException.class, + () -> newFixedThreadPool(-42), + () -> newFixedThreadPool(0), + () -> newFixedThreadPool(-42, fac), + () -> newFixedThreadPool(0, fac), + () -> newScheduledThreadPool(-42), + () -> new ScheduledThreadPoolExecutor(-42), + () -> new ScheduledThreadPoolExecutor(-42, reh), + () -> new ScheduledThreadPoolExecutor(-42, fac, reh)); try { newFixedThreadPool(1).shutdownNow(); pass(); } catch (Throwable t) { unexpected(t); } @@ -122,7 +120,7 @@ public class Throws { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private abstract static class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/concurrent/FutureTask/Customized.java b/jdk/test/java/util/concurrent/FutureTask/Customized.java index 15159ca0aab..a1afd9015a1 100644 --- a/jdk/test/java/util/concurrent/FutureTask/Customized.java +++ b/jdk/test/java/util/concurrent/FutureTask/Customized.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -70,8 +70,7 @@ public class Customized { check(! task.isDone()); check(! task.isCancelled()); THROWS(TimeoutException.class, - new Fun(){void f() throws Throwable { - task.get(0L, TimeUnit.SECONDS); }}); + () -> task.get(0L, TimeUnit.SECONDS)); } static void checkDone(final FutureTask task) { @@ -86,20 +85,16 @@ public class Customized { check(task.isDone()); check(task.isCancelled()); THROWS(CancellationException.class, - new Fun(){void f() throws Throwable { - task.get(0L, TimeUnit.SECONDS); }}, - new Fun(){void f() throws Throwable { - task.get(); }}); + () -> task.get(0L, TimeUnit.SECONDS), + () -> task.get()); } static void checkThrew(final FutureTask task) { check(task.isDone()); check(! task.isCancelled()); THROWS(ExecutionException.class, - new Fun(){void f() throws Throwable { - task.get(0L, TimeUnit.SECONDS); }}, - new Fun(){void f() throws Throwable { - task.get(); }}); + () -> task.get(0L, TimeUnit.SECONDS), + () -> task.get()); } static void cancel(FutureTask task, boolean mayInterruptIfRunning) { @@ -203,7 +198,7 @@ public class Customized { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private abstract static class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java index aed43ac68a8..d89ee28333e 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -72,7 +72,7 @@ public class ConfigChanges { check(((ThreadPoolExecutor) es).isTerminating() || es.isTerminated()); THROWS(RejectedExecutionException.class, - new Fun() {void f() {es.execute(nop);}}); + () -> es.execute(nop)); } } catch (Throwable t) { unexpected(t); } } @@ -241,7 +241,7 @@ public class ConfigChanges { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private abstract static class Fun {abstract void f() throws Throwable;} + interface Fun {void f() throws Throwable;} static void THROWS(Class k, Fun... fs) { for (Fun f : fs) try { f.f(); fail("Expected " + k.getName() + " not thrown"); } diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ShutdownNowExecuteRace.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ShutdownNowExecuteRace.java index dbf82f22ece..780aa4eeb06 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ShutdownNowExecuteRace.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ShutdownNowExecuteRace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -81,13 +81,6 @@ public class ShutdownNowExecuteRace { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private abstract static class Fun {abstract void f() throws Throwable;} - static void THROWS(Class k, Fun... fs) { - for (Fun f : fs) - try { f.f(); fail("Expected " + k.getName() + " not thrown"); } - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} private abstract static class CheckedThread extends Thread { abstract void realRun() throws Throwable; public void run() { diff --git a/jdk/test/sun/nio/ch/ServerSocketAdaptorTest.java b/jdk/test/sun/nio/ch/ServerSocketAdaptorTest.java new file mode 100644 index 00000000000..062fc784520 --- /dev/null +++ b/jdk/test/sun/nio/ch/ServerSocketAdaptorTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8024832 + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.SocketException; +import java.nio.channels.ServerSocketChannel; + +public class ServerSocketAdaptorTest { + + public static void main(String[] args) throws IOException { + + String message = null; + + try (ServerSocket s = new ServerSocket()) { + s.accept(); + throw new AssertionError(); + } catch (IOException e) { + message = e.getMessage(); + } + + try (ServerSocket ss = ServerSocketChannel.open().socket()) { + + assert !ss.isBound() : "the assumption !ss.isBound() doesn't hold"; + + try { + ss.accept(); + throw new AssertionError(); + } catch (Exception e) { + if (e instanceof SocketException && message.equals(e.getMessage())) { + return; + } else { + throw new AssertionError( + "Expected to throw SocketException with a particular message", e); + } + } + } + } +} diff --git a/jdk/test/sun/nio/cs/FindOneCharEncoderBugs.java b/jdk/test/sun/nio/cs/FindOneCharEncoderBugs.java index 0b244e8c0e6..95ce0fca6fa 100644 --- a/jdk/test/sun/nio/cs/FindOneCharEncoderBugs.java +++ b/jdk/test/sun/nio/cs/FindOneCharEncoderBugs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -155,13 +155,6 @@ public class FindOneCharEncoderBugs { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - private static abstract class Fun {abstract void f() throws Throwable;} - static void THROWS(Class k, Fun... fs) { - for (Fun f : fs) - try { f.f(); fail("Expected " + k.getName() + " not thrown"); } - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} private static abstract class CheckedThread extends Thread { abstract void realRun() throws Throwable; public void run() { diff --git a/jdk/test/sun/security/krb5/auto/KDC.java b/jdk/test/sun/security/krb5/auto/KDC.java index 356f84e9856..686e238579e 100644 --- a/jdk/test/sun/security/krb5/auto/KDC.java +++ b/jdk/test/sun/security/krb5/auto/KDC.java @@ -141,6 +141,8 @@ public class KDC { private BlockingQueue q = new ArrayBlockingQueue<>(100); // Options private Map options = new HashMap<>(); + // Realm-specific krb5.conf settings + private List conf = new ArrayList<>(); private Thread thread1, thread2, thread3; DatagramSocket u1 = null; @@ -243,7 +245,7 @@ public class KDC { /** * Sets an option * @param key the option name - * @param obj the value + * @param value the value */ public void setOption(Option key, Object value) { if (value == null) { @@ -372,6 +374,13 @@ public class KDC { return kdc; } + /** + * Add realm-specific krb5.conf setting + */ + public void addConf(String s) { + conf.add(s); + } + /** * Writes a krb5.conf for one or more KDC that includes KDC locations for * each realm and the default realm name. You can also add extra strings @@ -397,6 +406,7 @@ public class KDC { * [realms] * REALM.NAME = { * kdc = host:port_number + * # realm-specific settings * } * * @@ -444,10 +454,10 @@ public class KDC { } } sb.append("\n[realms]\n"); - sb.append(realmLineForKDC(kdc)); + sb.append(kdc.realmLine()); for (Object o: more) { if (o instanceof KDC) { - sb.append(realmLineForKDC((KDC)o)); + sb.append(((KDC)o).realmLine()); } } FileOutputStream fos = new FileOutputStream(f); @@ -1133,14 +1143,16 @@ public class KDC { /** * Generates a line for a KDC to put inside [realms] of krb5.conf - * @param kdc the KDC - * @return REALM.NAME = { kdc = host:port } + * @return REALM.NAME = { kdc = host:port etc } */ - private static String realmLineForKDC(KDC kdc) { - return String.format("%s = {\n kdc = %s:%d\n}\n", - kdc.realm, - kdc.kdc, - kdc.port); + private String realmLine() { + StringBuilder sb = new StringBuilder(); + sb.append(realm).append(" = {\n kdc = ") + .append(kdc).append(':').append(port).append('\n'); + for (String s: conf) { + sb.append(" ").append(s).append('\n'); + } + return sb.append("}\n").toString(); } /** diff --git a/jdk/test/sun/security/krb5/auto/UdpTcp.java b/jdk/test/sun/security/krb5/auto/UdpTcp.java index e66f5d459fb..ae54b793527 100644 --- a/jdk/test/sun/security/krb5/auto/UdpTcp.java +++ b/jdk/test/sun/security/krb5/auto/UdpTcp.java @@ -43,9 +43,15 @@ public class UdpTcp { OneKDC kdc = new OneKDC(null); kdc.writeJAASConf(); - KDC.saveConfig(OneKDC.KRB5_CONF, kdc, - "udp_preference_limit = " - + (args[0].equals("UDP") ? "1000" : "100")); + // Two styles of kdc_timeout setting. One global, one realm-specific. + if (args[0].equals("UDP")) { + KDC.saveConfig(OneKDC.KRB5_CONF, kdc, + "kdc_timeout = 10s"); + } else { + kdc.addConf("kdc_timeout = 10s"); + KDC.saveConfig(OneKDC.KRB5_CONF, kdc, + "udp_preference_limit = 1"); + } Config.refresh(); ByteArrayOutputStream bo = new ByteArrayOutputStream(); @@ -56,7 +62,7 @@ public class UdpTcp { for (String line: new String(bo.toByteArray()).split("\n")) { if (line.contains(">>> KDCCommunication")) { - if (!line.contains(args[0])) { + if (!line.contains(args[0]) || !line.contains("timeout=10000")) { throw new Exception("No " + args[0] + " in: " + line); } } diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 3699f880456..f1b179b00f5 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -457,7 +457,7 @@ public abstract class PKCS11Test { osMap.put("SunOS-x86-32", new String[]{"/usr/lib/mps/"}); osMap.put("SunOS-amd64-64", new String[]{"/usr/lib/mps/64/"}); osMap.put("Linux-i386-32", new String[]{ - "/usr/lib/i386-linux-gnu/", "/usr/lib/"}); + "/usr/lib/i386-linux-gnu/", "/usr/lib32/", "/usr/lib/"}); osMap.put("Linux-amd64-64", new String[]{ "/usr/lib/x86_64-linux-gnu/", "/usr/lib/x86_64-linux-gnu/nss/", "/usr/lib64/"}); diff --git a/jdk/test/sun/security/tools/jarsigner/certpolicy.sh b/jdk/test/sun/security/tools/jarsigner/certpolicy.sh new file mode 100644 index 00000000000..20cf92b1618 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/certpolicy.sh @@ -0,0 +1,80 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8036709 +# @summary Java 7 jarsigner displays warning about cert policy tree +# +# @run shell certpolicy.sh +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +KT="$TESTJAVA/bin/keytool $TESTTOOLVMOPTS \ + -keypass changeit -storepass changeit -keystore ks -keyalg rsa" +JS="$TESTJAVA/bin/jarsigner $TESTTOOLVMOPTS -storepass changeit -keystore ks" +JAR="$TESTJAVA/bin/jar $TESTTOOLVMOPTS" + +rm ks 2> /dev/null +$KT -genkeypair -alias ca -dname CN=CA -ext bc +$KT -genkeypair -alias int -dname CN=Int +$KT -genkeypair -alias ee -dname CN=EE + +# CertificatePolicies [[PolicyId: [1.2.3]], [PolicyId: [1.2.4]]] +# PolicyConstraints: [Require: 0; Inhibit: unspecified] +$KT -certreq -alias int | \ + $KT -gencert -rfc -alias ca \ + -ext 2.5.29.32="30 0C 30 04 06 02 2A 03 30 04 06 02 2A 04" \ + -ext "2.5.29.36=30 03 80 01 00" -ext bc | \ + $KT -import -alias int + +# CertificatePolicies [[PolicyId: [1.2.3]]] +$KT -certreq -alias ee | \ + $KT -gencert -rfc -alias int \ + -ext 2.5.29.32="30 06 30 04 06 02 2A 03" | \ + $KT -import -alias ee + +$KT -export -alias ee -rfc > cc +$KT -export -alias int -rfc >> cc +$KT -export -alias ca -rfc >> cc + +$KT -delete -alias int + +ERR='' +$JAR cvf a.jar cc + +# Make sure the certchain in the signed jar contains all 3 certs +$JS -strict -certchain cc a.jar ee -debug || ERR="sign" +$JS -strict -verify a.jar -debug || ERR="$ERR verify" + +if [ "$ERR" = "" ]; then + echo "Success" + exit 0 +else + echo "Failed: $ERR" + exit 1 +fi + diff --git a/jdk/test/sun/security/tools/keytool/autotest.sh b/jdk/test/sun/security/tools/keytool/autotest.sh index 90e0a66a268..8154af5939b 100644 --- a/jdk/test/sun/security/tools/keytool/autotest.sh +++ b/jdk/test/sun/security/tools/keytool/autotest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -72,6 +72,8 @@ case "$OS" in Linux ) if [ $B32 = true ]; then LIBNAME=`find_one \ + "/usr/lib32/libsoftokn3.so" \ + "/usr/lib32/nss/libsoftokn3.so" \ "/usr/lib/libsoftokn3.so" \ "/usr/lib/i386-linux-gnu/nss/libsoftokn3.so" \ "/usr/lib/nss/libsoftokn3.so"` diff --git a/jdk/test/sun/security/tools/keytool/weaksize.sh b/jdk/test/sun/security/tools/keytool/weaksize.sh new file mode 100644 index 00000000000..f095645976f --- /dev/null +++ b/jdk/test/sun/security/tools/keytool/weaksize.sh @@ -0,0 +1,60 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8044755 +# @summary Add a test for algorithm constraints check in jarsigner +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# The sigalg used is MD2withRSA, which is obsolete. + +KT="$TESTJAVA/bin/keytool ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -keypass changeit + -keyalg rsa -sigalg MD2withRSA -debug" +JS="$TESTJAVA/bin/jarsigner ${TESTTOOLVMOPTS} -keystore ks + -storepass changeit -strict -debug" +JAR="$TESTJAVA/bin/jar ${TESTTOOLVMOPTS}" + +rm ks 2> /dev/null + +$KT -genkeypair -alias ca -dname CN=CA -ext bc +$KT -genkeypair -alias signer -dname CN=Signer + +$KT -certreq -alias signer | \ + $KT -gencert -alias ca -ext ku=dS -rfc | \ + $KT -importcert -alias signer + +$JAR cvf a.jar ks + +# We always trust a TrustedCertificateEntry +$JS a.jar ca || exit 1 + +# An end-entity cert must follow algorithm constraints +$JS a.jar signer && exit 2 + +exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh index 921524be9e0..ab4cb16dc13 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -42,7 +42,7 @@ fi rm -f jrunscriptTest.out 2>/dev/null ${JRUNSCRIPT} -J-Djava.awt.headless=true -l nashorn > jrunscriptTest.out 2>&1 < noAnnotations = List.nil(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 9066a03ae2a..783f6282d10 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -4696,7 +4696,7 @@ public class Types { assembleClassSig(rawOuter ? types.erasure(outer) : outer); - append('.'); + append(rawOuter ? '$' : '.'); Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname)); append(rawOuter ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength() + 1, c.flatname.getByteLength()) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index defa825bfe5..ba72525a70f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -2060,7 +2060,7 @@ public class Attr extends JCTree.Visitor { tree.constructor = constructor.baseSymbol(); final TypeSymbol csym = clazztype.tsym; - ResultInfo diamondResult = new ResultInfo(MTH, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { + ResultInfo diamondResult = new ResultInfo(pkind, newMethodTemplate(resultInfo.pt, argtypes, typeargtypes), new Check.NestedCheckContext(resultInfo.checkContext) { @Override public void report(DiagnosticPosition _unused, JCDiagnostic details) { enclosingContext.report(tree.clazz, diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index 6265199a8d7..151794853f6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -1221,25 +1221,102 @@ public class DeferredAttr extends JCTree.Visitor { } //slow path + Symbol sym = quicklyResolveMethod(env, tree); + + if (sym == null) { + result = ArgumentExpressionKind.POLY; + return; + } + + result = analyzeCandidateMethods(sym, ArgumentExpressionKind.PRIMITIVE, + argumentKindAnalyzer); + } + //where + private boolean isSimpleReceiver(JCTree rec) { + switch (rec.getTag()) { + case IDENT: + return true; + case SELECT: + return isSimpleReceiver(((JCFieldAccess)rec).selected); + case TYPEAPPLY: + case TYPEARRAY: + return true; + case ANNOTATED_TYPE: + return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType); + case APPLY: + return true; + default: + return false; + } + } + private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) { + return argumentKindAnalyzer.reduce(result, kind); + } + MethodAnalyzer argumentKindAnalyzer = + new MethodAnalyzer() { + @Override + public ArgumentExpressionKind process(MethodSymbol ms) { + return ArgumentExpressionKind.methodKind(ms, types); + } + @Override + public ArgumentExpressionKind reduce(ArgumentExpressionKind kind1, + ArgumentExpressionKind kind2) { + switch (kind1) { + case PRIMITIVE: return kind2; + case NO_POLY: return kind2.isPoly() ? kind2 : kind1; + case POLY: return kind1; + default: + Assert.error(); + return null; + } + } + @Override + public boolean shouldStop(ArgumentExpressionKind result) { + return result.isPoly(); + } + }; + + @Override + public void visitLiteral(JCLiteral tree) { + Type litType = attr.litType(tree.typetag); + result = ArgumentExpressionKind.standaloneKind(litType, types); + } + + @Override + void skip(JCTree tree) { + result = ArgumentExpressionKind.NO_POLY; + } + + private Symbol quicklyResolveMethod(Env env, final JCMethodInvocation tree) { final JCExpression rec = tree.meth.hasTag(SELECT) ? ((JCFieldAccess)tree.meth).selected : null; if (rec != null && !isSimpleReceiver(rec)) { - //give up if receiver is too complex (to cut down analysis time) - result = ArgumentExpressionKind.POLY; - return; + return null; } - Type site = rec != null ? - attribSpeculative(rec, env, attr.unknownTypeExprInfo).type : - env.enclClass.sym.type; + Type site; - while (site.hasTag(TYPEVAR)) { - site = site.getUpperBound(); + if (rec != null) { + if (rec.hasTag(APPLY)) { + Symbol recSym = quicklyResolveMethod(env, (JCMethodInvocation) rec); + if (recSym == null) + return null; + Symbol resolvedReturnType = + analyzeCandidateMethods(recSym, syms.errSymbol, returnSymbolAnalyzer); + if (resolvedReturnType == null) + return null; + site = resolvedReturnType.type; + } else { + site = attribSpeculative(rec, env, attr.unknownTypeExprInfo).type; + } + } else { + site = env.enclClass.sym.type; } List args = rs.dummyArgs(tree.args.length()); + Name name = TreeInfo.name(tree.meth); Resolve.LookupHelper lh = rs.new LookupHelper(name, site, args, List.nil(), MethodResolutionPhase.VARARITY) { @Override @@ -1254,61 +1331,60 @@ public class DeferredAttr extends JCTree.Visitor { } }; - Symbol sym = rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh); + return rs.lookupMethod(env, tree, site.tsym, rs.arityMethodCheck, lh); + } + //where: + MethodAnalyzer returnSymbolAnalyzer = new MethodAnalyzer() { + @Override + public Symbol process(MethodSymbol ms) { + ArgumentExpressionKind kind = ArgumentExpressionKind.methodKind(ms, types); + return kind != ArgumentExpressionKind.POLY ? ms.getReturnType().tsym : null; + } + @Override + public Symbol reduce(Symbol s1, Symbol s2) { + return s1 == syms.errSymbol ? s2 : s1 == s2 ? s1 : null; + } + @Override + public boolean shouldStop(Symbol result) { + return result == null; + } + }; - if (sym.kind == Kinds.AMBIGUOUS) { - Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym.baseSymbol(); - result = ArgumentExpressionKind.PRIMITIVE; - for (Symbol s : err.ambiguousSyms) { - if (result.isPoly()) break; - if (s.kind == Kinds.MTH) { - result = reduce(ArgumentExpressionKind.methodKind(s, types)); + /** + * Process the result of Resolve.lookupMethod. If sym is a method symbol, the result of + * MethodAnalyzer.process is returned. If sym is an ambiguous symbol, all the candidate + * methods are inspected one by one, using MethodAnalyzer.process. The outcomes are + * reduced using MethodAnalyzer.reduce (using defaultValue as the first value over which + * the reduction runs). MethodAnalyzer.shouldStop can be used to stop the inspection early. + */ + E analyzeCandidateMethods(Symbol sym, E defaultValue, MethodAnalyzer analyzer) { + switch (sym.kind) { + case Kinds.MTH: + return analyzer.process((MethodSymbol) sym); + case Kinds.AMBIGUOUS: + Resolve.AmbiguityError err = (Resolve.AmbiguityError)sym.baseSymbol(); + E res = defaultValue; + for (Symbol s : err.ambiguousSyms) { + if (s.kind == Kinds.MTH) { + res = analyzer.reduce(res, analyzer.process((MethodSymbol) s)); + if (analyzer.shouldStop(res)) + return res; + } } - } - } else { - result = (sym.kind == Kinds.MTH) ? - ArgumentExpressionKind.methodKind(sym, types) : - ArgumentExpressionKind.NO_POLY; + return res; + default: + return defaultValue; } } - //where - private boolean isSimpleReceiver(JCTree rec) { - switch (rec.getTag()) { - case IDENT: - return true; - case SELECT: - return isSimpleReceiver(((JCFieldAccess)rec).selected); - case TYPEAPPLY: - case TYPEARRAY: - return true; - case ANNOTATED_TYPE: - return isSimpleReceiver(((JCAnnotatedType)rec).underlyingType); - default: - return false; - } - } - private ArgumentExpressionKind reduce(ArgumentExpressionKind kind) { - switch (result) { - case PRIMITIVE: return kind; - case NO_POLY: return kind.isPoly() ? kind : result; - case POLY: return result; - default: - Assert.error(); - return null; - } - } - - @Override - public void visitLiteral(JCLiteral tree) { - Type litType = attr.litType(tree.typetag); - result = ArgumentExpressionKind.standaloneKind(litType, types); - } - - @Override - void skip(JCTree tree) { - result = ArgumentExpressionKind.NO_POLY; - } } + + /** Analyzer for methods - used by analyzeCandidateMethods. */ + interface MethodAnalyzer { + E process(MethodSymbol ms); + E reduce(E e1, E e2); + boolean shouldStop(E result); + } + //where private EnumSet deferredCheckerTags = EnumSet.of(LAMBDA, REFERENCE, PARENS, TYPECAST, diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index df41f3763a8..d554e0e2cc9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -344,8 +344,10 @@ public class Infer { } private boolean commonSuperWithDiffParameterization(Type t, Type s) { - Pair supers = getParameterizedSupers(t, s); - return (supers != null && !types.isSameType(supers.fst, supers.snd)); + for (Pair supers : getParameterizedSupers(t, s)) { + if (!types.isSameType(supers.fst, supers.snd)) return true; + } + return false; } private Type generateReferenceToTargetConstraint(JCTree tree, UndetVar from, @@ -604,30 +606,38 @@ public class Infer { /** max number of incorporation rounds */ static final int MAX_INCORPORATION_STEPS = 100; - /* If for two types t and s there is a least upper bound that is a - * parameterized type G, then there exists a supertype of 't' of the form - * G and a supertype of 's' of the form G - * which will be returned by this method. If no such supertypes exists then - * null is returned. + /* If for two types t and s there is a least upper bound that contains + * parameterized types G1, G2 ... Gn, then there exists supertypes of 't' of the form + * G1, G2, ... Gn and supertypes of 's' of the form + * G1, G2, ... Gn which will be returned by this method. + * If no such common supertypes exists then an empty list is returned. * * As an example for the following input: * * t = java.util.ArrayList * s = java.util.List * - * we get this ouput: + * we get this ouput (singleton list): * - * Pair[java.util.List,java.util.List] + * [Pair[java.util.List,java.util.List]] */ - private Pair getParameterizedSupers(Type t, Type s) { + private List> getParameterizedSupers(Type t, Type s) { Type lubResult = types.lub(t, s); - if (lubResult == syms.errType || lubResult == syms.botType || - !lubResult.isParameterized()) { - return null; + if (lubResult == syms.errType || lubResult == syms.botType) { + return List.nil(); } - Type asSuperOfT = types.asSuper(t, lubResult.tsym); - Type asSuperOfS = types.asSuper(s, lubResult.tsym); - return new Pair<>(asSuperOfT, asSuperOfS); + List supertypesToCheck = lubResult.isCompound() ? + ((IntersectionClassType)lubResult).getComponents() : + List.of(lubResult); + ListBuffer> commonSupertypes = new ListBuffer<>(); + for (Type sup : supertypesToCheck) { + if (sup.isParameterized()) { + Type asSuperOfT = types.asSuper(t, sup.tsym); + Type asSuperOfS = types.asSuper(s, sup.tsym); + commonSupertypes.add(new Pair<>(asSuperOfT, asSuperOfS)); + } + } + return commonSupertypes.toList(); } /** @@ -813,16 +823,17 @@ public class Infer { Type b1 = boundList.head; Type b2 = tmpTail.head; if (b1 != b2) { - Pair commonSupers = infer.getParameterizedSupers(b1, b2); - if (commonSupers != null) { + for (Pair commonSupers : infer.getParameterizedSupers(b1, b2)) { List allParamsSuperBound1 = commonSupers.fst.allparams(); List allParamsSuperBound2 = commonSupers.snd.allparams(); while (allParamsSuperBound1.nonEmpty() && allParamsSuperBound2.nonEmpty()) { //traverse the list of all params comparing them if (!allParamsSuperBound1.head.hasTag(WILDCARD) && !allParamsSuperBound2.head.hasTag(WILDCARD)) { - isSameType(inferenceContext.asUndetVar(allParamsSuperBound1.head), - inferenceContext.asUndetVar(allParamsSuperBound2.head), infer); + if (!isSameType(inferenceContext.asUndetVar(allParamsSuperBound1.head), + inferenceContext.asUndetVar(allParamsSuperBound2.head), infer)) { + infer.reportBoundError(uv, BoundErrorKind.BAD_UPPER); + } } allParamsSuperBound1 = allParamsSuperBound1.tail; allParamsSuperBound2 = allParamsSuperBound2.tail; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 8f28fa0550e..b933b4632b6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1925,6 +1925,13 @@ public class Code { return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); } + void removeLastRange() { + Range lastRange = lastRange(); + if (lastRange != null) { + aliveRanges.remove(lastRange); + } + } + @Override public String toString() { if (aliveRanges == null) { @@ -1955,9 +1962,7 @@ public class Code { } } } else { - if (!aliveRanges.isEmpty()) { - aliveRanges.remove(aliveRanges.size() - 1); - } + removeLastRange(); } } @@ -1965,16 +1970,14 @@ public class Code { if (aliveRanges.isEmpty()) { return false; } - Range range = lastRange(); - return range.length == Character.MAX_VALUE; + return lastRange().length == Character.MAX_VALUE; } public boolean isLastRangeInitialized() { if (aliveRanges.isEmpty()) { return false; } - Range range = lastRange(); - return range.start_pc != Character.MAX_VALUE; + return lastRange().start_pc != Character.MAX_VALUE; } public Range getWidestRange() { @@ -2095,7 +2098,7 @@ public class Code { v.closeRange(length); putVar(v); } else { - v.lastRange().start_pc = Character.MAX_VALUE; + v.removeLastRange(); } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index 943fbb58d62..37050775fb8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1800,8 +1800,7 @@ public class Gen extends JCTree.Visitor { genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET); thenExit = code.branch(goto_); if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) { - code.closeAliveRanges(tree.thenpart, - thenExit != null && tree.elsepart == null ? thenExit.pc : code.cp); + code.closeAliveRanges(tree.thenpart, code.cp); } } if (elseChain != null) { diff --git a/langtools/test/tools/javac/CaptureInSubtype.java b/langtools/test/tools/javac/CaptureInSubtype.java index 02d2f0e76e7..41d5a3b0b1b 100644 --- a/langtools/test/tools/javac/CaptureInSubtype.java +++ b/langtools/test/tools/javac/CaptureInSubtype.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 5044157 + * @test /nodynamiccopyright/ + * @bug 5044626 * @summary type system loophole in wildcard substitution * @author Gilad Bracha * - * @compile/fail CaptureInSubtype.java + * @compile/fail/ref=CaptureInSubtype.out -XDrawDiagnostics CaptureInSubtype.java */ import java.util.List; diff --git a/langtools/test/tools/javac/CaptureInSubtype.out b/langtools/test/tools/javac/CaptureInSubtype.out new file mode 100644 index 00000000000..9f3b9d65600 --- /dev/null +++ b/langtools/test/tools/javac/CaptureInSubtype.out @@ -0,0 +1,2 @@ +CaptureInSubtype.java:38:17: compiler.err.override.incompatible.ret: (compiler.misc.cant.override: m(), CaptureInSubtype.ShowFlaw, m(), CaptureInSubtype.SuperOfShowFlaw), CaptureInSubtype.Flaw, CaptureInSubtype.SuperOfFlaw> +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.java b/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.java index 40ee562cad1..89438c1cf07 100644 --- a/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.java +++ b/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.java @@ -1,34 +1,11 @@ /* - * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4041948 + * @test /nodynamiccopyright/ + * @bug 4041948 * @summary javac previously allowed interfaces to inherit methods with * inconsistent return types. - * @author turnidge + * @author turnidge * - * @compile/fail InconsistentReturn.java + * @compile/fail/ref=InconsistentReturn.out -XDrawDiagnostics InconsistentReturn.java */ interface I1{ int f(); diff --git a/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.out b/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.out new file mode 100644 index 00000000000..6adccb4a11f --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/InconsistentReturn.out @@ -0,0 +1,2 @@ +InconsistentReturn.java:17:1: compiler.err.types.incompatible.diff.ret: I2, I1, f() +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/Private.java b/langtools/test/tools/javac/OverrideChecks/Private.java index 5c107828b63..1b52fbfe461 100644 --- a/langtools/test/tools/javac/OverrideChecks/Private.java +++ b/langtools/test/tools/javac/OverrideChecks/Private.java @@ -1,32 +1,9 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6399361 * @summary java.lang.Override specification should be revised * @author Peter von der Ah\u00e9 - * @compile/fail Private.java + * @compile/fail/ref=Private.out -XDrawDiagnostics Private.java */ public class Private { diff --git a/langtools/test/tools/javac/OverrideChecks/Private.out b/langtools/test/tools/javac/OverrideChecks/Private.out new file mode 100644 index 00000000000..f49ef46a255 --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/Private.out @@ -0,0 +1,2 @@ +Private.java:14:5: compiler.err.method.does.not.override.superclass +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/StaticOverride.java b/langtools/test/tools/javac/OverrideChecks/StaticOverride.java index 4a31721cecf..149faa2550a 100644 --- a/langtools/test/tools/javac/OverrideChecks/StaticOverride.java +++ b/langtools/test/tools/javac/OverrideChecks/StaticOverride.java @@ -1,34 +1,11 @@ /* - * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4041948 4022450 + * @test /nodynamiccopyright/ + * @bug 4041948 4022450 * @summary javac previously allowed static methods to override non-static * methods in some cases. - * @author turnidge + * @author turnidge * - * @compile/fail StaticOverride.java + * @compile/fail/ref=StaticOverride.out -XDrawDiagnostics StaticOverride.java */ interface I{ int f(); diff --git a/langtools/test/tools/javac/OverrideChecks/StaticOverride.out b/langtools/test/tools/javac/OverrideChecks/StaticOverride.out new file mode 100644 index 00000000000..fe4bde62e9a --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/StaticOverride.out @@ -0,0 +1,2 @@ +StaticOverride.java:20:1: compiler.err.override.static: (compiler.misc.cant.implement: f(), C, f(), I) +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/T4720356a.java b/langtools/test/tools/javac/OverrideChecks/T4720356a.java index d0d0eeba527..308f7646cc4 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4720356a.java +++ b/langtools/test/tools/javac/OverrideChecks/T4720356a.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4720356 + * @test /nodynamiccopyright/ + * @bug 4720356 * @summary compiler fails to check cross-package overriding - * @author gafter + * @author gafter * - * @compile/fail T4720356a.java T4720356b.java + * @compile/fail/ref=T4720356a.out -XDrawDiagnostics T4720356a.java T4720356b.java */ package p1; diff --git a/langtools/test/tools/javac/OverrideChecks/T4720356a.out b/langtools/test/tools/javac/OverrideChecks/T4720356a.out new file mode 100644 index 00000000000..4c00ed53e2b --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/T4720356a.out @@ -0,0 +1,2 @@ +T4720356a.java:16:16: compiler.err.override.incompatible.ret: (compiler.misc.cant.override: m(), p1.T4720356c, m(), p1.T4720356a), int, void +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/T4720359a.java b/langtools/test/tools/javac/OverrideChecks/T4720359a.java index 1eb122182fa..c11a1d5578c 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4720359a.java +++ b/langtools/test/tools/javac/OverrideChecks/T4720359a.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4720359 + * @test /nodynamiccopyright/ + * @bug 4720359 * @summary javac fails to check cross-package hiding - * @author gafter + * @author gafter * - * @compile/fail T4720359a.java T4720359b.java + * @compile/fail/ref=T4720359a.out -XDrawDiagnostics T4720359a.java T4720359b.java */ package p1; diff --git a/langtools/test/tools/javac/OverrideChecks/T4720359a.out b/langtools/test/tools/javac/OverrideChecks/T4720359a.out new file mode 100644 index 00000000000..54635de3a1f --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/T4720359a.out @@ -0,0 +1,2 @@ +T4720359a.java:16:23: compiler.err.override.incompatible.ret: (compiler.misc.cant.override: m(), p1.T4720359c, m(), p1.T4720359a), int, void +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/T4721069.java b/langtools/test/tools/javac/OverrideChecks/T4721069.java index 0913f786de9..18259f791d4 100644 --- a/langtools/test/tools/javac/OverrideChecks/T4721069.java +++ b/langtools/test/tools/javac/OverrideChecks/T4721069.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4721069 + * @test /nodynamiccopyright/ + * @bug 4721069 * @summary javac allows an interface to override a final method in Object - * @author gafter + * @author gafter * - * @compile/fail T4721069.java + * @compile/fail/ref=T4721069.out -XDrawDiagnostics T4721069.java */ interface I { diff --git a/langtools/test/tools/javac/OverrideChecks/T4721069.out b/langtools/test/tools/javac/OverrideChecks/T4721069.out new file mode 100644 index 00000000000..d60f8efc465 --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/T4721069.out @@ -0,0 +1,2 @@ +T4721069.java:11:11: compiler.err.override.meth: (compiler.misc.cant.override: getClass(), I, getClass(), java.lang.Object), final +1 error diff --git a/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.java b/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.java index df8767b6425..d6b1db528b0 100644 --- a/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.java +++ b/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 4022674 + * @test /nodynamiccopyright/ + * @bug 4022674 * @summary Compiler should detect throws-clauses' conflict. - * @author turnidge + * @author turnidge * - * @compile/fail ThrowsConflict.java + * @compile/fail/ref=ThrowsConflict.out -XDrawDiagnostics ThrowsConflict.java */ interface I { diff --git a/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.out b/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.out new file mode 100644 index 00000000000..b70bdaa45ce --- /dev/null +++ b/langtools/test/tools/javac/OverrideChecks/ThrowsConflict.out @@ -0,0 +1,2 @@ +ThrowsConflict.java:20:1: compiler.err.override.meth.doesnt.throw: (compiler.misc.cant.implement: method(), A, method(), I), java.lang.Exception +1 error diff --git a/langtools/test/tools/javac/api/6410643/T6410643.java b/langtools/test/tools/javac/api/6410643/T6410643.java index 80ac51d8742..d423ef67423 100644 --- a/langtools/test/tools/javac/api/6410643/T6410643.java +++ b/langtools/test/tools/javac/api/6410643/T6410643.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -40,7 +40,7 @@ public class T6410643 extends ToolTester { Iterable classes, Iterable compilationUnits) { try { - task = tool.getTask(null, null, null, null, null, singleton((JavaFileObject)null)); + task = tool.getTask(null, null, null, options, classes, compilationUnits); throw new AssertionError("Error expected"); } catch (NullPointerException e) { System.err.println("Expected error occurred: " + e); diff --git a/langtools/test/tools/javac/capture/Capture2.java b/langtools/test/tools/javac/capture/Capture2.java index 6a8c6832cb3..a844cf47091 100644 --- a/langtools/test/tools/javac/capture/Capture2.java +++ b/langtools/test/tools/javac/capture/Capture2.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 5029773 - * @summary soundness problem with failure to subsitute wildcard as type formal argument + * @summary soundness problem with failure to substitute wildcard as type formal argument * @author gafter * - * @compile/fail Capture2.java + * @compile/fail/ref=Capture2.out -XDrawDiagnostics Capture2.java */ package capture2; diff --git a/langtools/test/tools/javac/capture/Capture2.out b/langtools/test/tools/javac/capture/Capture2.out new file mode 100644 index 00000000000..062aaa6393d --- /dev/null +++ b/langtools/test/tools/javac/capture/Capture2.out @@ -0,0 +1,2 @@ +Capture2.java:17:23: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.captureof: 1, ?, T) +1 error diff --git a/langtools/test/tools/javac/capture/Martin.java b/langtools/test/tools/javac/capture/Martin.java index 0429f55186d..05052fdb1e1 100644 --- a/langtools/test/tools/javac/capture/Martin.java +++ b/langtools/test/tools/javac/capture/Martin.java @@ -1,32 +1,9 @@ -/* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - /** - * @test + * @test /nodynamiccopyright/ * @bug 6384510 * @summary improper handling of wildcard captures * @author Martin Buchholz - * @compile/fail Martin.java + * @compile/fail/ref=Martin.out -XDrawDiagnostics Martin.java */ import java.util.List; diff --git a/langtools/test/tools/javac/capture/Martin.out b/langtools/test/tools/javac/capture/Martin.out new file mode 100644 index 00000000000..58e306063e9 --- /dev/null +++ b/langtools/test/tools/javac/capture/Martin.out @@ -0,0 +1,2 @@ +Martin.java:15:11: compiler.err.cant.apply.symbols: kindname.method, addAll, java.util.List,{(compiler.misc.inapplicable.method: kindname.method, java.util.Collection, addAll(java.util.Collection), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.util.List, java.util.Collection))),(compiler.misc.inapplicable.method: kindname.method, java.util.List, addAll(java.util.Collection), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.util.List, java.util.Collection))),(compiler.misc.inapplicable.method: kindname.method, java.util.List, addAll(int,java.util.Collection), (compiler.misc.arg.length.mismatch))} +1 error diff --git a/langtools/test/tools/javac/capture/T6594284.java b/langtools/test/tools/javac/capture/T6594284.java index d6bba17f701..cb8f2e94a51 100644 --- a/langtools/test/tools/javac/capture/T6594284.java +++ b/langtools/test/tools/javac/capture/T6594284.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6594284 * @summary NPE thrown when calling a method on an intersection type * @author Maurizio Cimadamore * - * @compile/fail T6594284.java + * @compile/fail/ref=T6594284.out -XDrawDiagnostics T6594284.java */ public class T6594284 { diff --git a/langtools/test/tools/javac/capture/T6594284.out b/langtools/test/tools/javac/capture/T6594284.out new file mode 100644 index 00000000000..80a9c47c9aa --- /dev/null +++ b/langtools/test/tools/javac/capture/T6594284.out @@ -0,0 +1,2 @@ +T6594284.java:18:24: compiler.err.not.within.bounds: ? extends T6594284.E, T +1 error diff --git a/langtools/test/tools/javac/cast/5064736/T5064736.java b/langtools/test/tools/javac/cast/5064736/T5064736.java index c12562cdcec..7b4cd3cbf7b 100644 --- a/langtools/test/tools/javac/cast/5064736/T5064736.java +++ b/langtools/test/tools/javac/cast/5064736/T5064736.java @@ -1,31 +1,8 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 5064736 * @summary Incompatible types are cast without error - * @compile/fail T5064736.java + * @compile/fail/ref=T5064736.out -XDrawDiagnostics T5064736.java */ public class T5064736 { diff --git a/langtools/test/tools/javac/cast/5064736/T5064736.out b/langtools/test/tools/javac/cast/5064736/T5064736.out new file mode 100644 index 00000000000..3afe295b4a3 --- /dev/null +++ b/langtools/test/tools/javac/cast/5064736/T5064736.out @@ -0,0 +1,2 @@ +T5064736.java:14:34: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T5064736.Foo, T5064736.Foo) +1 error diff --git a/langtools/test/tools/javac/cast/6219964/T6219964.java b/langtools/test/tools/javac/cast/6219964/T6219964.java index e952f134cce..6372f77435c 100644 --- a/langtools/test/tools/javac/cast/6219964/T6219964.java +++ b/langtools/test/tools/javac/cast/6219964/T6219964.java @@ -1,31 +1,8 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6219964 * @summary Compiler allows illegal cast of anonymous inner class - * @compile/fail T6219964.java + * @compile/fail/ref=T6219964.out -XDrawDiagnostics T6219964.java */ public class T6219964 { diff --git a/langtools/test/tools/javac/cast/6219964/T6219964.out b/langtools/test/tools/javac/cast/6219964/T6219964.out new file mode 100644 index 00000000000..ef807150d9e --- /dev/null +++ b/langtools/test/tools/javac/cast/6219964/T6219964.out @@ -0,0 +1,2 @@ +T6219964.java:13:27: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, T6219964.I) +1 error diff --git a/langtools/test/tools/javac/cast/6302956/T6302956.java b/langtools/test/tools/javac/cast/6302956/T6302956.java index 53eb12de3d8..cd6f3b88a9c 100644 --- a/langtools/test/tools/javac/cast/6302956/T6302956.java +++ b/langtools/test/tools/javac/cast/6302956/T6302956.java @@ -1,31 +1,8 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 6302956 * @summary Illegal cast allowed Properties -> Map - * @compile/fail T6302956.java + * @compile/fail/ref=T6302956.out -XDrawDiagnostics T6302956.java */ import java.util.Map; diff --git a/langtools/test/tools/javac/cast/6302956/T6302956.out b/langtools/test/tools/javac/cast/6302956/T6302956.out new file mode 100644 index 00000000000..ffe6a4eab18 --- /dev/null +++ b/langtools/test/tools/javac/cast/6302956/T6302956.out @@ -0,0 +1,2 @@ +T6302956.java:12:57: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.Properties, java.util.Map) +1 error diff --git a/langtools/test/tools/javac/cast/6548436/T6548436d.java b/langtools/test/tools/javac/cast/6548436/T6548436d.java index bf8833b26b0..52ea32b1fc2 100644 --- a/langtools/test/tools/javac/cast/6548436/T6548436d.java +++ b/langtools/test/tools/javac/cast/6548436/T6548436d.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6548436 + * @test /nodynamiccopyright/ + * @bug 6548436 * @summary Incorrect inconvertible types error * @author Maurizio Cimadamore * - * @compile/fail T6548436d.java + * @compile/fail/ref=T6548436d.out -XDrawDiagnostics T6548436d.java */ public class T6548436d { diff --git a/langtools/test/tools/javac/cast/6548436/T6548436d.out b/langtools/test/tools/javac/cast/6548436/T6548436d.out new file mode 100644 index 00000000000..6d5bb7c1155 --- /dev/null +++ b/langtools/test/tools/javac/cast/6548436/T6548436d.out @@ -0,0 +1,2 @@ +T6548436d.java:15:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T6548436d.Base, T6548436d.Base) +1 error diff --git a/langtools/test/tools/javac/cast/BoxedArray.java b/langtools/test/tools/javac/cast/BoxedArray.java index 58d3678897e..13a6f4ca88e 100644 --- a/langtools/test/tools/javac/cast/BoxedArray.java +++ b/langtools/test/tools/javac/cast/BoxedArray.java @@ -1,33 +1,10 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 5014309 * @summary REGRESSION: compiler allows cast from Integer[] to int[] * @author gafter * - * @compile/fail BoxedArray.java + * @compile/fail/ref=BoxedArray.out -XDrawDiagnostics BoxedArray.java */ public class BoxedArray { diff --git a/langtools/test/tools/javac/cast/BoxedArray.out b/langtools/test/tools/javac/cast/BoxedArray.out new file mode 100644 index 00000000000..2d8770c3a12 --- /dev/null +++ b/langtools/test/tools/javac/cast/BoxedArray.out @@ -0,0 +1,2 @@ +BoxedArray.java:13:22: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer[], int[]) +1 error diff --git a/langtools/test/tools/javac/flow/LVTHarness.java b/langtools/test/tools/javac/flow/LVTHarness.java index c679f52f526..7039a626a57 100644 --- a/langtools/test/tools/javac/flow/LVTHarness.java +++ b/langtools/test/tools/javac/flow/LVTHarness.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,8 @@ /* * @test - * @bug 7047734 8027660 - * @summary The LVT is not generated correctly during some try/catch scenarios; + * @bug 7047734 8027660 8037937 + * @summary The LVT is not generated correctly during some try/catch scenarios * javac crash while creating LVT entry for a local variable defined in * an inner block * @library /tools/javac/lib @@ -120,7 +120,7 @@ public class LVTHarness { for (Map.Entry entry : aliveRangeMap.entrySet()) { if (!seenAliveRanges.contains(entry.getKey())) { error("Redundant @AliveRanges annotation on method " + - entry.getKey().elem); + entry.getKey().elem + " with key " + entry.getKey()); } } } @@ -134,7 +134,7 @@ public class LVTHarness { for (Method method : classFile.methods) { for (ElementKey elementKey: aliveRangeMap.keySet()) { String methodDesc = method.getName(constantPool) + - method.descriptor.getParameterTypes(constantPool); + method.descriptor.getParameterTypes(constantPool).replace(" ", ""); if (methodDesc.equals(elementKey.elem.toString())) { checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); seenAliveRanges.add(elementKey); diff --git a/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java b/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java index 3e6cc893794..d789853b43a 100644 --- a/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java +++ b/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java @@ -33,7 +33,7 @@ public class TestCaseIfElse { @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) @AliveRange(varName="o", bytecodeStart=21, bytecodeLength=9) - void m2(String[] args) { + void m2() { Object o; int i = 5; if (i != 5) { @@ -45,4 +45,19 @@ public class TestCaseIfElse { } o = "finish"; } + + @AliveRange(varName="o", bytecodeStart=11, bytecodeLength=3) + @AliveRange(varName="o", bytecodeStart=17, bytecodeLength=2) + Object m3(boolean cond1, boolean cond2) { + Object o; + if (cond1) { + if (cond2) { + o = "then"; + } else { + o = "else"; + return null; + } + } + return null; + } } diff --git a/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.java b/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.java new file mode 100644 index 00000000000..40014d68c25 --- /dev/null +++ b/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8041713 + * @summary Type inference of non-existent method references crashes the compiler + * @compile/fail/ref=DiamondPlusUnexistingMethodRefCrashTest.out -XDrawDiagnostics DiamondPlusUnexistingMethodRefCrashTest.java + */ + +public class DiamondPlusUnexistingMethodRefCrashTest { + DiamondPlusUnexistingMethodRefCrashTest m = + new DiamondPlusUnexistingMethodRefCrashTest<>(DiamondPlusUnexistingMethodRefCrashTest::doNotExists); +} diff --git a/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.out b/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.out new file mode 100644 index 00000000000..c7bba78d87d --- /dev/null +++ b/langtools/test/tools/javac/generics/diamond/T8041713/DiamondPlusUnexistingMethodRefCrashTest.out @@ -0,0 +1,2 @@ +DiamondPlusUnexistingMethodRefCrashTest.java:10:55: compiler.err.invalid.mref: kindname.method, (compiler.misc.cant.resolve.location.args: kindname.method, doNotExists, , , (compiler.misc.location: kindname.class, DiamondPlusUnexistingMethodRefCrashTest, null)) +1 error diff --git a/langtools/test/tools/javac/generics/inference/8043893/T8043893.java b/langtools/test/tools/javac/generics/inference/8043893/T8043893.java new file mode 100644 index 00000000000..9897582eae1 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8043893/T8043893.java @@ -0,0 +1,43 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8043893 + * @summary Inference doesn't report error on incompatible upper bounds + * + * @compile -source 7 T8043893.java + * @compile/fail/ref=T8043893.out -Xlint:-options -XDrawDiagnostics -source 8 T8043893.java + */ + +class T8043893 { + + interface S1 { } + + interface S2 { } + + interface T0 { } + + interface T1 extends S1, S2 { } + + interface T2 extends S1, S2 { } + + interface T3 extends S1, S2 { } + + interface T4 extends S1 { } + + interface T5 extends S1 { } + + void m_intersection(T8043893 a) { } + + void m_class(T8043893 a) { } + + void test() { + //intersection type checks + m_intersection(new T8043893()); //ok in both 7 and 8 - Z = T1 + m_intersection(new T8043893()); //ok in 7, fails in 8 + m_intersection(new T8043893()); //ok in 7, fails in 8 + m_intersection(new T8043893()); //ok in both 7 and 8 - Z = T0 & T1 + //class type checks + m_class(new T8043893()); //ok in both 7 and 8 - Z = T4 + m_class(new T8043893()); //ok in 7, fails in 8 + m_class(new T8043893()); //ok in both 7 and 8 - Z = T0 & T4 + } +} diff --git a/langtools/test/tools/javac/generics/inference/8043893/T8043893.out b/langtools/test/tools/javac/generics/inference/8043893/T8043893.out new file mode 100644 index 00000000000..5fd584a0669 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/8043893/T8043893.out @@ -0,0 +1,4 @@ +T8043893.java:35:9: compiler.err.cant.apply.symbol: kindname.method, m_intersection, T8043893, T8043893, kindname.class, T8043893, (compiler.misc.incompatible.upper.bounds: Z, T8043893.T2,T8043893.T1) +T8043893.java:36:9: compiler.err.cant.apply.symbol: kindname.method, m_intersection, T8043893, T8043893, kindname.class, T8043893, (compiler.misc.incompatible.upper.bounds: Z, T8043893.T3,T8043893.T1) +T8043893.java:40:9: compiler.err.cant.apply.symbol: kindname.method, m_class, T8043893, T8043893, kindname.class, T8043893, (compiler.misc.incompatible.upper.bounds: Z, T8043893.T5,T8043893.T4) +3 errors diff --git a/langtools/test/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out b/langtools/test/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out index 52b1702f12a..22d9a9729fc 100644 --- a/langtools/test/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out +++ b/langtools/test/tools/javac/generics/inference/EagerReturnTypeResolution/EagerReturnTypeResolutionTestb.out @@ -3,37 +3,37 @@ EagerReturnTypeResolutionTestb.java:43:9: compiler.err.cant.apply.symbol: kindna EagerReturnTypeResolutionTestb.java:44:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:45:26: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:74:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) -EagerReturnTypeResolutionTestb.java:75:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:75:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:77:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) EagerReturnTypeResolutionTestb.java:78:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) -EagerReturnTypeResolutionTestb.java:79:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:79:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:81:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:82:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) -EagerReturnTypeResolutionTestb.java:83:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) +EagerReturnTypeResolutionTestb.java:83:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:85:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) EagerReturnTypeResolutionTestb.java:86:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object)) EagerReturnTypeResolutionTestb.java:87:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) EagerReturnTypeResolutionTestb.java:89:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:90:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.I) EagerReturnTypeResolutionTestb.java:91:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:92:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:92:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:94:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.J>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) EagerReturnTypeResolutionTestb.java:95:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:96:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:96:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:98:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:99:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:100:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.J, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:100:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.J,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:102:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) EagerReturnTypeResolutionTestb.java:103:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) EagerReturnTypeResolutionTestb.java:104:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) EagerReturnTypeResolutionTestb.java:105:15: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:106:9: compiler.err.cant.apply.symbol: kindname.method, takeI, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Integer, java.lang.Integer,java.lang.String) +EagerReturnTypeResolutionTestb.java:106:15: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:108:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, EagerReturnTypeResolutionTestb.I>>, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object)) EagerReturnTypeResolutionTestb.java:109:21: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:110:9: compiler.err.cant.apply.symbol: kindname.method, takeIString, EagerReturnTypeResolutionTestb.I, java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object)) +EagerReturnTypeResolutionTestb.java:110:21: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:112:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: EagerReturnTypeResolutionTestb.I>>, EagerReturnTypeResolutionTestb.I,java.lang.Object) EagerReturnTypeResolutionTestb.java:113:24: compiler.err.cant.apply.symbol: kindname.method, eq2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.inferred.do.not.conform.to.eq.bounds: EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J) -EagerReturnTypeResolutionTestb.java:114:30: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object&EagerReturnTypeResolutionTestb.J&EagerReturnTypeResolutionTestb.K, EagerReturnTypeResolutionTestb.I,EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) +EagerReturnTypeResolutionTestb.java:114:24: compiler.err.cant.apply.symbol: kindname.method, upper2, java.util.List,java.util.List, java.util.List>,java.util.List, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.incompatible.upper.bounds: T, EagerReturnTypeResolutionTestb.K,EagerReturnTypeResolutionTestb.J,java.lang.Object) EagerReturnTypeResolutionTestb.java:174:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) EagerReturnTypeResolutionTestb.java:175:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) EagerReturnTypeResolutionTestb.java:176:9: compiler.err.cant.apply.symbol: kindname.method, takeLong, long, java.lang.Double, kindname.class, EagerReturnTypeResolutionTestb, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.infer.no.conforming.instance.exists: , T, long)) diff --git a/langtools/test/tools/javac/lambda/T8031967.java b/langtools/test/tools/javac/lambda/T8031967.java new file mode 100644 index 00000000000..3836ecd0406 --- /dev/null +++ b/langtools/test/tools/javac/lambda/T8031967.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8031967 + * @summary Ensure javac can handle very deeply nested chain of method invocations occurring as + * a parameter to other method invocations. + * @run main T8031967 + */ + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.List; + +import javax.tools.DiagnosticListener; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; + +public class T8031967 { + + public static void main(String... args) throws IOException { + new T8031967().run(); + } + + final int depth = 50; + + private void run() throws IOException { + runTestCase(true); + runTestCase(false); + } + + private void runTestCase(boolean withErrors) throws IOException { + StringBuilder code = new StringBuilder(); + + code.append("public class Test {\n" + + " private void test() {\n" + + " GroupLayout l = new GroupLayout();\n" + + " l.setHorizontalGroup(\n"); + + gen(code, depth); + code.append(" );\n" + + " }\n"); + if (!withErrors) { + code.append(" class GroupLayout {\n" + + " ParallelGroup createParallelGroup() {return null;}\n" + + " ParallelGroup createParallelGroup(int i) {return null;}\n" + + " ParallelGroup createParallelGroup(int i, int j) {return null;}\n" + + " void setHorizontalGroup(Group g) { }\n" + + " }\n" + + " \n" + + " class Group {\n" + + " Group addGroup(Group g) { return this; }\n" + + " Group addGroup(int i, Group g) { return this; }\n" + + " Group addGap(int i) { return this; }\n" + + " Group addGap(long l) { return this; }\n" + + " Group addGap(int i, int j) { return this; }\n" + + " Group addComponent(Object c) { return this; }\n" + + " Group addComponent(int i, Object c) { return this; }\n" + + " }\n" + + " class ParallelGroup extends Group {\n" + + " Group addGroup(Group g) { return this; }\n" + + " Group addGroup(int i, Group g) { return this; }\n" + + " Group addGap(int i) { return this; }\n" + + " Group addGap(int i, int j) { return this; }\n" + + " Group addComponent(Object c) { return this; }\n" + + " Group addComponent(int i, Object c) { return this; }\n" + + " }\n"); + } + + code.append("}\n"); + + JavaSource source = new JavaSource(code.toString()); + List sourceList = Arrays.asList(source); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + DiagnosticListener noErrors = (diagnostic) -> { + throw new IllegalStateException("Should not produce errors: " + diagnostic); + }; + JavacTask task = (JavacTask) compiler.getTask(null, null, withErrors ? null : noErrors, + null, null, sourceList); + + task.analyze(); + } + + private void gen(StringBuilder code, int depth) { + code.append("l.createParallelGroup()\n"); + if (depth > 0) { + code.append(".addGroup(\n"); + gen(code, depth - 1); + code.append(")"); + } + + code.append(".addGap(1)\n" + + ".addComponent(new Object())\n" + + ".addGap(1)\n" + + ".addComponent(new Object())"); + } + + class JavaSource extends SimpleJavaFileObject { + + final String code; + public JavaSource(String code) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.code = code; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return code; + } + } +} diff --git a/langtools/test/tools/javac/types/BadSigTest.java b/langtools/test/tools/javac/types/BadSigTest.java new file mode 100644 index 00000000000..14b3ff9cbb0 --- /dev/null +++ b/langtools/test/tools/javac/types/BadSigTest.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8037934 + * @summary Javac generates invalid signatures for local types + * @run main BadSigTest + */ + +public class BadSigTest { + void m(){ + class Local1{} + class Local2 extends Local1{} + Local2.class.getTypeParameters(); + } + public static void main(String[] args) { + new BadSigTest().m(); + } +} diff --git a/nashorn/.hgignore b/nashorn/.hgignore index 6d68c1d476d..6cfabad507b 100644 --- a/nashorn/.hgignore +++ b/nashorn/.hgignore @@ -13,6 +13,8 @@ webrev.zip *.clazz *.log *.orig +*.rej +*~ genfiles.properties hotspot.log .DS_Store* diff --git a/nashorn/.hgtags b/nashorn/.hgtags index f5e58e3f192..31e3bb77617 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -248,3 +248,5 @@ b3517e51f40477f10db8bc30a557aa0ea712c274 jdk9-b02 282e9a675e079cc84dbfaa4c10050f08397faab0 jdk9-b12 be4580ae56e2ef0ce521d3f840753eaa83cacf33 jdk9-b13 806df06b6ac58d3e9c9c6a680dbdd7a6c94ca700 jdk9-b14 +32b66f4661eac52f8b04fb3d7703feb2c96febb7 jdk9-b15 +fed8c83dfba4dce94d2ae1cb82f026634ff2a3e4 jdk9-b16 diff --git a/nashorn/bin/checkintest.sh b/nashorn/bin/checkintest.sh deleted file mode 100644 index c4a9e96ca12..00000000000 --- a/nashorn/bin/checkintest.sh +++ /dev/null @@ -1,266 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -#best pass rate at test 262 known -TEST262_PASS_AT_LEAST=435 - -RUN_TEST="true" -RUN_TEST262="true" -RUN_NODE="true" -KEEP_OUTPUT="true" -CLEAN_AND_BUILD_NASHORN="true" - -#the stable node version to sync against -NODE_LAST_STABLE=v0.6.18 - -#parse args -for arg in $* -do - if [ $arg = "--no-test" ]; then - RUN_TEST="false" - echo "**** WARNING - you have disabled 'ant test', which is a minimum checkin requirement..." - elif [ $arg = "--no-262" ]; then - RUN_TEST262="false" - elif [ $arg = "--no-node" ]; then - RUN_NODE="false" - elif [ $arg = "--no-build" ]; then - CLEAN_AND_BUILD_NASHORN="false" - elif [ $arg = "--no-logs" ]; then - KEEP_OUTPUT="false" - fi -done - -function lastpart() { - arr=$(echo $1 | tr "/" "\n") - for x in $arr - do - _last=$x - done - echo $_last -} - -function check_installed() { - which $1 >/dev/null - if [ $? -ne 0 ]; then - echo "Error $1 not installed: $?" - exit 2 - fi -} - -check_installed hg -check_installed git -check_installed mv -check_installed git - -PWD=$(pwd); - -while [ -z $NASHORN_ROOT ] -do - if [ -e $PWD/.hg ]; then - NASHORN_ROOT=${PWD} - break - fi - PWD=$(dirname ${PWD}) -done - -echo "Nashorn root detected at ${NASHORN_ROOT}" - -COMMON_ROOT=$(dirname $NASHORN_ROOT) -echo "Common root is ${COMMON_ROOT}" - -echo "Running checkintest..." - -ABSOLUTE_NASHORN_HOME=$COMMON_ROOT/$(lastpart $NASHORN_ROOT) - -if [ $CLEAN_AND_BUILD_NASHORN != "false" ]; then - echo "Cleaning and building nashorn at $ABSOLUTE_NASHORN_HOME/nashorn..." - $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant clean >/dev/null 2>/dev/null) - $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant jar >/dev/null 2>/dev/null) - echo "Done." -fi - -function failure_check() { - while read line - do - LINE=$(echo $line | grep "Tests run") - if [ "${LINE}" != "" ]; then - RESULT=$(echo $line | grep "Failures: 0" | grep "Errors: 0") - if [ "${RESULT}" == "" ]; then - TESTNAME=$2 - echo "There were errors in ${TESTNAME} : ${LINE}" - exit 1 - fi - fi - done < $1 -} - -function test() { - TEST_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) - echo "Running 'ant test' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..." - $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test >$TEST_OUTPUT) - echo "Done." - - failure_check $TEST_OUTPUT - - echo "**** SUCCESS: 'ant test' successful" - - if [ $KEEP_OUTPUT == "true" ]; then - cp $TEST_OUTPUT ./checkintest.test.log - rm -fr $TEST_OUTPUT - fi -} - -if [ $RUN_TEST != "false" ]; then - test; -fi - -function test262() { - - echo "Running 'ant test262parallel' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..." - TEST262_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) - - echo "Looking for ${ABSOLUTE_NASHORN_HOME}/test/test262..." - - if [ ! -e $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 ]; then - echo "test262 is missing... looking in $COMMON_ROOT..." - if [ ! -e $COMMON_ROOT/test262 ]; then - echo "... not there either... cloning from repo..." - hg clone http://hg.ecmascript.org/tests/test262 $COMMON_ROOT/test262 >/dev/null 2>/dev/null - echo "Done." - fi - echo "Adding soft link ${COMMON_ROOT}/test262 -> ${ABSOLUTE_NASHORN_HOME}/test/test262..." - ln -s $COMMON_ROOT/test262 $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 - echo "Done." - fi - - echo "Ensuring test262 is up to date..." - $(cd $ABSOLUTE_NASHORN_HOME/nashorn/test/test262; hg pull -u >/dev/null 2>/dev/null) - echo "Done." - - echo "Running test262..." - $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test262parallel > $TEST262_OUTPUT) - - FAILED=$(cat $TEST262_OUTPUT|grep "Tests run:"| cut -d ' ' -f 15 |tr -cd '"[[:digit:]]') - if [ $FAILED -gt $TEST262_PASS_AT_LEAST ]; then - echo "FAILURE: There are ${FAILED} failures in test262 and can be no more than ${TEST262_PASS_AT_LEAST}" - cp $TEST262_OUTPUT ./checkintest.test262.log - echo "See ./checkintest.test262.log" - echo "Terminating due to error" - exit 1 - elif [ $FAILED -lt $TEST262_PASS_AT_LEAST ]; then - echo "There seem to have been fixes to 262. ${FAILED} < ${TEST262_PASS_AT_LEAST}. Please update limit in bin/checkintest.sh" - fi - - echo "**** SUCCESS: Test262 passed with no more than ${TEST262_PASS_AT_LEAST} failures." - - if [ $KEEP_OUTPUT == "true" ]; then - cp $TEST262_OUTPUT ./checkintest.test262.log - rm -fr $TEST262_OUTPUT - fi -} - -if [ $RUN_TEST262 != "false" ]; then - test262; -fi; - -function testnode() { - TESTNODEJAR_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) - - echo "Running node tests..." -#replace node jar properties nashorn with this nashorn - - NODEJAR_PROPERTIES=~/nodejar.properties - - NODE_HOME=$(cat $NODEJAR_PROPERTIES | grep ^node.home | cut -f2 -d=) - NASHORN_HOME=$(cat $NODEJAR_PROPERTIES | grep ^nashorn.home | cut -f2 -d=) - - ABSOLUTE_NODE_HOME=$COMMON_ROOT/$(lastpart $NODE_HOME) - - echo "Writing nodejar.properties..." - - cat > $NODEJAR_PROPERTIES << EOF -node.home=../node -nashorn.home=../$(lastpart $NASHORN_ROOT) -EOF - echo "Done." - echo "Checking node home ${ABSOLUTE_NODE_HOME}..." - - if [ ! -e $ABSOLUTE_NODE_HOME ]; then - echo "Node base dir not found. Cloning node..." - $(cd $COMMON_ROOT; git clone https://github.com/joyent/node.git $(lastpart $NODE_HOME) >/dev/null 2>/dev/null) - echo "Done." - echo "Updating to last stable version ${NODE_LAST_STABLE}..." - $(cd $ABSOLUTE_NODE_HOME; git checkout $NODE_LAST_STABLE >/dev/null 2>/dev/null) - echo "Done." - echo "Running configure..." - $(cd $ABSOLUTE_NODE_HOME; ./configure >/dev/null 2>/dev/null) - echo "Done." - fi - - echo "Ensuring node is built..." -#make sure node is built - $(cd $ABSOLUTE_NODE_HOME; make >/dev/null 2>/dev/null) - echo "Done." - - NODEJAR_HOME=$COMMON_ROOT/nodejar - - if [ ! -e $NODEJAR_HOME ]; then - echo "No node jar home found. cloning from depot..." - $(cd $COMMON_ROOT; hg clone https://hg.kenai.com/hg/nodejs~source nodejar >/dev/null 2>/dev/null) - $(cd $COMMON_ROOT/nodejar; ant >/dev/null) - echo "Done." - echo "Copying node files..." - $(cd $COMMON_ROOT/nodejar; ant copy-node-files >/dev/null 2>/dev/null) - echo "Patching node files..." - $(cd $COMMON_ROOT/nodejar; ant patch-node-files >/dev/null 2>/dev/null) - echo "Done." - fi - - echo "Ensuring node.jar is up to date from source depot..." - $(cd $COMMON_ROOT/nodejar; hg pull -u >/dev/null 2>/dev/null) - echo "Done." - - echo "Installing nashorn..." - $(cd $COMMON_ROOT/nodejar; ant >/dev/null) - echo "Done." - - echo "Running node.jar test..." - $(cd $COMMON_ROOT/nodejar; mvn clean verify >$TESTNODEJAR_OUTPUT) - echo "Done." - - failure_check $TESTNODEJAR_OUTPUT - - echo "**** SUCCESS: Node test successful." - - if [ $KEEP_OUTPUT == "true" ]; then - rm -fr $TESTNODEJAR_OUTPUT - cp $TESTNODEJAR_OUTPUT ./checkintest.nodejar.log - fi -} - -if [ $RUN_NODE != "false" ]; then - testnode; -fi; - -echo "Finished" diff --git a/nashorn/bin/fixwhitespace.sh b/nashorn/bin/fixwhitespace.sh index cac757db100..d3274700f71 100644 --- a/nashorn/bin/fixwhitespace.sh +++ b/nashorn/bin/fixwhitespace.sh @@ -22,9 +22,16 @@ # questions. # -#convert tabs to spaces -find . -name "*.java" -exec sed -i "" 's/ / /g' {} \; - -#remove trailing whitespace -find . -name "*.java" -exec sed -i "" 's/[ ]*$//' \{} \; +fix() { + #convert tabs to spaces + find . -name $1 -exec sed -i "" 's/ / /g' {} \; + #remove trailing whitespace + find . -name $1 -exec sed -i "" 's/[ ]*$//' \{} \; +} +if [ ! -z $1 ]; then + fix $1; +else + fix "*.java" + fix "*.js" +fi diff --git a/nashorn/bin/run_octane.sh b/nashorn/bin/run_octane.sh new file mode 100644 index 00000000000..a50137f06fa --- /dev/null +++ b/nashorn/bin/run_octane.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# Copyright (c) 2010, 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. +# + +LOG="./octane_$(date|sed "s/ /_/g"|sed "s/:/_/g").log" + +run_one() { + sh ../bin/runopt.sh -scripting ../test/script/basic/run-octane.js -- $1 --verbose --iterations 25 | tee -a $LOG +} + +if [ -z $1 ]; then + + run_one "box2d" + run_one "code-load" + run_one "crypto" + run_one "deltablue" + run_one "earley-boyer" + run_one "gbemu" + run_one "mandreel" + run_one "navier-stokes" + run_one "pdfjs" + run_one "raytrace" + run_one "regexp" + run_one "richards" + run_one "splay" + run_one "typescript" + run_one "zlib" + +else + run_one $1 +fi diff --git a/nashorn/bin/rundiff.sh b/nashorn/bin/rundiff.sh new file mode 100644 index 00000000000..a672104ae7c --- /dev/null +++ b/nashorn/bin/rundiff.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +# do two runs of a script, one optimistic and one pessimistic, expect identical outputs +# if not, display and error message and a diff + +which opendiff >/dev/null +RES=$? +if [ $RES = 0 ]; then + DIFFTOOL=opendiff +else + DIFFTOOL=diff +fi + +OPTIMISTIC=out_optimistic +PESSIMISTIC=out_pessimistic +$JAVA_HOME/bin/java -ea -jar ../dist/nashorn.jar ${@} >$PESSIMISTIC +$JAVA_HOME/bin/java -ea -Dnashorn.optimistic -jar ../dist/nashorn.jar ${@} >$OPTIMISTIC + +if ! diff -q $PESSIMISTIC $OPTIMISTIC >/dev/null ; then + echo "Failure! Results are different" + echo "" + $DIFFTOOL $PESSIMISTIC $OPTIMISTIC +else + echo "OK - Results are identical" +fi diff --git a/nashorn/bin/runopt.sh b/nashorn/bin/runopt.sh new file mode 100644 index 00000000000..7c308bd1b64 --- /dev/null +++ b/nashorn/bin/runopt.sh @@ -0,0 +1,110 @@ +#!/bin/sh +# +# Copyright (c) 2010, 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. +# + +########################################################################################### +# This is a helper script to evaluate nashorn with optimistic types +# it produces a flight recording for every run, and uses the best +# known flags for performance for the current configration +########################################################################################### + +# Flags to instrument lambdaform computation, caching, interpretation and compilation +# Default compile threshold for lambdaforms is 30 +#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true" + + +# Flags to run trusted tests from the Nashorn test suite +#FLAGS="-Djava.security.manager -Djava.security.policy=../build/nashorn.policy -Dnashorn.debug" + + +# Unique timestamped file name for JFR recordings. For JFR, we also have to +# crank up the stack cutoff depth to 1024, because of ridiculously long lambda form +# stack traces. +# +# It is also recommended that you go into $JAVA_HOME/jre/lib/jfr/default.jfc and +# set the "method-sampling-interval" Normal and Maximum sample time as low as you +# can go (10 ms on most platforms). The default is normally higher. The increased +# sampling overhead is usually negligible for Nashorn runs, but the data is better + +JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr" + + +# Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming +# that we run the script from the make dir +DIR=.. +NASHORN_JAR=$DIR/dist/nashorn.jar + + +# The built Nashorn jar is placed first in the bootclasspath to override the JDK +# nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in +# nashorn count as system assertions in this configuration + +# Type profiling default level is 111, 222 adds some compile time, but is faster + +$JAVA_HOME/bin/java \ +$FLAGS \ +-ea \ +-esa \ +-Xbootclasspath/p:$NASHORN_JAR \ +-Xms2G -Xmx2G \ +-XX:TypeProfileLevel=222 \ +-cp $CLASSPATH:../build/test/classes/ \ +jdk.nashorn.tools.Shell ${@} + +# Below are flags that may come in handy, but aren't used for default runs + +# Testing out new code optimizations using the generic hotspot "new code" parameter +#-XX:+UnlockDiagnosticVMOptions \ +#-XX:+UseNewCode \ + +# Flight recorder +#-XX:+UnlockCommercialFeatures \ +#-XX:+FlightRecorder \ +#-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024 \ + + +# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine, +# keeping this flag around for experimental reasons. Replace + with - to switch it off +#-XX:+UseTypeSpeculation \ + + +# Same with math intrinsics. They should be enabled by default in 8u20 and 9 +#-XX:+UseMathExactIntrinsics \ + + +# Add -Dnashorn.time to time the compilation phases. +#-Dnashorn.time \ + + +# Add ShowHiddenFrames to get lambda form internals on the stack traces +#-XX:+ShowHiddenFrames \ + + +# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product, +# That tired compilation is switched off, for C2 only output and that the number of +# compiler threads is set to 1 for determinsm. +#-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \ + +# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments) +# -XX:IncreaseFirstTierCompileThresholdAt=XX + diff --git a/nashorn/bin/runopt_noassert.sh b/nashorn/bin/runopt_noassert.sh new file mode 100644 index 00000000000..6331972ab64 --- /dev/null +++ b/nashorn/bin/runopt_noassert.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true" + +FILENAME="./optimistic_noassert_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr" + +DIR=.. +NASHORN_JAR=$DIR/dist/nashorn.jar + +$JAVA_HOME/bin/java \ +$FLAGS \ +-Xbootclasspath/p:$NASHORN_JAR \ +-Xms2G -Xmx2G \ +-XX:+UnlockCommercialFeatures \ +-XX:+FlightRecorder \ +-XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$FILENAME,stackdepth=1024 \ +-XX:TypeProfileLevel=222 \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+UseTypeSpeculation \ +-XX:+UseMathExactIntrinsics \ +-XX:+UnlockDiagnosticVMOptions \ +-cp $CLASSPATH:../build/test/classes/ \ +jdk.nashorn.tools.Shell ${@} + +#-XX:+ShowHiddenFrames \ +#-XX:+PrintOptoAssembly \ +#-XX:-TieredCompilation \ +#-XX:CICompilerCount=1 \ diff --git a/nashorn/bin/runopt_nojfr.sh b/nashorn/bin/runopt_nojfr.sh new file mode 100644 index 00000000000..daf3c6a0073 --- /dev/null +++ b/nashorn/bin/runopt_nojfr.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +#FLAGS="-Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true" + +DIR=.. +NASHORN_JAR=$DIR/dist/nashorn.jar + +$JAVA_HOME/bin/java \ +$FLAGS \ +-ea \ +-esa \ +-Xbootclasspath/p:$NASHORN_JAR \ +-Xms2G -Xmx2G \ +-XX:+UnlockCommercialFeatures \ +-XX:TypeProfileLevel=222 \ +-XX:+UnlockExperimentalVMOptions \ +-XX:+UseTypeSpeculation \ +-XX:+UseMathExactIntrinsics \ +-XX:+UnlockDiagnosticVMOptions \ +-XX:+UseNewCode \ +-cp $CLASSPATH:../build/test/classes/ \ +jdk.nashorn.tools.Shell ${@} + +#-XX:+ShowHiddenFrames \ +#-XX:+PrintOptoAssembly \ +#-XX:-TieredCompilation \ +#-XX:CICompilerCount=1 \ diff --git a/nashorn/bin/verbose_octane.bat b/nashorn/bin/verbose_octane.bat deleted file mode 100644 index ab9e48469a5..00000000000 --- a/nashorn/bin/verbose_octane.bat +++ /dev/null @@ -1,59 +0,0 @@ -rem -rem Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. -rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -rem -rem This code is free software; you can redistribute it and/or modify it -rem under the terms of the GNU General Public License version 2 only, as -rem published by the Free Software Foundation. -rem -rem This code is distributed in the hope that it will be useful, but WITHOUT -rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -rem version 2 for more details (a copy is included in the LICENSE file that -rem accompanied this code). -rem -rem You should have received a copy of the GNU General Public License version -rem 2 along with this work; if not, write to the Free Software Foundation, -rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -rem -rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -rem or visit www.oracle.com if you need additional information or have any -rem questions. -rem -@echo off - -if "%JAVA_HOME%" neq "" ( - call :run "%JAVA_HOME%/bin/java" -) else ( - call :run java -) -goto :EOF - -:run -setlocal -set NASHORN_JAR=dist/nashorn.jar -set JVM_FLAGS=-Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -jar %NASHORN_JAR% -set JVM_FLAGS7=-Xbootclasspath/p:%NASHORN_JAR% %JVM_FLAGS% -set OCTANE_ARGS=--verbose --iterations 7 - -%1 -fullversion 2>&1 | findstr /L /C:"version ""1.7" -if %errorlevel% equ 0 ( - set CMD=%1 %JVM_FLAGS7% -) else ( - %1 -fullversion - set CMD=%1 %JVM_FLAGS% -) - -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/box2d.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/code-load.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/crypto.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/deltablue.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/gbemu.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/navier-stokes.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/pdfjs.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/raytrace.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/regexp.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/richards.js %OCTANE_ARGS% -%CMD% test/script/basic/run-octane.js -- test/script/external/octane/splay.js %OCTANE_ARGS% -endlocal -goto :EOF diff --git a/nashorn/bin/verbose_octane.sh b/nashorn/bin/verbose_octane.sh deleted file mode 100644 index 1895afed146..00000000000 --- a/nashorn/bin/verbose_octane.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -ITERS=$1 -if [ -z $ITERS ]; then - ITERS=7 -fi -NASHORN_JAR=dist/nashorn.jar -JVM_FLAGS="-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+UnlockDiagnosticVMOptions -Dnashorn.unstable.relink.threshold=8 -Xms2G -Xmx2G -XX:+TieredCompilation -server -jar ${NASHORN_JAR}" -JVM_FLAGS7="-Xbootclasspath/p:${NASHORN_JAR} ${JVM_FLAGS}" -OCTANE_ARGS="--verbose --iterations ${ITERS}" - -BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "navier-stokes.js" "pdfjs.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" ) -# TODO mandreel.js has metaspace issues - -if [ ! -z $JAVA7_HOME ]; then - echo "running ${ITERS} iterations with java7 using JAVA_HOME=${JAVA7_HOME}..." - for BENCHMARK in "${BENCHMARKS[@]}" - do - CMD="${JAVA7_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}" - $CMD - done -else - echo "no JAVA7_HOME set. skipping java7" -fi - -if [ ! -z $JAVA8_HOME ]; then - echo "running ${ITERS} iterations with java8 using JAVA_HOME=${JAVA8_HOME}..." - for BENCHMARK in "${BENCHMARKS[@]}" - do - CMD="${JAVA8_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/${BENCHMARK} ${OCTANE_ARGS}" - $CMD - done -else - echo "no JAVA8_HOME set." -fi - -echo "Done" diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java index bb6abbc0170..2059567bb31 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java @@ -31,29 +31,29 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.GETTER_PREFIX; import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME; import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_CREATE_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.ACCESSORPROPERTY_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.LIST_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.ARRAYLIST_INIT_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTION_ADD_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.COLLECTIONS_EMPTY_LIST; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC; diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java index 67cbde44fdd..2661e096a48 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java @@ -32,9 +32,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFFIX; import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java index e47f8b160ad..1132db98541 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java @@ -319,7 +319,7 @@ public final class MemberInfo implements Cloneable { break; case FUNCTION: { final Type returnType = Type.getReturnType(javaDesc); - if (!isValidJSType(returnType)) { + if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { error("return value of a @Function method should be a valid JS type, found " + returnType); } final Type[] argTypes = Type.getArgumentTypes(javaDesc); @@ -351,7 +351,7 @@ public final class MemberInfo implements Cloneable { break; case SPECIALIZED_FUNCTION: { final Type returnType = Type.getReturnType(javaDesc); - if (!isValidJSType(returnType)) { + if (!(isValidJSType(returnType) || Type.VOID_TYPE == returnType)) { error("return value of a @SpecializedFunction method should be a valid JS type, found " + returnType); } final Type[] argTypes = Type.getArgumentTypes(javaDesc); @@ -371,9 +371,8 @@ public final class MemberInfo implements Cloneable { error("first argument of a @Getter method should be of Object type, found: " + argTypes[0]); } - final Type returnType = Type.getReturnType(javaDesc); - if (!isJavaLangObject(returnType)) { - error("return type of a @Getter method should be Object, found: " + javaDesc); + if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) { + error("return type of getter should not be void"); } } break; diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java index 479d1d31f21..a8d6ae2b981 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java @@ -413,7 +413,8 @@ public class MethodGenerator extends MethodVisitor { super.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", - "(Ljava/lang/String;)V", false); + "(Ljava/lang/String;)V", + false); } // print the object on the top of the stack @@ -426,6 +427,7 @@ public class MethodGenerator extends MethodVisitor { super.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", - "(Ljava/lang/Object;)V", false); + "(Ljava/lang/Object;)V", + false); } } diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java index 7b1fff7607e..8eb19b7d112 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java @@ -31,9 +31,9 @@ import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_FIELD_NAME; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC; diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java index 1d724187dbe..fb72bbe65ec 100644 --- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java +++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java @@ -26,9 +26,8 @@ package jdk.nashorn.internal.tools.nasgen; import java.lang.invoke.MethodHandle; -import java.lang.reflect.Method; -import java.util.Collection; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import jdk.internal.org.objectweb.asm.Type; diff --git a/nashorn/docs/DEVELOPER_README b/nashorn/docs/DEVELOPER_README index 9a2fffdf84a..fe140954c1a 100644 --- a/nashorn/docs/DEVELOPER_README +++ b/nashorn/docs/DEVELOPER_README @@ -737,26 +737,6 @@ an implementation based on Joni, the regular expression engine used by the JRuby project. The default value for this flag is "joni" -SYSTEM PROPERTY: -Dnashorn.time - -This enables timers for various phases of script compilation. The timers -will be dumped when the Nashorn process exits. We see a percentage value -of how much time was spent not executing bytecode (i.e. compilation and -internal tasks) at the end of the report. - -Here is an example: - -[JavaScript Parsing] 61 ms -[Constant Folding] 11 ms -[Control Flow Lowering] 26 ms -[Type Attribution] 81 ms -[Range Analysis] 0 ms -[Code Splitting] 29 ms -[Type Finalization] 19 ms -[Bytecode Generation] 189 ms -[Code Installation] 7 ms -Total runtime: 508 ms (Non-runtime: 423 ms [83%]) - =============== 2. The loggers. =============== @@ -887,6 +867,34 @@ etc. It will also show the internal representation of respective field (Object in the normal case, unless running with the dual field representation) +* time + +This enables timers for various phases of script compilation. The timers +will be dumped when the Nashorn process exits. We see a percentage value +of how much time was spent not executing bytecode (i.e. compilation and +internal tasks) at the end of the report. + +A finer level than "info" will show individual compilation timings as they +happen. + +Here is an example: + +[time] Accumulated complation phase Timings: +[time] +[time] 'JavaScript Parsing' 1076 ms +[time] 'Constant Folding' 159 ms +[time] 'Control Flow Lowering' 303 ms +[time] 'Program Point Calculation' 282 ms +[time] 'Builtin Replacement' 71 ms +[time] 'Code Splitting' 670 ms +[time] 'Symbol Assignment' 474 ms +[time] 'Scope Depth Computation' 249 ms +[time] 'Optimistic Type Assignment' 186 ms +[time] 'Local Variable Type Calculation' 526 ms +[time] 'Bytecode Generation' 5177 ms +[time] 'Class Installation' 1854 ms +[time] +[time] Total runtime: 11994 ms (Non-runtime: 11027 ms [91%]) ======================= 3. Undocumented options @@ -914,11 +922,10 @@ A short summary follows: -cp, -classpath (-cp path. Specify where to find user class files.) - -co, --compile-only (Compile script without running. Exit after compilation) + -co, --compile-only (Compile without running.) param: [true|false] default: false - -d, --dump-debug-dir (specify a destination directory to dump class files. - This must be combined with the --compile-only option to work) + -d, --dump-debug-dir (specify a destination directory to dump class files.) param: --debug-lines (Generate line number table in .class files.) @@ -954,10 +961,6 @@ A short summary follows: -h, -help (Print help for command line flags.) param: [true|false] default: false - --lazy-compilation (EXPERIMENTAL: Use lazy code generation strategies - do not compile - the entire script at once.) - param: [true|false] default: false - --loader-per-compile (Create a new class loader per compile.) param: [true|false] default: true @@ -965,16 +968,16 @@ A short summary follows: param: default: en-US --log (Enable logging of a given level for a given number of sub systems. - [for example: --log=fields:finest,codegen:info]) + [for example: --log=fields:finest,codegen:info].) param: ,* - -nj, --no-java (No Java support) + -nj, --no-java (Disable Java support.) param: [true|false] default: false - -nse, --no-syntax-extensions (No non-standard syntax extensions) + -nse, --no-syntax-extensions (Disallow non-standard syntax extensions.) param: [true|false] default: false - -nta, --no-typed-arrays (No Typed arrays support) + -nta, --no-typed-arrays (Disable typed arrays support.) param: [true|false] default: false --parse-only (Parse without compiling.) @@ -983,13 +986,15 @@ A short summary follows: --print-ast (Print abstract syntax tree.) param: [true|false] default: false - --print-code (Print bytecode.) - param: [true|false] default: false + -pc, --print-code (Print generated bytecode. If a directory is specified, nothing will + be dumped to stderr. Also, in that case, .dot files will be generated + for all functions or for the function with the specified name only.) + param: [dir:,function:] --print-lower-ast (Print lowered abstract syntax tree.) param: [true|false] default: false - --print-lower-parse (Print the parse tree after lowering.) + -plp, --print-lower-parse (Print the parse tree after lowering.) param: [true|false] default: false --print-mem-usage (Print memory usage of IR after each compile stage.) @@ -998,7 +1003,7 @@ A short summary follows: --print-no-newline (Print function will not print new line char.) param: [true|false] default: false - --print-parse (Print the parse tree.) + -pp, --print-parse (Print the parse tree.) param: [true|false] default: false --print-symbols (Print the symbol table.) @@ -1007,21 +1012,13 @@ A short summary follows: -pcs, --profile-callsites (Dump callsite profile data.) param: [true|false] default: false - --range-analysis (EXPERIMENTAL: Do range analysis using known compile time types, - and try to narrow number types) - param: [true|false] default: false - -scripting (Enable scripting features.) param: [true|false] default: false - --specialize-calls (EXPERIMENTAL: Specialize all or a set of method according - to callsite parameter types) - param: [=function_1,...,function_n] - - --stderr (Redirect stderr to a filename or to another tty, e.g. stdout) + --stderr (Redirect stderr to a filename or to another tty, e.g. stdout.) param: - --stdout (Redirect stdout to a filename or to another tty, e.g. stderr) + --stdout (Redirect stdout to a filename or to another tty, e.g. stderr.) param: -strict (Run scripts in strict mode.) @@ -1031,7 +1028,7 @@ A short summary follows: param: default: Europe/Stockholm -tcs, --trace-callsites (Enable callsite trace mode. Options are: miss [trace callsite misses] - enterexit [trace callsite enter/exit], objects [print object properties]) + enterexit [trace callsite enter/exit], objects [print object properties].) param: [=[option,]*] --verify-code (Verify byte code before running.) diff --git a/nashorn/make/build-benchmark.xml b/nashorn/make/build-benchmark.xml index 8225df1cf0c..ae76718fd03 100644 --- a/nashorn/make/build-benchmark.xml +++ b/nashorn/make/build-benchmark.xml @@ -1,384 +1,333 @@ - - - - - - - - - - + + + + + + - - - - + + + - - - - + - - - - + - - - - - - + + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - - - + + + + + - - - - + - - - - + - - - - - - + + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - - + + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + - - - - + - - - - + - - - - - + + + + - - - - + - - - - + - - - - + + + - - - - + - - - + + + + + + + + + + + + + + + + + + + - - - + + + + + - - - - - - - - - - - - + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + - + - + @@ -386,11 +335,11 @@ - + - + @@ -400,12 +349,14 @@ fork="true" dir="."> + + - + - + @@ -416,18 +367,22 @@ - + + dir="${sunspider-test-sys-prop.test.js.roots}" + excludes="${sunspider-test-sys-prop.test.js.exclude.list}"> + + - + + + + + + @@ -448,6 +406,9 @@ + + + @@ -458,8 +419,13 @@ fork="true" dir="."> + + + + + diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 88c4e9cf379..0edc7e9e4c9 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -1,4 +1,5 @@ + + - - @@ -51,7 +51,7 @@ - + @@ -196,14 +196,16 @@ - - + + - + @@ -211,6 +213,19 @@ + + + + + + + + + + + + @@ -349,6 +364,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + @@ -380,6 +396,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + @@ -397,18 +414,6 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - - - - - - - - - - - - @@ -417,15 +422,15 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - + - + - + - - + + @@ -440,7 +445,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - + @@ -459,7 +464,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - + @@ -499,6 +504,26 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + + + + + + + + + + + + + + + + + + @@ -606,7 +631,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - + @@ -627,4 +652,6 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + + diff --git a/nashorn/make/nbproject/ide-targets.xml b/nashorn/make/nbproject/ide-targets.xml index 70b3e68fcb7..a592cff6a07 100644 --- a/nashorn/make/nbproject/ide-targets.xml +++ b/nashorn/make/nbproject/ide-targets.xml @@ -31,9 +31,10 @@ + - + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index ba4e57a1003..dd43dda4f2b 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 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 @@ -53,6 +53,7 @@ parallel.test.runner=jdk.nashorn.internal.test.framework.ParallelTestRunner # test classes directory build.test.classes.dir=${build.dir}/test/classes + # nashorn test jar - internal tests jar and api tests jar nashorn.internal.tests.jar=${build.dir}/nashorn-internal-tests.jar nashorn.api.tests.jar=${build.dir}/nashorn-api-tests.jar @@ -60,6 +61,7 @@ nashorn.api.tests.jar=${build.dir}/nashorn-api-tests.jar # test results directory build.test.results.dir=${build.dir}/test/reports build.nosecurity.test.results.dir=${build.dir}/test/nosecurity/reports +build.nooptimistic.test.results.dir=${build.dir}/test/nooptimistic/reports # This directory is removed when the project is cleaned: dist.dir=dist @@ -167,21 +169,14 @@ test-sys-prop.test.js.unchecked.dir=${test262.dir} # test root for octane octane-test-sys-prop.test.js.roots=${test.external.dir}/octane/ -# run octane benchmars in separate processes? +# run octane benchmars in separate processes? (recommended) octane-test-sys-prop.separate.process=true # framework root for octane octane-test-sys-prop.test.js.framework=${test.basic.dir}/run-octane.js -# list of tests to be excluded -# mandreel excluded due to OOM -octane-test-sys-prop.test.js.exclude.list=\ - base.js \ - run.js \ - mandreel.js - # test root for sunspider -sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0/ +sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/tests/sunspider-1.0.2/ # framework root for sunspider sunspider-test-sys-prop.test.js.framework=${test.basic.dir}/runsunspider.js @@ -197,6 +192,7 @@ test262-test-sys-prop.test.js.shared.context=true # test262 test root test262-test-sys-prop.test.js.roots=${test262.suite.dir} + # test262 enable/disable strict mode tests test262-test-sys-prop.test.js.enable.strict.mode=true @@ -268,48 +264,113 @@ test.src.dir=test/src run.test.xmx=2G run.test.xms=2G +# uncomment this jfr.args to enable light recordings. the stack needs to be cranked up to 1024 frames, +# or everything will as of the now drown in lambda forms and be cut off. +# +#jfr.args=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath="test_suite.jfr",stackdepth=1024 \ + +jfr.args= + run.test.user.language=tr run.test.user.country=TR -run.test.jvmargs.common=-server -XX:+TieredCompilation -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError - -#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M -# -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods +run.test.jvmargs.common=\ + -server \ + -Dfile.encoding=UTF-8 \ + -Duser.language=${run.test.user.language} \ + -Duser.country=${run.test.user.country} \ + ${jfr.args} \ + -XX:+HeapDumpOnOutOfMemoryError # turn on assertions for tests -run.test.jvmargs.main=${run.test.jvmargs.common} -ea +run.test.jvmargs.main=${run.test.jvmargs.common} -ea -Dnashorn.lazy -#-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M -run.test.jvmargs.octane.main=${run.test.jvmargs.common} +# extra jvmargs that might be useful for debugging +# +# -XX:+UnlockDiagnosticVMOptions +# +# turn off compressed class pointers in metaspace +# -XX:-UseCompressedKlassPointers +# +# dump the heap after every GC +# -XX:+PrintHeapAtGC +# +# manually set a metaspace size for class data +# -XX:ClassMetaspaceSize=300M +# +# print out methods compiled +# -XX:+PrintCompilation +# +# print all compiled nmethods with oopmaps and lots of other info +# -XX:+PrintNMethods +# Use best known performance options for octane +run.test.jvmargs.octane.main=${run.test.jvmargs.common} -Dnashorn.lazy -XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode -XX:TypeProfileLevel=222 + +# Security manager args - make sure that we run with the nashorn.policy that the build creates run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy # VM options for script tests with @fork option test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -cp ${run.test.classpath} # path of rhino.jar for benchmarks -rhino.jar= +rhino.dir= +rhino.jar=${rhino.dir}/js.jar v8.shell=d8 +# How many iterations should 'ant octane' run for each +# benchmark +octane.iterations=25 + +# List of octane tests to run, as properties prefixed with +# "octane.benchmark." mapping to the benchmark name in +# the test harness +# +# Octane tests that are disabled should have their entire line +# commented out Tests may be disabled for functionality reasons when +# they have bugs or when the runtime doesn't handle them (yet) +octane.benchmark.box2d=box2d +#octane.benchmark.code-load=code-load +octane.benchmark.crypto=crypto +octane.benchmark.deltablue=deltablue +octane.benchmark.earley-boyer=earley-boyer +octane.benchmark.gbemu=gbemu +octane.benchmark.navier-stokes=navier-stokes +octane.benchmark.mandreel=mandreel +octane.benchmark.pdfjs=pdfjs +octane.benchmark.raytrace=raytrace +octane.benchmark.regexp=regexp +octane.benchmark.richards=richards +octane.benchmark.splay=splay +#octane.benchmark.typescript=typescript +#octane.benchmark.zlib=zlib + #path to rhino jar file octaneperf-sys-prop.rhino.jar=${rhino.jar} #timeout for performance tests in minutes octaneperf-sys-prop.timeout.value=10 -################ -# codecoverage # -################ - #enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties +#how many iterations to run sunspider after warmup +sunspider.iterations=3000 + +################# +# code coverage # +################# + +#enable/disable code coverage; please redifine in the ${user.home}/.nashorn.project.local.properties make.code.coverage=false - #type of codecoverage; one of static or dynamic. Now only dynamic is supported + +#type of codecoverage; one of static or dynamic. Now only dynamic is supported jcov=dynamic - #naming of CC results - #NB directory specified in the cc.dir will be cleaned up!!! + +#naming of CC results +#NB directory specified in the cc.dir will be cleaned up!!! cc.dir=${basedir}/../Codecoverage_Nashorn cc.result.file.name=CC_${jcov}_nashorn.xml - #dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties + +#dynamic CC parameters; please redefine in the ${user.home}/.nashorn.project.local.properties jcov2.lib.dir=${basedir}/../jcov2/lib jcov.jar=${jcov2.lib.dir}/jcov.jar cc.include=jdk\.nashorn\.* diff --git a/nashorn/samples/filebrowser.js b/nashorn/samples/filebrowser.js new file mode 100644 index 00000000000..da00553a4ec --- /dev/null +++ b/nashorn/samples/filebrowser.js @@ -0,0 +1,100 @@ +#// Usage: jjs -fx filebrowser.js -- + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Uses -fx and javafx TreeView to visualize directories +if (!$OPTIONS._fx) { + print("Usage: jjs -fx filebrowser.js -- "); + exit(1); +} + +// Java classes used +var File = Java.type("java.io.File"); +var Files = Java.type("java.nio.file.Files"); + +// check directory argument, if passed +var dir = arguments.length > 0? new File(arguments[0]) : new File("."); +if (! dir.isDirectory()) { + print(dir + " is not a directory!"); + exit(2); +} + +// JavaFX classes used +var FXCollections = Java.type("javafx.collections.FXCollections"); +var Scene = Java.type("javafx.scene.Scene"); +var TreeItem = Java.type("javafx.scene.control.TreeItem"); +var TreeView = Java.type("javafx.scene.control.TreeView"); + +// create a subclass of JavaFX TreeItem class +var LazyTreeItem = Java.extend(TreeItem); + +// lazily filling children of a directory LazyTreeItem +function buildChildren(dir) { + var children = FXCollections.observableArrayList(); + var stream = Files.list(dir.toPath()); + stream.forEach(function(path) { + var file = path.toFile(); + var item = file.isDirectory()? + makeLazyTreeItem(file) : new TreeItem(file.name); + children.add(item); + }); + stream.close(); + return children; +} + +// create an instance LazyTreeItem with override methods +function makeLazyTreeItem(dir) { + var item = new LazyTreeItem(dir.name) { + expanded: false, + isLeaf: function() false, + getChildren: function() { + if (! this.expanded) { + // call super class (TreeItem) method + Java.super(item).getChildren().setAll(buildChildren(dir)); + this.expanded = true; + } + // call super class (TreeItem) method + return Java.super(item).getChildren(); + } + } + return item; +} + +// JavaFX start method +function start(stage) { + stage.title = dir.absolutePath; + var rootItem = makeLazyTreeItem(dir); + rootItem.expanded = true; + var tree = new TreeView(rootItem); + stage.scene = new Scene(tree, 300, 450); + stage.show(); +} diff --git a/nashorn/samples/word_histogram.js b/nashorn/samples/word_histogram.js new file mode 100644 index 00000000000..9c739ea0375 --- /dev/null +++ b/nashorn/samples/word_histogram.js @@ -0,0 +1,53 @@ +#nashorn word histogram of a file + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This example demonstrates how to print word histogram + * of a given text file using regex, array and JSON + * functions. + */ + +if (arguments.length < 1) { + print("Usage: jjs -scripting word_histogram.js -- "); + exit(1); +} + +var obj = {}; + +readFully(arguments[0]). + split(/[^\w+]/). + forEach(function(x) + (x in obj? obj[x]++ : obj[x] = 1)); + +print(JSON.stringify(obj)); + diff --git a/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java b/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java index c2ad4eb26c9..45f191a042f 100644 --- a/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java +++ b/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java @@ -103,8 +103,27 @@ import jdk.internal.dynalink.support.Lookup; * handle is always at the start of the chain. */ public class ChainedCallSite extends AbstractRelinkableCallSite { - private static final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class, - MethodHandle.class); + private static final MethodHandle PRUNE_CATCHES = + MethodHandles.insertArguments( + Lookup.findOwnSpecial( + MethodHandles.lookup(), + "prune", + MethodHandle.class, + MethodHandle.class, + boolean.class), + 2, + true); + + private static final MethodHandle PRUNE_SWITCHPOINTS = + MethodHandles.insertArguments( + Lookup.findOwnSpecial( + MethodHandles.lookup(), + "prune", + MethodHandle.class, + MethodHandle.class, + boolean.class), + 2, + false); private final AtomicReference> invocations = new AtomicReference<>(); @@ -112,7 +131,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite { * Creates a new chained call site. * @param descriptor the descriptor for the call site. */ - public ChainedCallSite(CallSiteDescriptor descriptor) { + public ChainedCallSite(final CallSiteDescriptor descriptor) { super(descriptor); } @@ -126,24 +145,26 @@ public class ChainedCallSite extends AbstractRelinkableCallSite { } @Override - public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback) { - relinkInternal(guardedInvocation, fallback, false); + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) { + relinkInternal(guardedInvocation, fallback, false, false); } @Override - public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback) { - relinkInternal(guardedInvocation, fallback, true); + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) { + relinkInternal(guardedInvocation, fallback, true, false); } - private MethodHandle relinkInternal(GuardedInvocation invocation, MethodHandle relink, boolean reset) { + private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) { final LinkedList currentInvocations = invocations.get(); @SuppressWarnings({ "unchecked", "rawtypes" }) final LinkedList newInvocations = currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone(); - // First, prune the chain of invalidated switchpoints. - for(Iterator it = newInvocations.iterator(); it.hasNext();) { - if(it.next().hasBeenInvalidated()) { + // First, prune the chain of invalidated switchpoints, we always do this + // We also remove any catches if the remove catches flag is set + for(final Iterator it = newInvocations.iterator(); it.hasNext();) { + final GuardedInvocation inv = it.next(); + if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) { it.remove(); } } @@ -160,12 +181,13 @@ public class ChainedCallSite extends AbstractRelinkableCallSite { // prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we // rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger. - final MethodHandle pruneAndInvoke = makePruneAndInvokeMethod(relink); + final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, getPruneSwitchpoints()); + final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, getPruneCatches()); // Fold the new chain MethodHandle target = relink; - for(GuardedInvocation inv: newInvocations) { - target = inv.compose(pruneAndInvoke, target); + for(final GuardedInvocation inv: newInvocations) { + target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches); } // If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case @@ -177,15 +199,31 @@ public class ChainedCallSite extends AbstractRelinkableCallSite { return target; } + /** + * Get the switchpoint pruning function for a chained call site + * @return function that removes invalidated switchpoints tied to callsite guard chain and relinks + */ + protected MethodHandle getPruneSwitchpoints() { + return PRUNE_SWITCHPOINTS; + } + + /** + * Get the catch pruning function for a chained call site + * @return function that removes all catches tied to callsite guard chain and relinks + */ + protected MethodHandle getPruneCatches() { + return PRUNE_CATCHES; + } + /** * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that * chain. * @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink). * @return a method handle for prune-and-invoke */ - private MethodHandle makePruneAndInvokeMethod(MethodHandle relink) { + private MethodHandle makePruneAndInvokeMethod(final MethodHandle relink, final MethodHandle prune) { // Bind prune to (this, relink) - final MethodHandle boundPrune = MethodHandles.insertArguments(PRUNE, 0, this, relink); + final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relink); // Make it ignore all incoming arguments final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList()); // Invoke prune, then invoke the call site target with original arguments @@ -193,7 +231,7 @@ public class ChainedCallSite extends AbstractRelinkableCallSite { } @SuppressWarnings("unused") - private MethodHandle prune(MethodHandle relink) { - return relinkInternal(null, relink, false); + private MethodHandle prune(final MethodHandle relink, final boolean catches) { + return relinkInternal(null, relink, false, catches); } } diff --git a/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java b/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java index b7edb9d8399..d687fd62f2c 100644 --- a/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java +++ b/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java @@ -117,7 +117,7 @@ public class DefaultBootstrapper { * @param type the method signature at the call site * @return a new {@link MonomorphicCallSite} linked with the default dynamic linker. */ - public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) { + public static CallSite bootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) { return bootstrapInternal(caller, name, type); } @@ -133,11 +133,11 @@ public class DefaultBootstrapper { * @param type the method signature at the call site * @return a new {@link MonomorphicCallSite} linked with the default dynamic linker. */ - public static CallSite publicBootstrap(MethodHandles.Lookup caller, String name, MethodType type) { + public static CallSite publicBootstrap(final MethodHandles.Lookup caller, final String name, final MethodType type) { return bootstrapInternal(MethodHandles.publicLookup(), name, type); } - private static CallSite bootstrapInternal(MethodHandles.Lookup caller, String name, MethodType type) { + private static CallSite bootstrapInternal(final MethodHandles.Lookup caller, final String name, final MethodType type) { return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type))); } } diff --git a/nashorn/src/jdk/internal/dynalink/DynamicLinker.java b/nashorn/src/jdk/internal/dynalink/DynamicLinker.java index 155ff309d01..e7e58d2a8f4 100644 --- a/nashorn/src/jdk/internal/dynalink/DynamicLinker.java +++ b/nashorn/src/jdk/internal/dynalink/DynamicLinker.java @@ -140,7 +140,6 @@ import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl; * @author Attila Szegedi */ public class DynamicLinker { - private static final String CLASS_NAME = DynamicLinker.class.getName(); private static final String RELINK_METHOD_NAME = "relink"; @@ -148,6 +147,7 @@ public class DynamicLinker { private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite"; private final LinkerServices linkerServices; + private final GuardedInvocationFilter prelinkFilter; private final int runtimeContextArgCount; private final boolean syncOnRelink; private final int unstableRelinkThreshold; @@ -156,18 +156,20 @@ public class DynamicLinker { * Creates a new dynamic linker. * * @param linkerServices the linkerServices used by the linker, created by the factory. + * @param prelinkFilter see {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter)} * @param runtimeContextArgCount see {@link DynamicLinkerFactory#setRuntimeContextArgCount(int)} */ - DynamicLinker(LinkerServices linkerServices, int runtimeContextArgCount, boolean syncOnRelink, - int unstableRelinkThreshold) { + DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationFilter prelinkFilter, final int runtimeContextArgCount, + final boolean syncOnRelink, final int unstableRelinkThreshold) { if(runtimeContextArgCount < 0) { throw new IllegalArgumentException("runtimeContextArgCount < 0"); } if(unstableRelinkThreshold < 0) { throw new IllegalArgumentException("unstableRelinkThreshold < 0"); } - this.runtimeContextArgCount = runtimeContextArgCount; this.linkerServices = linkerServices; + this.prelinkFilter = prelinkFilter; + this.runtimeContextArgCount = runtimeContextArgCount; this.syncOnRelink = syncOnRelink; this.unstableRelinkThreshold = unstableRelinkThreshold; } @@ -199,7 +201,7 @@ public class DynamicLinker { private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME, MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class); - private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, int relinkCount) { + private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) { // Make a bound MH of invoke() for this linker and call site final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf( relinkCount)); @@ -219,16 +221,15 @@ public class DynamicLinker { * @throws Exception rethrows any exception thrown by the linkers */ @SuppressWarnings("unused") - private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception { + private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception { final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor(); final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0; final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold; final LinkRequest linkRequest = - runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments) - : new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments, - runtimeContextArgCount); + runtimeContextArgCount == 0 ? + new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) : + new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount); - // Find a suitable method handle with a guard GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest); // None found - throw an exception @@ -248,6 +249,11 @@ public class DynamicLinker { } } + // Make sure we filter the invocation before linking it into the call site. This is typically used to match the + // return type of the invocation to the call site. + guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices); + guardedInvocation.getClass(); // null pointer check + int newRelinkCount = relinkCount; // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink diff --git a/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java b/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java index 72fbebe33be..af5eb119184 100644 --- a/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java +++ b/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java @@ -102,14 +102,15 @@ import jdk.internal.dynalink.support.BottomGuardingDynamicLinker; import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider; import jdk.internal.dynalink.support.CompositeGuardingDynamicLinker; import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.support.DefaultPrelinkFilter; import jdk.internal.dynalink.support.LinkerServicesImpl; import jdk.internal.dynalink.support.TypeConverterFactory; /** * A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition * of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any - * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker}. See - * {@link DynamicLinker} documentation for tips on how to use this class. + * {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker} and a + * {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on how to use this class. * * @author Attila Szegedi */ @@ -128,6 +129,7 @@ public class DynamicLinkerFactory { private int runtimeContextArgCount = 0; private boolean syncOnRelink = false; private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD; + private GuardedInvocationFilter prelinkFilter; /** * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread @@ -135,7 +137,7 @@ public class DynamicLinkerFactory { * * @param classLoader the class loader used for the autodiscovery of available linkers. */ - public void setClassLoader(ClassLoader classLoader) { + public void setClassLoader(final ClassLoader classLoader) { this.classLoader = classLoader; classLoaderExplicitlySet = true; } @@ -149,7 +151,7 @@ public class DynamicLinkerFactory { * @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers * (this is also the default value). */ - public void setPrioritizedLinkers(List prioritizedLinkers) { + public void setPrioritizedLinkers(final List prioritizedLinkers) { this.prioritizedLinkers = prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers); } @@ -162,7 +164,7 @@ public class DynamicLinkerFactory { * * @param prioritizedLinkers a list of prioritized linkers. */ - public void setPrioritizedLinkers(GuardingDynamicLinker... prioritizedLinkers) { + public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) { setPrioritizedLinkers(Arrays.asList(prioritizedLinkers)); } @@ -173,7 +175,7 @@ public class DynamicLinkerFactory { * @param prioritizedLinker the single prioritized linker. Must not be null. * @throws IllegalArgumentException if null is passed. */ - public void setPrioritizedLinker(GuardingDynamicLinker prioritizedLinker) { + public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) { if(prioritizedLinker == null) { throw new IllegalArgumentException("prioritizedLinker == null"); } @@ -188,7 +190,7 @@ public class DynamicLinkerFactory { * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no * fallback linkers. */ - public void setFallbackLinkers(List fallbackLinkers) { + public void setFallbackLinkers(final List fallbackLinkers) { this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers); } @@ -200,7 +202,7 @@ public class DynamicLinkerFactory { * @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no * fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used. */ - public void setFallbackLinkers(GuardingDynamicLinker... fallbackLinkers) { + public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) { setFallbackLinkers(Arrays.asList(fallbackLinkers)); } @@ -214,7 +216,7 @@ public class DynamicLinkerFactory { * * @param runtimeContextArgCount the number of language runtime context arguments in call sites. */ - public void setRuntimeContextArgCount(int runtimeContextArgCount) { + public void setRuntimeContextArgCount(final int runtimeContextArgCount) { if(runtimeContextArgCount < 0) { throw new IllegalArgumentException("runtimeContextArgCount < 0"); } @@ -227,7 +229,7 @@ public class DynamicLinkerFactory { * multithreaded execution of dynamically linked code. * @param syncOnRelink true for invoking sync on relink, false otherwise. */ - public void setSyncOnRelink(boolean syncOnRelink) { + public void setSyncOnRelink(final boolean syncOnRelink) { this.syncOnRelink = syncOnRelink; } @@ -238,7 +240,7 @@ public class DynamicLinkerFactory { * call sites will never be considered unstable. * @see LinkRequest#isCallSiteUnstable() */ - public void setUnstableRelinkThreshold(int unstableRelinkThreshold) { + public void setUnstableRelinkThreshold(final int unstableRelinkThreshold) { if(unstableRelinkThreshold < 0) { throw new IllegalArgumentException("unstableRelinkThreshold < 0"); } @@ -246,7 +248,19 @@ public class DynamicLinkerFactory { } /** - * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers. + * Set the pre-link filter. This is a {@link GuardedInvocationFilter} that will get the final chance to modify the + * guarded invocation after it has been created by a component linker and before the dynamic linker links it into + * the call site. It is normally used to adapt the return value type of the invocation to the type of the call site. + * When not set explicitly, {@link DefaultPrelinkFilter} will be used. + * @param prelinkFilter the pre-link filter for the dynamic linker. + */ + public void setPrelinkFilter(final GuardedInvocationFilter prelinkFilter) { + this.prelinkFilter = prelinkFilter; + } + + /** + * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as + * the pre-link filter. * * @return the new dynamic Linker */ @@ -275,7 +289,7 @@ public class DynamicLinkerFactory { // ... prioritized linkers, ... linkers.addAll(prioritizedLinkers); // ... filtered discovered linkers, ... - for(GuardingDynamicLinker linker: discovered) { + for(final GuardingDynamicLinker linker: discovered) { if(!knownLinkerClasses.contains(linker.getClass())) { linkers.add(linker); } @@ -300,14 +314,18 @@ public class DynamicLinkerFactory { } final List typeConverters = new LinkedList<>(); - for(GuardingDynamicLinker linker: linkers) { + for(final GuardingDynamicLinker linker: linkers) { if(linker instanceof GuardingTypeConverterFactory) { typeConverters.add((GuardingTypeConverterFactory)linker); } } + if(prelinkFilter == null) { + prelinkFilter = new DefaultPrelinkFilter(); + } + return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite), - runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold); + prelinkFilter, runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold); } private static ClassLoader getThreadContextClassLoader() { @@ -319,9 +337,9 @@ public class DynamicLinkerFactory { }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); } - private static void addClasses(Set> knownLinkerClasses, - List linkers) { - for(GuardingDynamicLinker linker: linkers) { + private static void addClasses(final Set> knownLinkerClasses, + final List linkers) { + for(final GuardingDynamicLinker linker: linkers) { knownLinkerClasses.add(linker.getClass()); } } diff --git a/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java b/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java new file mode 100644 index 00000000000..8560d82f68d --- /dev/null +++ b/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.internal.dynalink; + +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; + +/** + * Interface for objects that are used to transform one guarded invocation into another one. Typical usage is for + * implementing {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter) pre-link filters}. + */ +public interface GuardedInvocationFilter { + /** + * Given a guarded invocation, return a potentially different guarded invocation. + * @param inv the original guarded invocation. Null is never passed. + * @param linkRequest the link request for which the invocation was generated (usually by some linker). + * @param linkerServices the linker services that can be used during creation of a new invocation. + * @return either the passed guarded invocation or a different one, with the difference usually determined based on + * information in the link request and the differing invocation created with the assistance of the linker services. + * Whether or not {@code null} is an accepted return value is dependent on the user of the filter. + */ + public GuardedInvocation filter(GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices); +} diff --git a/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java b/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java index 7f1bbedebaf..98541f288f2 100644 --- a/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java +++ b/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java @@ -99,17 +99,17 @@ public class MonomorphicCallSite extends AbstractRelinkableCallSite { * Creates a new call site with monomorphic inline caching strategy. * @param descriptor the descriptor for this call site */ - public MonomorphicCallSite(CallSiteDescriptor descriptor) { + public MonomorphicCallSite(final CallSiteDescriptor descriptor) { super(descriptor); } @Override - public void relink(GuardedInvocation guardedInvocation, MethodHandle relink) { + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) { setTarget(guardedInvocation.compose(relink)); } @Override - public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relink) { + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) { relink(guardedInvocation, relink); } } diff --git a/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java b/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java index 8a73af922ea..879a4b0ed5e 100644 --- a/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java +++ b/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java @@ -97,7 +97,7 @@ public class NoSuchDynamicMethodException extends RuntimeException { * Creates a new NoSuchDynamicMethodException * @param message the message of the exception. */ - public NoSuchDynamicMethodException(String message) { + public NoSuchDynamicMethodException(final String message) { super(message); } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java b/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java index a6ef8c11b90..9e3fbe8231f 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java +++ b/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java @@ -97,7 +97,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; - import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; import jdk.internal.dynalink.linker.GuardedInvocation; @@ -107,6 +106,7 @@ import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.internal.dynalink.support.Guards; import jdk.internal.dynalink.support.Lookup; +import jdk.internal.dynalink.support.TypeUtilities; /** * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property @@ -123,18 +123,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { private final Map propertySetters = new HashMap<>(); private final Map methods = new HashMap<>(); - AbstractJavaLinker(Class clazz, MethodHandle classGuard) { + AbstractJavaLinker(final Class clazz, final MethodHandle classGuard) { this(clazz, classGuard, classGuard); } - AbstractJavaLinker(Class clazz, MethodHandle classGuard, MethodHandle assignableGuard) { + AbstractJavaLinker(final Class clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) { this.clazz = clazz; this.classGuard = classGuard; this.assignableGuard = assignableGuard; final FacetIntrospector introspector = createFacetIntrospector(); // Add methods and properties - for(Method method: introspector.getMethods()) { + for(final Method method: introspector.getMethods()) { final String name = method.getName(); // Add method addMember(name, method, methods); @@ -153,7 +153,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } // Add field getter/setters as property getters/setters. - for(Field field: introspector.getFields()) { + for(final Field field: introspector.getFields()) { final String name = field.getName(); // Only add a property getter when one is not defined already as a getXxx()/isXxx() method. if(!propertyGetters.containsKey(name)) { @@ -166,7 +166,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } // Add inner classes, but only those for which we don't hide a property with it - for(Map.Entry innerClassSpec: introspector.getInnerClassGetters().entrySet()) { + for(final Map.Entry innerClassSpec: introspector.getInnerClassGetters().entrySet()) { final String name = innerClassSpec.getKey(); if(!propertyGetters.containsKey(name)) { setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS); @@ -174,7 +174,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } } - private static String decapitalize(String str) { + private static String decapitalize(final String str) { assert str != null; if(str.isEmpty()) { return str; @@ -209,7 +209,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { return getUnmodifiableKeys(methods); } - private static Collection getUnmodifiableKeys(Map m) { + private static Collection getUnmodifiableKeys(final Map m) { return Collections.unmodifiableCollection(m.keySet()); } @@ -222,7 +222,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param handle the method handle that implements the property getter * @param validationType the validation type for the property */ - private void setPropertyGetter(String name, SingleDynamicMethod handle, ValidationType validationType) { + private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) { propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType)); } @@ -232,7 +232,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for * names starting with "is". */ - private void setPropertyGetter(Method getter, int prefixLen) { + private void setPropertyGetter(final Method getter, final int prefixLen) { setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod( getMostGenericGetter(getter)), ValidationType.INSTANCE_OF); } @@ -246,15 +246,15 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param handle the method handle that implements the property getter * @param validationType the validation type for the property */ - void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) { + void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) { setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType); } - private void addMember(String name, AccessibleObject ao, Map methodMap) { + private void addMember(final String name, final AccessibleObject ao, final Map methodMap) { addMember(name, createDynamicMethod(ao), methodMap); } - private void addMember(String name, SingleDynamicMethod method, Map methodMap) { + private void addMember(final String name, final SingleDynamicMethod method, final Map methodMap) { final DynamicMethod existingMethod = methodMap.get(name); final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name); if(newMethod != existingMethod) { @@ -270,9 +270,9 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param name the common name of the reflective members. * @return a dynamic method representing all the specified reflective members. */ - static DynamicMethod createDynamicMethod(Iterable members, Class clazz, String name) { + static DynamicMethod createDynamicMethod(final Iterable members, final Class clazz, final String name) { DynamicMethod dynMethod = null; - for(AccessibleObject method: members) { + for(final AccessibleObject method: members) { dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name); } return dynMethod; @@ -285,7 +285,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param m the reflective member * @return the single dynamic method representing the reflective member */ - private static SingleDynamicMethod createDynamicMethod(AccessibleObject m) { + private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) { if(CallerSensitiveDetector.isCallerSensitive(m)) { return new CallerSensitiveDynamicMethod(m); } @@ -301,7 +301,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param m the method or constructor * @return the method handle */ - private static MethodHandle unreflectSafely(AccessibleObject m) { + private static MethodHandle unreflectSafely(final AccessibleObject m) { if(m instanceof Method) { final Method reflMethod = (Method)m; final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod); @@ -313,7 +313,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor)m)); } - private static DynamicMethod mergeMethods(SingleDynamicMethod method, DynamicMethod existing, Class clazz, String name) { + private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class clazz, final String name) { if(existing == null) { return method; } else if(existing.contains(method)) { @@ -331,7 +331,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices) + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final LinkRequest ncrequest = request.withoutRuntimeContext(); // BeansLinker already checked that the name is at least 2 elements long and the first element is "dyn". @@ -353,8 +353,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { return null; } - protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List operations) throws Exception { + protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations) throws Exception { if(operations.isEmpty()) { return null; } @@ -374,27 +374,27 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { return null; } - static final List pop(List l) { + static final List pop(final List l) { return l.subList(1, l.size()); } - MethodHandle getClassGuard(CallSiteDescriptor desc) { + MethodHandle getClassGuard(final CallSiteDescriptor desc) { return getClassGuard(desc.getMethodType()); } - MethodHandle getClassGuard(MethodType type) { + MethodHandle getClassGuard(final MethodType type) { return Guards.asType(classGuard, type); } - GuardedInvocationComponent getClassGuardedInvocationComponent(MethodHandle invocation, MethodType type) { + GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) { return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } - private MethodHandle getAssignableGuard(MethodType type) { + private MethodHandle getAssignableGuard(final MethodType type) { return Guards.asType(assignableGuard, type); } - private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { + private GuardedInvocation getCallPropWithThis(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { switch(callSiteDescriptor.getNameTokenCount()) { case 3: { return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, @@ -406,25 +406,25 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } } - private GuardedInvocation createGuardedDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, String methodName, Map methodMap){ + private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final String methodName, final Map methodMap){ final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap); return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType())); } - private static MethodHandle getDynamicMethodInvocation(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, String methodName, Map methodMap) { + private static MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final String methodName, final Map methodMap) { final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null; } - private static DynamicMethod getDynamicMethod(String methodName, Map methodMap) { + private static DynamicMethod getDynamicMethod(final String methodName, final Map methodMap) { final DynamicMethod dynaMethod = methodMap.get(methodName); return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); } - private static SingleDynamicMethod getExplicitSignatureDynamicMethod(String methodName, - Map methodsMap) { + private static SingleDynamicMethod getExplicitSignatureDynamicMethod(final String methodName, + final Map methodsMap) { // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method // resolution works correctly in almost every situation. However, in presence of many language-specific @@ -457,14 +457,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments( MethodHandles.constant(Object.class, null), 0, MethodHandle.class); - private GuardedInvocationComponent getPropertySetter(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List operations) throws Exception { - final MethodType type = callSiteDescriptor.getMethodType(); + private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations) throws Exception { switch(callSiteDescriptor.getNameTokenCount()) { case 2: { // Must have three arguments: target object, property name, and property value. assertParameterCount(callSiteDescriptor, 3); + // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be + // valid for us to convert return values proactively. Also, since we don't know what setters will be + // invoked, we'll conservatively presume Object return type. + final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); + // What's below is basically: // foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation), // get_setter_handle(type, linkerServices)) @@ -473,8 +477,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { // component's invocation. // Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll - // abbreviate to R(O, N, V) going forward. - // We want setters that conform to "R(O, V)" + // abbreviate to R(O, N, V) going forward, although we don't really use R here (see above about using + // Object return type). final MethodType setterType = type.dropParameterTypes(1, 2); // Bind property setter handle to the expected setter type and linker services. Type is // MethodHandle(Object, String, Object) @@ -495,11 +499,11 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { final MethodHandle fallbackFolded; if(nextComponent == null) { - // Object(MethodHandle)->R(MethodHandle, O, N, V); returns constant null + // Object(MethodHandle)->Object(MethodHandle, O, N, V); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1, type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class)); } else { - // R(O, N, V)->R(MethodHandle, O, N, V); adapts the next component's invocation to drop the + // Object(O, N, V)->Object(MethodHandle, O, N, V); adapts the next component's invocation to drop the // extra argument resulting from fold fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), 0, MethodHandle.class); @@ -543,11 +547,14 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class)); private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)); - private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List ops) throws Exception { - final MethodType type = callSiteDescriptor.getMethodType(); + private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops) throws Exception { switch(callSiteDescriptor.getNameTokenCount()) { case 2: { + // Since we can't know what kind of a getter we'll get back on different invocations, we'll just + // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking + // runtime might not allow coercing at that call site. + final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); // Must have exactly two arguments: receiver and name assertParameterCount(callSiteDescriptor, 2); @@ -563,11 +570,11 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup()); final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0, callSiteBoundMethodGetter); - // Object(AnnotatedDynamicMethod, Object)->R(AnnotatedDynamicMethod, T0) + // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0) final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker, MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0))); // Since it's in the target of a fold, drop the unnecessary second argument - // R(AnnotatedDynamicMethod, T0)->R(AnnotatedDynamicMethod, T0, T1) + // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1) final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, type.parameterType(1)); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, @@ -575,17 +582,19 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { final MethodHandle fallbackFolded; if(nextComponent == null) { - // Object(AnnotatedDynamicMethod)->R(AnnotatedDynamicMethod, T0, T1); returns constant null + // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1, type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class)); } else { - // R(T0, T1)->R(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to drop the - // extra argument resulting from fold - fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(), - 0, AnnotatedDynamicMethod.class); + // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to + // drop the extra argument resulting from fold and to change its return type to Object. + final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation(); + final MethodType nextType = nextInvocation.type(); + fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType( + nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class); } - // fold(R(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1)) + // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1)) final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); if(nextComponent == null) { @@ -612,8 +621,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { // value is null. final ValidationType validationType = annGetter.validationType; // TODO: we aren't using the type that declares the most generic getter here! - return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType, - type), clazz, validationType); + return new GuardedInvocationComponent(getter, getGuard(validationType, + callSiteDescriptor.getMethodType()), clazz, validationType); } default: { // Can't do anything with more than 3 name components @@ -622,7 +631,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } } - private MethodHandle getGuard(ValidationType validationType, MethodType methodType) { + private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) { switch(validationType) { case EXACT_CLASS: { return getClassGuard(methodType); @@ -642,21 +651,25 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } } - private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(), - MethodType.methodType(boolean.class, DynamicMethod.class)); - private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class); + private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class, + MethodType.methodType(boolean.class, Object.class)); + private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class); - private GuardedInvocationComponent getMethodGetter(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List ops) throws Exception { - final MethodType type = callSiteDescriptor.getMethodType(); + private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops) throws Exception { + // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to + // be visible outside of this linker, declare it to return Object. + final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); switch(callSiteDescriptor.getNameTokenCount()) { case 2: { // Must have exactly two arguments: receiver and name assertParameterCount(callSiteDescriptor, 2); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops); - if(nextComponent == null) { - // No next component operation; just return a component for this operation. + if(nextComponent == null || !TypeUtilities.areAssignable(DynamicMethod.class, + nextComponent.getGuardedInvocation().getInvocation().type().returnType())) { + // No next component operation, or it can never produce a dynamic method; just return a component + // for this operation. return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type); } @@ -665,21 +678,20 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { // bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null // DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation. - final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType( - DynamicMethod.class)); + final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type); // Since it is part of the foldArgument() target, it will have extra args that we need to drop. final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments( - DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, - DynamicMethod.class)); + OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class)); final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation(); - // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly - assert nextComponentInvocation.type().equals(type); + // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the + // return type. + assert nextComponentInvocation.type().changeReturnType(type.returnType()).equals(type); // Since it is part of the foldArgument() target, we have to drop an extra arg it receives. final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0, - DynamicMethod.class); + Object.class); // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get) final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( - IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter); + IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter); return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); } @@ -695,7 +707,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { // No delegation to the next component of the composite operation; if we have a method with that name, // we'll always return it at this point. return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments( - MethodHandles.constant(DynamicMethod.class, method), 0, type.parameterType(0)), type), type); + MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type); } default: { // Can't do anything with more than 3 name components @@ -704,7 +716,31 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { } } - private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) { + static class MethodPair { + final MethodHandle method1; + final MethodHandle method2; + + MethodPair(final MethodHandle method1, final MethodHandle method2) { + this.method1 = method1; + this.method2 = method2; + } + + MethodHandle guardWithTest(final MethodHandle test) { + return MethodHandles.guardWithTest(test, method1, method2); + } + } + + static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) { + final MethodType type1 = m1.type(); + final MethodType type2 = m2.type(); + final Class commonRetType = TypeUtilities.getCommonLosslessConversionType(type1.returnType(), + type2.returnType()); + return new MethodPair( + m1.asType(type1.changeReturnType(commonRetType)), + m2.asType(type2.changeReturnType(commonRetType))); + } + + private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { if(descriptor.getMethodType().parameterCount() != paramCount) { throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters."); } @@ -719,7 +755,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @return the method handle for retrieving the property, or null if the property does not exist */ @SuppressWarnings("unused") - private Object getPropertyGetterHandle(Object id) { + private Object getPropertyGetterHandle(final Object id) { return propertyGetters.get(id); } @@ -733,17 +769,20 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this); @SuppressWarnings("unused") - private MethodHandle getPropertySetterHandle(CallSiteDescriptor setterDescriptor, LinkerServices linkerServices, - Object id) { + private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices, + final Object id) { return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters); } private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial( - "getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class); + "getDynamicMethod", Object.class, Object.class), 1, Object.class); private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this); @SuppressWarnings("unused") - private DynamicMethod getDynamicMethod(Object name) { + // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't + // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for + // "dyn:getMethod" linking). + private Object getDynamicMethod(final Object name) { return getDynamicMethod(String.valueOf(name), methods); } @@ -754,7 +793,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the * method with the specified name does not exist. */ - DynamicMethod getDynamicMethod(String name) { + DynamicMethod getDynamicMethod(final String name) { return getDynamicMethod(name, methods); } @@ -765,16 +804,16 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { * @param getter the getter * @return getter with same name, declared on the most generic superclass/interface of the declaring class */ - private static Method getMostGenericGetter(Method getter) { + private static Method getMostGenericGetter(final Method getter) { return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass()); } - private static Method getMostGenericGetter(String name, Class returnType, Class declaringClass) { + private static Method getMostGenericGetter(final String name, final Class returnType, final Class declaringClass) { if(declaringClass == null) { return null; } // Prefer interfaces - for(Class itf: declaringClass.getInterfaces()) { + for(final Class itf: declaringClass.getInterfaces()) { final Method itfGetter = getMostGenericGetter(name, returnType, itf); if(itfGetter != null) { return itfGetter; @@ -787,7 +826,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) { try { return declaringClass.getMethod(name); - } catch(NoSuchMethodException e) { + } catch(final NoSuchMethodException e) { // Intentionally ignored, meant to fall through } } @@ -798,18 +837,18 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker { private final SingleDynamicMethod method; /*private*/ final ValidationType validationType; - AnnotatedDynamicMethod(SingleDynamicMethod method, ValidationType validationType) { + AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) { this.method = method; this.validationType = validationType; } - MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { + MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { return method.getInvocation(callSiteDescriptor, linkerServices); } @SuppressWarnings("unused") - MethodHandle getTarget(MethodHandles.Lookup lookup) { - MethodHandle inv = method.getTarget(lookup); + MethodHandle getTarget(final MethodHandles.Lookup lookup) { + final MethodHandle inv = method.getTarget(lookup); assert inv != null; return inv; } diff --git a/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java b/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java index 72beadfe3b6..21789e45afe 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java +++ b/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java @@ -104,7 +104,7 @@ import java.util.Set; class AccessibleMembersLookup { private final Map methods; private final Set> innerClasses; - private boolean instance; + private final boolean instance; /** * Creates a mapping for all accessible methods and inner classes on a class. @@ -112,7 +112,7 @@ class AccessibleMembersLookup { * @param clazz the inspected class * @param instance true to inspect instance methods, false to inspect static methods. */ - AccessibleMembersLookup(final Class clazz, boolean instance) { + AccessibleMembersLookup(final Class clazz, final boolean instance) { this.methods = new HashMap<>(); this.innerClasses = new LinkedHashSet<>(); this.instance = instance; @@ -153,7 +153,7 @@ class AccessibleMembersLookup { * @param name the name of the method this signature represents. * @param args the argument types of the method. */ - MethodSignature(String name, Class[] args) { + MethodSignature(final String name, final Class[] args) { this.name = name; this.args = args; } @@ -210,7 +210,7 @@ class AccessibleMembersLookup { if(!CheckRestrictedPackage.isRestrictedClass(clazz)) { searchSuperTypes = false; - for(Method method: clazz.getMethods()) { + for(final Method method: clazz.getMethods()) { final boolean isStatic = Modifier.isStatic(method.getModifiers()); if(instance != isStatic) { final MethodSignature sig = new MethodSignature(method); @@ -237,7 +237,7 @@ class AccessibleMembersLookup { } } } - for(Class innerClass: clazz.getClasses()) { + for(final Class innerClass: clazz.getClasses()) { // Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just // expose non-static classes with explicit constructor outer class argument. // NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes diff --git a/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java b/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java index 39a03a8ef96..e749c490dd4 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java +++ b/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java @@ -108,7 +108,7 @@ class ApplicableOverloadedMethods { ApplicableOverloadedMethods(final List methods, final MethodType callSiteType, final ApplicabilityTest test) { this.methods = new LinkedList<>(); - for(SingleDynamicMethod m: methods) { + for(final SingleDynamicMethod m: methods) { if(test.isApplicable(callSiteType, m)) { this.methods.add(m); } @@ -143,7 +143,7 @@ class ApplicableOverloadedMethods { */ static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() { @Override - boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { final MethodType methodType = method.getMethodType(); final int methodArity = methodType.parameterCount(); if(methodArity != callSiteType.parameterCount()) { @@ -165,7 +165,7 @@ class ApplicableOverloadedMethods { */ static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() { @Override - boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { final MethodType methodType = method.getMethodType(); final int methodArity = methodType.parameterCount(); if(methodArity != callSiteType.parameterCount()) { @@ -188,7 +188,7 @@ class ApplicableOverloadedMethods { */ static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() { @Override - boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method) { + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { if(!method.isVarArgs()) { return false; } diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java index fc54e353a6e..754d88efb7b 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java +++ b/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java @@ -88,7 +88,7 @@ import java.util.Collections; import java.util.Map; class BeanIntrospector extends FacetIntrospector { - BeanIntrospector(Class clazz) { + BeanIntrospector(final Class clazz) { super(clazz, true); } @@ -98,7 +98,7 @@ class BeanIntrospector extends FacetIntrospector { } @Override - MethodHandle editMethodHandle(MethodHandle mh) { + MethodHandle editMethodHandle(final MethodHandle mh) { return mh; } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java b/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java index d0ad96bad21..f7f0c94a847 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java +++ b/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java @@ -106,7 +106,7 @@ import jdk.internal.dynalink.support.TypeUtilities; * @author Attila Szegedi */ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker { - BeanLinker(Class clazz) { + BeanLinker(final Class clazz) { super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz)); if(clazz.isArray()) { // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an @@ -119,7 +119,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL } @Override - public boolean canLinkType(Class type) { + public boolean canLinkType(final Class type) { return type == clazz; } @@ -129,8 +129,8 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL } @Override - protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List operations) throws Exception { + protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations) throws Exception { final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations); if(superGic != null) { @@ -166,7 +166,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, List operations) throws Exception { + final LinkerServices linkerServices, final List operations) throws Exception { final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class declaredType = callSiteType.parameterType(0); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, @@ -237,8 +237,9 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL } else { checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); } - return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard), - binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(), + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), + nextComponent.getGuardedInvocation().getInvocation()); + return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), gic.getValidatorClass(), gic.getValidationType()); } @@ -247,7 +248,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL CallSiteDescriptor.NAME_OPERAND); } - private static Object convertKeyToInteger(String fixedKey, LinkerServices linkerServices) throws Exception { + private static Object convertKeyToInteger(final String fixedKey, final LinkerServices linkerServices) throws Exception { try { if(linkerServices.canConvert(String.class, Number.class)) { try { @@ -267,18 +268,18 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL return Integer.valueOf(intIndex); } catch(Exception|Error e) { throw e; - } catch(Throwable t) { + } catch(final Throwable t) { throw new RuntimeException(t); } } return Integer.valueOf(fixedKey); - } catch(NumberFormatException e) { + } catch(final NumberFormatException e) { // key is not a number return null; } } - private static MethodHandle convertArgToInt(MethodHandle mh, LinkerServices ls, CallSiteDescriptor desc) { + private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) { final Class sourceType = desc.getMethodType().parameterType(1); if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) { return mh; @@ -301,21 +302,21 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL private final MethodType methodType; private final Object fixedKey; - Binder(LinkerServices linkerServices, MethodType methodType, Object fixedKey) { + Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) { this.linkerServices = linkerServices; this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass()); this.fixedKey = fixedKey; } - /*private*/ MethodHandle bind(MethodHandle handle) { - return bindToFixedKey(linkerServices.asType(handle, methodType)); + /*private*/ MethodHandle bind(final MethodHandle handle) { + return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType)); } - /*private*/ MethodHandle bindTest(MethodHandle handle) { + /*private*/ MethodHandle bindTest(final MethodHandle handle) { return bindToFixedKey(Guards.asType(handle, methodType)); } - private MethodHandle bindToFixedKey(MethodHandle handle) { + private MethodHandle bindToFixedKey(final MethodHandle handle) { return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey); } } @@ -325,12 +326,12 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey", MethodType.methodType(boolean.class, Object.class)); - private static MethodHandle findRangeCheck(Class collectionType) { + private static MethodHandle findRangeCheck(final Class collectionType) { return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class); } @SuppressWarnings("unused") - private static final boolean rangeCheck(Object array, Object index) { + private static final boolean rangeCheck(final Object array, final Object index) { if(!(index instanceof Number)) { return false; } @@ -347,7 +348,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL } @SuppressWarnings("unused") - private static final boolean rangeCheck(List list, Object index) { + private static final boolean rangeCheck(final List list, final Object index) { if(!(index instanceof Number)) { return false; } @@ -369,8 +370,8 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", MethodType.methodType(Object.class, Object.class, Object.class)); - private GuardedInvocationComponent getElementSetter(CallSiteDescriptor callSiteDescriptor, - LinkerServices linkerServices, List operations) throws Exception { + private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations) throws Exception { final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class declaredType = callSiteType.parameterType(0); @@ -440,8 +441,9 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST : RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); - return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard), - binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(), + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), + nextComponent.getGuardedInvocation().getInvocation()); + return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), gic.getValidatorClass(), gic.getValidationType()); } @@ -456,7 +458,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class); - private GuardedInvocationComponent getLengthGetter(CallSiteDescriptor callSiteDescriptor) { + private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) { assertParameterCount(callSiteDescriptor, 1); final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class declaredType = callSiteType.parameterType(0); @@ -486,7 +488,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL return null; } - private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) { + private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { if(descriptor.getMethodType().parameterCount() != paramCount) { throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters."); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java b/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java index e0c14b0d1d8..b1862de0f0c 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java +++ b/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java @@ -131,7 +131,7 @@ import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; public class BeansLinker implements GuardingDynamicLinker { private static final ClassValue linkers = new ClassValue() { @Override - protected TypeBasedGuardingDynamicLinker computeValue(Class clazz) { + protected TypeBasedGuardingDynamicLinker computeValue(final Class clazz) { // If ClassValue.put() were public, we could just pre-populate with these known mappings... return clazz == Class.class ? new ClassLinker() : @@ -154,7 +154,7 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a bean linker for that class */ - public static TypeBasedGuardingDynamicLinker getLinkerForClass(Class clazz) { + public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class clazz) { return linkers.get(clazz); } @@ -173,8 +173,8 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all readable instance properties of a class. */ - public static Collection getReadableInstancePropertyNames(Class clazz) { - TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + public static Collection getReadableInstancePropertyNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getReadablePropertyNames(); } @@ -186,8 +186,8 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all writable instance properties of a class. */ - public static Collection getWritableInstancePropertyNames(Class clazz) { - TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + public static Collection getWritableInstancePropertyNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getWritablePropertyNames(); } @@ -199,8 +199,8 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all instance methods of a class. */ - public static Collection getInstanceMethodNames(Class clazz) { - TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + public static Collection getInstanceMethodNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); if(linker instanceof BeanLinker) { return ((BeanLinker)linker).getMethodNames(); } @@ -212,7 +212,7 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all readable static properties of a class. */ - public static Collection getReadableStaticPropertyNames(Class clazz) { + public static Collection getReadableStaticPropertyNames(final Class clazz) { return StaticClassLinker.getReadableStaticPropertyNames(clazz); } @@ -221,7 +221,7 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all writable static properties of a class. */ - public static Collection getWritableStaticPropertyNames(Class clazz) { + public static Collection getWritableStaticPropertyNames(final Class clazz) { return StaticClassLinker.getWritableStaticPropertyNames(clazz); } @@ -230,12 +230,12 @@ public class BeansLinker implements GuardingDynamicLinker { * @param clazz the class * @return a collection of names of all static methods of a class. */ - public static Collection getStaticMethodNames(Class clazz) { + public static Collection getStaticMethodNames(final Class clazz) { return StaticClassLinker.getStaticMethodNames(clazz); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices) + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor(); final int l = callSiteDescriptor.getNameTokenCount(); diff --git a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java index 466bafe65dc..e4ada355e53 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java +++ b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java @@ -107,14 +107,14 @@ public class CallerSensitiveDetector { private static final DetectionStrategy DETECTION_STRATEGY = getDetectionStrategy(); - static boolean isCallerSensitive(AccessibleObject ao) { + static boolean isCallerSensitive(final AccessibleObject ao) { return DETECTION_STRATEGY.isCallerSensitive(ao); } private static DetectionStrategy getDetectionStrategy() { try { return new PrivilegedDetectionStrategy(); - } catch(Throwable t) { + } catch(final Throwable t) { return new UnprivilegedDetectionStrategy(); } } @@ -127,7 +127,7 @@ public class CallerSensitiveDetector { private static final Class CALLER_SENSITIVE_ANNOTATION_CLASS = CallerSensitive.class; @Override - boolean isCallerSensitive(AccessibleObject ao) { + boolean isCallerSensitive(final AccessibleObject ao) { return ao.getAnnotation(CALLER_SENSITIVE_ANNOTATION_CLASS) != null; } } @@ -136,8 +136,8 @@ public class CallerSensitiveDetector { private static final String CALLER_SENSITIVE_ANNOTATION_STRING = "@sun.reflect.CallerSensitive()"; @Override - boolean isCallerSensitive(AccessibleObject o) { - for(Annotation a: o.getAnnotations()) { + boolean isCallerSensitive(final AccessibleObject o) { + for(final Annotation a: o.getAnnotations()) { if(String.valueOf(a).equals(CALLER_SENSITIVE_ANNOTATION_STRING)) { return true; } diff --git a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java index 1e274d516e9..5fceb1a7af0 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java @@ -107,13 +107,13 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod { private final AccessibleObject target; private final MethodType type; - public CallerSensitiveDynamicMethod(AccessibleObject target) { + public CallerSensitiveDynamicMethod(final AccessibleObject target) { super(getName(target)); this.target = target; this.type = getMethodType(target); } - private static String getName(AccessibleObject target) { + private static String getName(final AccessibleObject target) { final Member m = (Member)target; return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(), m.getName())); @@ -124,7 +124,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod { return type; } - private static MethodType getMethodType(AccessibleObject ao) { + private static MethodType getMethodType(final AccessibleObject ao) { final boolean isMethod = ao instanceof Method; final Class rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor)ao).getDeclaringClass(); final Class[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor)ao).getParameterTypes(); @@ -144,7 +144,7 @@ class CallerSensitiveDynamicMethod extends SingleDynamicMethod { } @Override - MethodHandle getTarget(MethodHandles.Lookup lookup) { + MethodHandle getTarget(final MethodHandles.Lookup lookup) { if(target instanceof Method) { final MethodHandle mh = Lookup.unreflect(lookup, (Method)target); if(Modifier.isStatic(((Member)target).getModifiers())) { diff --git a/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java b/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java index 360759f8674..49723a12d38 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java +++ b/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java @@ -101,7 +101,7 @@ class CheckRestrictedPackage { * @param clazz the class to test * @return true if the class is either not public, or it resides in a package with restricted access. */ - static boolean isRestrictedClass(Class clazz) { + static boolean isRestrictedClass(final Class clazz) { if(!Modifier.isPublic(clazz.getModifiers())) { // Non-public classes are always restricted return true; @@ -126,7 +126,7 @@ class CheckRestrictedPackage { return null; } }, NO_PERMISSIONS_CONTEXT); - } catch(SecurityException e) { + } catch(final SecurityException e) { return true; } return false; diff --git a/nashorn/src/jdk/internal/dynalink/beans/ClassString.java b/nashorn/src/jdk/internal/dynalink/beans/ClassString.java index 2afbdb4f76b..00729cd7ae0 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/ClassString.java +++ b/nashorn/src/jdk/internal/dynalink/beans/ClassString.java @@ -104,16 +104,16 @@ final class ClassString { private final Class[] classes; private int hashCode; - ClassString(Class[] classes) { + ClassString(final Class[] classes) { this.classes = classes; } - ClassString(MethodType type) { + ClassString(final MethodType type) { this(type.parameterArray()); } @Override - public boolean equals(Object other) { + public boolean equals(final Object other) { if(!(other instanceof ClassString)) { return false; } @@ -150,7 +150,7 @@ final class ClassString { return true; } - List getMaximallySpecifics(List methods, LinkerServices linkerServices, boolean varArg) { + List getMaximallySpecifics(final List methods, final LinkerServices linkerServices, final boolean varArg) { return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg), varArg, classes, linkerServices); } @@ -158,7 +158,7 @@ final class ClassString { /** * Returns all methods that are applicable to actual parameter classes represented by this ClassString object. */ - LinkedList getApplicables(List methods, LinkerServices linkerServices, boolean varArg) { + LinkedList getApplicables(final List methods, final LinkerServices linkerServices, final boolean varArg) { final LinkedList list = new LinkedList<>(); for(final MethodHandle member: methods) { if(isApplicable(member, linkerServices, varArg)) { @@ -173,7 +173,7 @@ final class ClassString { * object. * */ - private boolean isApplicable(MethodHandle method, LinkerServices linkerServices, boolean varArg) { + private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) { final Class[] formalTypes = method.type().parameterArray(); final int cl = classes.length; final int fl = formalTypes.length - (varArg ? 1 : 0); @@ -203,7 +203,7 @@ final class ClassString { return true; } - private static boolean canConvert(LinkerServices ls, Class from, Class to) { + private static boolean canConvert(final LinkerServices ls, final Class from, final Class to) { if(from == NULL_CLASS) { return !to.isPrimitive(); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java index 6beb92b12f7..e72ca6dce54 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java @@ -99,7 +99,7 @@ import jdk.internal.dynalink.linker.LinkerServices; abstract class DynamicMethod { private final String name; - DynamicMethod(String name) { + DynamicMethod(final String name) { this.name = name; } @@ -138,7 +138,7 @@ abstract class DynamicMethod { */ abstract boolean contains(SingleDynamicMethod method); - static String getClassAndMethodName(Class clazz, String name) { + static String getClassAndMethodName(final Class clazz, final String name) { final String clazzName = clazz.getCanonicalName(); return (clazzName == null ? clazz.getName() : clazzName) + "." + name; } diff --git a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java index 32942b9a423..08f2a2581c1 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java +++ b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java @@ -99,12 +99,12 @@ import jdk.internal.dynalink.support.Guards; */ class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker { @Override - public boolean canLinkType(Class type) { + public boolean canLinkType(final Class type) { return DynamicMethod.class.isAssignableFrom(type); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) { + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) { final Object receiver = linkRequest.getReceiver(); if(!(receiver instanceof DynamicMethod)) { return null; diff --git a/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java index 4ac5deaa9da..29c98d042ff 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java +++ b/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java @@ -106,7 +106,7 @@ abstract class FacetIntrospector { protected final AccessibleMembersLookup membersLookup; - FacetIntrospector(Class clazz, boolean instance) { + FacetIntrospector(final Class clazz, final boolean instance) { this.clazz = clazz; this.instance = instance; isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz); @@ -135,7 +135,7 @@ abstract class FacetIntrospector { final Field[] fields = clazz.getFields(); final Collection cfields = new ArrayList<>(fields.length); - for(Field field: fields) { + for(final Field field: fields) { final boolean isStatic = Modifier.isStatic(field.getModifiers()); if(isStatic && clazz != field.getDeclaringClass()) { // ignore inherited static fields @@ -149,7 +149,7 @@ abstract class FacetIntrospector { return cfields; } - boolean isAccessible(Member m) { + boolean isAccessible(final Member m) { final Class declaring = m.getDeclaringClass(); // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a // non-restriced class, so if the declaring class is identical to the class being inspected, then forego @@ -166,11 +166,11 @@ abstract class FacetIntrospector { } - MethodHandle unreflectGetter(Field field) { + MethodHandle unreflectGetter(final Field field) { return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field)); } - MethodHandle unreflectSetter(Field field) { + MethodHandle unreflectSetter(final Field field) { return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field)); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java b/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java index f2c76dba828..9bacd218c16 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java +++ b/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java @@ -105,38 +105,38 @@ class GuardedInvocationComponent { private final GuardedInvocation guardedInvocation; private final Validator validator; - GuardedInvocationComponent(MethodHandle invocation) { + GuardedInvocationComponent(final MethodHandle invocation) { this(invocation, null, ValidationType.NONE); } - GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, ValidationType validationType) { + GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) { this(invocation, guard, null, validationType); } - GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Class validatorClass, - ValidationType validationType) { + GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class validatorClass, + final ValidationType validationType) { this(invocation, guard, new Validator(validatorClass, validationType)); } - GuardedInvocationComponent(GuardedInvocation guardedInvocation, Class validatorClass, - ValidationType validationType) { + GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class validatorClass, + final ValidationType validationType) { this(guardedInvocation, new Validator(validatorClass, validationType)); } - GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation) { + GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) { return replaceInvocation(newInvocation, guardedInvocation.getGuard()); } - GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation, MethodHandle newGuard) { + GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) { return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation, newGuard), validator); } - private GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Validator validator) { + private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) { this(new GuardedInvocation(invocation, guard), validator); } - private GuardedInvocationComponent(GuardedInvocation guardedInvocation, Validator validator) { + private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) { this.guardedInvocation = guardedInvocation; this.validator = validator; } @@ -153,8 +153,8 @@ class GuardedInvocationComponent { return validator.validationType; } - GuardedInvocationComponent compose(MethodHandle compositeInvocation, MethodHandle otherGuard, - Class otherValidatorClass, ValidationType otherValidationType) { + GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard, + final Class otherValidatorClass, final ValidationType otherValidationType) { final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType)); final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard; return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator); @@ -164,12 +164,12 @@ class GuardedInvocationComponent { /*private*/ final Class validatorClass; /*private*/ final ValidationType validationType; - Validator(Class validatorClass, ValidationType validationType) { + Validator(final Class validatorClass, final ValidationType validationType) { this.validatorClass = validatorClass; this.validationType = validationType; } - Validator compose(Validator other) { + Validator compose(final Validator other) { if(other.validationType == ValidationType.NONE) { return this; } @@ -240,7 +240,7 @@ class GuardedInvocationComponent { throw new AssertionError("Incompatible composition " + this + " vs " + other); } - private boolean isAssignableFrom(Validator other) { + private boolean isAssignableFrom(final Validator other) { return validatorClass.isAssignableFrom(other.validatorClass); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java b/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java index 3ee8e41ab30..8b5e3214a30 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java +++ b/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java @@ -105,7 +105,7 @@ class MaximallySpecific { * @param varArgs whether to assume the methods are varargs * @return the list of maximally specific methods. */ - static List getMaximallySpecificMethods(List methods, boolean varArgs) { + static List getMaximallySpecificMethods(final List methods, final boolean varArgs) { return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null); } @@ -116,7 +116,7 @@ class MaximallySpecific { private static final MethodTypeGetter METHOD_HANDLE_TYPE_GETTER = new MethodTypeGetter() { @Override - MethodType getMethodType(MethodHandle t) { + MethodType getMethodType(final MethodHandle t) { return t.type(); } }; @@ -124,7 +124,7 @@ class MaximallySpecific { private static final MethodTypeGetter DYNAMIC_METHOD_TYPE_GETTER = new MethodTypeGetter() { @Override - MethodType getMethodType(SingleDynamicMethod t) { + MethodType getMethodType(final SingleDynamicMethod t) { return t.getMethodType(); } }; @@ -138,8 +138,8 @@ class MaximallySpecific { * @param argTypes concrete argument types for the invocation * @return the list of maximally specific method handles. */ - static List getMaximallySpecificMethodHandles(List methods, boolean varArgs, - Class[] argTypes, LinkerServices ls) { + static List getMaximallySpecificMethodHandles(final List methods, final boolean varArgs, + final Class[] argTypes, final LinkerServices ls) { return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER); } @@ -152,8 +152,8 @@ class MaximallySpecific { * @param argTypes concrete argument types for the invocation * @return the list of maximally specific methods. */ - static List getMaximallySpecificSingleDynamicMethods(List methods, - boolean varArgs, Class[] argTypes, LinkerServices ls) { + static List getMaximallySpecificSingleDynamicMethods(final List methods, + final boolean varArgs, final Class[] argTypes, final LinkerServices ls) { return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER); } @@ -166,16 +166,16 @@ class MaximallySpecific { * @param argTypes concrete argument types for the invocation * @return the list of maximally specific methods. */ - private static List getMaximallySpecificMethods(List methods, boolean varArgs, - Class[] argTypes, LinkerServices ls, MethodTypeGetter methodTypeGetter) { + private static List getMaximallySpecificMethods(final List methods, final boolean varArgs, + final Class[] argTypes, final LinkerServices ls, final MethodTypeGetter methodTypeGetter) { if(methods.size() < 2) { return methods; } final LinkedList maximals = new LinkedList<>(); - for(T m: methods) { + for(final T m: methods) { final MethodType methodType = methodTypeGetter.getMethodType(m); boolean lessSpecific = false; - for(Iterator maximal = maximals.iterator(); maximal.hasNext();) { + for(final Iterator maximal = maximals.iterator(); maximal.hasNext();) { final T max = maximal.next(); switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) { case TYPE_1_BETTER: { @@ -202,8 +202,8 @@ class MaximallySpecific { return maximals; } - private static Comparison isMoreSpecific(MethodType t1, MethodType t2, boolean varArgs, Class[] argTypes, - LinkerServices ls) { + private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class[] argTypes, + final LinkerServices ls) { final int pc1 = t1.parameterCount(); final int pc2 = t2.parameterCount(); assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1); @@ -241,7 +241,7 @@ class MaximallySpecific { return Comparison.INDETERMINATE; } - private static Comparison compare(Class c1, Class c2, Class[] argTypes, int i, LinkerServices cmp) { + private static Comparison compare(final Class c1, final Class c2, final Class[] argTypes, final int i, final LinkerServices cmp) { if(cmp != null) { final Comparison c = cmp.compareConversion(argTypes[i], c1, c2); if(c != Comparison.INDETERMINATE) { @@ -256,7 +256,7 @@ class MaximallySpecific { return Comparison.INDETERMINATE; } - private static Class getParameterClass(MethodType t, int l, int i, boolean varArgs) { + private static Class getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) { return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i); } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java index 8ce41bc658c..7dc21a2978b 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java @@ -115,20 +115,20 @@ class OverloadedDynamicMethod extends DynamicMethod { * @param clazz the class this method belongs to * @param name the name of the method */ - OverloadedDynamicMethod(Class clazz, String name) { + OverloadedDynamicMethod(final Class clazz, final String name) { this(new LinkedList(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); } - private OverloadedDynamicMethod(LinkedList methods, ClassLoader classLoader, String name) { + private OverloadedDynamicMethod(final LinkedList methods, final ClassLoader classLoader, final String name) { super(name); this.methods = methods; this.classLoader = classLoader; } @Override - SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) { + SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { final LinkedList matchingMethods = new LinkedList<>(); - for(SingleDynamicMethod method: methods) { + for(final SingleDynamicMethod method: methods) { final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes); if(matchingMethod != null) { matchingMethods.add(matchingMethod); @@ -148,7 +148,6 @@ class OverloadedDynamicMethod extends DynamicMethod { } } - @SuppressWarnings("fallthrough") @Override public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { final MethodType callSiteType = callSiteDescriptor.getMethodType(); @@ -207,7 +206,7 @@ class OverloadedDynamicMethod extends DynamicMethod { case 1: { // Very lucky, we ended up with a single candidate method handle based on the call site signature; we // can link it very simply by delegating to the SingleDynamicMethod. - invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices); + return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices); } default: { // We have more than one candidate. We have no choice but to link to a method that resolves overloads on @@ -218,7 +217,7 @@ class OverloadedDynamicMethod extends DynamicMethod { // has an already determined Lookup. final List methodHandles = new ArrayList<>(invokables.size()); final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup(); - for(SingleDynamicMethod method: invokables) { + for(final SingleDynamicMethod method: invokables) { methodHandles.add(method.getTarget(lookup)); } return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker(); @@ -228,8 +227,8 @@ class OverloadedDynamicMethod extends DynamicMethod { } @Override - public boolean contains(SingleDynamicMethod m) { - for(SingleDynamicMethod method: methods) { + public boolean contains(final SingleDynamicMethod m) { + for(final SingleDynamicMethod method: methods) { if(method.contains(m)) { return true; } @@ -241,8 +240,8 @@ class OverloadedDynamicMethod extends DynamicMethod { return classLoader; } - private static boolean isApplicableDynamically(LinkerServices linkerServices, MethodType callSiteType, - SingleDynamicMethod m) { + private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType, + final SingleDynamicMethod m) { final MethodType methodType = m.getMethodType(); final boolean varArgs = m.isVarArgs(); final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0); @@ -288,13 +287,13 @@ class OverloadedDynamicMethod extends DynamicMethod { return true; } - private static boolean isApplicableDynamically(LinkerServices linkerServices, Class callSiteType, - Class methodType) { + private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class callSiteType, + final Class methodType) { return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType) || linkerServices.canConvert(callSiteType, methodType); } - private ApplicableOverloadedMethods getApplicables(MethodType callSiteType, ApplicabilityTest test) { + private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) { return new ApplicableOverloadedMethods(methods, callSiteType, test); } @@ -303,7 +302,7 @@ class OverloadedDynamicMethod extends DynamicMethod { * * @param method a method to add */ - public void addMethod(SingleDynamicMethod method) { + public void addMethod(final SingleDynamicMethod method) { methods.add(method); } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java b/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java index f711489b037..75332859f17 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java @@ -93,6 +93,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.support.Lookup; +import jdk.internal.dynalink.support.TypeUtilities; /** * Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or @@ -111,16 +112,18 @@ class OverloadedMethod { private final ArrayList fixArgMethods; private final ArrayList varArgMethods; - OverloadedMethod(List methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType, - LinkerServices linkerServices) { + OverloadedMethod(final List methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType, + final LinkerServices linkerServices) { this.parent = parent; - this.callSiteType = callSiteType; + final Class commonRetType = getCommonReturnType(methodHandles); + this.callSiteType = callSiteType.changeReturnType(commonRetType); this.linkerServices = linkerServices; fixArgMethods = new ArrayList<>(methodHandles.size()); varArgMethods = new ArrayList<>(methodHandles.size()); final int argNum = callSiteType.parameterCount(); for(MethodHandle mh: methodHandles) { + mh = mh.asType(mh.type().changeReturnType(commonRetType)); if(mh.isVarargsCollector()) { final MethodHandle asFixed = mh.asFixedArity(); if(argNum == asFixed.type().parameterCount()) { @@ -137,7 +140,7 @@ class OverloadedMethod { final MethodHandle bound = SELECT_METHOD.bindTo(this); final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType( callSiteType.changeReturnType(MethodHandle.class)); - invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting); + invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(this.callSiteType), collecting); } MethodHandle getInvoker() { @@ -148,7 +151,7 @@ class OverloadedMethod { MethodHandle.class, Object[].class); @SuppressWarnings("unused") - private MethodHandle selectMethod(Object[] args) throws NoSuchMethodException { + private MethodHandle selectMethod(final Object[] args) throws NoSuchMethodException { final Class[] argTypes = new Class[args.length]; for(int i = 0; i < argTypes.length; ++i) { final Object arg = args[i]; @@ -185,7 +188,7 @@ class OverloadedMethod { return method; } - private MethodHandle getNoSuchMethodThrower(Class[] argTypes) { + private MethodHandle getNoSuchMethodThrower(final Class[] argTypes) { return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes)); } @@ -193,7 +196,7 @@ class OverloadedMethod { "throwNoSuchMethod", void.class, Class[].class); @SuppressWarnings("unused") - private void throwNoSuchMethod(Class[] argTypes) throws NoSuchMethodException { + private void throwNoSuchMethod(final Class[] argTypes) throws NoSuchMethodException { if(varArgMethods.isEmpty()) { throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) + " of method " + parent.getName() + " match the argument types " + argTypesString(argTypes)); @@ -203,11 +206,11 @@ class OverloadedMethod { parent.getName() + " match the argument types " + argTypesString(argTypes)); } - private MethodHandle getAmbiguousMethodThrower(Class[] argTypes, List methods) { + private MethodHandle getAmbiguousMethodThrower(final Class[] argTypes, final List methods) { return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods)); } - private MethodHandle adaptThrower(MethodHandle rawThrower) { + private MethodHandle adaptThrower(final MethodHandle rawThrower) { return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType); } @@ -215,20 +218,20 @@ class OverloadedMethod { "throwAmbiguousMethod", void.class, Class[].class, List.class); @SuppressWarnings("unused") - private void throwAmbiguousMethod(Class[] argTypes, List methods) throws NoSuchMethodException { + private void throwAmbiguousMethod(final Class[] argTypes, final List methods) throws NoSuchMethodException { final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed"; throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " + getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " + argTypesString(argTypes)); } - private static String argTypesString(Class[] classes) { + private static String argTypesString(final Class[] classes) { final StringBuilder b = new StringBuilder().append('['); appendTypes(b, classes, false); return b.append(']').toString(); } - private static String getSignatureList(List methods) { + private static String getSignatureList(final List methods) { final StringBuilder b = new StringBuilder().append('['); final Iterator it = methods.iterator(); if(it.hasNext()) { @@ -240,13 +243,13 @@ class OverloadedMethod { return b.append(']').toString(); } - private static void appendSig(StringBuilder b, MethodHandle m) { + private static void appendSig(final StringBuilder b, final MethodHandle m) { b.append('('); appendTypes(b, m.type().parameterArray(), m.isVarargsCollector()); b.append(')'); } - private static void appendTypes(StringBuilder b, Class[] classes, boolean varArg) { + private static void appendTypes(final StringBuilder b, final Class[] classes, final boolean varArg) { final int l = classes.length; if(!varArg) { if(l > 1) { @@ -262,4 +265,13 @@ class OverloadedMethod { b.append(classes[l - 1].getComponentType().getCanonicalName()).append("..."); } } + + private static Class getCommonReturnType(final List methodHandles) { + final Iterator it = methodHandles.iterator(); + Class retType = it.next().type().returnType(); + while(it.hasNext()) { + retType = TypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType()); + } + return retType; + } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java index 9d4d6961081..2965cb4e401 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java @@ -107,12 +107,12 @@ class SimpleDynamicMethod extends SingleDynamicMethod { * @param clazz the class declaring the method * @param name the simple name of the method */ - SimpleDynamicMethod(MethodHandle target, Class clazz, String name) { + SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name) { super(getName(target, clazz, name)); this.target = target; } - private static String getName(MethodHandle target, Class clazz, String name) { + private static String getName(final MethodHandle target, final Class clazz, final String name) { return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name)); } @@ -127,7 +127,7 @@ class SimpleDynamicMethod extends SingleDynamicMethod { } @Override - MethodHandle getTarget(Lookup lookup) { + MethodHandle getTarget(final Lookup lookup) { return target; } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java index 6b55d81f15c..79dca9a3ce1 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java +++ b/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java @@ -104,7 +104,7 @@ abstract class SingleDynamicMethod extends DynamicMethod { private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class); - SingleDynamicMethod(String name) { + SingleDynamicMethod(final String name) { super(name); } @@ -128,22 +128,22 @@ abstract class SingleDynamicMethod extends DynamicMethod { abstract MethodHandle getTarget(MethodHandles.Lookup lookup); @Override - MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) { + MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(), linkerServices); } @Override - SingleDynamicMethod getMethodForExactParamTypes(String paramTypes) { + SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { return typeMatchesDescription(paramTypes, getMethodType()) ? this : null; } @Override - boolean contains(SingleDynamicMethod method) { + boolean contains(final SingleDynamicMethod method) { return getMethodType().parameterList().equals(method.getMethodType().parameterList()); } - static String getMethodNameWithSignature(MethodType type, String methodName) { + static String getMethodNameWithSignature(final MethodType type, final String methodName) { final String typeStr = type.toString(); final int retTypeIndex = typeStr.lastIndexOf(')') + 1; int secondParamIndex = typeStr.indexOf(',') + 1; @@ -156,13 +156,15 @@ abstract class SingleDynamicMethod extends DynamicMethod { /** * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type * conversions as needed using the specified linker services, and in case that the method handle is a vararg - * collector, matches it to the arity of the call site. + * collector, matches it to the arity of the call site. The type of the return value is only changed if it can be + * converted using a conversion that loses neither precision nor magnitude, see + * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}. * @param target the method handle to adapt * @param callSiteType the type of the call site * @param linkerServices the linker services used for type conversions * @return the adapted method handle. */ - static MethodHandle getInvocation(MethodHandle target, MethodType callSiteType, LinkerServices linkerServices) { + static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) { final MethodType methodType = target.type(); final int paramsLen = methodType.parameterCount(); final boolean varArgs = target.isVarargsCollector(); @@ -264,7 +266,7 @@ abstract class SingleDynamicMethod extends DynamicMethod { } @SuppressWarnings("unused") - private static boolean canConvertTo(final LinkerServices linkerServices, Class to, Object obj) { + private static boolean canConvertTo(final LinkerServices linkerServices, final Class to, final Object obj) { return obj == null ? false : linkerServices.canConvert(obj.getClass(), to); } @@ -277,7 +279,7 @@ abstract class SingleDynamicMethod extends DynamicMethod { * @param parameterCount the total number of arguments in the new method handle * @return a collecting method handle */ - static MethodHandle collectArguments(MethodHandle target, final int parameterCount) { + static MethodHandle collectArguments(final MethodHandle target, final int parameterCount) { final MethodType methodType = target.type(); final int fixParamsLen = methodType.parameterCount() - 1; final Class arrayType = methodType.parameterType(fixParamsLen); @@ -286,10 +288,10 @@ abstract class SingleDynamicMethod extends DynamicMethod { private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod, final LinkerServices linkerServices, final MethodType callSiteType) { - return linkerServices.asType(sizedMethod, callSiteType); + return linkerServices.asTypeLosslessReturn(sizedMethod, callSiteType); } - private static boolean typeMatchesDescription(String paramTypes, MethodType type) { + private static boolean typeMatchesDescription(final String paramTypes, final MethodType type) { final StringTokenizer tok = new StringTokenizer(paramTypes, ", "); for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) { @@ -299,7 +301,7 @@ abstract class SingleDynamicMethod extends DynamicMethod { return !tok.hasMoreTokens(); } - private static boolean typeNameMatches(String typeName, Class type) { + private static boolean typeNameMatches(final String typeName, final Class type) { return typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName()); } } diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java index 5008c211432..f70f264709b 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java +++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java @@ -96,7 +96,7 @@ import java.io.Serializable; public class StaticClass implements Serializable { private static final ClassValue staticClasses = new ClassValue() { @Override - protected StaticClass computeValue(Class type) { + protected StaticClass computeValue(final Class type) { return new StaticClass(type); } }; @@ -105,7 +105,7 @@ public class StaticClass implements Serializable { private final Class clazz; - /*private*/ StaticClass(Class clazz) { + /*private*/ StaticClass(final Class clazz) { clazz.getClass(); // NPE check this.clazz = clazz; } @@ -115,7 +115,7 @@ public class StaticClass implements Serializable { * @param clazz the class for which the static facet is requested. * @return the {@link StaticClass} instance representing the specified class. */ - public static StaticClass forClass(Class clazz) { + public static StaticClass forClass(final Class clazz) { return staticClasses.get(clazz); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java index 62ce41a95a6..8a07c1f12b1 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java +++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java @@ -90,14 +90,14 @@ import java.util.HashMap; import java.util.Map; class StaticClassIntrospector extends FacetIntrospector { - StaticClassIntrospector(Class clazz) { + StaticClassIntrospector(final Class clazz) { super(clazz, false); } @Override Map getInnerClassGetters() { final Map map = new HashMap<>(); - for(Class innerClass: membersLookup.getInnerClasses()) { + for(final Class innerClass: membersLookup.getInnerClasses()) { map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class, StaticClass.forClass(innerClass)))); } @@ -105,15 +105,15 @@ class StaticClassIntrospector extends FacetIntrospector { } @Override - MethodHandle editMethodHandle(MethodHandle mh) { + MethodHandle editMethodHandle(final MethodHandle mh) { return editStaticMethodHandle(mh); } - static MethodHandle editStaticMethodHandle(MethodHandle mh) { + static MethodHandle editStaticMethodHandle(final MethodHandle mh) { return dropReceiver(mh, Object.class); } - static MethodHandle editConstructorMethodHandle(MethodHandle cmh) { + static MethodHandle editConstructorMethodHandle(final MethodHandle cmh) { return dropReceiver(cmh, StaticClass.class); } diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java index 5f80caea74f..41955bb9e39 100644 --- a/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java +++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java @@ -104,7 +104,7 @@ import jdk.internal.dynalink.support.Lookup; class StaticClassLinker implements TypeBasedGuardingDynamicLinker { private static final ClassValue linkers = new ClassValue() { @Override - protected SingleClassStaticsLinker computeValue(Class clazz) { + protected SingleClassStaticsLinker computeValue(final Class clazz) { return new SingleClassStaticsLinker(clazz); } }; @@ -112,7 +112,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { private static class SingleClassStaticsLinker extends AbstractJavaLinker { private final DynamicMethod constructor; - SingleClassStaticsLinker(Class clazz) { + SingleClassStaticsLinker(final Class clazz) { super(clazz, IS_CLASS.bindTo(clazz)); // Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass // StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS. @@ -126,7 +126,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { * @return a dynamic method containing all overloads of a class' public constructor. If the class has no public * constructors, returns null. */ - private static DynamicMethod createConstructorMethod(Class clazz) { + private static DynamicMethod createConstructorMethod(final Class clazz) { if(clazz.isArray()) { final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType()); return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle( @@ -144,7 +144,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices); if(gi != null) { @@ -162,20 +162,20 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { } } - static Collection getReadableStaticPropertyNames(Class clazz) { + static Collection getReadableStaticPropertyNames(final Class clazz) { return linkers.get(clazz).getReadablePropertyNames(); } - static Collection getWritableStaticPropertyNames(Class clazz) { + static Collection getWritableStaticPropertyNames(final Class clazz) { return linkers.get(clazz).getWritablePropertyNames(); } - static Collection getStaticMethodNames(Class clazz) { + static Collection getStaticMethodNames(final Class clazz) { return linkers.get(clazz).getMethodNames(); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception { + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final Object receiver = request.getReceiver(); if(receiver instanceof StaticClass) { return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request, @@ -185,7 +185,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { } @Override - public boolean canLinkType(Class type) { + public boolean canLinkType(final Class type) { return type == StaticClass.class; } @@ -201,7 +201,7 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker { } @SuppressWarnings("unused") - private static boolean isClass(Class clazz, Object obj) { + private static boolean isClass(final Class clazz, final Object obj) { return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz; } } diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java b/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java index 26a741e8288..34dcdc03d76 100644 --- a/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java +++ b/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java @@ -83,6 +83,8 @@ package jdk.internal.dynalink.linker; +import static jdk.nashorn.internal.lookup.Lookup.MH; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -104,7 +106,18 @@ import jdk.internal.dynalink.support.Guards; public class GuardedInvocation { private final MethodHandle invocation; private final MethodHandle guard; - private final SwitchPoint switchPoint; + private final Class exception; + private final SwitchPoint[] switchPoints; + + /** + * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations. + * + * @param invocation the method handle representing the invocation. Must not be null. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation) { + this(invocation, null, (SwitchPoint)null, null); + } /** * Creates a new guarded invocation. @@ -115,8 +128,19 @@ public class GuardedInvocation { * an unconditional invocation, although that is unusual. * @throws NullPointerException if invocation is null. */ - public GuardedInvocation(MethodHandle invocation, MethodHandle guard) { - this(invocation, guard, null); + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) { + this(invocation, guard, (SwitchPoint)null, null); + } + + /** + * Creates a new guarded invocation. + * + * @param invocation the method handle representing the invocation. Must not be null. + * @param switchPoint the optional switch point that can be used to invalidate this linkage. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) { + this(invocation, null, switchPoint, null); } /** @@ -129,26 +153,50 @@ public class GuardedInvocation { * @param switchPoint the optional switch point that can be used to invalidate this linkage. * @throws NullPointerException if invocation is null. */ - public GuardedInvocation(MethodHandle invocation, MethodHandle guard, SwitchPoint switchPoint) { + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) { + this(invocation, guard, switchPoint, null); + } + + /** + * Creates a new guarded invocation. + * + * @param invocation the method handle representing the invocation. Must not be null. + * @param guard the method handle representing the guard. Must have the same method type as the invocation, except + * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it + * and the switch point are null, this represents an unconditional invocation, which is legal but unusual. + * @param switchPoint the optional switch point that can be used to invalidate this linkage. + * @param exception the optional exception type that is expected to be thrown by the invocation and that also + * invalidates the linkage. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class exception) { invocation.getClass(); // NPE check this.invocation = invocation; this.guard = guard; - this.switchPoint = switchPoint; + this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; + this.exception = exception; } /** - * Creates a new guarded invocation. + * Creates a new guarded invocation * * @param invocation the method handle representing the invocation. Must not be null. - * @param switchPoint the optional switch point that can be used to invalidate this linkage. * @param guard the method handle representing the guard. Must have the same method type as the invocation, except * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it * and the switch point are null, this represents an unconditional invocation, which is legal but unusual. + * @param switchPoints the optional switch points that can be used to invalidate this linkage. + * @param exception the optional exception type that is expected to be thrown by the invocation and that also + * invalidates the linkage. * @throws NullPointerException if invocation is null. */ - public GuardedInvocation(MethodHandle invocation, SwitchPoint switchPoint, MethodHandle guard) { - this(invocation, guard, switchPoint); + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class exception) { + invocation.getClass(); // NPE check + this.invocation = invocation; + this.guard = guard; + this.switchPoints = switchPoints; + this.exception = exception; } + /** * Returns the invocation method handle. * @@ -172,8 +220,17 @@ public class GuardedInvocation { * * @return the switch point that can be used to invalidate the invocation handle. Can be null. */ - public SwitchPoint getSwitchPoint() { - return switchPoint; + public SwitchPoint[] getSwitchPoints() { + return switchPoints == null ? null : switchPoints.clone(); + } + + /** + * Returns the exception type that if thrown should be used to invalidate the linkage. + * + * @return the exception type that if thrown should be used to invalidate the linkage. Can be null. + */ + public Class getException() { + return exception; } /** @@ -181,7 +238,15 @@ public class GuardedInvocation { * @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated. */ public boolean hasBeenInvalidated() { - return switchPoint != null && switchPoint.hasBeenInvalidated(); + if (switchPoints == null) { + return false; + } + for (final SwitchPoint sp : switchPoints) { + if (sp.hasBeenInvalidated()) { + return true; + } + } + return false; } /** @@ -191,9 +256,9 @@ public class GuardedInvocation { * @param type the asserted type * @throws WrongMethodTypeException if the invocation and the guard are not of the expected method type. */ - public void assertType(MethodType type) { + public void assertType(final MethodType type) { assertType(invocation, type); - if(guard != null) { + if (guard != null) { assertType(guard, type.changeReturnType(Boolean.TYPE)); } } @@ -205,12 +270,34 @@ public class GuardedInvocation { * @param newGuard the new guard * @return a new guarded invocation with the replaced methods and the same switch point as this invocation. */ - public GuardedInvocation replaceMethods(MethodHandle newInvocation, MethodHandle newGuard) { - return new GuardedInvocation(newInvocation, newGuard, switchPoint); + public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) { + return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception); } - private GuardedInvocation replaceMethodsOrThis(MethodHandle newInvocation, MethodHandle newGuard) { - if(newInvocation == invocation && newGuard == guard) { + /** + * Add a switchpoint to this guarded invocation + * @param newSwitchPoint new switchpoint, or null for nop + * @return new guarded invocation with the extra switchpoint + */ + public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) { + if (newSwitchPoint == null) { + return this; + } + + final SwitchPoint[] newSwitchPoints; + if (switchPoints != null) { + newSwitchPoints = new SwitchPoint[switchPoints.length + 1]; + System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length); + newSwitchPoints[switchPoints.length] = newSwitchPoint; + } else { + newSwitchPoints = new SwitchPoint[] { newSwitchPoint }; + } + + return new GuardedInvocation(invocation, guard, newSwitchPoints, exception); + } + + private GuardedInvocation replaceMethodsOrThis(final MethodHandle newInvocation, final MethodHandle newGuard) { + if (newInvocation == invocation && newGuard == guard) { return this; } return replaceMethods(newInvocation, newGuard); @@ -223,7 +310,7 @@ public class GuardedInvocation { * @param newType the new type of the invocation. * @return a guarded invocation with the new type applied to it. */ - public GuardedInvocation asType(MethodType newType) { + public GuardedInvocation asType(final MethodType newType) { return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType)); } @@ -235,11 +322,25 @@ public class GuardedInvocation { * @param newType the new type of the invocation. * @return a guarded invocation with the new type applied to it. */ - public GuardedInvocation asType(LinkerServices linkerServices, MethodType newType) { + public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) { return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null : Guards.asType(linkerServices, guard, newType)); } + /** + * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was + * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it + * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the + * invocation doesn't change its type, returns this object. + * @param linkerServices the linker services to use for the conversion + * @param newType the new type of the invocation. + * @return a guarded invocation with the new type applied to it. + */ + public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) { + return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null : + Guards.asType(linkerServices, guard, newType)); + } + /** * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation * and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the @@ -247,7 +348,7 @@ public class GuardedInvocation { * @param desc a call descriptor whose method type is adapted. * @return a guarded invocation with the new type applied to it. */ - public GuardedInvocation asType(CallSiteDescriptor desc) { + public GuardedInvocation asType(final CallSiteDescriptor desc) { return asType(desc.getMethodType()); } @@ -257,7 +358,7 @@ public class GuardedInvocation { * @param filters the argument filters * @return a filtered invocation */ - public GuardedInvocation filterArguments(int pos, MethodHandle... filters) { + public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) { return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null : MethodHandles.filterArguments(guard, pos, filters)); } @@ -268,7 +369,7 @@ public class GuardedInvocation { * @param valueTypes the types of the values being dropped * @return an invocation that drops arguments */ - public GuardedInvocation dropArguments(int pos, List> valueTypes) { + public GuardedInvocation dropArguments(final int pos, final List> valueTypes) { return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : MethodHandles.dropArguments(guard, pos, valueTypes)); } @@ -279,7 +380,7 @@ public class GuardedInvocation { * @param valueTypes the types of the values being dropped * @return an invocation that drops arguments */ - public GuardedInvocation dropArguments(int pos, Class... valueTypes) { + public GuardedInvocation dropArguments(final int pos, final Class... valueTypes) { return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : MethodHandles.dropArguments(guard, pos, valueTypes)); } @@ -290,23 +391,50 @@ public class GuardedInvocation { * @param fallback the fallback method handle in case switchpoint is invalidated or guard returns false. * @return a composite method handle. */ - public MethodHandle compose(MethodHandle fallback) { - return compose(fallback, fallback); + public MethodHandle compose(final MethodHandle fallback) { + return compose(fallback, fallback, fallback); } /** * Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back. * @param switchpointFallback the fallback method handle in case switchpoint is invalidated. * @param guardFallback the fallback method handle in case guard returns false. + * @param catchFallback the fallback method in case the exception handler triggers * @return a composite method handle. */ - public MethodHandle compose(MethodHandle switchpointFallback, MethodHandle guardFallback) { + public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) { final MethodHandle guarded = - guard == null ? invocation : MethodHandles.guardWithTest(guard, invocation, guardFallback); - return switchPoint == null ? guarded : switchPoint.guardWithTest(guarded, switchpointFallback); + guard == null ? + invocation : + MethodHandles.guardWithTest( + guard, + invocation, + guardFallback); + + final MethodHandle catchGuarded = + exception == null ? + guarded : + MH.catchException( + guarded, + exception, + MethodHandles.dropArguments( + catchFallback, + 0, + exception)); + + if (switchPoints == null) { + return catchGuarded; + } + + MethodHandle spGuarded = catchGuarded; + for (final SwitchPoint sp : switchPoints) { + spGuarded = sp.guardWithTest(spGuarded, switchpointFallback); + } + + return spGuarded; } - private static void assertType(MethodHandle mh, MethodType type) { + private static void assertType(final MethodHandle mh, final MethodType type) { if(!mh.type().equals(type)) { throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type()); } diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java b/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java index 9baed7c0ebd..88357ff0c98 100644 --- a/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java +++ b/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java @@ -83,19 +83,35 @@ package jdk.internal.dynalink.linker; +/** + * Guarded type conversion + */ public class GuardedTypeConversion { private final GuardedInvocation conversionInvocation; private final boolean cacheable; + /** + * Constructor + * @param conversionInvocation guarded invocation for this type conversion + * @param cacheable is this invocation cacheable + */ public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) { this.conversionInvocation = conversionInvocation; this.cacheable = cacheable; } + /** + * Get the invocation + * @return invocation + */ public GuardedInvocation getConversionInvocation() { return conversionInvocation; } + /** + * Check if invocation is cacheable + * @return true if cachable, false otherwise + */ public boolean isCacheable() { return cacheable; } diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java index 2cd0d0f04d1..82a361970ed 100644 --- a/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java +++ b/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java @@ -101,10 +101,16 @@ public interface GuardingDynamicLinker { * @return a guarded invocation with a method handle suitable for the arguments, as well as a guard condition that * if fails should trigger relinking. Must return null if it can't resolve the invocation. If the returned * invocation is unconditional (which is actually quite rare), the guard in the return value can be null. The - * invocation can also have a switch point for asynchronous invalidation of the linkage. If the linker does not - * recognize any native language runtime contexts in arguments, or does recognize its own, but receives a call site - * descriptor without its recognized context in the arguments, it should invoke - * {@link LinkRequest#withoutRuntimeContext()} and link for that. + * invocation can also have a switch point for asynchronous invalidation of the linkage, as well as a + * {@link Throwable} subclass that describes an expected exception condition that also triggers relinking (often it + * is faster to rely on an infrequent but expected {@link ClassCastException} than on an always evaluated + * {@code instanceof} guard). If the linker does not recognize any native language runtime contexts in arguments, or + * does recognize its own, but receives a call site descriptor without its recognized context in the arguments, it + * should invoke {@link LinkRequest#withoutRuntimeContext()} and link for that. While the linker must produce an + * invocation with parameter types matching those in the call site descriptor of the link request, it should not try + * to match the return type expected at the call site except when it can do it with only the conversions that lose + * neither precision nor magnitude, see {@link LinkerServices#asTypeLosslessReturn(java.lang.invoke.MethodHandle, + * java.lang.invoke.MethodType)}. * @throws Exception if the operation fails for whatever reason */ public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) diff --git a/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java b/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java index 1a82a4fab7b..63501cdc12e 100644 --- a/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java +++ b/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java @@ -100,6 +100,17 @@ public interface LinkRequest { */ public CallSiteDescriptor getCallSiteDescriptor(); + /** + * Returns the call site token for the call site being linked. This token is an opaque object that is guaranteed to + * have different identity for different call sites, and is also guaranteed to not become weakly reachable before + * the call site does and to become weakly reachable some time after the call site does. This makes it ideal as a + * candidate for a key in a weak hash map in which a linker might want to keep per-call site linking state (usually + * profiling information). + * + * @return the call site token for the call site being linked. + */ + public Object getCallSiteToken(); + /** * Returns the arguments for the invocation being linked. The returned array is a clone; modifications to it won't * affect the arguments in this request. @@ -115,6 +126,17 @@ public interface LinkRequest { */ public Object getReceiver(); + /** + * Returns the number of times this callsite has been linked/relinked. This can be useful if you want to + * change e.g. exception based relinking to guard based relinking. It's probably not a good idea to keep, + * for example, expensive exception throwing relinkage based on failed type checks/ClassCastException in + * a nested callsite tree where the exception is thrown repeatedly for the common case. There it would be + * much more performant to use exact type guards instead. + * + * @return link count for call site + */ + public int getLinkCount(); + /** * Returns true if the call site is considered unstable, that is, it has been relinked more times than was * specified in {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)}. Linkers should use this as a diff --git a/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java b/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java index deaf820f11b..9e35d7f6be5 100644 --- a/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java +++ b/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java @@ -87,7 +87,9 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import jdk.internal.dynalink.DynamicLinker; +import jdk.internal.dynalink.DynamicLinkerFactory; import jdk.internal.dynalink.linker.ConversionComparator.Comparison; +import jdk.internal.dynalink.support.TypeUtilities; /** * Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns @@ -103,17 +105,33 @@ public interface LinkerServices { * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive, * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions, * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters - * provided by {@link GuardingTypeConverterFactory} implementations. It doesn't use language-specific conversions on - * the return type. + * provided by {@link GuardingTypeConverterFactory} implementations. * * @param handle target method handle * @param fromType the types of source arguments - * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with - * {@link GuardingTypeConverterFactory} produced type converters as filters. + * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}, and + * {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)} with + * {@link GuardingTypeConverterFactory}-produced type converters as filters. */ public MethodHandle asType(MethodHandle handle, MethodType fromType); + /** + * Similar to {@link #asType(MethodHandle, MethodType)} except it only converts the return type of the method handle + * when it can be done using a conversion that loses neither precision nor magnitude, otherwise it leaves it + * unchanged. The idea is that other conversions should not be performed by individual linkers, but instead the + * {@link DynamicLinkerFactory#setPrelinkFilter(jdk.internal.dynalink.GuardedInvocationFilter) pre-link filter of + * the dynamic linker} should implement the strategy of dealing with potentially lossy return type conversions in a + * manner specific to the language runtime. + * + * @param handle target method handle + * @param fromType the types of source arguments + * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, and + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with + * {@link GuardingTypeConverterFactory}-produced type converters as filters. + */ + public MethodHandle asTypeLosslessReturn(MethodHandle handle, MethodType fromType); + /** * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst * case it will return an identity conversion (that might fail for some values at runtime). You rarely need to use @@ -161,4 +179,23 @@ public interface LinkerServices { * conversion. */ public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2); + + /** + * If we could just use Java 8 constructs, then {@code asTypeSafeReturn} would be a method with default + * implementation. Since we can't do that, we extract common default implementations into this static class. + */ + public static class Implementation { + /** + * Default implementation for {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}. + * @param linkerServices the linker services that delegates to this implementation + * @param handle the passed handle + * @param fromType the passed type + * @return the converted method handle, as per the {@code asTypeSafeReturn} semantics. + */ + public static MethodHandle asTypeLosslessReturn(final LinkerServices linkerServices, final MethodHandle handle, final MethodType fromType) { + final Class handleReturnType = handle.type().returnType(); + return linkerServices.asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ? + fromType : fromType.changeReturnType(handleReturnType)); + } + } } diff --git a/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java index 3161cf50a76..6bcbbbb3444 100644 --- a/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java +++ b/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java @@ -106,7 +106,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor { } @Override - public boolean equals(Object obj) { + public boolean equals(final Object obj) { return obj instanceof CallSiteDescriptor && equals((CallSiteDescriptor)obj); } @@ -115,7 +115,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor { * @param csd the other call site descriptor. * @return true if they are equal. */ - public boolean equals(CallSiteDescriptor csd) { + public boolean equals(final CallSiteDescriptor csd) { if(csd == null) { return false; } @@ -165,7 +165,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor { return l + c - 1; } - private StringBuilder appendName(StringBuilder b) { + private StringBuilder appendName(final StringBuilder b) { b.append(getNameToken(0)); final int c = getNameTokenCount(); for(int i = 1; i < c; ++i) { @@ -174,7 +174,7 @@ public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor { return b; } - private static boolean lookupsEqual(Lookup l1, Lookup l2) { + private static boolean lookupsEqual(final Lookup l1, final Lookup l2) { if(l1 == l2) { return true; } diff --git a/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java b/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java index c05d35e0948..e01880e56ca 100644 --- a/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java +++ b/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java @@ -100,7 +100,7 @@ public abstract class AbstractRelinkableCallSite extends MutableCallSite impleme * Creates a new relinkable call site. * @param descriptor the descriptor for this call site */ - protected AbstractRelinkableCallSite(CallSiteDescriptor descriptor) { + protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) { super(descriptor.getMethodType()); this.descriptor = descriptor; } @@ -111,7 +111,7 @@ public abstract class AbstractRelinkableCallSite extends MutableCallSite impleme } @Override - public void initialize(MethodHandle relinkAndInvoke) { + public void initialize(final MethodHandle relinkAndInvoke) { setTarget(relinkAndInvoke); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java b/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java index 2909365935b..ba318610c08 100644 --- a/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java +++ b/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java @@ -116,14 +116,14 @@ public class AutoDiscovery { * @return a list of guarding dynamic linkers available through the specified class loader. Can be zero-length list * but not null. */ - public static List loadLinkers(ClassLoader cl) { + public static List loadLinkers(final ClassLoader cl) { return getLinkers(ServiceLoader.load(GuardingDynamicLinker.class, cl)); } /** * I can't believe there's no Collections API for making a List given an Iterator... */ - private static List getLinkers(ServiceLoader loader) { + private static List getLinkers(final ServiceLoader loader) { final List list = new LinkedList<>(); for(final T linker: loader) { list.add(linker); diff --git a/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java index 7a2700e10ff..07abb6c398e 100644 --- a/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java +++ b/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java @@ -105,12 +105,12 @@ public class BottomGuardingDynamicLinker implements TypeBasedGuardingDynamicLink } @Override - public boolean canLinkType(Class type) { + public boolean canLinkType(final Class type) { return false; } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) { + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) { return null; } } diff --git a/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java b/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java index b0039d21c2c..9cbd5f04f3f 100644 --- a/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java +++ b/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java @@ -86,6 +86,7 @@ package jdk.internal.dynalink.support; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; +import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Collections; @@ -103,7 +104,7 @@ import jdk.internal.dynalink.CallSiteDescriptor; * @author Attila Szegedi */ public class CallSiteDescriptorFactory { - private static final WeakHashMap> publicDescs = + private static final WeakHashMap> publicDescs = new WeakHashMap<>(); @@ -121,7 +122,7 @@ public class CallSiteDescriptorFactory { * @return a call site descriptor representing the input. Note that although the method name is "create", it will * in fact return a weakly-referenced canonical instance. */ - public static CallSiteDescriptor create(Lookup lookup, String name, MethodType methodType) { + public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) { name.getClass(); // NPE check methodType.getClass(); // NPE check lookup.getClass(); // NPE check @@ -134,19 +135,28 @@ public class CallSiteDescriptorFactory { static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) { synchronized(publicDescs) { - final WeakReference ref = publicDescs.get(desc); + final Reference ref = publicDescs.get(desc); if(ref != null) { final CallSiteDescriptor canonical = ref.get(); if(canonical != null) { return canonical; } } - publicDescs.put(desc, new WeakReference<>(desc)); + publicDescs.put(desc, createReference(desc)); } return desc; } - private static CallSiteDescriptor createPublicCallSiteDescriptor(String[] tokenizedName, MethodType methodType) { + /** + * Override this to use a different kind of references for the cache + * @param desc desc + * @return reference + */ + protected static Reference createReference(final CallSiteDescriptor desc) { + return new WeakReference<>(desc); + } + + private static CallSiteDescriptor createPublicCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) { final int l = tokenizedName.length; if(l > 0 && tokenizedName[0] == "dyn") { if(l == 2) { @@ -158,7 +168,7 @@ public class CallSiteDescriptorFactory { return new DefaultCallSiteDescriptor(tokenizedName, methodType); } - private static boolean isPublicLookup(Lookup lookup) { + private static boolean isPublicLookup(final Lookup lookup) { return lookup == MethodHandles.publicLookup(); } @@ -169,7 +179,7 @@ public class CallSiteDescriptorFactory { * @param name the composite name consisting of colon-separated, possibly mangled tokens. * @return an array of tokens */ - public static String[] tokenizeName(String name) { + public static String[] tokenizeName(final String name) { final StringTokenizer tok = new StringTokenizer(name, CallSiteDescriptor.TOKEN_DELIMITER); final String[] tokens = new String[tok.countTokens()]; for(int i = 0; i < tokens.length; ++i) { @@ -188,7 +198,7 @@ public class CallSiteDescriptorFactory { * @param desc the call site descriptor with the operation * @return a list of tokens */ - public static List tokenizeOperators(CallSiteDescriptor desc) { + public static List tokenizeOperators(final CallSiteDescriptor desc) { final String ops = desc.getNameToken(CallSiteDescriptor.OPERATOR); final StringTokenizer tok = new StringTokenizer(ops, CallSiteDescriptor.OPERATOR_DELIMITER); final int count = tok.countTokens(); @@ -210,7 +220,7 @@ public class CallSiteDescriptorFactory { * @param end index of the first parameter to not remove * @return a new call site descriptor with modified method type */ - public static CallSiteDescriptor dropParameterTypes(CallSiteDescriptor desc, int start, int end) { + public static CallSiteDescriptor dropParameterTypes(final CallSiteDescriptor desc, final int start, final int end) { return desc.changeMethodType(desc.getMethodType().dropParameterTypes(start, end)); } @@ -222,7 +232,7 @@ public class CallSiteDescriptorFactory { * @param nptype the new parameter type * @return a new call site descriptor with modified method type */ - public static CallSiteDescriptor changeParameterType(CallSiteDescriptor desc, int num, Class nptype) { + public static CallSiteDescriptor changeParameterType(final CallSiteDescriptor desc, final int num, final Class nptype) { return desc.changeMethodType(desc.getMethodType().changeParameterType(num, nptype)); } @@ -233,7 +243,7 @@ public class CallSiteDescriptorFactory { * @param nrtype the new return type * @return a new call site descriptor with modified method type */ - public static CallSiteDescriptor changeReturnType(CallSiteDescriptor desc, Class nrtype) { + public static CallSiteDescriptor changeReturnType(final CallSiteDescriptor desc, final Class nrtype) { return desc.changeMethodType(desc.getMethodType().changeReturnType(nrtype)); } @@ -245,7 +255,7 @@ public class CallSiteDescriptorFactory { * @param ptypesToInsert the new types to insert * @return a new call site descriptor with modified method type */ - public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, Class... ptypesToInsert) { + public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final Class... ptypesToInsert) { return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert)); } @@ -257,7 +267,7 @@ public class CallSiteDescriptorFactory { * @param ptypesToInsert the new types to insert * @return a new call site descriptor with modified method type */ - public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, List> ptypesToInsert) { + public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final List> ptypesToInsert) { return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert)); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/ClassMap.java b/nashorn/src/jdk/internal/dynalink/support/ClassMap.java index d85b21d0033..758349b857a 100644 --- a/nashorn/src/jdk/internal/dynalink/support/ClassMap.java +++ b/nashorn/src/jdk/internal/dynalink/support/ClassMap.java @@ -110,7 +110,7 @@ public abstract class ClassMap { * * @param classLoader the classloader that determines strong referenceability. */ - protected ClassMap(ClassLoader classLoader) { + protected ClassMap(final ClassLoader classLoader) { this.classLoader = classLoader; } diff --git a/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java index 44f5c4b3874..007ab98d1e8 100644 --- a/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java +++ b/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java @@ -109,16 +109,16 @@ public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker, Se * * @param linkers a list of component linkers. */ - public CompositeGuardingDynamicLinker(Iterable linkers) { + public CompositeGuardingDynamicLinker(final Iterable linkers) { final List l = new LinkedList<>(); - for(GuardingDynamicLinker linker: linkers) { + for(final GuardingDynamicLinker linker: linkers) { l.add(linker); } this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices) + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { for(final GuardingDynamicLinker linker: linkers) { final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); diff --git a/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java index 180ab0c6b1a..814fc6936bf 100644 --- a/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java +++ b/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java @@ -112,7 +112,7 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin private final List[] singletonLinkers; @SuppressWarnings("unchecked") - ClassToLinker(TypeBasedGuardingDynamicLinker[] linkers) { + ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) { this.linkers = linkers; singletonLinkers = new List[linkers.length]; for(int i = 0; i < linkers.length; ++i) { @@ -121,7 +121,7 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin } @Override - protected List computeValue(Class clazz) { + protected List computeValue(final Class clazz) { List list = NO_LINKER; for(int i = 0; i < linkers.length; ++i) { final TypeBasedGuardingDynamicLinker linker = linkers[i]; @@ -152,27 +152,27 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin * * @param linkers the component linkers */ - public CompositeTypeBasedGuardingDynamicLinker(Iterable linkers) { + public CompositeTypeBasedGuardingDynamicLinker(final Iterable linkers) { final List l = new LinkedList<>(); - for(TypeBasedGuardingDynamicLinker linker: linkers) { + for(final TypeBasedGuardingDynamicLinker linker: linkers) { l.add(linker); } this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()])); } @Override - public boolean canLinkType(Class type) { + public boolean canLinkType(final Class type) { return !classToLinker.get(type).isEmpty(); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices) + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { final Object obj = linkRequest.getReceiver(); if(obj == null) { return null; } - for(TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) { + for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) { final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); if(invocation != null) { return invocation; @@ -189,10 +189,10 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin * @param linkers the list of linkers to optimize * @return the optimized list */ - public static List optimize(Iterable linkers) { + public static List optimize(final Iterable linkers) { final List llinkers = new LinkedList<>(); final List tblinkers = new LinkedList<>(); - for(GuardingDynamicLinker linker: linkers) { + for(final GuardingDynamicLinker linker: linkers) { if(linker instanceof TypeBasedGuardingDynamicLinker) { tblinkers.add((TypeBasedGuardingDynamicLinker)linker); } else { @@ -204,8 +204,8 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin return llinkers; } - private static void addTypeBased(List llinkers, - List tblinkers) { + private static void addTypeBased(final List llinkers, + final List tblinkers) { switch(tblinkers.size()) { case 0: { break; diff --git a/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java index 46d4fc8bba9..878d9aa00c2 100644 --- a/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java +++ b/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java @@ -98,7 +98,7 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor { private final String[] tokenizedName; private final MethodType methodType; - DefaultCallSiteDescriptor(String[] tokenizedName, MethodType methodType) { + DefaultCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) { this.tokenizedName = tokenizedName; this.methodType = methodType; } @@ -109,10 +109,10 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor { } @Override - public String getNameToken(int i) { + public String getNameToken(final int i) { try { return tokenizedName[i]; - } catch(ArrayIndexOutOfBoundsException e) { + } catch(final ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(e.getMessage()); } } @@ -127,7 +127,7 @@ class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor { } @Override - public CallSiteDescriptor changeMethodType(MethodType newMethodType) { + public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new DefaultCallSiteDescriptor(tokenizedName, newMethodType)); } diff --git a/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java b/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java new file mode 100644 index 00000000000..ad9679f6643 --- /dev/null +++ b/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.internal.dynalink.support; + +import jdk.internal.dynalink.GuardedInvocationFilter; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; + +/** + * Default filter for guarded invocation pre link filtering + */ +public class DefaultPrelinkFilter implements GuardedInvocationFilter { + @Override + public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) { + return inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType()); + } +} diff --git a/nashorn/src/jdk/internal/dynalink/support/Guards.java b/nashorn/src/jdk/internal/dynalink/support/Guards.java index 42aa675880a..02f3045daff 100644 --- a/nashorn/src/jdk/internal/dynalink/support/Guards.java +++ b/nashorn/src/jdk/internal/dynalink/support/Guards.java @@ -113,7 +113,7 @@ public class Guards { * @return a method handle testing whether its first argument is of the specified class. */ @SuppressWarnings("boxing") - public static MethodHandle isOfClass(Class clazz, MethodType type) { + public static MethodHandle isOfClass(final Class clazz, final MethodType type) { final Class declaredType = type.parameterType(0); if(clazz == declaredType) { LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); @@ -135,7 +135,7 @@ public class Guards { * @param type the method type * @return a method handle testing whether its first argument is of the specified class or subclass. */ - public static MethodHandle isInstance(Class clazz, MethodType type) { + public static MethodHandle isInstance(final Class clazz, final MethodType type) { return isInstance(clazz, 0, type); } @@ -150,7 +150,7 @@ public class Guards { * @return a method handle testing whether its first argument is of the specified class or subclass. */ @SuppressWarnings("boxing") - public static MethodHandle isInstance(Class clazz, int pos, MethodType type) { + public static MethodHandle isInstance(final Class clazz, final int pos, final MethodType type) { final Class declaredType = type.parameterType(pos); if(clazz.isAssignableFrom(declaredType)) { LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); @@ -172,7 +172,7 @@ public class Guards { * the arguments are ignored. */ @SuppressWarnings("boxing") - public static MethodHandle isArray(int pos, MethodType type) { + public static MethodHandle isArray(final int pos, final MethodType type) { final Class declaredType = type.parameterType(pos); if(declaredType.isArray()) { LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); @@ -193,7 +193,7 @@ public class Guards { * @param referredLoader the referred class loader * @return true if it is safe to strongly reference the class */ - public static boolean canReferenceDirectly(ClassLoader referrerLoader, final ClassLoader referredLoader) { + public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) { if(referredLoader == null) { // Can always refer directly to a system class return true; @@ -215,7 +215,7 @@ public class Guards { return false; } - private static MethodHandle getClassBoundArgumentTest(MethodHandle test, Class clazz, int pos, MethodType type) { + private static MethodHandle getClassBoundArgumentTest(final MethodHandle test, final Class clazz, final int pos, final MethodType type) { // Bind the class to the first argument of the test return asType(test.bindTo(clazz), pos, type); } @@ -227,7 +227,7 @@ public class Guards { * @param type the type to adapt the method handle to * @return the adapted method handle */ - public static MethodHandle asType(MethodHandle test, MethodType type) { + public static MethodHandle asType(final MethodHandle test, final MethodType type) { return test.asType(getTestType(test, type)); } @@ -239,16 +239,16 @@ public class Guards { * @param type the type to adapt the method handle to * @return the adapted method handle */ - public static MethodHandle asType(LinkerServices linkerServices, MethodHandle test, MethodType type) { + public static MethodHandle asType(final LinkerServices linkerServices, final MethodHandle test, final MethodType type) { return linkerServices.asType(test, getTestType(test, type)); } - private static MethodType getTestType(MethodHandle test, MethodType type) { + private static MethodType getTestType(final MethodHandle test, final MethodType type) { return type.dropParameterTypes(test.type().parameterCount(), type.parameterCount()).changeReturnType(boolean.class); } - private static MethodHandle asType(MethodHandle test, int pos, MethodType type) { + private static MethodHandle asType(final MethodHandle test, final int pos, final MethodType type) { assert test != null; assert type != null; assert type.parameterCount() > 0; @@ -283,7 +283,7 @@ public class Guards { * @param clazz the class to test for. * @return the desired guard method. */ - public static MethodHandle getClassGuard(Class clazz) { + public static MethodHandle getClassGuard(final Class clazz) { return IS_OF_CLASS.bindTo(clazz); } @@ -292,7 +292,7 @@ public class Guards { * @param clazz the class to test for. * @return the desired guard method. */ - public static MethodHandle getInstanceOfGuard(Class clazz) { + public static MethodHandle getInstanceOfGuard(final Class clazz) { return IS_INSTANCE.bindTo(clazz); } @@ -301,7 +301,7 @@ public class Guards { * @param obj the object used as referential identity test * @return the desired guard method. */ - public static MethodHandle getIdentityGuard(Object obj) { + public static MethodHandle getIdentityGuard(final Object obj) { return IS_IDENTICAL.bindTo(obj); } @@ -322,39 +322,39 @@ public class Guards { } @SuppressWarnings("unused") - private static boolean isNull(Object obj) { + private static boolean isNull(final Object obj) { return obj == null; } @SuppressWarnings("unused") - private static boolean isNotNull(Object obj) { + private static boolean isNotNull(final Object obj) { return obj != null; } @SuppressWarnings("unused") - private static boolean isArray(Object o) { + private static boolean isArray(final Object o) { return o != null && o.getClass().isArray(); } @SuppressWarnings("unused") - private static boolean isOfClass(Class c, Object o) { + private static boolean isOfClass(final Class c, final Object o) { return o != null && o.getClass() == c; } @SuppressWarnings("unused") - private static boolean isIdentical(Object o1, Object o2) { + private static boolean isIdentical(final Object o1, final Object o2) { return o1 == o2; } - private static MethodHandle constantTrue(MethodType type) { + private static MethodHandle constantTrue(final MethodType type) { return constantBoolean(Boolean.TRUE, type); } - private static MethodHandle constantFalse(MethodType type) { + private static MethodHandle constantFalse(final MethodType type) { return constantBoolean(Boolean.FALSE, type); } - private static MethodHandle constantBoolean(Boolean value, MethodType type) { + private static MethodHandle constantBoolean(final Boolean value, final MethodType type) { return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value), type.changeReturnType(Boolean.TYPE)); } diff --git a/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java b/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java index c2b0092bf99..2d4c0b1822c 100644 --- a/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java +++ b/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java @@ -95,18 +95,24 @@ import jdk.internal.dynalink.linker.LinkRequest; public class LinkRequestImpl implements LinkRequest { private final CallSiteDescriptor callSiteDescriptor; + private final Object callSiteToken; private final Object[] arguments; private final boolean callSiteUnstable; + private final int linkCount; /** * Creates a new link request. * * @param callSiteDescriptor the descriptor for the call site being linked + * @param callSiteToken the opaque token for the call site being linked. + * @param linkCount how many times this callsite has been linked/relinked * @param callSiteUnstable true if the call site being linked is considered unstable * @param arguments the arguments for the invocation */ - public LinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable, Object... arguments) { + public LinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, final int linkCount, final boolean callSiteUnstable, final Object... arguments) { this.callSiteDescriptor = callSiteDescriptor; + this.callSiteToken = callSiteToken; + this.linkCount = linkCount; this.callSiteUnstable = callSiteUnstable; this.arguments = arguments; } @@ -126,18 +132,28 @@ public class LinkRequestImpl implements LinkRequest { return callSiteDescriptor; } + @Override + public Object getCallSiteToken() { + return callSiteToken; + } + @Override public boolean isCallSiteUnstable() { return callSiteUnstable; } + @Override + public int getLinkCount() { + return linkCount; + } + @Override public LinkRequest withoutRuntimeContext() { return this; } @Override - public LinkRequest replaceArguments(CallSiteDescriptor newCallSiteDescriptor, Object[] newArguments) { - return new LinkRequestImpl(newCallSiteDescriptor, callSiteUnstable, newArguments); + public LinkRequest replaceArguments(final CallSiteDescriptor newCallSiteDescriptor, final Object[] newArguments) { + return new LinkRequestImpl(newCallSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, newArguments); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java b/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java index 3b8e7b46abe..38d93c849c1 100644 --- a/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java +++ b/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java @@ -117,27 +117,32 @@ public class LinkerServicesImpl implements LinkerServices { } @Override - public boolean canConvert(Class from, Class to) { + public boolean canConvert(final Class from, final Class to) { return typeConverterFactory.canConvert(from, to); } @Override - public MethodHandle asType(MethodHandle handle, MethodType fromType) { + public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { return typeConverterFactory.asType(handle, fromType); } @Override - public MethodHandle getTypeConverter(Class sourceType, Class targetType) { + public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) { + return Implementation.asTypeLosslessReturn(this, handle, fromType); + } + + @Override + public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { return typeConverterFactory.getTypeConverter(sourceType, targetType); } @Override - public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2) { + public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2); } @Override - public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception { + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception { final LinkRequest prevLinkRequest = threadLinkRequest.get(); threadLinkRequest.set(linkRequest); try { @@ -154,7 +159,7 @@ public class LinkerServicesImpl implements LinkerServices { * permission. */ public static LinkRequest getCurrentLinkRequest() { - SecurityManager sm = System.getSecurityManager(); + final SecurityManager sm = System.getSecurityManager(); if(sm != null) { sm.checkPermission(GET_CURRENT_LINK_REQUEST); } diff --git a/nashorn/src/jdk/internal/dynalink/support/Lookup.java b/nashorn/src/jdk/internal/dynalink/support/Lookup.java index ba4ff77c6f3..ab64ebb1e5c 100644 --- a/nashorn/src/jdk/internal/dynalink/support/Lookup.java +++ b/nashorn/src/jdk/internal/dynalink/support/Lookup.java @@ -104,7 +104,7 @@ public class Lookup { * * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to. */ - public Lookup(MethodHandles.Lookup lookup) { + public Lookup(final MethodHandles.Lookup lookup) { this.lookup = lookup; } @@ -120,7 +120,7 @@ public class Lookup { * @param m the method to unreflect * @return the unreflected method handle. */ - public MethodHandle unreflect(Method m) { + public MethodHandle unreflect(final Method m) { return unreflect(lookup, m); } @@ -132,10 +132,10 @@ public class Lookup { * @param m the method to unreflect * @return the unreflected method handle. */ - public static MethodHandle unreflect(MethodHandles.Lookup lookup, Method m) { + public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { try { return lookup.unreflect(m); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m); ee.initCause(e); throw ee; @@ -149,10 +149,10 @@ public class Lookup { * @param f the field for which a getter is unreflected * @return the unreflected field getter handle. */ - public MethodHandle unreflectGetter(Field f) { + public MethodHandle unreflectGetter(final Field f) { try { return lookup.unreflectGetter(f); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f); ee.initCause(e); throw ee; @@ -171,15 +171,15 @@ public class Lookup { * @throws IllegalAccessError if the field is inaccessible. * @throws NoSuchFieldError if the field does not exist. */ - public MethodHandle findGetter(Classrefc, String name, Class type) { + public MethodHandle findGetter(final Classrefc, final String name, final Class type) { try { return lookup.findGetter(refc, name, type); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() + "." + name + " of type " + type.getName()); ee.initCause(e); throw ee; - } catch(NoSuchFieldException e) { + } catch(final NoSuchFieldException e) { final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() + "." + name + " of type " + type.getName()); ee.initCause(e); @@ -194,10 +194,10 @@ public class Lookup { * @param f the field for which a setter is unreflected * @return the unreflected field setter handle. */ - public MethodHandle unreflectSetter(Field f) { + public MethodHandle unreflectSetter(final Field f) { try { return lookup.unreflectSetter(f); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f); ee.initCause(e); throw ee; @@ -211,7 +211,7 @@ public class Lookup { * @param c the constructor to unreflect * @return the unreflected constructor handle. */ - public MethodHandle unreflectConstructor(Constructor c) { + public MethodHandle unreflectConstructor(final Constructor c) { return unreflectConstructor(lookup, c); } @@ -223,10 +223,10 @@ public class Lookup { * @param c the constructor to unreflect * @return the unreflected constructor handle. */ - public static MethodHandle unreflectConstructor(MethodHandles.Lookup lookup, Constructor c) { + public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor c) { try { return lookup.unreflectConstructor(c); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c); ee.initCause(e); throw ee; @@ -244,15 +244,15 @@ public class Lookup { * @throws IllegalAccessError if the method is inaccessible. * @throws NoSuchMethodError if the method does not exist. */ - public MethodHandle findSpecial(Class declaringClass, String name, MethodType type) { + public MethodHandle findSpecial(final Class declaringClass, final String name, final MethodType type) { try { return lookup.findSpecial(declaringClass, name, type, declaringClass); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; - } catch(NoSuchMethodException e) { + } catch(final NoSuchMethodException e) { final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription( declaringClass, name, type)); ee.initCause(e); @@ -260,7 +260,7 @@ public class Lookup { } } - private static String methodDescription(Class declaringClass, String name, MethodType type) { + private static String methodDescription(final Class declaringClass, final String name, final MethodType type) { return declaringClass.getName() + "#" + name + type; } @@ -275,15 +275,15 @@ public class Lookup { * @throws IllegalAccessError if the method is inaccessible. * @throws NoSuchMethodError if the method does not exist. */ - public MethodHandle findStatic(Class declaringClass, String name, MethodType type) { + public MethodHandle findStatic(final Class declaringClass, final String name, final MethodType type) { try { return lookup.findStatic(declaringClass, name, type); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; - } catch(NoSuchMethodException e) { + } catch(final NoSuchMethodException e) { final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription( declaringClass, name, type)); ee.initCause(e); @@ -302,15 +302,15 @@ public class Lookup { * @throws IllegalAccessError if the method is inaccessible. * @throws NoSuchMethodError if the method does not exist. */ - public MethodHandle findVirtual(Class declaringClass, String name, MethodType type) { + public MethodHandle findVirtual(final Class declaringClass, final String name, final MethodType type) { try { return lookup.findVirtual(declaringClass, name, type); - } catch(IllegalAccessException e) { + } catch(final IllegalAccessException e) { final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription( declaringClass, name, type)); ee.initCause(e); throw ee; - } catch(NoSuchMethodException e) { + } catch(final NoSuchMethodException e) { final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription( declaringClass, name, type)); ee.initCause(e); @@ -327,7 +327,7 @@ public class Lookup { * @param ptypes the parameter types of the method * @return the method handle for the method */ - public static MethodHandle findOwnSpecial(MethodHandles.Lookup lookup, String name, Class rtype, Class... ptypes) { + public static MethodHandle findOwnSpecial(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes); } @@ -341,7 +341,7 @@ public class Lookup { * @param ptypes the parameter types of the method * @return the method handle for the method */ - public MethodHandle findOwnSpecial(String name, Class rtype, Class... ptypes) { + public MethodHandle findOwnSpecial(final String name, final Class rtype, final Class... ptypes) { return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); } @@ -355,7 +355,7 @@ public class Lookup { * @param ptypes the parameter types of the method * @return the method handle for the method */ - public static MethodHandle findOwnStatic(MethodHandles.Lookup lookup, String name, Class rtype, Class... ptypes) { + public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { return new Lookup(lookup).findOwnStatic(name, rtype, ptypes); } @@ -368,7 +368,7 @@ public class Lookup { * @param ptypes the parameter types of the method * @return the method handle for the method */ - public MethodHandle findOwnStatic(String name, Class rtype, Class... ptypes) { + public MethodHandle findOwnStatic(final String name, final Class rtype, final Class... ptypes) { return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java index bc5521bbfc7..e04321e6da3 100644 --- a/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java +++ b/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java @@ -92,7 +92,7 @@ import jdk.internal.dynalink.CallSiteDescriptor; * @author Attila Szegedi */ class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor { - private Lookup lookup; + private final Lookup lookup; /** * Create a new call site descriptor from explicit information. @@ -100,7 +100,7 @@ class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor { * @param methodType the method type * @param lookup the lookup */ - LookupCallSiteDescriptor(String[] tokenizedName, MethodType methodType, Lookup lookup) { + LookupCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType, final Lookup lookup) { super(tokenizedName, methodType); this.lookup = lookup; } @@ -111,7 +111,7 @@ class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor { } @Override - public CallSiteDescriptor changeMethodType(MethodType newMethodType) { + public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { return new LookupCallSiteDescriptor(getTokenizedName(), newMethodType, lookup); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/NameCodec.java b/nashorn/src/jdk/internal/dynalink/support/NameCodec.java index 1c7cd29b95f..9a402a59825 100644 --- a/nashorn/src/jdk/internal/dynalink/support/NameCodec.java +++ b/nashorn/src/jdk/internal/dynalink/support/NameCodec.java @@ -137,7 +137,7 @@ public class NameCodec { * @param name the symbolic name to mangle * @return the mangled form of the symbolic name. */ - public static String encode(String name) { + public static String encode(final String name) { final int l = name.length(); if(l == 0) { return EMPTY_NAME; @@ -176,7 +176,7 @@ public class NameCodec { * @param name the symbolic name to demangle * @return the demangled form of the symbolic name. */ - public static String decode(String name) { + public static String decode(final String name) { if(name.charAt(0) != ESCAPE_CHAR) { return name; } @@ -184,11 +184,11 @@ public class NameCodec { if(l == 2 && name.charAt(1) == EMPTY_CHAR) { return ""; } - StringBuilder b = new StringBuilder(name.length()); + final StringBuilder b = new StringBuilder(name.length()); int lastEscape = -2; int lastBackslash = -1; for(;;) { - int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1); + final int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1); if(nextBackslash == -1 || nextBackslash == l - 1) { break; } @@ -211,7 +211,7 @@ public class NameCodec { return b.toString(); } - private static void addEncoding(char from, char to) { + private static void addEncoding(final char from, final char to) { ENCODING[from - MIN_ENCODING] = to; DECODING[to - MIN_DECODING] = from; } diff --git a/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java index 71cbb1d299e..817df52a899 100644 --- a/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java +++ b/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java @@ -89,7 +89,7 @@ import jdk.internal.dynalink.CallSiteDescriptor; class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor { private final String name; - NamedDynCallSiteDescriptor(String op, String name, MethodType methodType) { + NamedDynCallSiteDescriptor(final String op, final String name, final MethodType methodType) { super(op, methodType); this.name = name; } @@ -100,7 +100,7 @@ class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor { } @Override - public String getNameToken(int i) { + public String getNameToken(final int i) { switch(i) { case 0: return "dyn"; case 1: return getOp(); @@ -110,7 +110,7 @@ class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor { } @Override - public CallSiteDescriptor changeMethodType(MethodType newMethodType) { + public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new NamedDynCallSiteDescriptor(getOp(), name, newMethodType)); } diff --git a/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java b/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java index 03309a7c26a..3f43621a13e 100644 --- a/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java +++ b/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java @@ -101,15 +101,17 @@ public class RuntimeContextLinkRequestImpl extends LinkRequestImpl { * Creates a new link request. * * @param callSiteDescriptor the descriptor for the call site being linked + * @param callSiteToken the opaque token for the call site being linked. * @param arguments the arguments for the invocation + * @param linkCount number of times callsite has been linked/relinked * @param callSiteUnstable true if the call site being linked is considered unstable * @param runtimeContextArgCount the number of the leading arguments on the stack that represent the language * runtime specific context arguments. * @throws IllegalArgumentException if runtimeContextArgCount is less than 1. */ - public RuntimeContextLinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable, - Object[] arguments, int runtimeContextArgCount) { - super(callSiteDescriptor, callSiteUnstable, arguments); + public RuntimeContextLinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, + final int linkCount, final boolean callSiteUnstable, final Object[] arguments, final int runtimeContextArgCount) { + super(callSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, arguments); if(runtimeContextArgCount < 1) { throw new IllegalArgumentException("runtimeContextArgCount < 1"); } @@ -121,14 +123,14 @@ public class RuntimeContextLinkRequestImpl extends LinkRequestImpl { if(contextStrippedRequest == null) { contextStrippedRequest = new LinkRequestImpl(CallSiteDescriptorFactory.dropParameterTypes(getCallSiteDescriptor(), 1, - runtimeContextArgCount + 1), isCallSiteUnstable(), getTruncatedArguments()); + runtimeContextArgCount + 1), getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), getTruncatedArguments()); } return contextStrippedRequest; } @Override - public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments) { - return new RuntimeContextLinkRequestImpl(callSiteDescriptor, isCallSiteUnstable(), arguments, + public LinkRequest replaceArguments(final CallSiteDescriptor callSiteDescriptor, final Object[] arguments) { + return new RuntimeContextLinkRequestImpl(callSiteDescriptor, getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), arguments, runtimeContextArgCount); } diff --git a/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java b/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java index 436acad7faf..79f6549b3b7 100644 --- a/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java +++ b/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java @@ -115,12 +115,12 @@ public class TypeConverterFactory { protected ClassMap computeValue(final Class sourceType) { return new ClassMap(getClassLoader(sourceType)) { @Override - protected MethodHandle computeValue(Class targetType) { + protected MethodHandle computeValue(final Class targetType) { try { return createConverter(sourceType, targetType); - } catch (RuntimeException e) { + } catch (final RuntimeException e) { throw e; - } catch (Exception e) { + } catch (final Exception e) { throw new RuntimeException(e); } } @@ -133,7 +133,7 @@ public class TypeConverterFactory { protected ClassMap computeValue(final Class sourceType) { return new ClassMap(getClassLoader(sourceType)) { @Override - protected MethodHandle computeValue(Class targetType) { + protected MethodHandle computeValue(final Class targetType) { if(!canAutoConvert(sourceType, targetType)) { final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); if(converter != IDENTITY_CONVERSION) { @@ -151,12 +151,12 @@ public class TypeConverterFactory { protected ClassMap computeValue(final Class sourceType) { return new ClassMap(getClassLoader(sourceType)) { @Override - protected Boolean computeValue(Class targetType) { + protected Boolean computeValue(final Class targetType) { try { return getTypeConverterNull(sourceType, targetType) != null; - } catch (RuntimeException e) { + } catch (final RuntimeException e) { throw e; - } catch (Exception e) { + } catch (final Exception e) { throw new RuntimeException(e); } } @@ -178,10 +178,10 @@ public class TypeConverterFactory { * * @param factories the {@link GuardingTypeConverterFactory} instances to compose. */ - public TypeConverterFactory(Iterable factories) { + public TypeConverterFactory(final Iterable factories) { final List l = new LinkedList<>(); final List c = new LinkedList<>(); - for(GuardingTypeConverterFactory factory: factories) { + for(final GuardingTypeConverterFactory factory: factories) { l.add(factory); if(factory instanceof ConversionComparator) { c.add((ConversionComparator)factory); @@ -206,7 +206,7 @@ public class TypeConverterFactory { * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with * {@link GuardingTypeConverterFactory} produced type converters as filters. */ - public MethodHandle asType(MethodHandle handle, final MethodType fromType) { + public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { MethodHandle newHandle = handle; final MethodType toType = newHandle.type(); final int l = toType.parameterCount(); @@ -250,7 +250,7 @@ public class TypeConverterFactory { return newHandle.asType(fromType); } - private static MethodHandle applyConverters(MethodHandle handle, int pos, List converters) { + private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List converters) { if(converters.isEmpty()) { return handle; } @@ -285,8 +285,8 @@ public class TypeConverterFactory { * @return one of Comparison constants that establish which - if any - of the target types is preferable for the * conversion. */ - public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2) { - for(ConversionComparator comparator: comparators) { + public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { + for(final ConversionComparator comparator: comparators) { final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2); if(result != Comparison.INDETERMINATE) { return result; @@ -313,20 +313,20 @@ public class TypeConverterFactory { return TypeUtilities.isMethodInvocationConvertible(fromType, toType); } - /*private*/ MethodHandle getCacheableTypeConverterNull(Class sourceType, Class targetType) { + /*private*/ MethodHandle getCacheableTypeConverterNull(final Class sourceType, final Class targetType) { final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); return converter == IDENTITY_CONVERSION ? null : converter; } - /*private*/ MethodHandle getTypeConverterNull(Class sourceType, Class targetType) { + /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) { try { return getCacheableTypeConverterNull(sourceType, targetType); - } catch(NotCacheableConverter e) { + } catch(final NotCacheableConverter e) { return e.converter; } } - /*private*/ MethodHandle getCacheableTypeConverter(Class sourceType, Class targetType) { + /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) { return converterMap.get(sourceType).get(targetType); } @@ -339,15 +339,15 @@ public class TypeConverterFactory { * @param targetType the type to convert to * @return a method handle performing the conversion. */ - public MethodHandle getTypeConverter(Class sourceType, Class targetType) { + public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { try { return converterIdentityMap.get(sourceType).get(targetType); - } catch(NotCacheableConverter e) { + } catch(final NotCacheableConverter e) { return e.converter; } } - /*private*/ MethodHandle createConverter(Class sourceType, Class targetType) throws Exception { + /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception { final MethodType type = MethodType.methodType(targetType, sourceType); final MethodHandle identity = IDENTITY_CONVERSION.asType(type); MethodHandle last = identity; @@ -372,6 +372,7 @@ public class TypeConverterFactory { /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); + @SuppressWarnings("serial") private static class NotCacheableConverter extends RuntimeException { final MethodHandle converter; diff --git a/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java b/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java index 57fea990efa..6403f3d5e40 100644 --- a/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java +++ b/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java @@ -106,38 +106,49 @@ public class TypeUtilities { } /** - * Given two types represented by c1 and c2, returns a type that is their most specific common superclass or - * superinterface. + * Given two types represented by c1 and c2, returns a type that is their most specific common supertype for + * purposes of lossless conversions. * * @param c1 one type * @param c2 another type - * @return their most common superclass or superinterface. If they have several unrelated superinterfaces as their - * most specific common type, or the types themselves are completely unrelated interfaces, {@link java.lang.Object} - * is returned. + * @return their most common superclass or superinterface for purposes of lossless conversions. If they have several + * unrelated superinterfaces as their most specific common type, or the types themselves are completely + * unrelated interfaces, {@link java.lang.Object} is returned. */ - public static Class getMostSpecificCommonType(Class c1, Class c2) { + public static Class getCommonLosslessConversionType(final Class c1, final Class c2) { if(c1 == c2) { return c1; + } else if(isConvertibleWithoutLoss(c2, c1)) { + return c1; + } else if(isConvertibleWithoutLoss(c1, c2)) { + return c2; } - Class c3 = c2; - if(c3.isPrimitive()) { - if(c3 == Byte.TYPE) - c3 = Byte.class; - else if(c3 == Short.TYPE) - c3 = Short.class; - else if(c3 == Character.TYPE) - c3 = Character.class; - else if(c3 == Integer.TYPE) - c3 = Integer.class; - else if(c3 == Float.TYPE) - c3 = Float.class; - else if(c3 == Long.TYPE) - c3 = Long.class; - else if(c3 == Double.TYPE) - c3 = Double.class; + if(c1 == void.class) { + return c2; + } else if(c2 == void.class) { + return c1; } - Set> a1 = getAssignables(c1, c3); - Set> a2 = getAssignables(c3, c1); + if(c1.isPrimitive() && c2.isPrimitive()) { + if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) { + // byte + char = int + return int.class; + } else if((c1 == short.class && c2 == char.class) || (c1 == char.class && c2 == short.class)) { + // short + char = int + return int.class; + } else if((c1 == int.class && c2 == float.class) || (c1 == float.class && c2 == int.class)) { + // int + float = double + return double.class; + } + } + // For all other cases. This will handle long + (float|double) = Number case as well as boolean + anything = Object case too. + return getMostSpecificCommonTypeUnequalNonprimitives(c1, c2); + } + + private static Class getMostSpecificCommonTypeUnequalNonprimitives(final Class c1, final Class c2) { + final Class npc1 = c1.isPrimitive() ? getWrapperType(c1) : c1; + final Class npc2 = c2.isPrimitive() ? getWrapperType(c2) : c2; + final Set> a1 = getAssignables(npc1, npc2); + final Set> a2 = getAssignables(npc2, npc1); a1.retainAll(a2); if(a1.isEmpty()) { // Can happen when at least one of the arguments is an interface, @@ -148,10 +159,10 @@ public class TypeUtilities { // thank to interfaces. I.e., if you call this method for String.class // and Number.class, you'll have Comparable, Serializable, and Object // as maximal elements. - List> max = new ArrayList<>(); - outer: for(Class clazz: a1) { - for(Iterator> maxiter = max.iterator(); maxiter.hasNext();) { - Class maxClazz = maxiter.next(); + final List> max = new ArrayList<>(); + outer: for(final Class clazz: a1) { + for(final Iterator> maxiter = max.iterator(); maxiter.hasNext();) { + final Class maxClazz = maxiter.next(); if(isSubtype(maxClazz, clazz)) { // It can't be maximal, if there's already a more specific // maximal than it. @@ -168,26 +179,26 @@ public class TypeUtilities { max.add(clazz); } if(max.size() > 1) { - return OBJECT_CLASS; + return Object.class; } return max.get(0); } - private static Set> getAssignables(Class c1, Class c2) { - Set> s = new HashSet<>(); + private static Set> getAssignables(final Class c1, final Class c2) { + final Set> s = new HashSet<>(); collectAssignables(c1, c2, s); return s; } - private static void collectAssignables(Class c1, Class c2, Set> s) { + private static void collectAssignables(final Class c1, final Class c2, final Set> s) { if(c1.isAssignableFrom(c2)) { s.add(c1); } - Class sc = c1.getSuperclass(); + final Class sc = c1.getSuperclass(); if(sc != null) { collectAssignables(sc, c2, s); } - Class[] itf = c1.getInterfaces(); + final Class[] itf = c1.getInterfaces(); for(int i = 0; i < itf.length; ++i) { collectAssignables(itf[i], c2, s); } @@ -210,17 +221,17 @@ public class TypeUtilities { return Collections.unmodifiableMap(wrapperTypes); } - private static Map> createClassNameMapping(Collection> classes) { + private static Map> createClassNameMapping(final Collection> classes) { final Map> map = new HashMap<>(); - for(Class clazz: classes) { + for(final Class clazz: classes) { map.put(clazz.getName(), clazz); } return map; } - private static Map invertMap(Map map) { + private static Map invertMap(final Map map) { final Map inverted = new IdentityHashMap<>(map.size()); - for(Map.Entry entry: map.entrySet()) { + for(final Map.Entry entry: map.entrySet()) { inverted.put(entry.getValue(), entry.getKey()); } return Collections.unmodifiableMap(inverted); @@ -232,29 +243,58 @@ public class TypeUtilities { * {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening * reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion. * - * @param callSiteType the parameter type at the call site - * @param methodType the parameter type in the method declaration - * @return true if callSiteType is method invocation convertible to the methodType. + * @param sourceType the type being converted from (call site type for parameter types, method type for return types) + * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types) + * @return true if source type is method invocation convertible to target type. */ - public static boolean isMethodInvocationConvertible(Class callSiteType, Class methodType) { - if(methodType.isAssignableFrom(callSiteType)) { + public static boolean isMethodInvocationConvertible(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType)) { return true; } - if(callSiteType.isPrimitive()) { - if(methodType.isPrimitive()) { - return isProperPrimitiveSubtype(callSiteType, methodType); + if(sourceType.isPrimitive()) { + if(targetType.isPrimitive()) { + return isProperPrimitiveSubtype(sourceType, targetType); } // Boxing + widening reference conversion - return methodType.isAssignableFrom(WRAPPER_TYPES.get(callSiteType)); + assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName(); + return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType)); } - if(methodType.isPrimitive()) { - final Class unboxedCallSiteType = PRIMITIVE_TYPES.get(callSiteType); + if(targetType.isPrimitive()) { + final Class unboxedCallSiteType = PRIMITIVE_TYPES.get(sourceType); return unboxedCallSiteType != null - && (unboxedCallSiteType == methodType || isProperPrimitiveSubtype(unboxedCallSiteType, methodType)); + && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType)); } return false; } + /** + * Determines whether a type can be converted to another without losing any + * precision. + * + * @param sourceType the source type + * @param targetType the target type + * @return true if lossless conversion is possible + */ + public static boolean isConvertibleWithoutLoss(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType)) { + return true; + } + if(sourceType.isPrimitive()) { + if(sourceType == void.class) { + return false; // Void can't be losslessly represented by any type + } + if(targetType.isPrimitive()) { + return isProperPrimitiveLosslessSubtype(sourceType, targetType); + } + // Boxing + widening reference conversion + assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName(); + return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType)); + } + // Can't convert from any non-primitive type to any primitive type without data loss because of null. + // Also, can't convert non-assignable reference types. + return false; + } + /** * Determines whether one type can be potentially converted to another type at runtime. Allows a conversion between * any subtype and supertype in either direction, and also allows a conversion between any two primitive types, as @@ -264,9 +304,9 @@ public class TypeUtilities { * @param methodType the parameter type in the method declaration * @return true if callSiteType is potentially convertible to the methodType. */ - public static boolean isPotentiallyConvertible(Class callSiteType, Class methodType) { + public static boolean isPotentiallyConvertible(final Class callSiteType, final Class methodType) { // Widening or narrowing reference conversion - if(methodType.isAssignableFrom(callSiteType) || callSiteType.isAssignableFrom(methodType)) { + if(areAssignable(callSiteType, methodType)) { return true; } if(callSiteType.isPrimitive()) { @@ -286,6 +326,16 @@ public class TypeUtilities { return false; } + /** + * Returns true if either of the types is assignable from the other. + * @param c1 one of the types + * @param c2 another one of the types + * @return true if either c1 is assignable from c2 or c2 is assignable from c1. + */ + public static boolean areAssignable(final Class c1, final Class c2) { + return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1); + } + /** * Determines whether one type is a subtype of another type, as per JLS 4.10 "Subtyping". Note: this is not strict * or proper subtype, therefore true is also returned for identical types; to be completely precise, it allows @@ -297,7 +347,7 @@ public class TypeUtilities { * @return true if subType can be converted by identity conversion, widening primitive conversion, or widening * reference conversion to superType. */ - public static boolean isSubtype(Class subType, Class superType) { + public static boolean isSubtype(final Class subType, final Class superType) { // Covers both JLS 4.10.2 "Subtyping among Class and Interface Types" // and JLS 4.10.3 "Subtyping among Array Types", as well as primitive // type identity. @@ -328,7 +378,7 @@ public class TypeUtilities { * @param superType the supposed supertype * @return true if subType is a proper (not identical to) primitive subtype of the superType */ - private static boolean isProperPrimitiveSubtype(Class subType, Class superType) { + private static boolean isProperPrimitiveSubtype(final Class subType, final Class superType) { if(superType == boolean.class || subType == boolean.class) { return false; } @@ -353,6 +403,37 @@ public class TypeUtilities { return false; } + /** + * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to + * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and + * anything else (similar to boolean) as char is not meant to be an arithmetic type. + * @param subType the supposed subtype + * @param superType the supposed supertype + * @return true if subType is a proper (not identical to) primitive subtype of the superType that can be represented + * by the supertype without no precision loss. + */ + private static boolean isProperPrimitiveLosslessSubtype(final Class subType, final Class superType) { + if(superType == boolean.class || subType == boolean.class) { + return false; + } + if(superType == char.class || subType == char.class) { + return false; + } + if(subType == byte.class) { + return true; + } + if(subType == short.class) { + return superType != byte.class; + } + if(subType == int.class) { + return superType == long.class || superType == double.class; + } + if(subType == float.class) { + return superType == double.class; + } + return false; + } + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPES = createWrapperToPrimitiveTypes(); private static Map, Class> createWrapperToPrimitiveTypes() { @@ -384,13 +465,13 @@ public class TypeUtilities { return classes.keySet(); } - private static void addClassHierarchy(Map, Class> map, Class clazz) { + private static void addClassHierarchy(final Map, Class> map, final Class clazz) { if(clazz == null) { return; } map.put(clazz, clazz); addClassHierarchy(map, clazz.getSuperclass()); - for(Class itf: clazz.getInterfaces()) { + for(final Class itf: clazz.getInterfaces()) { addClassHierarchy(map, itf); } } @@ -402,7 +483,7 @@ public class TypeUtilities { * @return true if the class can be assigned from any boxed primitive. Basically, it is true if the class is any * primitive wrapper class, or a superclass or superinterface of any primitive wrapper class. */ - private static boolean isAssignableFromBoxedPrimitive(Class clazz) { + private static boolean isAssignableFromBoxedPrimitive(final Class clazz) { return PRIMITIVE_WRAPPER_TYPES.contains(clazz); } @@ -413,7 +494,7 @@ public class TypeUtilities { * @return the class representing the primitive type, or null if the name does not correspond to a primitive type * or is "void". */ - public static Class getPrimitiveTypeByName(String name) { + public static Class getPrimitiveTypeByName(final String name) { return PRIMITIVE_TYPES_BY_NAME.get(name); } @@ -424,7 +505,7 @@ public class TypeUtilities { * @param wrapperType the class object representing a wrapper for a primitive type * @return the class object representing the primitive type, or null if the passed class is not a primitive wrapper. */ - public static Class getPrimitiveType(Class wrapperType) { + public static Class getPrimitiveType(final Class wrapperType) { return WRAPPER_TO_PRIMITIVE_TYPES.get(wrapperType); } @@ -436,7 +517,7 @@ public class TypeUtilities { * @param primitiveType the class object representing a primitive type * @return the class object representing the wrapper type, or null if the passed class is not a primitive. */ - public static Class getWrapperType(Class primitiveType) { + public static Class getWrapperType(final Class primitiveType) { return WRAPPER_TYPES.get(primitiveType); } } diff --git a/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java index da8c0096f49..89a0677e91f 100644 --- a/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java +++ b/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java @@ -90,7 +90,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor { private final MethodType methodType; private final String op; - UnnamedDynCallSiteDescriptor(String op, MethodType methodType) { + UnnamedDynCallSiteDescriptor(final String op, final MethodType methodType) { this.op = op; this.methodType = methodType; } @@ -105,7 +105,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor { } @Override - public String getNameToken(int i) { + public String getNameToken(final int i) { switch(i) { case 0: return "dyn"; case 1: return op; @@ -119,7 +119,7 @@ class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor { } @Override - public CallSiteDescriptor changeMethodType(MethodType newMethodType) { + public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new UnnamedDynCallSiteDescriptor(op, newMethodType)); } diff --git a/nashorn/src/jdk/internal/dynalink/support/messages.properties b/nashorn/src/jdk/internal/dynalink/support/messages.properties index 88d59908071..ed26299e0c4 100644 --- a/nashorn/src/jdk/internal/dynalink/support/messages.properties +++ b/nashorn/src/jdk/internal/dynalink/support/messages.properties @@ -83,4 +83,4 @@ isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true -isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false \ No newline at end of file +isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false diff --git a/nashorn/src/jdk/nashorn/api/scripting/Formatter.java b/nashorn/src/jdk/nashorn/api/scripting/Formatter.java index a14a83e4ce3..544e70ce452 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/Formatter.java +++ b/nashorn/src/jdk/nashorn/api/scripting/Formatter.java @@ -65,8 +65,8 @@ final class Formatter { while (m.find()) { int index = index(m.group(1)); - boolean previous = isPreviousArgument(m.group(2)); - char conversion = m.group(6).charAt(0); + final boolean previous = isPreviousArgument(m.group(2)); + final char conversion = m.group(6).charAt(0); // skip over some formats if (index < 0 || previous @@ -85,7 +85,7 @@ final class Formatter { } // current argument - Object arg = args[index - 1]; + final Object arg = args[index - 1]; // for date we convert double to long if (m.group(5) != null) { diff --git a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java index bd6e820be3d..8d818642ef5 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java +++ b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java @@ -26,7 +26,6 @@ package jdk.nashorn.api.scripting; import java.util.Collection; -import java.util.Collections; import java.util.Set; /** diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java index a5f8c24a2e6..c48bf4b26aa 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java @@ -182,7 +182,7 @@ public abstract class NashornException extends RuntimeException { if (ECMAErrors.isScriptFrame(st)) { final String className = "<" + st.getFileName() + ">"; String methodName = st.getMethodName(); - if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) { + if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) { methodName = ""; } @@ -224,10 +224,22 @@ public abstract class NashornException extends RuntimeException { return buf.toString(); } + /** + * Get the thrown object. Subclass responsibility + * @return thrown object + */ protected Object getThrown() { return null; } + /** + * Initialization function for ECMA errors. Stores the error + * in the ecmaError field of this class. It is only initialized + * once, and then reused + * + * @param global the global + * @return initialized exception + */ protected NashornException initEcmaError(final ScriptObject global) { if (ecmaError != null) { return this; // initialized already! diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java index 7ebe5c91656..514c6ab1bc1 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -123,7 +123,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } // load engine.js - @SuppressWarnings("resource") private static Source loadEngineJSSource() { final String script = "resources/engine.js"; try { @@ -281,7 +280,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException { try { return sourceFor(getScriptName(ctxt), reader); - } catch (IOException e) { + } catch (final IOException e) { throw new ScriptException(e); } } @@ -380,7 +379,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it! - Object scope = bindings.get(NASHORN_GLOBAL); + final Object scope = bindings.get(NASHORN_GLOBAL); if (scope instanceof ScriptObjectMirror) { final Global glob = globalFromMirror((ScriptObjectMirror)scope); if (glob != null) { @@ -397,7 +396,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C // Retrieve nashorn Global object from a given ScriptObjectMirror private Global globalFromMirror(final ScriptObjectMirror mirror) { - ScriptObject sobj = mirror.getScriptObject(); + final ScriptObject sobj = mirror.getScriptObject(); if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) { return (Global)sobj; } @@ -456,7 +455,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) { // set "context" global variable via contextProperty - because this // property is non-writable - contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false); + contextProperty.setValue(ctxtGlobal, ctxtGlobal, ctxt, false); Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal); if (args == null || args == UNDEFINED) { args = ScriptRuntime.EMPTY_ARRAY; @@ -671,7 +670,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C continue; } - Object obj = sobj.get(method.getName()); + final Object obj = sobj.get(method.getName()); if (! (obj instanceof ScriptFunction)) { return false; } diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java index beb0c2a0fef..777edc9dfe9 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java @@ -164,7 +164,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { * @param args arguments array passed to script engine. * @return newly created script engine. */ - public ScriptEngine getScriptEngine(final String[] args) { + public ScriptEngine getScriptEngine(final String... args) { checkConfigPermission(); return new NashornScriptEngine(this, args, getAppClassLoader()); } @@ -220,7 +220,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { // Revisit: script engine implementation needs the capability to // find the class loader of the context in which the script engine // is running so that classes will be found and loaded properly - ClassLoader ccl = Thread.currentThread().getContextClassLoader(); + final ClassLoader ccl = Thread.currentThread().getContextClassLoader(); return (ccl == null)? NashornScriptEngineFactory.class.getClassLoader() : ccl; } } diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java index b12553369d4..8763c22f466 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -43,13 +43,13 @@ import java.util.Set; import java.util.concurrent.Callable; import javax.script.Bindings; import jdk.nashorn.internal.objects.Global; -import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.arrays.ArrayData; /** * Mirror object that wraps a given Nashorn Script object. @@ -169,6 +169,12 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin }); } + /** + * Call member function + * @param functionName function name + * @param args arguments + * @return return value of function + */ public Object callMember(final String functionName, final Object... args) { functionName.getClass(); // null check final Global oldGlobal = Context.getGlobal(); @@ -496,7 +502,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin public void setProto(final Object proto) { inGlobal(new Callable() { @Override public Void call() { - sobj.setProtoCheck(unwrap(proto, global)); + sobj.setPrototypeOf(unwrap(proto, global)); return null; } }); @@ -621,6 +627,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin /** * Utilitity to convert this script object to the given type. * + * @param destination type to convert to * @param type destination type to convert to * @return converted object */ @@ -728,7 +735,7 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin return global; } - static Object translateUndefined(Object obj) { + static Object translateUndefined(final Object obj) { return (obj == ScriptRuntime.UNDEFINED)? null : obj; } diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java index 29d03db4f4b..da5b9bdb663 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java +++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java @@ -28,11 +28,11 @@ package jdk.nashorn.api.scripting; import java.lang.invoke.MethodHandle; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.linker.Bootstrap; /** * Utilities that are to be called from script code. diff --git a/nashorn/src/jdk/nashorn/api/scripting/URLReader.java b/nashorn/src/jdk/nashorn/api/scripting/URLReader.java index 13f69843d5a..53efeee7d0a 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/URLReader.java +++ b/nashorn/src/jdk/nashorn/api/scripting/URLReader.java @@ -81,7 +81,7 @@ public final class URLReader extends Reader { } @Override - public int read(char cbuf[], int off, int len) throws IOException { + public int read(final char cbuf[], final int off, final int len) throws IOException { return getReader().read(cbuf, off, len); } diff --git a/nashorn/src/jdk/nashorn/api/scripting/package-info.java b/nashorn/src/jdk/nashorn/api/scripting/package-info.java index 6876151e330..f017ba9ef4f 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/package-info.java +++ b/nashorn/src/jdk/nashorn/api/scripting/package-info.java @@ -32,7 +32,8 @@ * ScriptEngine nashornEngine = new ScriptEngineManager().getEngineByName("Nashorn"); * *

Nashorn script engines implement the optional {@link javax.script.Invocable} and {@link javax.script.Compilable} - * interfaces, allowing for efficient pre-compilation and repeated execution of scripts. See + * interfaces, allowing for efficient pre-compilation and repeated execution of scripts. In addition, + * this package provides nashorn specific extension classes, interfaces and methods. See * {@link jdk.nashorn.api.scripting.NashornScriptEngineFactory} for further details. */ package jdk.nashorn.api.scripting; diff --git a/nashorn/src/jdk/nashorn/internal/IntDeque.java b/nashorn/src/jdk/nashorn/internal/IntDeque.java new file mode 100644 index 00000000000..477afcf94ae --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/IntDeque.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal; + +/** + * Small helper class for fast int deques + */ +public class IntDeque { + private int[] deque = new int[16]; + private int nextFree = 0; + + /** + * Push an int value + * @param value value + */ + public void push(final int value) { + if (nextFree == deque.length) { + final int[] newDeque = new int[nextFree * 2]; + System.arraycopy(deque, 0, newDeque, 0, nextFree); + deque = newDeque; + } + deque[nextFree++] = value; + } + + /** + * Pop an int value + * @return value + */ + public int pop() { + return deque[--nextFree]; + } + + /** + * Peek + * @return top value + */ + public int peek() { + return deque[nextFree - 1]; + } + + /** + * Get the value of the top element and increment it. + * @return top value + */ + public int getAndIncrement() { + return deque[nextFree - 1]++; + } + + /** + * Decrement the value of the top element and return it. + * @return decremented top value + */ + public int decrementAndGet() { + return --deque[nextFree - 1]; + } + + /** + * Check if deque is empty + * @return true if empty + */ + public boolean isEmpty() { + return nextFree == 0; + } +} diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java new file mode 100644 index 00000000000..a5fbfdf9134 --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2010, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.codegen; + +import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; +import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX; + +import java.lang.invoke.MethodType; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import jdk.nashorn.internal.ir.AccessNode; +import jdk.nashorn.internal.ir.CallNode; +import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.IdentNode; +import jdk.nashorn.internal.ir.LexicalContext; +import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.objects.Global; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import jdk.nashorn.internal.runtime.logging.Loggable; +import jdk.nashorn.internal.runtime.logging.Logger; +import jdk.nashorn.internal.runtime.options.Options; + +/** + * An optimization that attempts to turn applies into calls. This pattern + * is very common for fake class instance creation, and apply + * introduces expensive args collection and boxing + * + *

+ * var Class = {
+ *     create: function() {
+ *         return function() { //vararg
+ *             this.initialize.apply(this, arguments);
+ *         }
+ *     }
+ * };
+ *
+ * Color = Class.create();
+ *
+ * Color.prototype = {
+ *    red: 0, green: 0, blue: 0,
+ *    initialize: function(r,g,b) {
+ *        this.red = r;
+ *        this.green = g;
+ *        this.blue = b;
+ *    }
+ * }
+ *
+ * new Color(17, 47, 11);
+ * 
+ */ + +@Logger(name="apply2call") +public final class ApplySpecialization extends NodeVisitor implements Loggable { + + private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true); + + private final DebugLogger log; + + private final Compiler compiler; + + private final Set changed = new HashSet<>(); + + private final Deque> explodedArguments = new ArrayDeque<>(); + + private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName(); + + /** + * Apply specialization optimization. Try to explode arguments and call + * applies as calls if they just pass on the "arguments" array and + * "arguments" doesn't escape. + * + * @param compiler compiler + */ + public ApplySpecialization(final Compiler compiler) { + super(new LexicalContext()); + this.compiler = compiler; + this.log = initLogger(compiler.getContext()); + } + + @Override + public DebugLogger getLogger() { + return log; + } + + @Override + public DebugLogger initLogger(final Context context) { + return context.getLogger(this.getClass()); + } + + /** + * Arguments may only be used as args to the apply. Everything else is disqualified + * We cannot control arguments if they escape from the method and go into an unknown + * scope, thus we are conservative and treat any access to arguments outside the + * apply call as a case of "we cannot apply the optimization". + * + * @return true if arguments escape + */ + private boolean argumentsEscape(final FunctionNode functionNode) { + + final Deque> stack = new ArrayDeque<>(); + //ensure that arguments is only passed as arg to apply + try { + functionNode.accept(new NodeVisitor(new LexicalContext()) { + private boolean isCurrentArg(final Expression expr) { + return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call + } + + private boolean isArguments(final Expression expr) { + return expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName()); + } + + private boolean isParam(final String name) { + for (final IdentNode param : functionNode.getParameters()) { + if (param.getName().equals(name)) { + return true; + } + } + return false; + } + + @Override + public Node leaveIdentNode(final IdentNode identNode) { + if (isParam(identNode.getName()) || ARGUMENTS.equals(identNode.getName()) && !isCurrentArg(identNode)) { + throw new UnsupportedOperationException(); + } + return identNode; + } + + @Override + public boolean enterCallNode(final CallNode callNode) { + final Set callArgs = new HashSet<>(); + if (isApply(callNode)) { + final List argList = callNode.getArgs(); + if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) { + throw new UnsupportedOperationException(); + } + callArgs.addAll(callNode.getArgs()); + } + stack.push(callArgs); + return true; + } + + @Override + public Node leaveCallNode(final CallNode callNode) { + stack.pop(); + return callNode; + } + }); + } catch (final UnsupportedOperationException e) { + log.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting"); + return true; //bad + } + + return false; + } + + @Override + public boolean enterCallNode(final CallNode callNode) { + return !explodedArguments.isEmpty(); + } + + @Override + public Node leaveCallNode(final CallNode callNode) { + //apply needs to be a global symbol or we don't allow it + + final List newParams = explodedArguments.peek(); + if (isApply(callNode)) { + final List newArgs = new ArrayList<>(); + for (final Expression arg : callNode.getArgs()) { + if (arg instanceof IdentNode && ARGUMENTS.equals(((IdentNode)arg).getName())) { + newArgs.addAll(newParams); + } else { + newArgs.add(arg); + } + } + + changed.add(lc.getCurrentFunction().getId()); + + final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall(); + + log.fine("Transformed ", + callNode, + " from apply to call => ", + newCallNode, + " in ", + DebugLogger.quote(lc.getCurrentFunction().getName())); + + return newCallNode; + } + + return callNode; + } + + private boolean pushExplodedArgs(final FunctionNode functionNode) { + int start = 0; + + final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode); + if (actualCallSiteType == null) { + return false; + } + assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType; + + final TypeMap ptm = compiler.getTypeMap(); + if (ptm.needsCallee()) { + start++; + } + + start++; //we always uses this + + final List params = functionNode.getParameters(); + final List newParams = new ArrayList<>(); + final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start); + for (int i = 0; i < to; i++) { + if (i >= params.size()) { + newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i))); + } else { + newParams.add(params.get(i)); + } + } + + explodedArguments.push(newParams); + return true; + } + + @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + if (!USE_APPLY2CALL) { + return false; + } + + if (!Global.instance().isSpecialNameValid("apply")) { + log.fine("Apply transform disabled: apply/call overridden"); + assert !Global.instance().isSpecialNameValid("call") : "call and apply should have the same SwitchPoint"; + return false; + } + + if (!compiler.isOnDemandCompilation()) { + return false; + } + + if (functionNode.hasEval()) { + return false; + } + + if (argumentsEscape(functionNode)) { + return false; + } + + return pushExplodedArgs(functionNode); + } + + /** + * Try to do the apply to call transformation + * @return true if successful, false otherwise + */ + @Override + public Node leaveFunctionNode(final FunctionNode functionNode0) { + FunctionNode newFunctionNode = functionNode0; + final String functionName = newFunctionNode.getName(); + + if (changed.contains(newFunctionNode.getId())) { + newFunctionNode = newFunctionNode.clearFlag(lc, FunctionNode.USES_ARGUMENTS). + setFlag(lc, FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION). + setParameters(lc, explodedArguments.peek()); + + if (log.isEnabled()) { + log.info("Successfully specialized apply to call in '", + functionName, + " params=", + explodedArguments.peek(), + "' id=", + newFunctionNode.getId(), + " source=", + newFunctionNode.getSource().getURL()); + } + } + + explodedArguments.pop(); + + return newFunctionNode; + } + + private static boolean isApply(final CallNode callNode) { + final Expression f = callNode.getFunction(); + return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty()); + } + +} diff --git a/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java b/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java new file mode 100644 index 00000000000..4a817fae3db --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java @@ -0,0 +1,946 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.codegen; + +import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; +import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; +import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE; +import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX; +import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX; +import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN; +import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; +import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX; +import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; +import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; +import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE; +import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF; +import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; +import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; +import static jdk.nashorn.internal.ir.Symbol.IS_LET; +import static jdk.nashorn.internal.ir.Symbol.IS_PARAM; +import static jdk.nashorn.internal.ir.Symbol.IS_PROGRAM_LEVEL; +import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE; +import static jdk.nashorn.internal.ir.Symbol.IS_THIS; +import static jdk.nashorn.internal.ir.Symbol.IS_VAR; +import static jdk.nashorn.internal.ir.Symbol.KINDMASK; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Deque; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import jdk.nashorn.internal.ir.AccessNode; +import jdk.nashorn.internal.ir.BinaryNode; +import jdk.nashorn.internal.ir.Block; +import jdk.nashorn.internal.ir.CatchNode; +import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ForNode; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.FunctionNode.CompilationState; +import jdk.nashorn.internal.ir.IdentNode; +import jdk.nashorn.internal.ir.IndexNode; +import jdk.nashorn.internal.ir.LexicalContext; +import jdk.nashorn.internal.ir.LexicalContextNode; +import jdk.nashorn.internal.ir.LiteralNode; +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; +import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.RuntimeNode; +import jdk.nashorn.internal.ir.RuntimeNode.Request; +import jdk.nashorn.internal.ir.SplitNode; +import jdk.nashorn.internal.ir.Statement; +import jdk.nashorn.internal.ir.SwitchNode; +import jdk.nashorn.internal.ir.Symbol; +import jdk.nashorn.internal.ir.TryNode; +import jdk.nashorn.internal.ir.UnaryNode; +import jdk.nashorn.internal.ir.VarNode; +import jdk.nashorn.internal.ir.WithNode; +import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; +import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.Property; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import jdk.nashorn.internal.runtime.logging.Loggable; +import jdk.nashorn.internal.runtime.logging.Logger; + +/** + * This visitor assigns symbols to identifiers denoting variables. It does few more minor calculations that are only + * possible after symbols have been assigned; such is the transformation of "delete" and "typeof" operators into runtime + * nodes and counting of number of properties assigned to "this" in constructor functions. This visitor is also notable + * for what it doesn't do, most significantly it does no type calculations as in JavaScript variables can change types + * during runtime and as such symbols don't have types. Calculation of expression types is performed by a separate + * visitor. + */ +@Logger(name="symbols") +final class AssignSymbols extends NodeOperatorVisitor implements Loggable { + private final DebugLogger log; + private final boolean debug; + + private static boolean isParamOrVar(final IdentNode identNode) { + final Symbol symbol = identNode.getSymbol(); + return symbol.isParam() || symbol.isVar(); + } + + private static String name(final Node node) { + final String cn = node.getClass().getName(); + final int lastDot = cn.lastIndexOf('.'); + if (lastDot == -1) { + return cn; + } + return cn.substring(lastDot + 1); + } + + /** + * Checks if various symbols that were provisionally marked as needing a slot ended up unused, and marks them as not + * needing a slot after all. + * @param functionNode the function node + * @return the passed in node, for easy chaining + */ + private static FunctionNode removeUnusedSlots(final FunctionNode functionNode) { + if (!functionNode.needsCallee()) { + functionNode.compilerConstant(CALLEE).setNeedsSlot(false); + } + if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) { + functionNode.compilerConstant(SCOPE).setNeedsSlot(false); + } + if (!functionNode.usesReturnSymbol()) { + functionNode.compilerConstant(RETURN).setNeedsSlot(false); + } + // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol. + if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) { + final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName()); + if(selfSymbol != null) { + if(selfSymbol.isFunctionSelf()) { + selfSymbol.setNeedsSlot(false); + selfSymbol.clearFlag(Symbol.IS_VAR); + } + } else { + assert functionNode.isProgram(); + } + } + return functionNode; + } + + private final Deque> thisProperties = new ArrayDeque<>(); + private final Map globalSymbols = new HashMap<>(); //reuse the same global symbol + private final Compiler compiler; + + public AssignSymbols(final Compiler compiler) { + super(new LexicalContext()); + this.compiler = compiler; + this.log = initLogger(compiler.getContext()); + this.debug = log.isEnabled(); + } + + @Override + public DebugLogger getLogger() { + return log; + } + + @Override + public DebugLogger initLogger(final Context context) { + return context.getLogger(this.getClass()); + } + + /** + * Define symbols for all variable declarations at the top of the function scope. This way we can get around + * problems like + * + * while (true) { + * break; + * if (true) { + * var s; + * } + * } + * + * to an arbitrary nesting depth. + * + * see NASHORN-73 + * + * @param functionNode the FunctionNode we are entering + * @param body the body of the FunctionNode we are entering + */ + private void acceptDeclarations(final FunctionNode functionNode, final Block body) { + // This visitor will assign symbol to all declared variables, except function declarations (which are taken care + // in a separate step above) and "var" declarations in for loop initializers. + // + body.accept(new NodeVisitor(new LexicalContext()) { + @Override + public boolean enterFunctionNode(final FunctionNode nestedFn) { + // Don't descend into nested functions + return false; + } + + @Override + public Node leaveVarNode(final VarNode varNode) { + if (varNode.isStatement()) { + final IdentNode ident = varNode.getName(); + final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); + functionNode.addDeclaredSymbol(symbol); + if (varNode.isFunctionDeclaration()) { + symbol.setIsFunctionDeclaration(); + } + return varNode.setName((IdentNode)ident.setSymbol(symbol)); + } + return varNode; + } + }); + } + + private IdentNode compilerConstantIdentifier(final CompilerConstants cc) { + return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc)); + } + + /** + * Creates an ident node for an implicit identifier within the function (one not declared in the script source + * code). These identifiers are defined with function's token and finish. + * @param name the name of the identifier + * @return an ident node representing the implicit identifier. + */ + private IdentNode createImplicitIdentifier(final String name) { + final FunctionNode fn = lc.getCurrentFunction(); + return new IdentNode(fn.getToken(), fn.getFinish(), name); + } + + private Symbol createSymbol(final String name, final int flags) { + if ((flags & Symbol.KINDMASK) == IS_GLOBAL) { + //reuse global symbols so they can be hashed + Symbol global = globalSymbols.get(name); + if (global == null) { + global = new Symbol(name, flags); + globalSymbols.put(name, global); + } + return global; + } + return new Symbol(name, flags); + } + + /** + * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically + * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function + * expressions as well as for assignment of {@code :arguments} to {@code arguments}. + * + * @param name the ident node identifying the variable to initialize + * @param initConstant the compiler constant it is initialized to + * @param fn the function node the assignment is for + * @return a var node with the appropriate assignment + */ + private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) { + final IdentNode init = compilerConstantIdentifier(initConstant); + assert init.getSymbol() != null && init.getSymbol().isBytecodeLocal(); + + final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init); + + final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName()); + assert nameSymbol != null; + + return (VarNode)synthVar.setName((IdentNode)name.setSymbol(nameSymbol)).accept(this); + } + + private FunctionNode createSyntheticInitializers(final FunctionNode functionNode) { + final List syntheticInitializers = new ArrayList<>(2); + + // Must visit the new var nodes in the context of the body. We could also just set the new statements into the + // block and then revisit the entire block, but that seems to be too much double work. + final Block body = functionNode.getBody(); + lc.push(body); + try { + if (functionNode.usesSelfSymbol()) { + // "var fn = :callee" + syntheticInitializers.add(createSyntheticInitializer(functionNode.getIdent(), CALLEE, functionNode)); + } + + if (functionNode.needsArguments()) { + // "var arguments = :arguments" + syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()), + ARGUMENTS, functionNode)); + } + + if (syntheticInitializers.isEmpty()) { + return functionNode; + } + + for(final ListIterator it = syntheticInitializers.listIterator(); it.hasNext();) { + it.set((VarNode)it.next().accept(this)); + } + } finally { + lc.pop(body); + } + + final List stmts = body.getStatements(); + final List newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size()); + newStatements.addAll(syntheticInitializers); + newStatements.addAll(stmts); + return functionNode.setBody(lc, body.setStatements(lc, newStatements)); + } + + private Symbol defineGlobalSymbol(final Block block, final String name) { + return defineSymbol(block, name, IS_GLOBAL); + } + + /** + * Defines a new symbol in the given block. + * + * @param block the block in which to define the symbol + * @param name name of symbol. + * @param symbolFlags Symbol flags. + * + * @return Symbol for given name or null for redefinition. + */ + private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) { + int flags = symbolFlags; + Symbol symbol = findSymbol(block, name); // Locate symbol. + final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; + + // Global variables are implicitly always scope variables too. + if (isGlobal) { + flags |= IS_SCOPE; + } + + if (lc.getCurrentFunction().isProgram()) { + flags |= IS_PROGRAM_LEVEL; + } + + final boolean isParam = (flags & KINDMASK) == IS_PARAM; + final boolean isVar = (flags & KINDMASK) == IS_VAR; + + final FunctionNode function = lc.getFunction(block); + if (symbol != null) { + // Symbol was already defined. Check if it needs to be redefined. + if (isParam) { + if (!isLocal(function, symbol)) { + // Not defined in this function. Create a new definition. + symbol = null; + } else if (symbol.isParam()) { + // Duplicate parameter. Null return will force an error. + throw new AssertionError("duplicate parameter"); + } + } else if (isVar) { + if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) { + // Always create a new definition. + symbol = null; + } else { + // Not defined in this function. Create a new definition. + if (!isLocal(function, symbol) || symbol.less(IS_VAR)) { + symbol = null; + } + } + } + } + + if (symbol == null) { + // If not found, then create a new one. + Block symbolBlock; + + // Determine where to create it. + if (isVar && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { + symbolBlock = block; //internal vars are always defined in the block closest to them + } else if (isGlobal) { + symbolBlock = lc.getOutermostFunction().getBody(); + } else { + symbolBlock = lc.getFunctionBody(function); + } + + // Create and add to appropriate block. + symbol = createSymbol(name, flags); + symbolBlock.putSymbol(lc, symbol); + + if ((flags & IS_SCOPE) == 0) { + // Initial assumption; symbol can lose its slot later + symbol.setNeedsSlot(true); + } + } else if (symbol.less(flags)) { + symbol.setFlags(flags); + } + + if((isVar || isParam) && compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { + compiler.declareLocalSymbol(name); + } + + return symbol; + } + + private T end(final T node) { + return end(node, true); + } + + private T end(final T node, final boolean printNode) { + if (debug) { + final StringBuilder sb = new StringBuilder(); + + sb.append("[LEAVE "). + append(name(node)). + append("] "). + append(printNode ? node.toString() : ""). + append(" in '"). + append(lc.getCurrentFunction().getName()). + append('\''); + + if (node instanceof IdentNode) { + final Symbol symbol = ((IdentNode)node).getSymbol(); + if (symbol == null) { + sb.append(" "); + } else { + sb.append(" '); + } + } + + log.unindent(); + log.info(sb); + } + + return node; + } + + @Override + public boolean enterBlock(final Block block) { + start(block); + block.clearSymbols(); + + if (lc.isFunctionBody()) { + enterFunctionBody(); + } + + return true; + } + + @Override + public boolean enterCatchNode(final CatchNode catchNode) { + final IdentNode exception = catchNode.getException(); + final Block block = lc.getCurrentBlock(); + + start(catchNode); + + // define block-local exception variable + final String exname = exception.getName(); + // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its + // symbol is naturally internal, and should be treated as such. + final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName()); + defineSymbol(block, exname, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE); + + return true; + } + + private void enterFunctionBody() { + final FunctionNode functionNode = lc.getCurrentFunction(); + final Block body = lc.getCurrentBlock(); + + initFunctionWideVariables(functionNode, body); + + if (functionNode.isProgram()) { + initGlobalSymbols(body); + } else if (!functionNode.isDeclared() && !functionNode.isAnonymous()) { + // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's + // anonymous. + final String name = functionNode.getIdent().getName(); + assert name != null; + assert body.getExistingSymbol(name) == null; + defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE); + if(functionNode.allVarsInScope()) { // basically, has deep eval + lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL); + } + } + + acceptDeclarations(functionNode, body); + } + + @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + // TODO: once we have information on symbols used by nested functions, we can stop descending into nested + // functions with on-demand compilation, e.g. add + // if(!thisProperties.isEmpty() && env.isOnDemandCompilation()) { + // return false; + // } + start(functionNode, false); + + thisProperties.push(new HashSet()); + + //an outermost function in our lexical context that is not a program + //is possible - it is a function being compiled lazily + if (functionNode.isDeclared()) { + final Iterator blocks = lc.getBlocks(); + if (blocks.hasNext()) { + defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR); + } + } + + return true; + } + + @Override + public boolean enterVarNode(final VarNode varNode) { + start(varNode); + defineSymbol(lc.getCurrentBlock(), varNode.getName().getName(), IS_VAR | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); + return true; + } + + private Symbol exceptionSymbol() { + return newObjectInternal(EXCEPTION_PREFIX); + } + + /** + * This has to run before fix assignment types, store any type specializations for + * paramters, then turn then to objects for the generic version of this method + * + * @param functionNode functionNode + */ + private FunctionNode finalizeParameters(final FunctionNode functionNode) { + final List newParams = new ArrayList<>(); + final boolean isVarArg = functionNode.isVarArg(); + + final Block body = functionNode.getBody(); + for (final IdentNode param : functionNode.getParameters()) { + final Symbol paramSymbol = body.getExistingSymbol(param.getName()); + assert paramSymbol != null; + assert paramSymbol.isParam() : paramSymbol + " " + paramSymbol.getFlags(); + newParams.add((IdentNode)param.setSymbol(paramSymbol)); + + // parameters should not be slots for a function that uses variable arity signature + if (isVarArg) { + paramSymbol.setNeedsSlot(false); + } + } + + return functionNode.setParameters(lc, newParams); + } + + /** + * Search for symbol in the lexical context starting from the given block. + * @param name Symbol name. + * @return Found symbol or null if not found. + */ + private Symbol findSymbol(final Block block, final String name) { + for (final Iterator blocks = lc.getBlocks(block); blocks.hasNext();) { + final Symbol symbol = blocks.next().getExistingSymbol(name); + if (symbol != null) { + return symbol; + } + } + return null; + } + + /** + * Marks the current function as one using any global symbol. The function and all its parent functions will all be + * marked as needing parent scope. + * @see FunctionNode#needsParentScope() + */ + private void functionUsesGlobalSymbol() { + for (final Iterator fns = lc.getFunctions(); fns.hasNext();) { + lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE); + } + } + + /** + * Marks the current function as one using a scoped symbol. The block defining the symbol will be marked as needing + * its own scope to hold the variable. If the symbol is defined outside of the current function, it and all + * functions up to (but not including) the function containing the defining block will be marked as needing parent + * function scope. + * @see FunctionNode#needsParentScope() + */ + private void functionUsesScopeSymbol(final Symbol symbol) { + final String name = symbol.getName(); + for (final Iterator contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) { + final LexicalContextNode node = contextNodeIter.next(); + if (node instanceof Block) { + final Block block = (Block)node; + if (block.getExistingSymbol(name) != null) { + assert lc.contains(block); + lc.setBlockNeedsScope(block); + break; + } + } else if (node instanceof FunctionNode) { + lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE); + } + } + } + + /** + * Declares that the current function is using the symbol. + * @param symbol the symbol used by the current function. + */ + private void functionUsesSymbol(final Symbol symbol) { + assert symbol != null; + if (symbol.isScope()) { + if (symbol.isGlobal()) { + functionUsesGlobalSymbol(); + } else { + functionUsesScopeSymbol(symbol); + } + } else { + assert !symbol.isGlobal(); // Every global is also scope + } + } + + private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) { + defineSymbol(block, cc.symbolName(), flags).setNeedsSlot(true); + } + + private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) { + initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE); + initCompileConstant(THIS, body, IS_PARAM | IS_THIS | HAS_OBJECT_VALUE); + + if (functionNode.isVarArg()) { + initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE); + if (functionNode.needsArguments()) { + initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE); + defineSymbol(body, ARGUMENTS_VAR.symbolName(), IS_VAR | HAS_OBJECT_VALUE); + } + } + + initParameters(functionNode, body); + initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE); + initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL); + } + + + /** + * Move any properties from the global map into the scope of this function (which must be a program function). + * @param block the function node body for which to init scope vars + */ + private void initGlobalSymbols(final Block block) { + final PropertyMap map = Context.getGlobalMap(); + + for (final Property property : map.getProperties()) { + final Symbol symbol = defineGlobalSymbol(block, property.getKey()); + log.info("Added global symbol from property map ", symbol); + } + } + + /** + * Initialize parameters for function node. + * @param functionNode the function node + */ + private void initParameters(final FunctionNode functionNode, final Block body) { + final boolean isVarArg = functionNode.isVarArg(); + final boolean scopeParams = functionNode.allVarsInScope() || isVarArg; + for (final IdentNode param : functionNode.getParameters()) { + final Symbol symbol = defineSymbol(body, param.getName(), IS_PARAM); + if(scopeParams) { + // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored. + // It will force creation of scopes where they would otherwise not necessarily be needed (functions + // using arguments object and other variable arity functions). Tracked by JDK-8038942. + symbol.setIsScope(); + assert symbol.hasSlot(); + if(isVarArg) { + symbol.setNeedsSlot(false); + } + } + } + } + + /** + * Is the symbol local to (that is, defined in) the specified function? + * @param function the function + * @param symbol the symbol + * @return true if the symbol is defined in the specified function + */ + private boolean isLocal(final FunctionNode function, final Symbol symbol) { + final FunctionNode definingFn = lc.getDefiningFunction(symbol); + assert definingFn != null; + return definingFn == function; + } + + @Override + public Node leaveASSIGN(final BinaryNode binaryNode) { + // If we're assigning a property of the this object ("this.foo = ..."), record it. + + final Expression lhs = binaryNode.lhs(); + if (lhs instanceof AccessNode) { + final AccessNode accessNode = (AccessNode) lhs; + final Expression base = accessNode.getBase(); + if (base instanceof IdentNode) { + final Symbol symbol = ((IdentNode)base).getSymbol(); + if(symbol.isThis()) { + thisProperties.peek().add(accessNode.getProperty()); + } + } + } + return binaryNode; + } + + @Override + public Node leaveDELETE(final UnaryNode unaryNode) { + final FunctionNode currentFunctionNode = lc.getCurrentFunction(); + final boolean strictMode = currentFunctionNode.isStrict(); + final Expression rhs = unaryNode.getExpression(); + final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this); + + Request request = Request.DELETE; + final List args = new ArrayList<>(); + + if (rhs instanceof IdentNode) { + final IdentNode ident = (IdentNode)rhs; + // If this is a declared variable or a function parameter, delete always fails (except for globals). + final String name = ident.getName(); + final Symbol symbol = ident.getSymbol(); + final boolean failDelete = strictMode || symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()); + + if (failDelete && symbol.isThis()) { + return LiteralNode.newInstance(unaryNode, true).accept(this); + } + final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); + + if (!failDelete) { + args.add(compilerConstantIdentifier(SCOPE)); + } + args.add(literalNode); + args.add(strictFlagNode); + + if (failDelete) { + request = Request.FAIL_DELETE; + } + } else if (rhs instanceof AccessNode) { + final Expression base = ((AccessNode)rhs).getBase(); + final String property = ((AccessNode)rhs).getProperty(); + + args.add(base); + args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this)); + args.add(strictFlagNode); + + } else if (rhs instanceof IndexNode) { + final IndexNode indexNode = (IndexNode)rhs; + final Expression base = indexNode.getBase(); + final Expression index = indexNode.getIndex(); + + args.add(base); + args.add(index); + args.add(strictFlagNode); + + } else { + return LiteralNode.newInstance(unaryNode, true).accept(this); + } + return new RuntimeNode(unaryNode, request, args).accept(this); + } + + @Override + public Node leaveForNode(final ForNode forNode) { + if (forNode.isForIn()) { + forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 + } + + return end(forNode); + } + + @Override + public Node leaveFunctionNode(final FunctionNode functionNode) { + + return markProgramBlock( + removeUnusedSlots( + createSyntheticInitializers( + finalizeParameters( + lc.applyTopFlags(functionNode)))) + .setThisProperties(lc, thisProperties.pop().size()) + .setState(lc, CompilationState.SYMBOLS_ASSIGNED)); + } + + @Override + public Node leaveIdentNode(final IdentNode identNode) { + final String name = identNode.getName(); + + if (identNode.isPropertyName()) { + return identNode; + } + + final Block block = lc.getCurrentBlock(); + + Symbol symbol = findSymbol(block, name); + + //If an existing symbol with the name is found, use that otherwise, declare a new one + if (symbol != null) { + log.info("Existing symbol = ", symbol); + if (symbol.isFunctionSelf()) { + final FunctionNode functionNode = lc.getDefiningFunction(symbol); + assert functionNode != null; + assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null; + lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL); + } + + // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already) + maybeForceScope(symbol); + } else { + log.info("No symbol exists. Declare as global: ", symbol); + symbol = defineGlobalSymbol(block, name); + Symbol.setSymbolIsScope(lc, symbol); + } + + functionUsesSymbol(symbol); + + if (!identNode.isInitializedHere()) { + symbol.increaseUseCount(); + } + + return end(identNode.setSymbol(symbol)); + } + + @Override + public Node leaveSwitchNode(final SwitchNode switchNode) { + // We only need a symbol for the tag if it's not an integer switch node + if(!switchNode.isInteger()) { + switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX)); + } + return switchNode; + } + + @Override + public Node leaveTryNode(final TryNode tryNode) { + tryNode.setException(exceptionSymbol()); + if (tryNode.getFinallyBody() != null) { + tryNode.setFinallyCatchAll(exceptionSymbol()); + } + + end(tryNode); + + return tryNode; + } + + @Override + public Node leaveTYPEOF(final UnaryNode unaryNode) { + final Expression rhs = unaryNode.getExpression(); + + final List args = new ArrayList<>(); + if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { + args.add(compilerConstantIdentifier(SCOPE)); + args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null + } else { + args.add(rhs); + args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' + } + + final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this); + + end(unaryNode); + + return runtimeNode; + } + + private FunctionNode markProgramBlock(final FunctionNode functionNode) { + if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) { + return functionNode; + } + + assert functionNode.getId() == 1; + return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE)); + } + + /** + * If the symbol isn't already a scope symbol, but it needs to be (see {@link #symbolNeedsToBeScope(Symbol)}, it is + * promoted to a scope symbol and its block marked as needing a scope. + * @param symbol the symbol that might be scoped + */ + private void maybeForceScope(final Symbol symbol) { + if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) { + Symbol.setSymbolIsScope(lc, symbol); + } + } + + private Symbol newInternal(final CompilerConstants cc, final int flags) { + return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), IS_VAR | IS_INTERNAL | flags); //NASHORN-73 + } + + private Symbol newObjectInternal(final CompilerConstants cc) { + return newInternal(cc, HAS_OBJECT_VALUE); + } + + private boolean start(final Node node) { + return start(node, true); + } + + private boolean start(final Node node, final boolean printNode) { + if (debug) { + final StringBuilder sb = new StringBuilder(); + + sb.append("[ENTER "). + append(name(node)). + append("] "). + append(printNode ? node.toString() : ""). + append(" in '"). + append(lc.getCurrentFunction().getName()). + append("'"); + log.info(sb); + log.indent(); + } + + return true; + } + + /** + * Determines if the symbol has to be a scope symbol. In general terms, it has to be a scope symbol if it can only + * be reached from the current block by traversing a function node, a split node, or a with node. + * @param symbol the symbol checked for needing to be a scope symbol + * @return true if the symbol has to be a scope symbol. + */ + private boolean symbolNeedsToBeScope(final Symbol symbol) { + if (symbol.isThis() || symbol.isInternal()) { + return false; + } + + if (lc.getCurrentFunction().allVarsInScope()) { + return true; + } + + boolean previousWasBlock = false; + for (final Iterator it = lc.getAllNodes(); it.hasNext();) { + final LexicalContextNode node = it.next(); + if (node instanceof FunctionNode || node instanceof SplitNode || isSplitArray(node)) { + // We reached the function boundary or a splitting boundary without seeing a definition for the symbol. + // It needs to be in scope. + return true; + } else if (node instanceof WithNode) { + if (previousWasBlock) { + // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately + // preceded by a block, this means we're currently processing its expression, not its body, + // therefore it doesn't count. + return true; + } + previousWasBlock = false; + } else if (node instanceof Block) { + if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) { + // We reached the block that defines the symbol without reaching either the function boundary, or a + // WithNode. The symbol need not be scoped. + return false; + } + previousWasBlock = true; + } else { + previousWasBlock = false; + } + } + throw new AssertionError(); + } + + private static boolean isSplitArray(final LexicalContextNode expr) { + if(!(expr instanceof ArrayLiteralNode)) { + return false; + } + final List units = ((ArrayLiteralNode)expr).getUnits(); + return !(units == null || units.isEmpty()); + } +} diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java deleted file mode 100644 index 61ccb712772..00000000000 --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java +++ /dev/null @@ -1,1947 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.codegen; - -import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; -import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; -import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE; -import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.LITERAL_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN; -import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; -import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; -import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; -import static jdk.nashorn.internal.ir.Symbol.IS_ALWAYS_DEFINED; -import static jdk.nashorn.internal.ir.Symbol.IS_CONSTANT; -import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF; -import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL; -import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; -import static jdk.nashorn.internal.ir.Symbol.IS_LET; -import static jdk.nashorn.internal.ir.Symbol.IS_PARAM; -import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE; -import static jdk.nashorn.internal.ir.Symbol.IS_THIS; -import static jdk.nashorn.internal.ir.Symbol.IS_VAR; -import static jdk.nashorn.internal.ir.Symbol.KINDMASK; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Deque; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import jdk.nashorn.internal.codegen.types.Type; -import jdk.nashorn.internal.ir.AccessNode; -import jdk.nashorn.internal.ir.BinaryNode; -import jdk.nashorn.internal.ir.Block; -import jdk.nashorn.internal.ir.CallNode; -import jdk.nashorn.internal.ir.CaseNode; -import jdk.nashorn.internal.ir.CatchNode; -import jdk.nashorn.internal.ir.Expression; -import jdk.nashorn.internal.ir.ForNode; -import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; -import jdk.nashorn.internal.ir.IdentNode; -import jdk.nashorn.internal.ir.IndexNode; -import jdk.nashorn.internal.ir.LexicalContext; -import jdk.nashorn.internal.ir.LexicalContextNode; -import jdk.nashorn.internal.ir.LiteralNode; -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; -import jdk.nashorn.internal.ir.Node; -import jdk.nashorn.internal.ir.ObjectNode; -import jdk.nashorn.internal.ir.ReturnNode; -import jdk.nashorn.internal.ir.RuntimeNode; -import jdk.nashorn.internal.ir.RuntimeNode.Request; -import jdk.nashorn.internal.ir.Statement; -import jdk.nashorn.internal.ir.SwitchNode; -import jdk.nashorn.internal.ir.Symbol; -import jdk.nashorn.internal.ir.TemporarySymbols; -import jdk.nashorn.internal.ir.TernaryNode; -import jdk.nashorn.internal.ir.TryNode; -import jdk.nashorn.internal.ir.UnaryNode; -import jdk.nashorn.internal.ir.VarNode; -import jdk.nashorn.internal.ir.WithNode; -import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; -import jdk.nashorn.internal.parser.TokenType; -import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.Debug; -import jdk.nashorn.internal.runtime.DebugLogger; -import jdk.nashorn.internal.runtime.JSType; -import jdk.nashorn.internal.runtime.Property; -import jdk.nashorn.internal.runtime.PropertyMap; - -/** - * This is the attribution pass of the code generator. Attr takes Lowered IR, - * that is, IR where control flow has been computed and high level to low level - * substitions for operations have been performed. - * - * After Attr, every symbol will have a conservative correct type. - * - * Any expression that requires temporary storage as part of computation will - * also be detected here and give a temporary symbol - * - * Types can be narrowed after Attr by Access Specialization in FinalizeTypes, - * but in general, this is where the main symbol type information is - * computed. - */ - -final class Attr extends NodeOperatorVisitor { - - /** - * Local definitions in current block (to discriminate from function - * declarations always defined in the function scope. This is for - * "can be undefined" analysis. - */ - private final Deque> localDefs; - - /** - * Local definitions in current block to guard against cases like - * NASHORN-467 when things can be undefined as they are used before - * their local var definition. *sigh* JavaScript... - */ - private final Deque> localUses; - - private final Deque returnTypes; - - private int catchNestingLevel; - - private static final DebugLogger LOG = new DebugLogger("attr"); - private static final boolean DEBUG = LOG.isEnabled(); - - private final TemporarySymbols temporarySymbols; - - /** - * Constructor. - */ - Attr(final TemporarySymbols temporarySymbols) { - super(new LexicalContext()); - this.temporarySymbols = temporarySymbols; - this.localDefs = new ArrayDeque<>(); - this.localUses = new ArrayDeque<>(); - this.returnTypes = new ArrayDeque<>(); - } - - @Override - protected boolean enterDefault(final Node node) { - return start(node); - } - - @Override - protected Node leaveDefault(final Node node) { - return end(node); - } - - @Override - public Node leaveAccessNode(final AccessNode accessNode) { - //While Object type is assigned here, Access Specialization in FinalizeTypes may narrow this, that - //is why we can't set the access node base to be an object here, that will ruin access specialization - //for example for a.x | 17. - return end(ensureSymbol(Type.OBJECT, accessNode)); - } - - private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) { - initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL); - initCompileConstant(THIS, body, IS_PARAM | IS_THIS, Type.OBJECT); - - if (functionNode.isVarArg()) { - initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL); - if (functionNode.needsArguments()) { - initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED); - final String argumentsName = ARGUMENTS_VAR.symbolName(); - newType(defineSymbol(body, argumentsName, IS_VAR | IS_ALWAYS_DEFINED), Type.typeFor(ARGUMENTS_VAR.type())); - addLocalDef(argumentsName); - } - } - - initParameters(functionNode, body); - initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED); - initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT); - } - - - /** - * This pushes all declarations (except for non-statements, i.e. for - * node temporaries) to the top of the function scope. This way we can - * get around problems like - * - * while (true) { - * break; - * if (true) { - * var s; - * } - * } - * - * to an arbitrary nesting depth. - * - * see NASHORN-73 - * - * @param functionNode the FunctionNode we are entering - * @param body the body of the FunctionNode we are entering - */ - private void acceptDeclarations(final FunctionNode functionNode, final Block body) { - // This visitor will assign symbol to all declared variables, except function declarations (which are taken care - // in a separate step above) and "var" declarations in for loop initializers. - // - // It also handles the case that a variable can be undefined, e.g - // if (cond) { - // x = x.y; - // } - // var x = 17; - // - // by making sure that no identifier has been found earlier in the body than the - // declaration - if such is the case the identifier is flagged as caBeUndefined to - // be safe if it turns into a local var. Otherwise corrupt bytecode results - - body.accept(new NodeVisitor(new LexicalContext()) { - private final Set uses = new HashSet<>(); - private final Set canBeUndefined = new HashSet<>(); - - @Override - public boolean enterFunctionNode(final FunctionNode nestedFn) { - return false; - } - - @Override - public Node leaveIdentNode(final IdentNode identNode) { - uses.add(identNode.getName()); - return identNode; - } - - @Override - public boolean enterVarNode(final VarNode varNode) { - final String name = varNode.getName().getName(); - //if this is used before the var node, the var node symbol needs to be tagged as can be undefined - if (uses.contains(name)) { - canBeUndefined.add(name); - } - - // all uses of the declared varnode inside the var node are potentially undefined - // however this is a bit conservative as e.g. var x = 17; var x = 1 + x; does work - if (!varNode.isFunctionDeclaration() && varNode.getInit() != null) { - varNode.getInit().accept(new NodeVisitor(new LexicalContext()) { - @Override - public boolean enterIdentNode(final IdentNode identNode) { - if (name.equals(identNode.getName())) { - canBeUndefined.add(name); - } - return false; - } - }); - } - - return true; - } - - @Override - public Node leaveVarNode(final VarNode varNode) { - // any declared symbols that aren't visited need to be typed as well, hence the list - if (varNode.isStatement()) { - final IdentNode ident = varNode.getName(); - final Symbol symbol = defineSymbol(body, ident.getName(), IS_VAR); - if (canBeUndefined.contains(ident.getName())) { - symbol.setType(Type.OBJECT); - symbol.setCanBeUndefined(); - } - functionNode.addDeclaredSymbol(symbol); - if (varNode.isFunctionDeclaration()) { - newType(symbol, FunctionNode.FUNCTION_TYPE); - symbol.setIsFunctionDeclaration(); - } - return varNode.setName((IdentNode)ident.setSymbol(lc, symbol)); - } - - return varNode; - } - }); - } - - private void enterFunctionBody() { - - final FunctionNode functionNode = lc.getCurrentFunction(); - final Block body = lc.getCurrentBlock(); - - initFunctionWideVariables(functionNode, body); - - if (functionNode.isProgram()) { - initFromPropertyMap(body); - } else if (!functionNode.isDeclared()) { - // It's neither declared nor program - it's a function expression then; assign it a self-symbol. - assert functionNode.getSymbol() == null; - - final boolean anonymous = functionNode.isAnonymous(); - final String name = anonymous ? null : functionNode.getIdent().getName(); - if (!(anonymous || body.getExistingSymbol(name) != null)) { - assert !anonymous && name != null; - newType(defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF), Type.OBJECT); - } - } - - acceptDeclarations(functionNode, body); - } - - @Override - public boolean enterBlock(final Block block) { - start(block); - //ensure that we don't use information from a previous compile. This is very ugly TODO - //the symbols in the block should really be stateless - block.clearSymbols(); - - if (lc.isFunctionBody()) { - enterFunctionBody(); - } - pushLocalsBlock(); - - return true; - } - - @Override - public Node leaveBlock(final Block block) { - popLocals(); - return end(block); - } - - @Override - public boolean enterCallNode(final CallNode callNode) { - return start(callNode); - } - - @Override - public Node leaveCallNode(final CallNode callNode) { - return end(ensureSymbol(callNode.getType(), callNode)); - } - - @Override - public boolean enterCatchNode(final CatchNode catchNode) { - final IdentNode exception = catchNode.getException(); - final Block block = lc.getCurrentBlock(); - - start(catchNode); - catchNestingLevel++; - - // define block-local exception variable - final String exname = exception.getName(); - final Symbol def = defineSymbol(block, exname, IS_VAR | IS_LET | IS_ALWAYS_DEFINED); - newType(def, Type.OBJECT); //we can catch anything, not just ecma exceptions - - addLocalDef(exname); - - return true; - } - - @Override - public Node leaveCatchNode(final CatchNode catchNode) { - final IdentNode exception = catchNode.getException(); - final Block block = lc.getCurrentBlock(); - final Symbol symbol = findSymbol(block, exception.getName()); - - catchNestingLevel--; - - assert symbol != null; - return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol))); - } - - /** - * Declare the definition of a new symbol. - * - * @param name Name of symbol. - * @param symbolFlags Symbol flags. - * - * @return Symbol for given name or null for redefinition. - */ - private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) { - int flags = symbolFlags; - Symbol symbol = findSymbol(block, name); // Locate symbol. - boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL; - - if (isGlobal) { - flags |= IS_SCOPE; - } - - final FunctionNode function = lc.getFunction(block); - if (symbol != null) { - // Symbol was already defined. Check if it needs to be redefined. - if ((flags & KINDMASK) == IS_PARAM) { - if (!isLocal(function, symbol)) { - // Not defined in this function. Create a new definition. - symbol = null; - } else if (symbol.isParam()) { - // Duplicate parameter. Null return will force an error. - assert false : "duplicate parameter"; - return null; - } - } else if ((flags & KINDMASK) == IS_VAR) { - if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) { - // Always create a new definition. - symbol = null; - } else { - // Not defined in this function. Create a new definition. - if (!isLocal(function, symbol) || symbol.less(IS_VAR)) { - symbol = null; - } - } - } - } - - if (symbol == null) { - // If not found, then create a new one. - Block symbolBlock; - - // Determine where to create it. - if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) { - symbolBlock = block; //internal vars are always defined in the block closest to them - } else if (isGlobal) { - symbolBlock = lc.getOutermostFunction().getBody(); - } else { - symbolBlock = lc.getFunctionBody(function); - } - - // Create and add to appropriate block. - symbol = new Symbol(name, flags); - symbolBlock.putSymbol(lc, symbol); - - if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { - symbol.setNeedsSlot(true); - } - } else if (symbol.less(flags)) { - symbol.setFlags(flags); - } - - return symbol; - } - - @Override - public boolean enterFunctionNode(final FunctionNode functionNode) { - start(functionNode, false); - - if (functionNode.isLazy()) { - return false; - } - - //an outermost function in our lexical context that is not a program (runScript) - //is possible - it is a function being compiled lazily - if (functionNode.isDeclared()) { - final Iterator blocks = lc.getBlocks(); - if (blocks.hasNext()) { - defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR); - } - } - - returnTypes.push(functionNode.getReturnType()); - pushLocalsFunction(); - - return true; - } - - @Override - public Node leaveFunctionNode(final FunctionNode functionNode) { - FunctionNode newFunctionNode = functionNode; - - final Block body = newFunctionNode.getBody(); - - //look for this function in the parent block - if (functionNode.isDeclared()) { - final Iterator blocks = lc.getBlocks(); - if (blocks.hasNext()) { - newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName())); - } - } else if (!functionNode.isProgram()) { - final boolean anonymous = functionNode.isAnonymous(); - final String name = anonymous ? null : functionNode.getIdent().getName(); - if (anonymous || body.getExistingSymbol(name) != null) { - newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode); - } else { - assert name != null; - final Symbol self = body.getExistingSymbol(name); - assert self != null && self.isFunctionSelf(); - newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, body.getExistingSymbol(name)); - } - } - - //unknown parameters are promoted to object type. - if (newFunctionNode.hasLazyChildren()) { - //the final body has already been assigned as we have left the function node block body by now - objectifySymbols(body); - } - newFunctionNode = finalizeParameters(newFunctionNode); - newFunctionNode = finalizeTypes(newFunctionNode); - for (final Symbol symbol : newFunctionNode.getDeclaredSymbols()) { - if (symbol.getSymbolType().isUnknown()) { - symbol.setType(Type.OBJECT); - symbol.setCanBeUndefined(); - } - } - - List syntheticInitializers = null; - - if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) { - syntheticInitializers = new ArrayList<>(2); - LOG.info("Accepting self symbol init for ", newFunctionNode.getName()); - // "var fn = :callee" - syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode)); - } - - if (newFunctionNode.needsArguments()) { - if (syntheticInitializers == null) { - syntheticInitializers = new ArrayList<>(1); - } - // "var arguments = :arguments" - syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()), - ARGUMENTS, newFunctionNode)); - } - - if (syntheticInitializers != null) { - final List stmts = newFunctionNode.getBody().getStatements(); - final List newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size()); - newStatements.addAll(syntheticInitializers); - newStatements.addAll(stmts); - newFunctionNode = newFunctionNode.setBody(lc, newFunctionNode.getBody().setStatements(lc, newStatements)); - } - - if (returnTypes.peek().isUnknown()) { - LOG.info("Unknown return type promoted to object"); - newFunctionNode = newFunctionNode.setReturnType(lc, Type.OBJECT); - } - final Type returnType = returnTypes.pop(); - newFunctionNode = newFunctionNode.setReturnType(lc, returnType.isUnknown() ? Type.OBJECT : returnType); - newFunctionNode = newFunctionNode.setState(lc, CompilationState.ATTR); - - popLocals(); - - end(newFunctionNode, false); - - return newFunctionNode; - } - - /** - * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically - * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function - * expressions as well as for assignment of {@code :arguments} to {@code arguments}. - * - * @param name the ident node identifying the variable to initialize - * @param initConstant the compiler constant it is initialized to - * @param fn the function node the assignment is for - * @return a var node with the appropriate assignment - */ - private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) { - final IdentNode init = compilerConstant(initConstant); - assert init.getSymbol() != null && init.getSymbol().hasSlot(); - - VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init); - - final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName()); - assert nameSymbol != null; - - return synthVar.setName((IdentNode)name.setSymbol(lc, nameSymbol)); - } - - @Override - public Node leaveIdentNode(final IdentNode identNode) { - final String name = identNode.getName(); - - if (identNode.isPropertyName()) { - // assign a pseudo symbol to property name - final Symbol pseudoSymbol = pseudoSymbol(name); - LOG.info("IdentNode is property name -> assigning pseudo symbol ", pseudoSymbol); - LOG.unindent(); - return end(identNode.setSymbol(lc, pseudoSymbol)); - } - - final Block block = lc.getCurrentBlock(); - - Symbol symbol = findSymbol(block, name); - - //If an existing symbol with the name is found, use that otherwise, declare a new one - if (symbol != null) { - LOG.info("Existing symbol = ", symbol); - if (symbol.isFunctionSelf()) { - final FunctionNode functionNode = lc.getDefiningFunction(symbol); - assert functionNode != null; - assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null; - lc.setFlag(functionNode.getBody(), Block.NEEDS_SELF_SYMBOL); - newType(symbol, FunctionNode.FUNCTION_TYPE); - } else if (!identNode.isInitializedHere()) { - /* - * See NASHORN-448, JDK-8016235 - * - * Here is a use outside the local def scope - * the inCatch check is a conservative approach to handle things that might have only been - * defined in the try block, but with variable declarations, which due to JavaScript rules - * have to be lifted up into the function scope outside the try block anyway, but as the - * flow can fault at almost any place in the try block and get us to the catch block, all we - * know is that we have a declaration, not a definition. This can be made better and less - * conservative once we superimpose a CFG onto the AST. - */ - if (!isLocalDef(name) || inCatch()) { - newType(symbol, Type.OBJECT); - symbol.setCanBeUndefined(); - } - } - - // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already) - maybeForceScope(symbol); - } else { - LOG.info("No symbol exists. Declare undefined: ", symbol); - symbol = defineSymbol(block, name, IS_GLOBAL); - // we have never seen this before, it can be undefined - newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway? - symbol.setCanBeUndefined(); - Symbol.setSymbolIsScope(lc, symbol); - } - - setBlockScope(name, symbol); - - if (!identNode.isInitializedHere()) { - symbol.increaseUseCount(); - } - addLocalUse(identNode.getName()); - - return end(identNode.setSymbol(lc, symbol)); - } - - private boolean inCatch() { - return catchNestingLevel > 0; - } - - /** - * If the symbol isn't already a scope symbol, and it is either not local to the current function, or it is being - * referenced from within a with block, we force it to be a scope symbol. - * @param symbol the symbol that might be scoped - */ - private void maybeForceScope(final Symbol symbol) { - if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) { - Symbol.setSymbolIsScope(lc, symbol); - } - } - - private boolean symbolNeedsToBeScope(Symbol symbol) { - if (symbol.isThis() || symbol.isInternal()) { - return false; - } - boolean previousWasBlock = false; - for (final Iterator it = lc.getAllNodes(); it.hasNext();) { - final LexicalContextNode node = it.next(); - if (node instanceof FunctionNode) { - // We reached the function boundary without seeing a definition for the symbol - it needs to be in - // scope. - return true; - } else if (node instanceof WithNode) { - if (previousWasBlock) { - // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately - // preceded by a block, this means we're currently processing its expression, not its body, - // therefore it doesn't count. - return true; - } - previousWasBlock = false; - } else if (node instanceof Block) { - if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) { - // We reached the block that defines the symbol without reaching either the function boundary, or a - // WithNode. The symbol need not be scoped. - return false; - } - previousWasBlock = true; - } else { - previousWasBlock = false; - } - } - throw new AssertionError(); - } - - private void setBlockScope(final String name, final Symbol symbol) { - assert symbol != null; - if (symbol.isGlobal()) { - setUsesGlobalSymbol(); - return; - } - - if (symbol.isScope()) { - Block scopeBlock = null; - for (final Iterator contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) { - final LexicalContextNode node = contextNodeIter.next(); - if (node instanceof Block) { - if (((Block)node).getExistingSymbol(name) != null) { - scopeBlock = (Block)node; - break; - } - } else if (node instanceof FunctionNode) { - lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE); - } - } - - if (scopeBlock != null) { - assert lc.contains(scopeBlock); - lc.setBlockNeedsScope(scopeBlock); - } - } - } - - /** - * Marks the current function as one using any global symbol. The function and all its parent functions will all be - * marked as needing parent scope. - * @see #needsParentScope() - */ - private void setUsesGlobalSymbol() { - for (final Iterator fns = lc.getFunctions(); fns.hasNext();) { - lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE); - } - } - - /** - * Search for symbol in the lexical context starting from the given block. - * @param name Symbol name. - * @return Found symbol or null if not found. - */ - private Symbol findSymbol(final Block block, final String name) { - // Search up block chain to locate symbol. - - for (final Iterator blocks = lc.getBlocks(block); blocks.hasNext();) { - // Find name. - final Symbol symbol = blocks.next().getExistingSymbol(name); - // If found then we are good. - if (symbol != null) { - return symbol; - } - } - return null; - } - - @Override - public Node leaveIndexNode(final IndexNode indexNode) { - return end(ensureSymbol(Type.OBJECT, indexNode)); - } - - @SuppressWarnings("rawtypes") - @Override - public Node leaveLiteralNode(final LiteralNode literalNode) { - assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens - assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported"; - final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType()); - if (literalNode instanceof ArrayLiteralNode) { - ((ArrayLiteralNode)literalNode).analyze(); - } - return end(literalNode.setSymbol(lc, symbol)); - } - - @Override - public boolean enterObjectNode(final ObjectNode objectNode) { - return start(objectNode); - } - - @Override - public Node leaveObjectNode(final ObjectNode objectNode) { - return end(ensureSymbol(Type.OBJECT, objectNode)); - } - - @Override - public Node leaveReturnNode(final ReturnNode returnNode) { - final Expression expr = returnNode.getExpression(); - final Type returnType; - - if (expr != null) { - //we can't do parameter specialization if we return something that hasn't been typed yet - final Symbol symbol = expr.getSymbol(); - if (expr.getType().isUnknown() && symbol.isParam()) { - symbol.setType(Type.OBJECT); - } - - returnType = widestReturnType(returnTypes.pop(), symbol.getSymbolType()); - } else { - returnType = Type.OBJECT; //undefined - } - LOG.info("Returntype is now ", returnType); - returnTypes.push(returnType); - - end(returnNode); - - return returnNode; - } - - @Override - public Node leaveSwitchNode(final SwitchNode switchNode) { - Type type = Type.UNKNOWN; - - final List newCases = new ArrayList<>(); - for (final CaseNode caseNode : switchNode.getCases()) { - final Node test = caseNode.getTest(); - - CaseNode newCaseNode = caseNode; - if (test != null) { - if (test instanceof LiteralNode) { - //go down to integers if we can - final LiteralNode lit = (LiteralNode)test; - if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) { - if (JSType.isRepresentableAsInt(lit.getNumber())) { - newCaseNode = caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this)); - } - } - } else { - // the "all integer" case that CodeGenerator optimizes for currently assumes literals only - type = Type.OBJECT; - } - - final Type newCaseType = newCaseNode.getTest().getType(); - if (newCaseType.isBoolean()) { - type = Type.OBJECT; //booleans and integers aren't assignment compatible - } else { - type = Type.widest(type, newCaseType); - } - } - - newCases.add(newCaseNode); - } - - //only optimize for all integers - if (!type.isInteger()) { - type = Type.OBJECT; - } - - switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type)); - - end(switchNode); - - return switchNode.setCases(lc, newCases); - } - - @Override - public Node leaveTryNode(final TryNode tryNode) { - tryNode.setException(exceptionSymbol()); - - if (tryNode.getFinallyBody() != null) { - tryNode.setFinallyCatchAll(exceptionSymbol()); - } - - end(tryNode); - - return tryNode; - } - - @Override - public boolean enterVarNode(final VarNode varNode) { - start(varNode); - - final IdentNode ident = varNode.getName(); - final String name = ident.getName(); - - final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR); - assert symbol != null; - - // NASHORN-467 - use before definition of vars - conservative - if (isLocalUse(ident.getName())) { - newType(symbol, Type.OBJECT); - symbol.setCanBeUndefined(); - } - - return true; - } - - @Override - public Node leaveVarNode(final VarNode varNode) { - final Expression init = varNode.getInit(); - final IdentNode ident = varNode.getName(); - final String name = ident.getName(); - - final Symbol symbol = findSymbol(lc.getCurrentBlock(), name); - assert ident.getSymbol() == symbol; - - if (init == null) { - // var x; with no init will be treated like a use of x by - // leaveIdentNode unless we remove the name from the localdef list. - removeLocalDef(name); - return end(varNode); - } - - addLocalDef(name); - - assert symbol != null; - - final IdentNode newIdent = (IdentNode)ident.setSymbol(lc, symbol); - - final VarNode newVarNode = varNode.setName(newIdent); - - final boolean isScript = lc.getDefiningFunction(symbol).isProgram(); //see NASHORN-56 - if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) { - // Forbid integers as local vars for now as we have no way to treat them as undefined - newType(symbol, init.getType()); - } else { - newType(symbol, Type.OBJECT); - } - - assert newVarNode.getName().hasType() : newVarNode + " has no type"; - - return end(newVarNode); - } - - @Override - public Node leaveADD(final UnaryNode unaryNode) { - return end(ensureSymbol(arithType(), unaryNode)); - } - - @Override - public Node leaveBIT_NOT(final UnaryNode unaryNode) { - return end(ensureSymbol(Type.INT, unaryNode)); - } - - @Override - public Node leaveDECINC(final UnaryNode unaryNode) { - // @see assignOffset - final Type type = arithType(); - newType(unaryNode.rhs().getSymbol(), type); - return end(ensureSymbol(type, unaryNode)); - } - - @Override - public Node leaveDELETE(final UnaryNode unaryNode) { - final FunctionNode currentFunctionNode = lc.getCurrentFunction(); - final boolean strictMode = currentFunctionNode.isStrict(); - final Expression rhs = unaryNode.rhs(); - final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this); - - Request request = Request.DELETE; - final List args = new ArrayList<>(); - - if (rhs instanceof IdentNode) { - // If this is a declared variable or a function parameter, delete always fails (except for globals). - final String name = ((IdentNode)rhs).getName(); - - final boolean failDelete = strictMode || rhs.getSymbol().isParam() || (rhs.getSymbol().isVar() && !isProgramLevelSymbol(name)); - - if (failDelete && rhs.getSymbol().isThis()) { - return LiteralNode.newInstance(unaryNode, true).accept(this); - } - final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); - - if (!failDelete) { - args.add(compilerConstant(SCOPE)); - } - args.add(literalNode); - args.add(strictFlagNode); - - if (failDelete) { - request = Request.FAIL_DELETE; - } - } else if (rhs instanceof AccessNode) { - final Expression base = ((AccessNode)rhs).getBase(); - final IdentNode property = ((AccessNode)rhs).getProperty(); - - args.add(base); - args.add((Expression)LiteralNode.newInstance(unaryNode, property.getName()).accept(this)); - args.add(strictFlagNode); - - } else if (rhs instanceof IndexNode) { - final IndexNode indexNode = (IndexNode)rhs; - final Expression base = indexNode.getBase(); - final Expression index = indexNode.getIndex(); - - args.add(base); - args.add(index); - args.add(strictFlagNode); - - } else { - return LiteralNode.newInstance(unaryNode, true).accept(this); - } - - final RuntimeNode runtimeNode = new RuntimeNode(unaryNode, request, args); - assert runtimeNode.getSymbol() == unaryNode.getSymbol(); //unary parent constructor should do this - - return leaveRuntimeNode(runtimeNode); - } - - /** - * Is the symbol denoted by the specified name in the current lexical context defined in the program level - * @param name the name of the symbol - * @return true if the symbol denoted by the specified name in the current lexical context defined in the program level. - */ - private boolean isProgramLevelSymbol(final String name) { - for(final Iterator it = lc.getBlocks(); it.hasNext();) { - final Block next = it.next(); - if(next.getExistingSymbol(name) != null) { - return next == lc.getFunctionBody(lc.getOutermostFunction()); - } - } - throw new AssertionError("Couldn't find symbol " + name + " in the context"); - } - - @Override - public Node leaveNEW(final UnaryNode unaryNode) { - return end(ensureSymbol(Type.OBJECT, unaryNode.setRHS(((CallNode)unaryNode.rhs()).setIsNew()))); - } - - @Override - public Node leaveNOT(final UnaryNode unaryNode) { - return end(ensureSymbol(Type.BOOLEAN, unaryNode)); - } - - private IdentNode compilerConstant(CompilerConstants cc) { - return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc)); - } - - /** - * Creates an ident node for an implicit identifier within the function (one not declared in the script source - * code). These identifiers are defined with function's token and finish. - * @param name the name of the identifier - * @return an ident node representing the implicit identifier. - */ - private IdentNode createImplicitIdentifier(final String name) { - final FunctionNode fn = lc.getCurrentFunction(); - return new IdentNode(fn.getToken(), fn.getFinish(), name); - } - - @Override - public Node leaveTYPEOF(final UnaryNode unaryNode) { - final Expression rhs = unaryNode.rhs(); - - List args = new ArrayList<>(); - if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) { - args.add(compilerConstant(SCOPE)); - args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null - } else { - args.add(rhs); - args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' - } - - RuntimeNode runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); - assert runtimeNode.getSymbol() == unaryNode.getSymbol(); - - runtimeNode = (RuntimeNode)leaveRuntimeNode(runtimeNode); - - end(unaryNode); - - return runtimeNode; - } - - @Override - public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { - return end(ensureSymbol(runtimeNode.getRequest().getReturnType(), runtimeNode)); - } - - @Override - public Node leaveSUB(final UnaryNode unaryNode) { - return end(ensureSymbol(arithType(), unaryNode)); - } - - @Override - public Node leaveVOID(final UnaryNode unaryNode) { - return end(ensureSymbol(Type.OBJECT, unaryNode)); - } - - /** - * Add is a special binary, as it works not only on arithmetic, but for - * strings etc as well. - */ - @Override - public Node leaveADD(final BinaryNode binaryNode) { - final Expression lhs = binaryNode.lhs(); - final Expression rhs = binaryNode.rhs(); - - ensureTypeNotUnknown(lhs); - ensureTypeNotUnknown(rhs); - //even if we are adding two known types, this can overflow. i.e. - //int and number -> number. - //int and int are also number though. - //something and object is object - return end(ensureSymbol(Type.widest(arithType(), Type.widest(lhs.getType(), rhs.getType())), binaryNode)); - } - - @Override - public Node leaveAND(final BinaryNode binaryNode) { - return end(ensureSymbol(Type.OBJECT, binaryNode)); - } - - /** - * This is a helper called before an assignment. - * @param binaryNode assignment node - */ - private boolean enterAssignmentNode(final BinaryNode binaryNode) { - start(binaryNode); - - return true; - } - - - /** - * This assign helper is called after an assignment, when all children of - * the assign has been processed. It fixes the types and recursively makes - * sure that everyhing has slots that should have them in the chain. - * - * @param binaryNode assignment node - */ - private Node leaveAssignmentNode(final BinaryNode binaryNode) { - final Expression lhs = binaryNode.lhs(); - final Expression rhs = binaryNode.rhs(); - final Type type; - - if (lhs instanceof IdentNode) { - final Block block = lc.getCurrentBlock(); - final IdentNode ident = (IdentNode)lhs; - final String name = ident.getName(); - final Symbol symbol = findSymbol(block, name); - - if (symbol == null) { - defineSymbol(block, name, IS_GLOBAL); - } else { - maybeForceScope(symbol); - } - - addLocalDef(name); - } - - if (rhs.getType().isNumeric()) { - type = Type.widest(lhs.getType(), rhs.getType()); - } else { - type = Type.OBJECT; //force lhs to be an object if not numeric assignment, e.g. strings too. - } - - newType(lhs.getSymbol(), type); - return end(ensureSymbol(type, binaryNode)); - } - - private boolean isLocal(FunctionNode function, Symbol symbol) { - final FunctionNode definingFn = lc.getDefiningFunction(symbol); - // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local - return definingFn == null || definingFn == function; - } - - @Override - public boolean enterASSIGN(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN(final BinaryNode binaryNode) { - return leaveAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_ADD(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_ADD(final BinaryNode binaryNode) { - final Expression lhs = binaryNode.lhs(); - final Expression rhs = binaryNode.rhs(); - - final Type widest = Type.widest(lhs.getType(), rhs.getType()); - //Type.NUMBER if we can't prove that the add doesn't overflow. todo - return leaveSelfModifyingAssignmentNode(binaryNode, widest.isNumeric() ? Type.NUMBER : Type.OBJECT); - } - - @Override - public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_BIT_AND(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_BIT_OR(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_BIT_XOR(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_DIV(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_DIV(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_MOD(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_MOD(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_MUL(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_MUL(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_SAR(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_SAR(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_SHL(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_SHL(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_SHR(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_SHR(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public boolean enterASSIGN_SUB(final BinaryNode binaryNode) { - return enterAssignmentNode(binaryNode); - } - - @Override - public Node leaveASSIGN_SUB(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode); - } - - @Override - public Node leaveBIT_AND(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.INT)); - } - - @Override - public Node leaveBIT_OR(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.INT)); - } - - @Override - public Node leaveBIT_XOR(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.INT)); - } - - @Override - public Node leaveCOMMARIGHT(final BinaryNode binaryNode) { - return leaveComma(binaryNode, binaryNode.rhs()); - } - - @Override - public Node leaveCOMMALEFT(final BinaryNode binaryNode) { - return leaveComma(binaryNode, binaryNode.lhs()); - } - - private Node leaveComma(final BinaryNode commaNode, final Expression effectiveExpr) { - ensureTypeNotUnknown(effectiveExpr); - return end(ensureSymbol(effectiveExpr.getType(), commaNode)); - } - - @Override - public Node leaveDIV(final BinaryNode binaryNode) { - return leaveBinaryArithmetic(binaryNode); - } - - private Node leaveCmp(final BinaryNode binaryNode) { - ensureTypeNotUnknown(binaryNode.lhs()); - ensureTypeNotUnknown(binaryNode.rhs()); - Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()); - ensureSymbol(widest, binaryNode.lhs()); - ensureSymbol(widest, binaryNode.rhs()); - return end(ensureSymbol(Type.BOOLEAN, binaryNode)); - } - - private Node coerce(final BinaryNode binaryNode, final Type operandType, final Type destType) { - // TODO we currently don't support changing inferred type based on uses, only on - // definitions. we would need some additional logic. We probably want to do that - // in the future, if e.g. a specialized method gets parameter that is only used - // as, say, an int : function(x) { return x & 4711 }, and x is not defined in - // the function. to make this work, uncomment the following two type inferences - // and debug. - //newType(binaryNode.lhs().getSymbol(), operandType); - //newType(binaryNode.rhs().getSymbol(), operandType); - return ensureSymbol(destType, binaryNode); - } - - private Node coerce(final BinaryNode binaryNode, final Type type) { - return coerce(binaryNode, type, type); - } - - //leave a binary node and inherit the widest type of lhs , rhs - private Node leaveBinaryArithmetic(final BinaryNode binaryNode) { - assert !Compiler.shouldUseIntegerArithmetic(); - return end(coerce(binaryNode, Type.NUMBER)); - } - - @Override - public Node leaveEQ(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveEQ_STRICT(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveGE(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveGT(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveIN(final BinaryNode binaryNode) { - return leaveBinaryRuntimeOperator(binaryNode, Request.IN); - } - - @Override - public Node leaveINSTANCEOF(final BinaryNode binaryNode) { - return leaveBinaryRuntimeOperator(binaryNode, Request.INSTANCEOF); - } - - private Node leaveBinaryRuntimeOperator(final BinaryNode binaryNode, final Request request) { - try { - // Don't do a full RuntimeNode.accept, as we don't want to double-visit the binary node operands - return leaveRuntimeNode(new RuntimeNode(binaryNode, request)); - } finally { - end(binaryNode); - } - } - - @Override - public Node leaveLE(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveLT(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveMOD(final BinaryNode binaryNode) { - return leaveBinaryArithmetic(binaryNode); - } - - @Override - public Node leaveMUL(final BinaryNode binaryNode) { - return leaveBinaryArithmetic(binaryNode); - } - - @Override - public Node leaveNE(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveNE_STRICT(final BinaryNode binaryNode) { - return leaveCmp(binaryNode); - } - - @Override - public Node leaveOR(final BinaryNode binaryNode) { - return end(ensureSymbol(Type.OBJECT, binaryNode)); - } - - @Override - public Node leaveSAR(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.INT)); - } - - @Override - public Node leaveSHL(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.INT)); - } - - @Override - public Node leaveSHR(final BinaryNode binaryNode) { - return end(coerce(binaryNode, Type.LONG)); - } - - @Override - public Node leaveSUB(final BinaryNode binaryNode) { - return leaveBinaryArithmetic(binaryNode); - } - - @Override - public Node leaveForNode(final ForNode forNode) { - if (forNode.isForIn()) { - forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.typeFor(ITERATOR_PREFIX.type()))); //NASHORN-73 - /* - * Iterators return objects, so we need to widen the scope of the - * init variable if it, for example, has been assigned double type - * see NASHORN-50 - */ - newType(forNode.getInit().getSymbol(), Type.OBJECT); - } - - end(forNode); - - return forNode; - } - - @Override - public Node leaveTernaryNode(final TernaryNode ternaryNode) { - final Expression trueExpr = ternaryNode.getTrueExpression(); - final Expression falseExpr = ternaryNode.getFalseExpression(); - - ensureTypeNotUnknown(trueExpr); - ensureTypeNotUnknown(falseExpr); - - final Type type = widestReturnType(trueExpr.getType(), falseExpr.getType()); - return end(ensureSymbol(type, ternaryNode)); - } - - /** - * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to - * anything other than Object. Also, widening a numeric type to an object type must widen to Object proper and not - * any more specific subclass (e.g. widest of int/long/double and String is Object). - * @param t1 type 1 - * @param t2 type 2 - * @return wider of t1 and t2, except if one is boolean and the other is neither boolean nor unknown, or if one is - * numeric and the other is neither numeric nor unknown in which case {@code Type.OBJECT} is returned. - */ - private static Type widestReturnType(final Type t1, final Type t2) { - if (t1.isUnknown()) { - return t2; - } else if (t2.isUnknown()) { - return t1; - } else if (t1.isBoolean() != t2.isBoolean() || t1.isNumeric() != t2.isNumeric()) { - return Type.OBJECT; - } - return Type.widest(t1, t2); - } - - private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) { - final Class type = cc.type(); - // Must not call this method for constants with no explicit types; use the one with (..., Type) signature instead. - assert type != null; - initCompileConstant(cc, block, flags, Type.typeFor(type)); - } - - private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags, final Type type) { - final Symbol symbol = defineSymbol(block, cc.symbolName(), flags); - symbol.setTypeOverride(type); - symbol.setNeedsSlot(true); - } - - /** - * Initialize parameters for function node. This may require specializing - * types if a specialization profile is known - * - * @param functionNode the function node - */ - private void initParameters(final FunctionNode functionNode, final Block body) { - int pos = 0; - for (final IdentNode param : functionNode.getParameters()) { - addLocalDef(param.getName()); - - final Type callSiteParamType = functionNode.getHints().getParameterType(pos); - int flags = IS_PARAM; - if (callSiteParamType != null) { - LOG.info("Param ", param, " has a callsite type ", callSiteParamType, ". Using that."); - flags |= Symbol.IS_SPECIALIZED_PARAM; - } - - final Symbol paramSymbol = defineSymbol(body, param.getName(), flags); - assert paramSymbol != null; - - newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType); - - LOG.info("Initialized param ", pos, "=", paramSymbol); - pos++; - } - - } - - /** - * This has to run before fix assignment types, store any type specializations for - * paramters, then turn then to objects for the generic version of this method - * - * @param functionNode functionNode - */ - private FunctionNode finalizeParameters(final FunctionNode functionNode) { - final List newParams = new ArrayList<>(); - final boolean isVarArg = functionNode.isVarArg(); - final int nparams = functionNode.getParameters().size(); - - int specialize = 0; - int pos = 0; - for (final IdentNode param : functionNode.getParameters()) { - final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName()); - assert paramSymbol != null; - assert paramSymbol.isParam(); - newParams.add((IdentNode)param.setSymbol(lc, paramSymbol)); - - assert paramSymbol != null; - Type type = functionNode.getHints().getParameterType(pos); - if (type == null) { - type = Type.OBJECT; - } - - // if we know that a parameter is only used as a certain type throughout - // this function, we can tell the runtime system that no matter what the - // call site is, use this information: - // we also need more than half of the parameters to be specializable - // for the heuristic to be worth it, and we need more than one use of - // the parameter to consider it, i.e. function(x) { call(x); } doens't count - if (paramSymbol.getUseCount() > 1 && !paramSymbol.getSymbolType().isObject()) { - LOG.finest("Parameter ", param, " could profit from specialization to ", paramSymbol.getSymbolType()); - specialize++; - } - - newType(paramSymbol, Type.widest(type, paramSymbol.getSymbolType())); - - // parameters should not be slots for a function that uses variable arity signature - if (isVarArg) { - paramSymbol.setNeedsSlot(false); - } - - pos++; - } - - FunctionNode newFunctionNode = functionNode; - - if (nparams == 0 || (specialize * 2) < nparams) { - newFunctionNode = newFunctionNode.clearSnapshot(lc); - } - - return newFunctionNode.setParameters(lc, newParams); - } - - /** - * Move any properties from a global map into the scope of this method - * @param block the function node body for which to init scope vars - */ - private void initFromPropertyMap(final Block block) { - // For a script, add scope symbols as defined in the property map - - final PropertyMap map = Context.getGlobalMap(); - - for (final Property property : map.getProperties()) { - final String key = property.getKey(); - final Symbol symbol = defineSymbol(block, key, IS_GLOBAL); - newType(symbol, Type.OBJECT); - LOG.info("Added global symbol from property map ", symbol); - } - } - - private static void ensureTypeNotUnknown(final Expression node) { - - final Symbol symbol = node.getSymbol(); - - LOG.info("Ensure type not unknown for: ", symbol); - - /* - * Note that not just unknowns, but params need to be blown - * up to objects, because we can have something like - * - * function f(a) { - * var b = ~a; //b and a are inferred to be int - * return b; - * } - * - * In this case, it would be correct to say that "if you have - * an int at the callsite, just pass it". - * - * However - * - * function f(a) { - * var b = ~a; //b and a are inferred to be int - * return b == 17; //b is still inferred to be int. - * } - * - * can be called with f("17") and if we assume that b is an - * int and don't blow it up to an object in the comparison, we - * are screwed. I hate JavaScript. - * - * This check has to be done for any operation that might take - * objects as parameters, for example +, but not *, which is known - * to coerce types into doubles - */ - if (node.getType().isUnknown() || (symbol.isParam() && !symbol.isSpecializedParam())) { - newType(symbol, Type.OBJECT); - symbol.setCanBeUndefined(); - } - } - - private static Symbol pseudoSymbol(final String name) { - return new Symbol(name, 0, Type.OBJECT); - } - - private Symbol exceptionSymbol() { - return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(EXCEPTION_PREFIX.type())); - } - - /** - * Return the type that arithmetic ops should use. Until we have implemented better type - * analysis (range based) or overflow checks that are fast enough for int arithmetic, - * this is the number type - * @return the arithetic type - */ - private static Type arithType() { - return Compiler.shouldUseIntegerArithmetic() ? Type.INT : Type.NUMBER; - } - - /** - * If types have changed, we can have failed to update vars. For example - * - * var x = 17; //x is int - * x = "apa"; //x is object. This will be converted fine - * - * @param functionNode - */ - private FunctionNode finalizeTypes(final FunctionNode functionNode) { - final Set changed = new HashSet<>(); - FunctionNode currentFunctionNode = functionNode; - do { - changed.clear(); - final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor(new LexicalContext()) { - - private Expression widen(final Expression node, final Type to) { - if (node instanceof LiteralNode) { - return node; - } - Type from = node.getType(); - if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) { - LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to); - Symbol symbol = node.getSymbol(); - if (symbol.isShared() && symbol.wouldChangeType(to)) { - symbol = temporarySymbols.getTypedTemporarySymbol(to); - } - newType(symbol, to); - final Expression newNode = node.setSymbol(lc, symbol); - changed.add(newNode); - return newNode; - } - return node; - } - - @Override - public boolean enterFunctionNode(final FunctionNode node) { - return !node.isLazy(); - } - - // - // Eg. - // - // var d = 17; - // var e; - // e = d; //initially typed as int for node type, should retype as double - // e = object; - // - // var d = 17; - // var e; - // e -= d; //initially type number, should number remain with a final conversion supplied by Store. ugly, but the computation result of the sub is numeric - // e = object; - // - @SuppressWarnings("fallthrough") - @Override - public Node leaveBinaryNode(final BinaryNode binaryNode) { - final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()); - BinaryNode newBinaryNode = binaryNode; - - if (isAdd(binaryNode)) { - newBinaryNode = (BinaryNode)widen(newBinaryNode, widest); - if (newBinaryNode.getType().isObject() && !isAddString(newBinaryNode)) { - return new RuntimeNode(newBinaryNode, Request.ADD); - } - } else if (binaryNode.isComparison()) { - final Expression lhs = newBinaryNode.lhs(); - final Expression rhs = newBinaryNode.rhs(); - - Type cmpWidest = Type.widest(lhs.getType(), rhs.getType()); - - boolean newRuntimeNode = false, finalized = false; - switch (newBinaryNode.tokenType()) { - case EQ_STRICT: - case NE_STRICT: - if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) { - newRuntimeNode = true; - cmpWidest = Type.OBJECT; - finalized = true; - } - //fallthru - default: - if (newRuntimeNode || cmpWidest.isObject()) { - return new RuntimeNode(newBinaryNode, Request.requestFor(binaryNode)).setIsFinal(finalized); - } - break; - } - - return newBinaryNode; - } else { - if (!binaryNode.isAssignment() || binaryNode.isSelfModifying()) { - return newBinaryNode; - } - checkThisAssignment(binaryNode); - newBinaryNode = newBinaryNode.setLHS(widen(newBinaryNode.lhs(), widest)); - newBinaryNode = (BinaryNode)widen(newBinaryNode, widest); - } - - return newBinaryNode; - - } - - private boolean isAdd(final Node node) { - return node.isTokenType(TokenType.ADD); - } - - /** - * Determine if the outcome of + operator is a string. - * - * @param node Node to test. - * @return true if a string result. - */ - private boolean isAddString(final Node node) { - if (node instanceof BinaryNode && isAdd(node)) { - final BinaryNode binaryNode = (BinaryNode)node; - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); - - return isAddString(lhs) || isAddString(rhs); - } - - return node instanceof LiteralNode && ((LiteralNode)node).isString(); - } - - private void checkThisAssignment(final BinaryNode binaryNode) { - if (binaryNode.isAssignment()) { - if (binaryNode.lhs() instanceof AccessNode) { - final AccessNode accessNode = (AccessNode) binaryNode.lhs(); - - if (accessNode.getBase().getSymbol().isThis()) { - lc.getCurrentFunction().addThisProperty(accessNode.getProperty().getName()); - } - } - } - } - }); - lc.replace(currentFunctionNode, newFunctionNode); - currentFunctionNode = newFunctionNode; - } while (!changed.isEmpty()); - - return currentFunctionNode; - } - - private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode) { - return leaveSelfModifyingAssignmentNode(binaryNode, binaryNode.getWidestOperationType()); - } - - private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode, final Type destType) { - //e.g. for -=, Number, no wider, destType (binaryNode.getWidestOperationType()) is the coerce type - final Expression lhs = binaryNode.lhs(); - - newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType - - return end(ensureSymbol(destType, binaryNode)); - } - - private Expression ensureSymbol(final Type type, final Expression expr) { - LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type); - return temporarySymbols.ensureSymbol(lc, type, expr); - } - - private Symbol newInternal(final String name, final Type type) { - final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL); - iter.setType(type); // NASHORN-73 - return iter; - } - - private static void newType(final Symbol symbol, final Type type) { - final Type oldType = symbol.getSymbolType(); - symbol.setType(type); - - if (symbol.getSymbolType() != oldType) { - LOG.info("New TYPE ", type, " for ", symbol," (was ", oldType, ")"); - } - - if (symbol.isParam()) { - symbol.setType(type); - LOG.info("Param type change ", symbol); - } - } - - private void pushLocalsFunction() { - localDefs.push(new HashSet()); - localUses.push(new HashSet()); - } - - private void pushLocalsBlock() { - localDefs.push(new HashSet<>(localDefs.peek())); - localUses.push(new HashSet<>(localUses.peek())); - } - - private void popLocals() { - localDefs.pop(); - localUses.pop(); - } - - private boolean isLocalDef(final String name) { - return localDefs.peek().contains(name); - } - - private void addLocalDef(final String name) { - LOG.info("Adding local def of symbol: '", name, "'"); - localDefs.peek().add(name); - } - - private void removeLocalDef(final String name) { - LOG.info("Removing local def of symbol: '", name, "'"); - localDefs.peek().remove(name); - } - - private boolean isLocalUse(final String name) { - return localUses.peek().contains(name); - } - - private void addLocalUse(final String name) { - LOG.info("Adding local use of symbol: '", name, "'"); - localUses.peek().add(name); - } - - /** - * Pessimistically promote all symbols in current function node to Object types - * This is done when the function contains unevaluated black boxes such as - * lazy sub-function nodes that have not been compiled. - * - * @param body body for the function node we are leaving - */ - private static void objectifySymbols(final Block body) { - body.accept(new NodeVisitor(new LexicalContext()) { - private void toObject(final Block block) { - for (final Symbol symbol : block.getSymbols()) { - if (!symbol.isTemp()) { - newType(symbol, Type.OBJECT); - } - } - } - - @Override - public boolean enterBlock(final Block block) { - toObject(block); - return true; - } - - @Override - public boolean enterFunctionNode(final FunctionNode node) { - return false; - } - }); - } - - private static String name(final Node node) { - final String cn = node.getClass().getName(); - int lastDot = cn.lastIndexOf('.'); - if (lastDot == -1) { - return cn; - } - return cn.substring(lastDot + 1); - } - - private boolean start(final Node node) { - return start(node, true); - } - - private boolean start(final Node node, final boolean printNode) { - if (DEBUG) { - final StringBuilder sb = new StringBuilder(); - - sb.append("[ENTER "). - append(name(node)). - append("] "). - append(printNode ? node.toString() : ""). - append(" in '"). - append(lc.getCurrentFunction().getName()). - append("'"); - LOG.info(sb); - LOG.indent(); - } - - return true; - } - - private T end(final T node) { - return end(node, true); - } - - private T end(final T node, final boolean printNode) { - if(node instanceof Statement) { - // If we're done with a statement, all temporaries can be reused. - temporarySymbols.reuse(); - } - if (DEBUG) { - final StringBuilder sb = new StringBuilder(); - - sb.append("[LEAVE "). - append(name(node)). - append("] "). - append(printNode ? node.toString() : ""). - append(" in '"). - append(lc.getCurrentFunction().getName()). - append('\''); - - if (node instanceof Expression) { - final Symbol symbol = ((Expression)node).getSymbol(); - if (symbol == null) { - sb.append(" "); - } else { - sb.append(" '); - } - } - - LOG.unindent(); - LOG.info(sb); - } - - return node; - } -} diff --git a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java index ad9bdb07436..5c8f96454ef 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java @@ -32,10 +32,10 @@ import static jdk.nashorn.internal.codegen.Condition.LE; import static jdk.nashorn.internal.codegen.Condition.LT; import static jdk.nashorn.internal.codegen.Condition.NE; -import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Expression; -import jdk.nashorn.internal.ir.TernaryNode; +import jdk.nashorn.internal.ir.JoinPredecessorExpression; +import jdk.nashorn.internal.ir.LocalVariableConversion; import jdk.nashorn.internal.ir.UnaryNode; /** @@ -57,7 +57,7 @@ final class BranchOptimizer { } private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) { - final Expression rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.getExpression(); switch (unaryNode.tokenType()) { case NOT: @@ -71,13 +71,7 @@ final class BranchOptimizer { break; } - // convert to boolean - codegen.load(unaryNode, Type.BOOLEAN); - if (state) { - method.ifne(label); - } else { - method.ifeq(label); - } + loadTestAndJump(unaryNode, label, state); } private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) { @@ -88,86 +82,97 @@ final class BranchOptimizer { case AND: if (state) { final Label skip = new Label("skip"); - branchOptimizer(lhs, skip, false); - branchOptimizer(rhs, label, true); + optimizeLogicalOperand(lhs, skip, false, false); + optimizeLogicalOperand(rhs, label, true, true); method.label(skip); } else { - branchOptimizer(lhs, label, false); - branchOptimizer(rhs, label, false); + optimizeLogicalOperand(lhs, label, false, false); + optimizeLogicalOperand(rhs, label, false, true); } return; case OR: if (state) { - branchOptimizer(lhs, label, true); - branchOptimizer(rhs, label, true); + optimizeLogicalOperand(lhs, label, true, false); + optimizeLogicalOperand(rhs, label, true, true); } else { final Label skip = new Label("skip"); - branchOptimizer(lhs, skip, true); - branchOptimizer(rhs, label, false); + optimizeLogicalOperand(lhs, skip, true, false); + optimizeLogicalOperand(rhs, label, false, true); method.label(skip); } return; case EQ: case EQ_STRICT: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); + codegen.loadBinaryOperands(binaryNode); method.conditionalJump(state ? EQ : NE, true, label); return; case NE: case NE_STRICT: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); + codegen.loadBinaryOperands(binaryNode); method.conditionalJump(state ? NE : EQ, true, label); return; case GE: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); - method.conditionalJump(state ? GE : LT, !state, label); + codegen.loadBinaryOperands(binaryNode); + method.conditionalJump(state ? GE : LT, false, label); return; case GT: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); - method.conditionalJump(state ? GT : LE, !state, label); + codegen.loadBinaryOperands(binaryNode); + method.conditionalJump(state ? GT : LE, false, label); return; case LE: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); - method.conditionalJump(state ? LE : GT, state, label); + codegen.loadBinaryOperands(binaryNode); + method.conditionalJump(state ? LE : GT, true, label); return; case LT: - codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType())); - method.conditionalJump(state ? LT : GE, state, label); + codegen.loadBinaryOperands(binaryNode); + method.conditionalJump(state ? LT : GE, true, label); return; default: break; } - codegen.load(binaryNode, Type.BOOLEAN); - if (state) { - method.ifne(label); - } else { - method.ifeq(label); - } + loadTestAndJump(binaryNode, label, state); } + private void optimizeLogicalOperand(final Expression expr, final Label label, final boolean state, final boolean isRhs) { + final JoinPredecessorExpression jpexpr = (JoinPredecessorExpression)expr; + if(LocalVariableConversion.hasLiveConversion(jpexpr)) { + final Label after = new Label("after"); + branchOptimizer(jpexpr.getExpression(), after, !state); + method.beforeJoinPoint(jpexpr); + method._goto(label); + method.label(after); + if(isRhs) { + method.beforeJoinPoint(jpexpr); + } + } else { + branchOptimizer(jpexpr.getExpression(), label, state); + } + } private void branchOptimizer(final Expression node, final Label label, final boolean state) { - if (!(node instanceof TernaryNode)) { - - if (node instanceof BinaryNode) { - branchOptimizer((BinaryNode)node, label, state); - return; - } - - if (node instanceof UnaryNode) { - branchOptimizer((UnaryNode)node, label, state); - return; - } + if (node instanceof BinaryNode) { + branchOptimizer((BinaryNode)node, label, state); + return; } - codegen.load(node, Type.BOOLEAN); + if (node instanceof UnaryNode) { + branchOptimizer((UnaryNode)node, label, state); + return; + } + + loadTestAndJump(node, label, state); + } + + private void loadTestAndJump(final Expression node, final Label label, final boolean state) { + codegen.loadExpressionAsBoolean(node); if (state) { method.ifne(label); } else { diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java index 09c6a0651cb..386effdc120 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java @@ -49,25 +49,27 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; import static jdk.nashorn.internal.codegen.CompilerConstants.className; import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; -import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; +import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; -import java.util.Arrays; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.EnumSet; import java.util.HashSet; import java.util.Set; - -import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.SplitNode; +import jdk.nashorn.internal.ir.debug.NashornClassReader; +import jdk.nashorn.internal.ir.debug.NashornTextifier; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptEnvironment; +import jdk.nashorn.internal.runtime.RewriteException; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Source; @@ -106,6 +108,8 @@ import jdk.nashorn.internal.runtime.Source; * @see Compiler */ public class ClassEmitter implements Emitter { + /** Default flags for class generation - public class */ + private static final EnumSet DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC); /** Sanity check flag - have we started on a class? */ private boolean classStarted; @@ -123,10 +127,7 @@ public class ClassEmitter implements Emitter { protected final ClassWriter cw; /** The script environment */ - protected final ScriptEnvironment env; - - /** Default flags for class generation - oublic class */ - private static final EnumSet DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC); + protected final Context context; /** Compile unit class name. */ private String unitClassName; @@ -141,10 +142,8 @@ public class ClassEmitter implements Emitter { * @param env script environment * @param cw ASM classwriter */ - private ClassEmitter(final ScriptEnvironment env, final ClassWriter cw) { - assert env != null; - - this.env = env; + private ClassEmitter(final Context context, final ClassWriter cw) { + this.context = context; this.cw = cw; this.methodsStarted = new HashSet<>(); } @@ -157,8 +156,8 @@ public class ClassEmitter implements Emitter { * @param superClassName super class name for class * @param interfaceNames names of interfaces implemented by this class, or null if none */ - ClassEmitter(final ScriptEnvironment env, final String className, final String superClassName, final String... interfaceNames) { - this(env, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); + ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) { + this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames); } @@ -170,8 +169,8 @@ public class ClassEmitter implements Emitter { * @param unitClassName Compile unit class name. * @param strictMode Should we generate this method in strict mode */ - ClassEmitter(final ScriptEnvironment env, final String sourceName, final String unitClassName, final boolean strictMode) { - this(env, + ClassEmitter(final Context context, final String sourceName, final String unitClassName, final boolean strictMode) { + this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) { private static final String OBJECT_CLASS = "java/lang/Object"; @@ -197,6 +196,10 @@ public class ClassEmitter implements Emitter { defineCommonStatics(strictMode); } + Context getContext() { + return context; + } + /** * Returns the name of the compile unit class name. * @return the name of the compile unit class name. @@ -274,51 +277,51 @@ public class ClassEmitter implements Emitter { } // $getXXXX$array - get the ith entry from the constants table and cast to XXXX[]. - for (final Class cls : constantMethodNeeded) { - if (cls.isArray()) { - defineGetArrayMethod(cls); + for (final Class clazz : constantMethodNeeded) { + if (clazz.isArray()) { + defineGetArrayMethod(clazz); } } } /** - * Constructs a primitive specific method for getting the ith entry from the constants table and cast. - * @param cls Array class. + * Constructs a primitive specific method for getting the ith entry from the constants table as an array. + * @param clazz Array class. */ - private void defineGetArrayMethod(final Class cls) { + private void defineGetArrayMethod(final Class clazz) { assert unitClassName != null; - final String methodName = getArrayMethodName(cls); - final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, cls, int.class); + final String methodName = getArrayMethodName(clazz); + final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, clazz, int.class); getArrayMethod.begin(); getArrayMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor()) .load(Type.INT, 0) .arrayload() - .checkcast(cls) - .dup() - .arraylength() - .invoke(staticCallNoLookup(Arrays.class, "copyOf", cls, cls, int.class)) + .checkcast(clazz) + .invoke(virtualCallNoLookup(clazz, "clone", Object.class)) + .checkcast(clazz) ._return(); getArrayMethod.end(); } + /** * Generate the name of a get array from constant pool method. - * @param cls Name of array class. + * @param clazz Name of array class. * @return Method name. */ - static String getArrayMethodName(final Class cls) { - assert cls.isArray(); - return GET_ARRAY_PREFIX.symbolName() + cls.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName(); + static String getArrayMethodName(final Class clazz) { + assert clazz.isArray(); + return GET_ARRAY_PREFIX.symbolName() + clazz.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName(); } /** * Ensure a get constant method is issued for the class. - * @param cls Class of constant. + * @param clazz Class of constant. */ - void needGetConstantMethod(final Class cls) { - constantMethodNeeded.add(cls); + void needGetConstantMethod(final Class clazz) { + constantMethodNeeded.add(clazz); } /** @@ -376,16 +379,19 @@ public class ClassEmitter implements Emitter { static String disassemble(final byte[] bytecode) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (final PrintWriter pw = new PrintWriter(baos)) { - new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0); + final NashornClassReader cr = new NashornClassReader(bytecode); + final Context ctx = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Context run() { + return Context.getContext(); + } + }); + final TraceClassVisitor tcv = new TraceClassVisitor(null, new NashornTextifier(ctx.getEnv(), cr), pw); + cr.accept(tcv, 0); } - return new String(baos.toByteArray()); - } - /** - * @return env used for class emission - */ - ScriptEnvironment getEnv() { - return env; + final String str = new String(baos.toByteArray()); + return str; } /** @@ -475,16 +481,35 @@ public class ClassEmitter implements Emitter { * @return method emitter to use for weaving this method */ MethodEmitter method(final FunctionNode functionNode) { + final FunctionSignature signature = new FunctionSignature(functionNode); final MethodVisitor mv = cw.visitMethod( ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0), functionNode.getName(), - new FunctionSignature(functionNode).toString(), + signature.toString(), null, null); return new MethodEmitter(this, mv, functionNode); } + /** + * Add a new method to the class, representing a rest-of version of the function node + * + * @param functionNode the function node to generate a method for + * @return method emitter to use for weaving this method + */ + MethodEmitter restOfMethod(final FunctionNode functionNode) { + final MethodVisitor mv = cw.visitMethod( + ACC_PUBLIC | ACC_STATIC, + functionNode.getName(), + Type.getMethodDescriptor(functionNode.getReturnType().getTypeClass(), RewriteException.class), + null, + null); + + return new MethodEmitter(this, mv, functionNode); + } + + /** * Start generating the method in the class * @@ -636,7 +661,7 @@ public class ClassEmitter implements Emitter { } } - private MethodVisitor methodVisitor(EnumSet flags, final String methodName, final Class rtype, final Class... ptypes) { + private MethodVisitor methodVisitor(final EnumSet flags, final String methodName, final Class rtype, final Class... ptypes) { return cw.visitMethod(Flag.getValue(flags), methodName, methodDescriptor(rtype, ptypes), null, null); } diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java index 882846c6334..21b51b334c3 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -29,6 +29,7 @@ import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE; import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC; import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE; +import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION; import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP; import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING; import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX; @@ -45,25 +46,39 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; +import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT; import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; -import static jdk.nashorn.internal.ir.Symbol.IS_TEMP; +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; +import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE; +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; +import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; import java.io.PrintWriter; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.Collections; +import java.util.Deque; import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.function.Supplier; +import jdk.nashorn.internal.IntDeque; import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; -import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode; import jdk.nashorn.internal.codegen.types.ArrayType; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; @@ -86,14 +101,20 @@ import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IfNode; import jdk.nashorn.internal.ir.IndexNode; +import jdk.nashorn.internal.ir.JoinPredecessor; +import jdk.nashorn.internal.ir.JoinPredecessorExpression; +import jdk.nashorn.internal.ir.LabelNode; import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LexicalContextNode; import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; +import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; +import jdk.nashorn.internal.ir.LocalVariableConversion; import jdk.nashorn.internal.ir.LoopNode; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.ObjectNode; +import jdk.nashorn.internal.ir.Optimistic; import jdk.nashorn.internal.ir.PropertyNode; import jdk.nashorn.internal.ir.ReturnNode; import jdk.nashorn.internal.ir.RuntimeNode; @@ -117,20 +138,25 @@ import jdk.nashorn.internal.parser.Lexer.RegexToken; import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.Debug; -import jdk.nashorn.internal.runtime.DebugLogger; import jdk.nashorn.internal.runtime.ECMAException; import jdk.nashorn.internal.runtime.JSType; -import jdk.nashorn.internal.runtime.Property; +import jdk.nashorn.internal.runtime.OptimisticReturnFilters; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; +import jdk.nashorn.internal.runtime.RewriteException; import jdk.nashorn.internal.runtime.Scope; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.Source; import jdk.nashorn.internal.runtime.Undefined; +import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import jdk.nashorn.internal.runtime.logging.Loggable; +import jdk.nashorn.internal.runtime.logging.Logger; +import jdk.nashorn.internal.runtime.options.Options; /** * This is the lowest tier of the code generator. It takes lowered ASTs emitted @@ -151,11 +177,34 @@ import jdk.nashorn.internal.runtime.linker.LinkerCallSite; * The CodeGenerator visits nodes only once, tags them as resolved and emits * bytecode for them. */ -final class CodeGenerator extends NodeOperatorVisitor { +@Logger(name="codegen") +final class CodeGenerator extends NodeOperatorVisitor implements Loggable { + + private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class); private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class); - private static final String SCRIPTFUNCTION_IMPL_OBJECT = Type.getInternalName(ScriptFunctionImpl.class); + private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class); + private static final Type SCRIPTFUNCTION_IMPL_TYPE = Type.typeFor(ScriptFunction.class); + + private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class, + "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class); + private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class, + "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class); + + private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, + "ensureInt", int.class, Object.class, int.class); + private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, + "ensureLong", long.class, Object.class, int.class); + private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, + "ensureNumber", double.class, Object.class, int.class); + + private static final Class ITERATOR_CLASS = Iterator.class; + static { + assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type(); + } + private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS); + private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type()); /** Constant data & installation. The only reason the compiler keeps this is because it is assigned * by reflection in class installation */ @@ -180,22 +229,54 @@ final class CodeGenerator extends NodeOperatorVisitor emittedMethods = new HashSet<>(); + // Function Id -> ContinuationInfo. Used by compilation of rest-of function only. + private final Map fnIdToContinuationInfo = new HashMap<>(); + + private final Deque