# HG changeset patch # User xiomara # Date 1183679253 0 # Node ID 64ed597c0ad3b8b87d7d7c40411ba216e72c04a5 # Parent 16f2b6c91171e38b45cb12629f5d0d55a8324f35 [svn] Load openjdk/jdk7/b15 into jdk/trunk. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/build/linux/makefiles/vm.make --- a/hotspot/build/linux/makefiles/vm.make Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/build/linux/makefiles/vm.make Thu Jul 05 23:47:33 2007 +0000 @@ -138,6 +138,8 @@ rm -f $@ cat $^ > $@ +STATIC_CXX = true + ifeq ($(LINK_INTO),AOUT) LIBJVM.o = LIBJVM_MAPFILE = @@ -151,8 +153,14 @@ # JVM is statically linked with libgcc[_s] and libstdc++; this is needed to # get around library dependency and compatibility issues. Must use gcc not # g++ to link. - LFLAGS_VM += $(STATIC_LIBGCC) - LIBS_VM += $(STATIC_STDCXX) $(LIBS) + ifeq ($(STATIC_CXX), true) + LFLAGS_VM += $(STATIC_LIBGCC) + LIBS_VM += $(STATIC_STDCXX) + else + LIBS_VM += -lstdc++ + endif + + LIBS_VM += $(LIBS) endif LINK_VM = $(LINK_LIB.c) diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/build/solaris/makefiles/dtrace.make --- a/hotspot/build/solaris/makefiles/dtrace.make Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/build/solaris/makefiles/dtrace.make Thu Jul 05 23:47:33 2007 +0000 @@ -178,13 +178,17 @@ # command, and libgenerateJvmOffsets.so depends on LIBJVM.o, 'make' will # think it needs to rebuild libgenerateJvmOffsets.so and thus JvmOffsets* # files, but it doesn't, so we touch the necessary files to prevent later - # recompilation. But, we can't touch the *.h files: This rule depends + # recompilation. Note: we only touch the necessary files if they already + # exist in order to close a race where an empty file can be created + # before the real build rule is executed. + # But, we can't touch the *.h files: This rule depends # on them, and that would cause an infinite cycle of rebuilding. # Neither the *.h or *.ccp files need to be touched, since they have # rules which do not update them when the generator file has not # changed their contents. - $(QUIETLY) touch lib$(GENOFFS).so $(GENOFFS) - $(QUIETLY) touch $(JVMOFFS.o) + $(QUIETLY) if [ -f lib$(GENOFFS).so ]; then touch lib$(GENOFFS).so; fi + $(QUIETLY) if [ -f $(GENOFFS) ]; then touch $(GENOFFS); fi + $(QUIETLY) if [ -f $(JVMOFFS.o) ]; then touch $(JVMOFFS.o); fi .PHONY: dtraceCheck diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/amd64.ad --- a/hotspot/src/cpu/amd64/vm/amd64.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/amd64.ad Thu Jul 05 23:47:33 2007 +0000 @@ -1807,8 +1807,8 @@ // static stub relocation stores the instruction address of the call __ relocate(static_stub_Relocation::spec(mark), RELOC_IMM64); // static stub relocation also tags the methodOop in the code-stream. - __ movq(rbx, (jobject) NULL); // method is zapped till fixup time - __ jmp(__ pc(), relocInfo::runtime_call_type); // jmp entry + __ movoop(rbx, (jobject) NULL); // method is zapped till fixup time + __ jump(RuntimeAddress(__ pc())); // Update current stubs pointer and restore code_end. __ end_a_stub(); @@ -1847,8 +1847,9 @@ uint code_size = cbuf.code_size(); #endif masm.cmpq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); - masm.jcc(Assembler::notEqual, - SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); + + masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + /* WARNING these NOPs are critical so that verified entry point is properly aligned for patching by NativeJump::patch_verified_entry() */ int nops_cnt = 1; @@ -1888,7 +1889,7 @@ __ start_a_stub(size_exception_handler()); if (base == NULL) return 0; // CodeBuffer::expand failed int offset = __ offset(); - __ jmp(OptoRuntime::exception_blob()->instructions_begin(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(OptoRuntime::exception_blob()->instructions_begin())); assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); __ end_a_stub(); return offset; @@ -1920,8 +1921,8 @@ __ call(next, relocInfo::none); // reloc none is fine since it is a disp32 __ bind(next); // adjust it so it matches "the_pc" - __ subq(Address(rsp), __ offset() - offset); - __ jmp(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type); + __ subq(Address(rsp, 0), __ offset() - offset); + __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); __ end_a_stub(); return offset; @@ -2525,8 +2526,8 @@ __ cmpq(Rrax, Rrsi); __ jcc(Assembler::equal, hit); #ifndef PRODUCT - __ movq(Rrcx, (intptr_t) &SharedRuntime::_partial_subtype_ctr); - __ incrementl(Address(Rrcx)); + __ lea(Rrcx, ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); + __ incrementl(Address(Rrcx, 0)); #endif //PRODUCT __ movq(Rrdi, Address(Rrsi, sizeof(oopDesc) + @@ -2868,8 +2869,16 @@ Register dest_reg = as_Register($dest$$reg); address table_base = masm.address_table_constant(_index2label); - masm.leaq(dest_reg, Address(table_base, relocInfo::internal_word_type)); - masm.jmp(Address(dest_reg, switch_reg, Address::times_1)); + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, Address::times_1); + // ArrayAddress dispatch(table, index); + + Address dispatch(dest_reg, switch_reg, Address::times_1); + + masm.lea(dest_reg, InternalAddress(table_base)); + masm.jmp(dispatch); %} enc_class jump_enc_addr(rRegL switch_val, immI2 shift, immL32 offset, rRegI dest) %{ @@ -2879,8 +2888,16 @@ Register dest_reg = as_Register($dest$$reg); address table_base = masm.address_table_constant(_index2label); - masm.leaq(dest_reg, Address(table_base, relocInfo::internal_word_type)); - masm.jmp(Address(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant)); + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); + // ArrayAddress dispatch(table, index); + + Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant, (int)$offset$$constant); + + masm.lea(dest_reg, InternalAddress(table_base)); + masm.jmp(dispatch); %} enc_class jump_enc_offset(rRegL switch_val, immI2 shift, rRegI dest) %{ @@ -2890,8 +2907,16 @@ Register dest_reg = as_Register($dest$$reg); address table_base = masm.address_table_constant(_index2label); - masm.leaq(dest_reg, Address(table_base, relocInfo::internal_word_type)); - masm.jmp(Address(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant)); + // We could use jump(ArrayAddress) except that the macro assembler needs to use r10 + // to do that and the compiler is using that register as one it can allocate. + // So we build it all by hand. + // Address index(noreg, switch_reg, (Address::ScaleFactor)$shift$$constant); + // ArrayAddress dispatch(table, index); + + Address dispatch(dest_reg, switch_reg, (Address::ScaleFactor)$shift$$constant); + masm.lea(dest_reg, InternalAddress(table_base)); + masm.jmp(dispatch); + %} enc_class lock_prefix() @@ -3368,11 +3393,11 @@ objReg != scrReg && tmpReg != scrReg, "invariant") ; if (_counters != NULL) { - masm.atomic_incl(Address((address) _counters->total_entry_count_addr(), relocInfo::none)); + masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); } if (EmitSync & 1) { - masm.movq (Address(boxReg), intptr_t(markOopDesc::unused_mark())) ; - masm.cmpq (rsp, 0) ; + masm.movptr (Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())) ; + masm.cmpq (rsp, 0) ; } else if (EmitSync & 2) { Label DONE_LABEL; @@ -3381,25 +3406,25 @@ masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); } masm.movl(tmpReg, 0x1); - masm.orq(tmpReg, Address(objReg)); - masm.movq(Address(boxReg), tmpReg); + masm.orq(tmpReg, Address(objReg, 0)); + masm.movq(Address(boxReg, 0), tmpReg); if (os::is_MP()) { masm.lock(); } - masm.cmpxchgq(boxReg, Address(objReg)); // Updates tmpReg + masm.cmpxchgq(boxReg, Address(objReg, 0)); // Updates tmpReg masm.jcc(Assembler::equal, DONE_LABEL); // Recursive locking masm.subq(tmpReg, rsp); masm.andq(tmpReg, 7 - os::vm_page_size()); - masm.movq(Address(boxReg), tmpReg); + masm.movq(Address(boxReg, 0), tmpReg); masm.bind(DONE_LABEL); masm.nop(); // avoid branch to branch } else { Label DONE_LABEL, IsInflated, Egress; - masm.movq (tmpReg, Address(objReg)) ; + masm.movq (tmpReg, Address(objReg, 0)) ; masm.testq (tmpReg, 0x02) ; // inflated vs stack-locked|neutral|biased masm.jcc (Assembler::notZero, IsInflated) ; @@ -3412,26 +3437,26 @@ if (UseBiasedLocking) { masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, _counters); - masm.movq (tmpReg, Address(objReg)) ; // [FETCH] + masm.movq (tmpReg, Address(objReg, 0)) ; // [FETCH] } masm.orq (tmpReg, 1) ; - masm.movq (Address(boxReg), tmpReg) ; + masm.movq (Address(boxReg, 0), tmpReg) ; if (os::is_MP()) { masm.lock(); } - masm.cmpxchgq(boxReg, Address(objReg)); // Updates tmpReg + masm.cmpxchgq(boxReg, Address(objReg, 0)); // Updates tmpReg if (_counters != NULL) { - masm.cond_incl(Assembler::equal, - Address((address) _counters->fast_path_entry_count_addr(), relocInfo::none)); + masm.cond_inc32(Assembler::equal, + ExternalAddress((address) _counters->fast_path_entry_count_addr())); } masm.jcc (Assembler::equal, DONE_LABEL); // Recursive locking masm.subq (tmpReg, rsp); masm.andq (tmpReg, 7 - os::vm_page_size()); - masm.movq (Address(boxReg), tmpReg); + masm.movq (Address(boxReg, 0), tmpReg); if (_counters != NULL) { - masm.cond_incl(Assembler::equal, - Address((address) _counters->fast_path_entry_count_addr(), relocInfo::none)); + masm.cond_inc32(Assembler::equal, + ExternalAddress((address) _counters->fast_path_entry_count_addr())); } masm.jmp (DONE_LABEL) ; @@ -3443,7 +3468,7 @@ // We should also think about trying a CAS without having // fetched _owner. If the CAS is successful we may // avoid an RTO->RTS upgrade on the $line. - masm.movq (Address(boxReg), intptr_t(markOopDesc::unused_mark())) ; + masm.movptr(Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())) ; masm.movq (boxReg, tmpReg) ; masm.movq (tmpReg, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; @@ -3482,7 +3507,7 @@ // Check whether the displaced header is 0 //(=> recursive unlock) - masm.movq(tmpReg, Address(boxReg)); + masm.movq(tmpReg, Address(boxReg, 0)); masm.testq(tmpReg, tmpReg); masm.jcc(Assembler::zero, DONE_LABEL); @@ -3490,7 +3515,7 @@ if (os::is_MP()) { masm.lock(); } - masm.cmpxchgq(tmpReg, Address(objReg)); // Uses RAX which is box + masm.cmpxchgq(tmpReg, Address(objReg, 0)); // Uses RAX which is box masm.bind(DONE_LABEL); masm.nop(); // avoid branch to branch } else { @@ -3500,8 +3525,8 @@ masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); } - masm.movq (tmpReg, Address(objReg)) ; - masm.cmpq (Address(boxReg), 0L) ; + masm.movq (tmpReg, Address(objReg, 0)) ; + masm.cmpq (Address(boxReg, 0), (int)NULL_WORD) ; masm.jcc (Assembler::zero, DONE_LABEL) ; masm.testq (tmpReg, 0x02) ; masm.jcc (Assembler::zero, Stacked) ; @@ -3514,27 +3539,27 @@ masm.movq (boxReg, Address (tmpReg, ObjectMonitor::cxq_offset_in_bytes()-2)) ; masm.orq (boxReg, Address (tmpReg, ObjectMonitor::EntryList_offset_in_bytes()-2)) ; masm.jcc (Assembler::notZero, CheckSucc) ; - masm.movq (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), intptr_t(0L)) ; + masm.mov64 (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int)NULL_WORD) ; masm.jmp (DONE_LABEL) ; if ((EmitSync & 65536) == 0) { Label LSuccess, LGoSlowPath ; masm.bind (CheckSucc) ; - masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0L) ; + masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int)NULL_WORD) ; masm.jcc (Assembler::zero, LGoSlowPath) ; // I'd much rather use lock:andl m->_owner, 0 as it's faster than the // the explicit ST;MEMBAR combination, but masm doesn't currently support // "ANDQ M,IMM". Don't use MFENCE here. lock:add to TOS, xchg, etc // are all faster when the write buffer is populated. - masm.movq (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), intptr_t(0L)) ; + masm.movptr (Address (tmpReg, ObjectMonitor::owner_offset_in_bytes()-2), (int)NULL_WORD) ; if (os::is_MP()) { - masm.lock () ; masm.addq (Address(rsp), 0) ; + masm.lock () ; masm.addq (Address(rsp, 0), 0) ; } - masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), 0L) ; + masm.cmpq (Address (tmpReg, ObjectMonitor::succ_offset_in_bytes()-2), (int)NULL_WORD) ; masm.jcc (Assembler::notZero, LSuccess) ; - masm.movq (boxReg, intptr_t(0L)) ; // box is really EAX + masm.movptr (boxReg, (int)NULL_WORD) ; // box is really EAX if (os::is_MP()) { masm.lock(); } masm.cmpxchgq (r15_thread, Address(tmpReg, ObjectMonitor::owner_offset_in_bytes()-2)); masm.jcc (Assembler::notEqual, LSuccess) ; @@ -3550,9 +3575,9 @@ } masm.bind (Stacked) ; - masm.movq (tmpReg, Address (boxReg)) ; // re-fetch + masm.movq (tmpReg, Address (boxReg, 0)) ; // re-fetch if (os::is_MP()) { masm.lock(); } - masm.cmpxchgq(tmpReg, Address(objReg)); // Uses RAX which is box + masm.cmpxchgq(tmpReg, Address(objReg, 0)); // Uses RAX which is box if (EmitSync & 65536) { masm.bind (CheckSucc) ; @@ -3601,8 +3626,8 @@ masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); // Load first characters - masm.load_unsigned_word(rcx, Address(rbx)); - masm.load_unsigned_word(rdi, Address(rax)); + masm.load_unsigned_word(rcx, Address(rbx, 0)); + masm.load_unsigned_word(rdi, Address(rax, 0)); // Compare first characters masm.subl(rcx, rdi); @@ -3618,7 +3643,7 @@ masm.jcc(Assembler::notEqual, LSkip2); // Check if the length difference is zero (from stack) - masm.cmpl(Address(rsp), 0x0); + masm.cmpl(Address(rsp, 0), 0x0); masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); // Strings might not be equivalent diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/assembler_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/assembler_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/assembler_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_amd64.cpp 1.57 07/06/08 18:13:29 JVM" +#pragma ident "@(#)assembler_amd64.cpp 1.58 07/06/19 09:07:59 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -28,15 +28,18 @@ #include "incls/_precompiled.incl" #include "incls/_assembler_amd64.cpp.incl" -// Implementation of Address -Address::Address(address target, relocInfo::relocType rtype) -{ - _base = noreg; - _index = noreg; - _scale = no_scale; - _disp = 0; +// Implementation of AddressLiteral + +AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { + _is_lval = false; _target = target; switch (rtype) { + case relocInfo::oop_type: + // Oops are a special case. Normally they would be their own section + // but in cases like icBuffer they are literals in the code stream that + // we don't have a section for. We use none so that we get a literal address + // which is always patchable. + break; case relocInfo::external_word_type: _rspec = external_word_Relocation::spec(target); break; @@ -60,16 +63,107 @@ } } +// Implementation of Address + +Address Address::make_array(ArrayAddress adr) { +#ifdef _LP64 + // Not implementable on 64bit machines + // Should have been handled higher up the call chain. + ShouldNotReachHere(); + return Address(); +#else + AddressLiteral base = adr.base(); + Address index = adr.index(); + assert(index._disp == 0, "must not have disp"); // maybe it can? + Address array(index._base, index._index, index._scale, (intptr_t) base.target()); + array._rspec = base._rspec; + return array; +#endif // _LP64 +} + +// exceedingly dangerous constructor +Address::Address(int disp, address loc, relocInfo::relocType rtype) { + _base = noreg; + _index = noreg; + _scale = no_scale; + _disp = disp; + switch (rtype) { + case relocInfo::external_word_type: + _rspec = external_word_Relocation::spec(loc); + break; + case relocInfo::internal_word_type: + _rspec = internal_word_Relocation::spec(loc); + break; + case relocInfo::runtime_call_type: + // HMM + _rspec = runtime_call_Relocation::spec(); + break; + case relocInfo::none: + break; + default: + ShouldNotReachHere(); + } +} + + // Implementation of Assembler -int AbstractAssembler::code_fill_byte() -{ +int AbstractAssembler::code_fill_byte() { return (u_char)'\xF4'; // hlt } +// This should only be used by 64bit instructions that can use rip-relative +// it cannot be used by instructions that want an immediate value. + +bool Assembler::reachable(AddressLiteral adr) { + int64_t disp; + // None will force a 64bit literal to the code stream. Likely a placeholder + // for something that will be patched later and we need to certain it will + // always be reachable. + if (adr.reloc() == relocInfo::none) { + return false; + } + if (adr.reloc() == relocInfo::internal_word_type) { + // This should be rip relative and easily reachable. + return true; + } + if (adr.reloc() != relocInfo::external_word_type && + adr.reloc() != relocInfo::runtime_call_type ) { + return false; + } + // For external_word_type/runtime_call_type if it is reachable from where we + // are now (possibly a temp buffer) and where we might end up + // anywhere in the codeCache then we are always reachable. + // This would have to change if we ever save/restore shared code + // to be more pessimistic. + + disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int)); + if (!is_simm32(disp)) return false; + disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int)); + if (!is_simm32(disp)) return false; + + disp = (int64_t)adr._target - ((int64_t)_code_pos + sizeof(int)); + + // Because rip relative is a disp + address_of_next_instruction and we + // don't know the value of address_of_next_instruction we apply a fudge factor + // to make sure we will be ok no matter the size of the instruction we get placed into. + // We don't have to fudge the checks above here because they are already worst case. + + // 12 == override/rex byte, opcode byte, rm byte, sib byte, a 4-byte disp , 4-byte literal + // + 4 because better safe than sorry. + const int fudge = 12 + 4; + if (disp < 0) { + disp -= fudge; + } else { + disp += fudge; + } + return is_simm32(disp); +} + + +// make this go away eventually void Assembler::emit_data(jint data, relocInfo::relocType rtype, - int format) -{ + int format) { if (rtype == relocInfo::none) { emit_long(data); } else { @@ -79,24 +173,29 @@ void Assembler::emit_data(jint data, RelocationHolder const& rspec, - int format) -{ + int format) { assert(imm64_operand == 0, "default format must be imm64 in this file"); assert(imm64_operand != format, "must not be imm64"); assert(inst_mark() != NULL, "must be inside InstructionMark"); - // Do not use AbstractAssembler::relocate, which is not intended for - // embedded words. Instead, relocate to the enclosing instruction. - code_section()->relocate(inst_mark(), rspec, format); -#ifdef ASSERT - check_relocation(rspec, format); -#endif + if (rspec.type() != relocInfo::none) { + #ifdef ASSERT + check_relocation(rspec, format); + #endif + // Do not use AbstractAssembler::relocate, which is not intended for + // embedded words. Instead, relocate to the enclosing instruction. + + // hack. call32 is too wide for mask so use disp32 + if (format == call32_operand) + code_section()->relocate(inst_mark(), rspec, disp32_operand); + else + code_section()->relocate(inst_mark(), rspec, format); + } emit_long(data); } void Assembler::emit_data64(jlong data, relocInfo::relocType rtype, - int format) -{ + int format) { if (rtype == relocInfo::none) { emit_long64(data); } else { @@ -106,8 +205,7 @@ void Assembler::emit_data64(jlong data, RelocationHolder const& rspec, - int format) -{ + int format) { assert(imm64_operand == 0, "default format must be imm64 in this file"); assert(imm64_operand == format, "must be imm64"); assert(inst_mark() != NULL, "must be inside InstructionMark"); @@ -120,8 +218,7 @@ emit_long64(data); } -void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) -{ +void Assembler::emit_arith_b(int op1, int op2, Register dst, int imm8) { assert(isByte(op1) && isByte(op2), "wrong opcode"); assert(isByte(imm8), "not a byte"); assert((op1 & 0x01) == 0, "should be 8bit operation"); @@ -134,8 +231,7 @@ emit_byte(imm8); } -void Assembler::emit_arith(int op1, int op2, Register dst, int imm32) -{ +void Assembler::emit_arith(int op1, int op2, Register dst, int imm32) { assert(isByte(op1) && isByte(op2), "wrong opcode"); assert((op1 & 0x01) == 1, "should be 32bit operation"); assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); @@ -157,8 +253,7 @@ // immediate-to-memory forms void Assembler::emit_arith_operand(int op1, Register rm, Address adr, - int imm32) -{ + int imm32) { assert((op1 & 0x01) == 1, "should be 32bit operation"); assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); if (is8bit(imm32)) { @@ -173,8 +268,7 @@ } -void Assembler::emit_arith(int op1, int op2, Register dst, Register src) -{ +void Assembler::emit_arith(int op1, int op2, Register dst, Register src) { assert(isByte(op1) && isByte(op2), "wrong opcode"); int dstenc = dst->encoding(); int srcenc = src->encoding(); @@ -190,10 +284,8 @@ void Assembler::emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, - address target, RelocationHolder const& rspec, - int rip_relative_correction) -{ + int rip_relative_correction) { relocInfo::relocType rtype = (relocInfo::relocType) rspec.type(); int regenc = reg->encoding(); if (regenc >= 8) { @@ -290,33 +382,40 @@ emit_byte(0x04 | regenc << 3); emit_byte(scale << 6 | indexenc << 3 | 0x05); emit_data(disp, rspec, disp32_operand); - } else if (target == NULL) { +#ifdef _LP64 + } else if (rtype != relocInfo::none ) { + // [disp] RIP-RELATIVE + // [00 000 101] disp32 + + emit_byte(0x05 | regenc << 3); + // Note that the RIP-rel. correction applies to the generated + // disp field, but _not_ to the target address in the rspec. + + // disp was created by converting the target address minus the pc + // at the start of the instruction. That needs more correction here. + // intptr_t disp = target - next_ip; + assert(inst_mark() != NULL, "must be inside InstructionMark"); + address next_ip = pc() + sizeof(int32_t) + rip_relative_correction; + int64_t adjusted = (int64_t) disp - (next_ip - inst_mark()); + assert(is_simm32(adjusted), + "must be 32bit offset (RIP relative address)"); + emit_data((int) adjusted, rspec, disp32_operand); + +#endif // _LP64 + } else { // [disp] ABSOLUTE // [00 reg 100][00 100 101] disp32 emit_byte(0x04 | regenc << 3); emit_byte(0x25); emit_data(disp, rspec, disp32_operand); - } else { - // [disp] RIP-RELATIVE - // [00 reg 101] disp32 - emit_byte(0x05 | regenc << 3); - // Note that the RIP-rel. correction applies to the generated - // disp field, but _not_ to the target address in the rspec. - address next_ip = pc() + sizeof(int) + rip_relative_correction; - intptr_t disp = target - next_ip; - assert(is_simm32(disp), - "must be 32bit offset (RIP relative address)"); - emit_data((int) disp, rspec, disp32_operand); } } } void Assembler::emit_operand(FloatRegister reg, Register base, Register index, Address::ScaleFactor scale, int disp, - address target, RelocationHolder const& rspec, - int rip_relative_correction) -{ + int rip_relative_correction) { relocInfo::relocType rtype = (relocInfo::relocType) rspec.type(); int regenc = reg->encoding(); if (regenc >= 8) { @@ -413,23 +512,32 @@ emit_byte(0x04 | regenc << 3); emit_byte(scale << 6 | indexenc << 3 | 0x05); emit_data(disp, rspec, disp32_operand); - } else if (target == NULL) { +#ifdef _LP64 + } else if ( rtype != relocInfo::none ) { + // [disp] RIP-RELATIVE + // [00 reg 101] disp32 + emit_byte(0x05 | regenc << 3); + // Note that the RIP-rel. correction applies to the generated + // disp field, but _not_ to the target address in the rspec. + + // disp was created by converting the target address minus the pc + // at the start of the instruction. That needs more correction here. + // intptr_t disp = target - next_ip; + + assert(inst_mark() != NULL, "must be inside InstructionMark"); + address next_ip = pc() + sizeof(int32_t) + rip_relative_correction; + + int64_t adjusted = (int64_t) disp - (next_ip - inst_mark()); + assert(is_simm32(adjusted), + "must be 32bit offset (RIP relative address)"); + emit_data((int) adjusted, rspec, disp32_operand); +#endif // _LP64 + } else { // [disp] ABSOLUTE // [00 reg 100][00 100 101] disp32 emit_byte(0x04 | regenc << 3); emit_byte(0x25); emit_data(disp, rspec, disp32_operand); - } else { - // [disp] RIP-RELATIVE - // [00 reg 101] disp32 - emit_byte(0x05 | regenc << 3); - // Note that the RIP-rel. correction applies to the generated - // disp field, but _not_ to the target address in the rspec. - address next_ip = pc() + sizeof(int) + rip_relative_correction; - intptr_t disp = target - next_ip; - assert(is_simm32(disp), - "must be 32bit offset (RIP relative address)"); - emit_data((int) disp, rspec, disp32_operand); } } } @@ -506,6 +614,7 @@ case 0x8A: // movb r, a case 0x8B: // movl r, a case 0x8F: // popl a + debug_only(has_disp32 = true); break; case 0x68: // pushq #32 @@ -585,9 +694,11 @@ case 0xC1: // xaddl case 0xC7: // cmpxchg8 case REP16(0x90): // setcc a + debug_only(has_disp32 = true); // fall out of the switch to decode the address break; case 0xAC: // shrd r, a, #8 + debug_only(has_disp32 = true); tail_size = 1; // the imm8 break; case REP16(0x80): // jcc rdisp32 @@ -607,12 +718,14 @@ case 0x83: // addl a, #8; addl r, #8 // also: orl, adcl, sbbl, andl, subl, xorl, cmpl + debug_only(has_disp32 = true); // has both kinds of operands! tail_size = 1; break; case 0x9B: switch (0xFF & *ip++) { case 0xD9: // fnstcw a + debug_only(has_disp32 = true); break; default: ShouldNotReachHere(); @@ -628,6 +741,7 @@ case REP4(0x28): // sub... case 0xF7: // mull a case 0x87: // xchg r, a + debug_only(has_disp32 = true); break; case REP4(0x38): // cmp... case 0x8D: // lea r, a @@ -639,6 +753,7 @@ case 0xC6: // movb a, #8 case 0x80: // cmpb a, #8 case 0x6B: // imul r, a, #8 + debug_only(has_disp32 = true); // has both kinds of operands! tail_size = 1; // the imm8 break; @@ -657,6 +772,7 @@ case 0xD8: // fadd_s a; fsubr_s a; fmul_s a; fdivr_s a; fcomp_s a case 0xDC: // fadd_d a; fsubr_d a; fmul_d a; fdivr_d a; fcomp_d a case 0xDE: // faddp_d a; fsubrp_d a; fmulp_d a; fdivrp_d a; fcompp_d a + debug_only(has_disp32 = true); break; case 0xF3: // For SSE @@ -694,8 +810,7 @@ assert(which != call32_operand, "instruction is not a call, jmp, or jcc"); assert(which != imm64_operand, "instruction is not a movq reg, imm64"); - assert(which != disp32_operand || has_disp32, - "instruction has no disp32 field"); + assert(which != disp32_operand || has_disp32, "instruction has no disp32 field"); // parse the output of emit_operand int op2 = 0xFF & *ip++; @@ -753,15 +868,13 @@ return ip; } -address Assembler::locate_next_instruction(address inst) -{ +address Assembler::locate_next_instruction(address inst) { // Secretly share code with locate_operand: return locate_operand(inst, end_pc_operand); } #ifdef ASSERT -void Assembler::check_relocation(RelocationHolder const& rspec, int format) -{ +void Assembler::check_relocation(RelocationHolder const& rspec, int format) { address inst = inst_mark(); assert(inst != NULL && inst < pc(), "must point to beginning of instruction"); @@ -783,26 +896,212 @@ } #endif +int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { + if (reg_enc >= 8) { + prefix(REX_B); + reg_enc -= 8; + } else if (byteinst && reg_enc >= 4) { + prefix(REX); + } + return reg_enc; +} + +int Assembler::prefixq_and_encode(int reg_enc) { + if (reg_enc < 8) { + prefix(REX_W); + } else { + prefix(REX_WB); + reg_enc -= 8; + } + return reg_enc; +} + +int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { + if (dst_enc < 8) { + if (src_enc >= 8) { + prefix(REX_B); + src_enc -= 8; + } else if (byteinst && src_enc >= 4) { + prefix(REX); + } + } else { + if (src_enc < 8) { + prefix(REX_R); + } else { + prefix(REX_RB); + src_enc -= 8; + } + dst_enc -= 8; + } + return dst_enc << 3 | src_enc; +} + +int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { + if (dst_enc < 8) { + if (src_enc < 8) { + prefix(REX_W); + } else { + prefix(REX_WB); + src_enc -= 8; + } + } else { + if (src_enc < 8) { + prefix(REX_WR); + } else { + prefix(REX_WRB); + src_enc -= 8; + } + dst_enc -= 8; + } + return dst_enc << 3 | src_enc; +} + +void Assembler::prefix(Register reg) { + if (reg->encoding() >= 8) { + prefix(REX_B); + } +} + +void Assembler::prefix(Address adr) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_XB); + } else { + prefix(REX_B); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_X); + } + } +} + +void Assembler::prefixq(Address adr) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_WXB); + } else { + prefix(REX_WB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_WX); + } else { + prefix(REX_W); + } + } +} + + +void Assembler::prefix(Address adr, Register reg, bool byteinst) { + if (reg->encoding() < 8) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_XB); + } else { + prefix(REX_B); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_X); + } else if (reg->encoding() >= 4 ) { + prefix(REX); + } + } + } else { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_RXB); + } else { + prefix(REX_RB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_RX); + } else { + prefix(REX_R); + } + } + } +} + +void Assembler::prefixq(Address adr, Register src) { + if (src->encoding() < 8) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_WXB); + } else { + prefix(REX_WB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_WX); + } else { + prefix(REX_W); + } + } + } else { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_WRXB); + } else { + prefix(REX_WRB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_WRX); + } else { + prefix(REX_WR); + } + } + } +} + +void Assembler::prefix(Address adr, FloatRegister reg) { + if (reg->encoding() < 8) { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_XB); + } else { + prefix(REX_B); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_X); + } + } + } else { + if (adr.base_needs_rex()) { + if (adr.index_needs_rex()) { + prefix(REX_RXB); + } else { + prefix(REX_RB); + } + } else { + if (adr.index_needs_rex()) { + prefix(REX_RX); + } else { + prefix(REX_R); + } + } + } +} + void Assembler::emit_operand(Register reg, Address adr, - int rip_relative_correction) -{ + int rip_relative_correction) { emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp, - adr._target, adr._rspec, rip_relative_correction); } void Assembler::emit_operand(FloatRegister reg, Address adr, - int rip_relative_correction) -{ + int rip_relative_correction) { emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp, - adr._target, adr._rspec, rip_relative_correction); } -void Assembler::emit_farith(int b1, int b2, int i) -{ +void Assembler::emit_farith(int b1, int b2, int i) { assert(isByte(b1) && isByte(b2), "wrong opcode"); assert(0 <= i && i < 8, "illegal stack offset"); emit_byte(b1); @@ -811,8 +1110,7 @@ // pushad is invalid, use this instead. // NOTE: Kills flags!! -void Assembler::pushaq() -{ +void Assembler::pushaq() { // we have to store original rsp. ABI says that 128 bytes // below rsp are local scratch. movq(Address(rsp, -5 * wordSize), rsp); @@ -834,14 +1132,13 @@ movq(Address(rsp, 3 * wordSize), r12); movq(Address(rsp, 2 * wordSize), r13); movq(Address(rsp, wordSize), r14); - movq(Address(rsp), r15); + movq(Address(rsp, 0), r15); } // popad is invalid, use this instead // NOTE: Kills flags!! -void Assembler::popaq() -{ - movq(r15, Address(rsp)); +void Assembler::popaq() { + movq(r15, Address(rsp, 0)); movq(r14, Address(rsp, wordSize)); movq(r13, Address(rsp, 2 * wordSize)); movq(r12, Address(rsp, 3 * wordSize)); @@ -861,1065 +1158,293 @@ addq(rsp, 16 * wordSize); } -void Assembler::pushfq() -{ +void Assembler::pushfq() { emit_byte(0x9C); } -void Assembler::popfq() -{ +void Assembler::popfq() { emit_byte(0x9D); } -void Assembler::pushq(int imm32) -{ +void Assembler::pushq(int imm32) { emit_byte(0x68); emit_long(imm32); } -void Assembler::pushq(Register src) -{ - int srcenc = src->encoding(); - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - emit_byte(0x50 | srcenc); -} - -void Assembler::pushq(Address src) -{ +void Assembler::pushq(Register src) { + int encode = prefix_and_encode(src->encoding()); + + emit_byte(0x50 | encode); +} + +void Assembler::pushq(Address src) { InstructionMark im(this); - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(src); emit_byte(0xFF); emit_operand(rsi, src); } -void Assembler::popq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } - emit_byte(0x58 | dstenc); -} - -void Assembler::popq(Address dst) -{ +void Assembler::popq(Register dst) { + int encode = prefix_and_encode(dst->encoding()); + emit_byte(0x58 | encode); +} + +void Assembler::popq(Address dst) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0x8F); emit_operand(rax, dst); } -void Assembler::prefix(Prefix p) -{ +void Assembler::prefix(Prefix p) { a_byte(p); } -void Assembler::movb(Register dst, Address src) -{ +void Assembler::movb(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } else if (dst->encoding() >= 4) { - prefix(REX); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst, true); emit_byte(0x8A); emit_operand(dst, src); } -void Assembler::movb(Address dst, int imm8) -{ +void Assembler::movb(Address dst, int imm8) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0xC6); emit_operand(rax, dst, 1); emit_byte(imm8); } -void Assembler::movb(Address dst, Register src) -{ +void Assembler::movb(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } else if (src->encoding() >= 4) { - prefix(REX); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src, true); emit_byte(0x88); emit_operand(src, dst); } -void Assembler::movw(Address dst, int imm16) -{ +void Assembler::movw(Address dst, int imm16) { InstructionMark im(this); emit_byte(0x66); // switch to 16-bit mode - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0xC7); emit_operand(rax, dst, 2); emit_word(imm16); } -void Assembler::movw(Register dst, Address src) -{ +void Assembler::movw(Register dst, Address src) { InstructionMark im(this); emit_byte(0x66); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x8B); emit_operand(dst, src); } -void Assembler::movw(Address dst, Register src) -{ +void Assembler::movw(Address dst, Register src) { InstructionMark im(this); emit_byte(0x66); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x89); emit_operand(src, dst); } // Uses zero extension. -void Assembler::movl(Register dst, int imm32) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } - emit_byte(0xB8 | dstenc); +void Assembler::movl(Register dst, int imm32) { + int encode = prefix_and_encode(dst->encoding()); + emit_byte(0xB8 | encode); emit_long(imm32); } -void Assembler::movl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x8B); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movl(Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x8B); emit_operand(dst, src); } -void Assembler::movl(Address dst, int imm32) -{ +void Assembler::movl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0xC7); emit_operand(rax, dst, 4); emit_long(imm32); } -void Assembler::movl(Address dst, Register src) -{ +void Assembler::movl(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x89); emit_operand(src, dst); } -void Assembler::movq(Register dst, int64_t imm64) -{ +void Assembler::mov64(Register dst, int64_t imm64) { InstructionMark im(this); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } - emit_byte(0xB8 | dstenc); + int encode = prefixq_and_encode(dst->encoding()); + emit_byte(0xB8 | encode); emit_long64(imm64); } -void Assembler::movq(Register dst, address imm64, relocInfo::relocType rtype) -{ +void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) { InstructionMark im(this); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } - emit_byte(0xB8 | dstenc); - switch (rtype) { - case relocInfo::none: - emit_data64((jlong) imm64, relocInfo::none); - break; - case relocInfo::internal_word_type: - { - // Internal words will need to be relocated if we relocate since - // they very obviously move. - RelocationHolder rspec = internal_word_Relocation::spec_for_immediate(); - emit_data64((jlong) imm64, rspec); - } - break; - case relocInfo::oop_type: - { - RelocationHolder rspec = oop_Relocation::spec_for_immediate(); - emit_data64((jlong) imm64, rspec); - } - break; - case relocInfo::runtime_call_type: - case relocInfo::external_word_type: - { - RelocationHolder rspec = external_word_Relocation::spec_for_immediate(); - emit_data64((jlong) imm64, rspec); - } - break; - default: - ShouldNotReachHere(); - } -} - -void Assembler::movq(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); + emit_byte(0xB8 | encode); + emit_data64(imm64, rspec); +} + +void Assembler::movq(Register dst, Register src) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x8B); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movq(Register dst, jobject obj) -{ - InstructionMark im(this); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } - emit_byte(0xB8 | dstenc); - emit_data64((jlong) obj, relocInfo::oop_type); -} - -void Assembler::movq(Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movq(Register dst, Address src) { InstructionMark im(this); - int dstenc = dst->encoding(); - if (dstenc < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - dstenc -= 8; - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } - if (is_reachable(src)) { - emit_byte(0x8B); - emit_operand(dst, src); - } - else { - emit_byte(0xB8 | dstenc); -// [RGV] using relocInfo::none for now to work around assert. - emit_data64((jlong) src._target, relocInfo::none ); - } -} - -void Assembler::movq(Address dst, int64_t imm32) -{ + prefixq(src, dst); + emit_byte(0x8B); + emit_operand(dst, src); +} + +void Assembler::mov64(Address dst, int64_t imm32) { assert(is_simm32(imm32), "lost bits"); InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_byte(0xC7); emit_operand(rax, dst, 4); emit_long(imm32); } -void Assembler::movq(Address dst, Register src) -{ +void Assembler::movq(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(dst, src); emit_byte(0x89); emit_operand(src, dst); } -void Assembler::movsbl(Register dst, Address src) -{ +void Assembler::movsbl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0xBE); emit_operand(dst, src); } -void Assembler::movsbl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } else if (srcenc >= 4) { - prefix(REX); - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movsbl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); emit_byte(0x0F); emit_byte(0xBE); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movswl(Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movswl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0xBF); emit_operand(dst, src); } -void Assembler::movswl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movswl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0xBF); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movslq(Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movslq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x63); emit_operand(dst, src); } -void Assembler::movslq(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movslq(Register dst, Register src) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x63); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); } -void Assembler::movzbl(Register dst, Address src) -{ +void Assembler::movzbl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0xB6); emit_operand(dst, src); } -void Assembler::movzbl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } else if (srcenc >= 4) { - prefix(REX); - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movzbl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding(), true); emit_byte(0x0F); emit_byte(0xB6); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movzwl(Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movzwl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0xB7); emit_operand(dst, src); } -void Assembler::movzwl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::movzwl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0xB7); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::movss(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x10); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movss(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movss(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF3); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x10); emit_operand(dst, src); } -void Assembler::movss(Address dst, FloatRegister src) -{ +void Assembler::movss(Address dst, FloatRegister src) { InstructionMark im(this); emit_byte(0xF3); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x0F); emit_byte(0x11); emit_operand(src, dst); } -void Assembler::movsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::movsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x10); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::movsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x10); emit_operand(dst, src); } -void Assembler::movsd(Address dst, FloatRegister src) -{ +void Assembler::movsd(Address dst, FloatRegister src) { InstructionMark im(this); emit_byte(0xF2); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x0F); emit_byte(0x11); emit_operand(src, dst); @@ -1928,44 +1453,16 @@ // New cpus require to use movsd and movss to avoid partial register stall // when loading from memory. But for old Opteron use movlpd instead of movsd. // The selection is done in MacroAssembler::movdbl() and movflt(). -void Assembler::movlpd(FloatRegister dst, Address src) -{ +void Assembler::movlpd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0x66); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x12); emit_operand(dst, src); } -void Assembler::movapd(FloatRegister dst, FloatRegister src) -{ +void Assembler::movapd(FloatRegister dst, FloatRegister src) { int dstenc = dst->encoding(); int srcenc = src->encoding(); emit_byte(0x66); @@ -1988,8 +1485,7 @@ emit_byte(0xC0 | dstenc << 3 | srcenc); } -void Assembler::movaps(FloatRegister dst, FloatRegister src) -{ +void Assembler::movaps(FloatRegister dst, FloatRegister src) { int dstenc = dst->encoding(); int srcenc = src->encoding(); if (dstenc < 8) { @@ -2011,238 +1507,72 @@ emit_byte(0xC0 | dstenc << 3 | srcenc); } -void Assembler::movdl(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::movdl(FloatRegister dst, Register src) { emit_byte(0x66); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x6E); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movdl(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::movdl(Register dst, FloatRegister src) { emit_byte(0x66); - if (srcenc < 8) { - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } - } else { - if (dstenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - dstenc -= 8; - } - srcenc -= 8; - } + // swap src/dst to get correct prefix + int encode = prefix_and_encode(src->encoding(), dst->encoding()); emit_byte(0x0F); emit_byte(0x7E); - emit_byte(0xC0 | srcenc << 3 | dstenc); -} - -void Assembler::movdq(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::movdq(FloatRegister dst, Register src) { emit_byte(0x66); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x6E); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::movdq(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::movdq(Register dst, FloatRegister src) { emit_byte(0x66); - if (srcenc < 8) { - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } - } else { - if (dstenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - dstenc -= 8; - } - srcenc -= 8; - } + // swap src/dst to get correct prefix + int encode = prefixq_and_encode(src->encoding(), dst->encoding()); emit_byte(0x0F); emit_byte(0x7E); - emit_byte(0xC0 | srcenc << 3 | dstenc); -} - -void Assembler::cmovl(Condition cc, Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + emit_byte(0xC0 | encode); +} + +void Assembler::cmovl(Condition cc, Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x40 | cc); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cmovl(Condition cc, Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::cmovl(Condition cc, Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x40 | cc); emit_operand(dst, src); } -void Assembler::cmovq(Condition cc, Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::cmovq(Condition cc, Register dst, Register src) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x40 | cc); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cmovq(Condition cc, Register dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::cmovq(Condition cc, Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x0F); emit_byte(0x40 | cc); emit_operand(dst, src); } void Assembler::prefetch_prefix(Address src) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(src); emit_byte(0x0F); } @@ -2281,1647 +1611,618 @@ emit_operand(rcx, src); // 1, src } -void Assembler::adcl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::adcl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xD0, dst, imm32); } -void Assembler::adcl(Register dst, Address src) -{ +void Assembler::adcl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x13); emit_operand(dst, src); } -void Assembler::adcl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::adcl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x13, 0xC0, dst, src); } -void Assembler::adcq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::adcq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xD0, dst, imm32); } -void Assembler::adcq(Register dst, Address src) -{ +void Assembler::adcq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x13); emit_operand(dst, src); } -void Assembler::adcq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::adcq(Register dst, Register src) { + (int) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x13, 0xC0, dst, src); } -void Assembler::addl(Address dst, int imm32) -{ +void Assembler::addl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_arith_operand(0x81, rax, dst,imm32); } -void Assembler::addl(Address dst, Register src) -{ +void Assembler::addl(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x01); emit_operand(src, dst); } -void Assembler::addl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::addl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xC0, dst, imm32); } -void Assembler::addl(Register dst, Address src) -{ +void Assembler::addl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x03); emit_operand(dst, src); } -void Assembler::addl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::addl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x03, 0xC0, dst, src); } -void Assembler::addq(Address dst, int imm32) -{ +void Assembler::addq(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_arith_operand(0x81, rax, dst,imm32); } -void Assembler::addq(Address dst, Register src) -{ +void Assembler::addq(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(dst, src); emit_byte(0x01); emit_operand(src, dst); } -void Assembler::addq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::addq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xC0, dst, imm32); } -void Assembler::addq(Register dst, Address src) -{ +void Assembler::addq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x03); emit_operand(dst, src); } -void Assembler::addq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::addq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x03, 0xC0, dst, src); } -void Assembler::andl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::andl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xE0, dst, imm32); } -void Assembler::andl(Register dst, Address src) -{ +void Assembler::andl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x23); emit_operand(dst, src); } -void Assembler::andl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::andl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x23, 0xC0, dst, src); } -void Assembler::andq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::andq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xE0, dst, imm32); } -void Assembler::andq(Register dst, Address src) -{ +void Assembler::andq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x23); emit_operand(dst, src); } -void Assembler::andq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::andq(Register dst, Register src) { + (int) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x23, 0xC0, dst, src); } -void Assembler::cmpb(Address dst, int imm8) -{ +void Assembler::cmpb(Address dst, int imm8) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0x80); emit_operand(rdi, dst, 1); emit_byte(imm8); } -void Assembler::cmpl(Address dst, int imm32) -{ +void Assembler::cmpl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0x81); emit_operand(rdi, dst, 4); emit_long(imm32); } -void Assembler::cmpl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::cmpl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xF8, dst, imm32); } -void Assembler::cmpl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::cmpl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x3B, 0xC0, dst, src); } -void Assembler::cmpl(Register dst, Address src) -{ +void Assembler::cmpl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x3B); emit_operand(dst, src); } -void Assembler::cmpq(Address dst, int imm32) -{ +void Assembler::cmpq(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_byte(0x81); emit_operand(rdi, dst, 4); emit_long(imm32); } -void Assembler::cmpq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::cmpq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xF8, dst, imm32); } -void Assembler::cmpq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::cmpq(Address dst, Register src) { + prefixq(dst, src); + emit_byte(0x3B); + emit_operand(src, dst); +} + +void Assembler::cmpq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x3B, 0xC0, dst, src); } -void Assembler::cmpq(Register dst, Address src) -{ +void Assembler::cmpq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x3B); emit_operand(dst, src); } -void Assembler::ucomiss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::ucomiss(FloatRegister dst, FloatRegister src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2E); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::ucomisd(FloatRegister dst, FloatRegister src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::ucomisd(FloatRegister dst, FloatRegister src) { emit_byte(0x66); ucomiss(dst, src); } -void Assembler::decl(Register dst) -{ +void Assembler::decl(Register dst) { // Don't use it directly. Use MacroAssembler::decrementl() instead. // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xFF); - emit_byte(0xC8 | dstenc); -} - -void Assembler::decl(Address dst) -{ + emit_byte(0xC8 | encode); +} + +void Assembler::decl(Address dst) { // Don't use it directly. Use MacroAssembler::decrementl() instead. InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0xFF); emit_operand(rcx, dst); } -void Assembler::decq(Register dst) -{ +void Assembler::decq(Register dst) { // Don't use it directly. Use MacroAssembler::decrementq() instead. // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xFF); - emit_byte(0xC8 | dstenc); -} - -void Assembler::decq(Address dst) -{ + emit_byte(0xC8 | encode); +} + +void Assembler::decq(Address dst) { // Don't use it directly. Use MacroAssembler::decrementq() instead. InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_byte(0xFF); emit_operand(rcx, dst); } -void Assembler::idivl(Register src) -{ - int srcenc = src->encoding(); - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } +void Assembler::idivl(Register src) { + int encode = prefix_and_encode(src->encoding()); + emit_byte(0xF7); + emit_byte(0xF8 | encode); +} + +void Assembler::idivq(Register src) { + int encode = prefixq_and_encode(src->encoding()); emit_byte(0xF7); - emit_byte(0xF8 | srcenc); -} - -void Assembler::idivq(Register src) -{ - int srcenc = src->encoding(); - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - emit_byte(0xF7); - emit_byte(0xF8 | srcenc); -} - -void Assembler::cdql() -{ + emit_byte(0xF8 | encode); +} + +void Assembler::cdql() { emit_byte(0x99); } -void Assembler::cdqq() -{ +void Assembler::cdqq() { prefix(REX_W); emit_byte(0x99); } -void Assembler::imull(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::imull(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0xAF); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::imull(Register dst, Register src, int value) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + emit_byte(0xC0 | encode); +} + +void Assembler::imull(Register dst, Register src, int value) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); if (is8bit(value)) { emit_byte(0x6B); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); emit_byte(value); } else { emit_byte(0x69); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); emit_long(value); } } -void Assembler::imulq(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::imulq(Register dst, Register src) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0xAF); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::imulq(Register dst, Register src, int value) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + emit_byte(0xC0 | encode); +} + +void Assembler::imulq(Register dst, Register src, int value) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); if (is8bit(value)) { emit_byte(0x6B); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); emit_byte(value); } else { emit_byte(0x69); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); emit_long(value); } } -void Assembler::incl(Register dst) -{ +void Assembler::incl(Register dst) { // Don't use it directly. Use MacroAssembler::incrementl() instead. // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xFF); - emit_byte(0xC0 | dstenc); -} - -void Assembler::incl(Address dst) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::incl(Address dst) { // Don't use it directly. Use MacroAssembler::incrementl() instead. InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0xFF); emit_operand(rax, dst); } -void Assembler::incq(Register dst) -{ +void Assembler::incq(Register dst) { // Don't use it directly. Use MacroAssembler::incrementq() instead. // Use two-byte form (one-byte from is a REX prefix in 64-bit mode) - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xFF); - emit_byte(0xC0 | dstenc); -} - -void Assembler::incq(Address dst) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::incq(Address dst) { // Don't use it directly. Use MacroAssembler::incrementq() instead. InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_byte(0xFF); emit_operand(rax, dst); } -void Assembler::leal(Register dst, Address src) -{ +void Assembler::leal(Register dst, Address src) { InstructionMark im(this); emit_byte(0x67); // addr32 - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x8D); emit_operand(dst, src); } -void Assembler::leaq(Register dst, Address src) -{ +void Assembler::leaq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x8D); emit_operand(dst, src); } -void Assembler::mull(Address src) -{ +void Assembler::mull(Address src) { InstructionMark im(this); + // was missing + prefix(src); emit_byte(0xF7); emit_operand(rsp, src); } -void Assembler::mull(Register src) -{ +void Assembler::mull(Register src) { + // was missing + int encode = prefix_and_encode(src->encoding()); emit_byte(0xF7); - emit_byte(0xE0 | src->encoding()); -} - -void Assembler::negl(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + emit_byte(0xE0 | encode); +} + +void Assembler::negl(Register dst) { + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xF7); - emit_byte(0xD8 | dstenc); -} - -void Assembler::negq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + emit_byte(0xD8 | encode); +} + +void Assembler::negq(Register dst) { + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xF7); - emit_byte(0xD8 | dstenc); -} - -void Assembler::notl(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + emit_byte(0xD8 | encode); +} + +void Assembler::notl(Register dst) { + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xF7); - emit_byte(0xD0 | dstenc); -} - -void Assembler::notq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + emit_byte(0xD0 | encode); +} + +void Assembler::notq(Register dst) { + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xF7); - emit_byte(0xD0 | dstenc); -} - -void Assembler::orl(Address dst, int imm32) -{ + emit_byte(0xD0 | encode); +} + +void Assembler::orl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0x81); emit_operand(rcx, dst, 4); emit_long(imm32); } -void Assembler::orl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::orl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xC8, dst, imm32); } -void Assembler::orl(Register dst, Address src) -{ +void Assembler::orl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0B); emit_operand(dst, src); } -void Assembler::orl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::orl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x0B, 0xC0, dst, src); } -void Assembler::orq(Address dst, int imm32) -{ +void Assembler::orq(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); emit_byte(0x81); emit_operand(rcx, dst, 4); emit_long(imm32); } -void Assembler::orq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::orq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xC8, dst, imm32); } -void Assembler::orq(Register dst, Address src) -{ +void Assembler::orq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x0B); emit_operand(dst, src); } -void Assembler::orq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::orq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x0B, 0xC0, dst, src); } -void Assembler::rcll(Register dst, int imm8) -{ +void Assembler::rcll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding()); if (imm8 == 1) { emit_byte(0xD1); - emit_byte(0xD0 | dstenc); + emit_byte(0xD0 | encode); } else { emit_byte(0xC1); - emit_byte(0xD0 | dstenc); + emit_byte(0xD0 | encode); emit_byte(imm8); } } -void Assembler::rclq(Register dst, int imm8) -{ +void Assembler::rclq(Register dst, int imm8) { assert(isShiftCount(imm8 >> 1), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc < 8) { - emit_byte(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); if (imm8 == 1) { emit_byte(0xD1); - emit_byte(0xD0 | dstenc); + emit_byte(0xD0 | encode); } else { emit_byte(0xC1); - emit_byte(0xD0 | dstenc); + emit_byte(0xD0 | encode); emit_byte(imm8); } } -void Assembler::sarl(Register dst, int imm8) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } +void Assembler::sarl(Register dst, int imm8) { + int encode = prefix_and_encode(dst->encoding()); assert(isShiftCount(imm8), "illegal shift count"); if (imm8 == 1) { emit_byte(0xD1); - emit_byte(0xF8 | dstenc); + emit_byte(0xF8 | encode); } else { emit_byte(0xC1); - emit_byte(0xF8 | dstenc); + emit_byte(0xF8 | encode); emit_byte(imm8); } } -void Assembler::sarl(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } +void Assembler::sarl(Register dst) { + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xD3); - emit_byte(0xF8 | dstenc); -} - -void Assembler::sarq(Register dst, int imm8) -{ + emit_byte(0xF8 | encode); +} + +void Assembler::sarq(Register dst, int imm8) { assert(isShiftCount(imm8 >> 1), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); if (imm8 == 1) { emit_byte(0xD1); - emit_byte(0xF8 | dstenc); + emit_byte(0xF8 | encode); } else { emit_byte(0xC1); - emit_byte(0xF8 | dstenc); + emit_byte(0xF8 | encode); emit_byte(imm8); } } -void Assembler::sarq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } +void Assembler::sarq(Register dst) { + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xD3); - emit_byte(0xF8 | dstenc); -} - -void Assembler::sbbl(Address dst, int imm32) -{ + emit_byte(0xF8 | encode); +} + +void Assembler::sbbl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_arith_operand(0x81, rbx, dst, imm32); } -void Assembler::sbbl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::sbbl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xD8, dst, imm32); } -void Assembler::sbbl(Register dst, Address src) -{ +void Assembler::sbbl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); + emit_byte(0x1B); + emit_operand(dst, src); +} + +void Assembler::sbbl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); + emit_arith(0x1B, 0xC0, dst, src); +} + +void Assembler::sbbq(Address dst, int imm32) { + InstructionMark im(this); + prefixq(dst); + emit_arith_operand(0x81, rbx, dst, imm32); +} + +void Assembler::sbbq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); + emit_arith(0x81, 0xD8, dst, imm32); +} + +void Assembler::sbbq(Register dst, Address src) { + InstructionMark im(this); + prefixq(src, dst); emit_byte(0x1B); emit_operand(dst, src); } -void Assembler::sbbl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::sbbq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x1B, 0xC0, dst, src); } -void Assembler::sbbq(Address dst, int imm32) -{ - InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - emit_arith_operand(0x81, rbx, dst, imm32); -} - -void Assembler::sbbq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - emit_arith(0x81, 0xD8, dst, imm32); -} - -void Assembler::sbbq(Register dst, Address src) -{ - InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } - emit_byte(0x1B); - emit_operand(dst, src); -} - -void Assembler::sbbq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } - emit_arith(0x1B, 0xC0, dst, src); -} - -void Assembler::shll(Register dst, int imm8) -{ +void Assembler::shll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding()); if (imm8 == 1 ) { emit_byte(0xD1); - emit_byte(0xE0 | dstenc); + emit_byte(0xE0 | encode); + } else { + emit_byte(0xC1); + emit_byte(0xE0 | encode); + emit_byte(imm8); + } +} + +void Assembler::shll(Register dst) { + int encode = prefix_and_encode(dst->encoding()); + emit_byte(0xD3); + emit_byte(0xE0 | encode); +} + +void Assembler::shlq(Register dst, int imm8) { + assert(isShiftCount(imm8 >> 1), "illegal shift count"); + int encode = prefixq_and_encode(dst->encoding()); + if (imm8 == 1) { + emit_byte(0xD1); + emit_byte(0xE0 | encode); } else { emit_byte(0xC1); - emit_byte(0xE0 | dstenc); - emit_byte(imm8); - } -} - -void Assembler::shll(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } - emit_byte(0xD3); - emit_byte(0xE0 | dstenc); -} - -void Assembler::shlq(Register dst, int imm8) -{ - assert(isShiftCount(imm8 >> 1), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } - if (imm8 == 1) { - emit_byte(0xD1); - emit_byte(0xE0 | dstenc); - } else { - emit_byte(0xC1); - emit_byte(0xE0 | dstenc); + emit_byte(0xE0 | encode); emit_byte(imm8); } } -void Assembler::shlq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } +void Assembler::shlq(Register dst) { + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xD3); - emit_byte(0xE0 | dstenc); -} - -void Assembler::shrl(Register dst, int imm8) -{ + emit_byte(0xE0 | encode); +} + +void Assembler::shrl(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xC1); - emit_byte(0xE8 | dstenc); + emit_byte(0xE8 | encode); emit_byte(imm8); } -void Assembler::shrl(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } +void Assembler::shrl(Register dst) { + int encode = prefix_and_encode(dst->encoding()); emit_byte(0xD3); - emit_byte(0xE8 | dstenc); -} - -void Assembler::shrq(Register dst, int imm8) -{ + emit_byte(0xE8 | encode); +} + +void Assembler::shrq(Register dst, int imm8) { assert(isShiftCount(imm8 >> 1), "illegal shift count"); - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xC1); - emit_byte(0xE8 | dstenc); + emit_byte(0xE8 | encode); emit_byte(imm8); } -void Assembler::shrq(Register dst) -{ - int dstenc = dst->encoding(); - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } +void Assembler::shrq(Register dst) { + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xD3); - emit_byte(0xE8 | dstenc); + emit_byte(0xE8 | encode); } -void Assembler::subl(Address dst, int imm32) -{ +void Assembler::subl(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); if (is8bit(imm32)) { emit_byte(0x83); emit_operand(rbp, dst, 1); @@ -3933,114 +2234,33 @@ } } -void Assembler::subl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::subl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xE8, dst, imm32); } -void Assembler::subl(Address dst, Register src) -{ +void Assembler::subl(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x29); emit_operand(src, dst); } -void Assembler::subl(Register dst, Address src) -{ +void Assembler::subl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x2B); emit_operand(dst, src); } -void Assembler::subl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::subl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x2B, 0xC0, dst, src); } -void Assembler::subq(Address dst, int imm32) -{ +void Assembler::subq(Address dst, int imm32) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } + prefixq(dst); if (is8bit(imm32)) { emit_byte(0x83); emit_operand(rbp, dst, 1); @@ -4052,605 +2272,185 @@ } } -void Assembler::subq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::subq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xE8, dst, imm32); } -void Assembler::subq(Address dst, Register src) -{ +void Assembler::subq(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(dst, src); emit_byte(0x29); emit_operand(src, dst); } -void Assembler::subq(Register dst, Address src) -{ +void Assembler::subq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x2B); emit_operand(dst, src); } -void Assembler::subq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::subq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x2B, 0xC0, dst, src); } -void Assembler::testb(Register dst, int imm8) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - } else if (dstenc >= 4) { - prefix(REX); - } +void Assembler::testb(Register dst, int imm8) { + (void) prefix_and_encode(dst->encoding(), true); emit_arith_b(0xF6, 0xC0, dst, imm8); } -void Assembler::testl(Register dst, int imm32) -{ +void Assembler::testl(Register dst, int imm32) { // not using emit_arith because test // doesn't support sign-extension of // 8bit operands - int dstenc = dst->encoding(); - if (dstenc == 0) { + int encode = dst->encoding(); + if (encode == 0) { emit_byte(0xA9); } else { - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } + encode = prefix_and_encode(encode); emit_byte(0xF7); - emit_byte(0xC0 | dstenc); + emit_byte(0xC0 | encode); } emit_long(imm32); } -void Assembler::testl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::testl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x85, 0xC0, dst, src); } -void Assembler::testq(Register dst, int imm32) -{ +void Assembler::testq(Register dst, int imm32) { // not using emit_arith because test // doesn't support sign-extension of // 8bit operands - int dstenc = dst->encoding(); - if (dstenc == 0) { + int encode = dst->encoding(); + if (encode == 0) { prefix(REX_W); emit_byte(0xA9); } else { - if (dstenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - dstenc -= 8; - } + encode = prefixq_and_encode(encode); emit_byte(0xF7); - emit_byte(0xC0 | dstenc); + emit_byte(0xC0 | encode); } emit_long(imm32); } -void Assembler::testq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::testq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x85, 0xC0, dst, src); } -void Assembler::xaddl(Address dst, Register src) -{ +void Assembler::xaddl(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(dst, src); emit_byte(0x0F); emit_byte(0xC1); emit_operand(src, dst); } -void Assembler::xaddq(Address dst, Register src) -{ +void Assembler::xaddq(Address dst, Register src) { InstructionMark im(this); - if (src->encoding() < 8) { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(dst, src); emit_byte(0x0F); emit_byte(0xC1); emit_operand(src, dst); } -void Assembler::xorl(Register dst, int imm32) -{ - if (dst->encoding() >= 8) { - prefix(REX_B); - } +void Assembler::xorl(Register dst, int imm32) { + prefix(dst); emit_arith(0x81, 0xF0, dst, imm32); } -void Assembler::xorl(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() >= 8) { - prefix(REX_B); - } - } else { - if (src->encoding() < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - } - } +void Assembler::xorl(Register dst, Register src) { + (void) prefix_and_encode(dst->encoding(), src->encoding()); emit_arith(0x33, 0xC0, dst, src); } -void Assembler::xorl(Register dst, Address src) -{ +void Assembler::xorl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x33); emit_operand(dst, src); } -void Assembler::xorq(Register dst, int imm32) -{ - if (dst->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } +void Assembler::xorq(Register dst, int imm32) { + (void) prefixq_and_encode(dst->encoding()); emit_arith(0x81, 0xF0, dst, imm32); } -void Assembler::xorq(Register dst, Register src) -{ - if (dst->encoding() < 8) { - if (src->encoding() < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - } - } else { - if (src->encoding() < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - } - } +void Assembler::xorq(Register dst, Register src) { + (void) prefixq_and_encode(dst->encoding(), src->encoding()); emit_arith(0x33, 0xC0, dst, src); } -void Assembler::xorq(Register dst, Address src) -{ +void Assembler::xorq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x33); emit_operand(dst, src); } -void Assembler::bswapl(Register reg) -{ - int regenc = reg->encoding(); - if (regenc >= 8) { - prefix(REX_B); - regenc -= 8; - } +void Assembler::bswapl(Register reg) { + int encode = prefix_and_encode(reg->encoding()); emit_byte(0x0F); - emit_byte(0xC8 | regenc); -} - -void Assembler::bswapq(Register reg) -{ - int regenc = reg->encoding(); - if (regenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - regenc -= 8; - } + emit_byte(0xC8 | encode); +} + +void Assembler::bswapq(Register reg) { + int encode = prefixq_and_encode(reg->encoding()); emit_byte(0x0F); - emit_byte(0xC8 | regenc); -} - -void Assembler::lock() -{ + emit_byte(0xC8 | encode); +} + +void Assembler::lock() { emit_byte(0xF0); } -void Assembler::xchgl(Register dst, Address src) -{ +void Assembler::xchgl(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x87); emit_operand(dst, src); } -void Assembler::xchgl(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::xchgl(Register dst, Register src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x87); - emit_byte(0xc0 | dstenc << 3 | srcenc); -} - -void Assembler::xchgq(Register dst, Address src) -{ + emit_byte(0xc0 | encode); +} + +void Assembler::xchgq(Register dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(src, dst); emit_byte(0x87); emit_operand(dst, src); } -void Assembler::xchgq(Register dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::xchgq(Register dst, Register src) { + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x87); - emit_byte(0xc0 | dstenc << 3 | srcenc); -} - -void Assembler::cmpxchgl(Register reg, Address adr) -{ + emit_byte(0xc0 | encode); +} + +void Assembler::cmpxchgl(Register reg, Address adr) { InstructionMark im(this); - if (reg->encoding() < 8) { - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(adr, reg); emit_byte(0x0F); emit_byte(0xB1); emit_operand(reg, adr); } -void Assembler::cmpxchgq(Register reg, Address adr) -{ +void Assembler::cmpxchgq(Register reg, Address adr) { InstructionMark im(this); - if (reg->encoding() < 8) { - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } - } else { - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_WRXB); - } else { - prefix(REX_WRB); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_WRX); - } else { - prefix(REX_WR); - } - } - } + prefixq(adr, reg); emit_byte(0x0F); emit_byte(0xB1); emit_operand(reg, adr); } -void Assembler::hlt() -{ +void Assembler::hlt() { emit_byte(0xF4); } @@ -4794,8 +2594,7 @@ } } -void Assembler::ret(int imm16) -{ +void Assembler::ret(int imm16) { if (imm16 == 0) { emit_byte(0xC3); } else { @@ -4810,8 +2609,7 @@ } // copies data from [rsi] to [rdi] using rcx words (m32) -void Assembler::rep_movl() -{ +void Assembler::rep_movl() { // REP emit_byte(0xF3); // MOVSL @@ -4819,8 +2617,7 @@ } // copies data from [rsi] to [rdi] using rcx double words (m64) -void Assembler::rep_movq() -{ +void Assembler::rep_movq() { // REP emit_byte(0xF3); // MOVSQ @@ -4829,8 +2626,7 @@ } // sets rcx double words (m64) with rax value at [rdi] -void Assembler::rep_set() -{ +void Assembler::rep_set() { // REP emit_byte(0xF3); // STOSQ @@ -4839,8 +2635,7 @@ } // scans rcx double words (m64) at [rdi] for occurance of rax -void Assembler::repne_scan() -{ +void Assembler::repne_scan() { // REPNE/REPNZ emit_byte(0xF2); // SCASQ @@ -4848,41 +2643,22 @@ emit_byte(0xAF); } -void Assembler::setb(Condition cc, Register dst) -{ +void Assembler::setb(Condition cc, Register dst) { assert(0 <= cc && cc < 16, "illegal cc"); - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } else if (dstenc >= 4) { - prefix(REX); - } + int encode = prefix_and_encode(dst->encoding(), true); emit_byte(0x0F); emit_byte(0x90 | cc); - emit_byte(0xC0 | dstenc); -} - -void Assembler::clflush(Address adr) -{ - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_X); - } - } + emit_byte(0xC0 | encode); +} + +void Assembler::clflush(Address adr) { + prefix(adr); emit_byte(0x0F); emit_byte(0xAE); emit_operand(rdi, adr); } -void Assembler::call(Label& L, relocInfo::relocType rtype) -{ +void Assembler::call(Label& L, relocInfo::relocType rtype) { if (L.is_bound()) { const int long_size = 5; int offs = (int)( target(L) - pc() ); @@ -4901,122 +2677,74 @@ } } -void Assembler::call(address entry, relocInfo::relocType rtype) -{ - assert(rtype != relocInfo::virtual_call_type, - "must use virtual_call_Relocation::spec"); +void Assembler::call_literal(address entry, RelocationHolder const& rspec) { assert(entry != NULL, "call most probably wrong"); InstructionMark im(this); emit_byte(0xE8); - intptr_t disp = (intptr_t) entry - ((intptr_t) _code_pos + sizeof(int)); - assert(is_simm32(disp), "must be 32bit offset (call1)"); - // Technically, should use call32_operand, but this format is - // implied by the fact that we're emitting a call instruction. - emit_data((int) disp, rtype, disp32_operand); -} - -void Assembler::call(address entry, RelocationHolder const& rspec) -{ - assert(entry != NULL, "call most probably wrong"); - InstructionMark im(this); - emit_byte(0xE8); - intptr_t disp = (intptr_t) entry - ((intptr_t) _code_pos + sizeof(int)); + intptr_t disp = entry - (_code_pos + sizeof(int32_t)); assert(is_simm32(disp), "must be 32bit offset (call2)"); // Technically, should use call32_operand, but this format is // implied by the fact that we're emitting a call instruction. emit_data((int) disp, rspec, disp32_operand); } -void Assembler::call(Register dst, relocInfo::relocType rtype) -{ - int dstenc = dst->encoding(); - if (dstenc >= 8) { - prefix(REX_B); - dstenc -= 8; - } - relocate(rtype); + +void Assembler::call(Register dst) { + // This was originally using a 32bit register encoding + // and surely we want 64bit! + // this is a 32bit encoding but in 64bit mode the default + // operand size is 64bit so there is no need for the + // wide prefix. So prefix only happens if we use the + // new registers. Much like push/pop. + int encode = prefixq_and_encode(dst->encoding()); emit_byte(0xFF); - emit_byte(0xD0 | dstenc); -} - -void Assembler::call(Address adr) -{ + emit_byte(0xD0 | encode); +} + +void Assembler::call(Address adr) { InstructionMark im(this); - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(adr); emit_byte(0xFF); emit_operand(rdx, adr); } -void Assembler::jmp(Register reg, relocInfo::relocType rtype) -{ - int regenc = reg->encoding(); - if (regenc >= 8) { - prefix(REX_B); - regenc -= 8; - } - relocate(rtype); +void Assembler::jmp(Register reg) { + int encode = prefix_and_encode(reg->encoding()); emit_byte(0xFF); - emit_byte(0xE0 | regenc); -} - -void Assembler::jmp(Address adr) -{ + emit_byte(0xE0 | encode); +} + +void Assembler::jmp(Address adr) { InstructionMark im(this); - if (adr.base_needs_rex()) { - if (adr.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (adr.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(adr); emit_byte(0xFF); emit_operand(rsp, adr); } -void Assembler::jmp(address entry, relocInfo::relocType rtype) -{ - assert(entry != NULL, "jmp most probably wrong"); +void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { InstructionMark im(this); - relocate(rtype); - const int short_size = 2; - const int long_size = 5; - intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos; - if (rtype == relocInfo::none && is8bit(offs - short_size)) { - emit_byte(0xEB); - emit_byte((offs - short_size) & 0xFF); - } else { - assert(is_simm32(offs - long_size), - "must be 32bit offset (call3)"); - emit_byte(0xE9); - emit_long(offs - long_size); - } -} - -void Assembler::jmpb(address entry) { - const int short_size = 2; - assert(is8bit((intptr_t)entry - ((intptr_t)_code_pos + short_size)), - "Dispacement too large for a short jmp"); - jmp(entry, relocInfo::none); -} - -void Assembler::jmp(Label& L, relocInfo::relocType rtype) -{ + emit_byte(0xE9); + assert(dest != NULL, "must have a target"); + intptr_t disp = dest - (_code_pos + sizeof(int32_t)); + assert(is_simm32(disp), "must be 32bit offset (jmp)"); + emit_data(disp, rspec.reloc(), call32_operand); +} + +void Assembler::jmp(Label& L, relocInfo::relocType rtype) { if (L.is_bound()) { - jmp(target(L), rtype); + address entry = target(L); + assert(entry != NULL, "jmp most probably wrong"); + InstructionMark im(this); + const int short_size = 2; + const int long_size = 5; + intptr_t offs = entry - _code_pos; + if (relocInfo::none && is8bit(offs - short_size)) { + emit_byte(0xEB); + emit_byte((offs - short_size) & 0xFF); + } else { + emit_byte(0xE9); + emit_long(offs - long_size); + } } else { // By default, forward jumps are always 32-bit displacements, since // we can't yet know where the label will be bound. If you're sure that @@ -5032,7 +2760,14 @@ void Assembler::jmpb(Label& L) { if (L.is_bound()) { - jmpb(target(L)); + const int short_size = 2; + address entry = target(L); + assert(is8bit((entry - _code_pos) + short_size), + "Dispacement too large for a short jmp"); + assert(entry != NULL, "jmp most probably wrong"); + intptr_t offs = entry - _code_pos; + emit_byte(0xEB); + emit_byte((offs - short_size) & 0xFF); } else { InstructionMark im(this); L.add_patch_at(code(), locator()); @@ -5041,42 +2776,34 @@ } } -void Assembler::jcc(Condition cc, address dst, relocInfo::relocType rtype) -{ - assert((0 <= cc) && (cc < 16), "illegal cc"); - assert(dst != NULL, "jcc most probably wrong"); - +void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { InstructionMark im(this); relocate(rtype); - const int short_size = 2; - const int long_size = 6; - intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos; - if (rtype == relocInfo::none && is8bit(offs - short_size)) { - // 0111 tttn #8-bit disp - emit_byte(0x70 | cc); - emit_byte((offs - short_size) & 0xFF); - } else { - // 0000 1111 1000 tttn #32-bit disp - assert(is_simm32(offs - long_size), - "must be 32bit offset (call4)"); - emit_byte(0x0F); - emit_byte(0x80 | cc); - emit_long(offs - long_size); - } -} - -void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) -{ assert((0 <= cc) && (cc < 16), "illegal cc"); if (L.is_bound()) { - jcc(cc, target(L), rtype); + address dst = target(L); + assert(dst != NULL, "jcc most probably wrong"); + + const int short_size = 2; + const int long_size = 6; + intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos; + if (rtype == relocInfo::none && is8bit(offs - short_size)) { + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + } else { + // 0000 1111 1000 tttn #32-bit disp + assert(is_simm32(offs - long_size), + "must be 32bit offset (call4)"); + emit_byte(0x0F); + emit_byte(0x80 | cc); + emit_long(offs - long_size); + } } else { // Note: could eliminate cond. jumps to this jump if condition // is the same however, seems to be rather unlikely case. // Note: use jccb() if label to be bound is very close to get // an 8-bit displacement - InstructionMark im(this); - relocate(rtype); L.add_patch_at(code(), locator()); emit_byte(0x0F); emit_byte(0x80 | cc); @@ -5086,7 +2813,15 @@ void Assembler::jccb(Condition cc, Label& L) { if (L.is_bound()) { - jccb(cc, target(L)); + const int short_size = 2; + const int long_size = 6; + address entry = target(L); + assert(is8bit((intptr_t)entry - ((intptr_t)_code_pos + short_size)), + "Dispacement too large for a short jmp"); + intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos; + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); } else { InstructionMark im(this); L.add_patch_at(code(), locator()); @@ -5095,987 +2830,324 @@ } } -void Assembler::jccb(Condition cc, address dst) { - const int short_size = 2; - assert(is8bit((intptr_t)dst - ((intptr_t)_code_pos + short_size)), - "Distance too far for short jmp"); - jcc(cc, dst, relocInfo::none); -} - - - // FP instructions -void Assembler::fxsave(Address dst) -{ - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } +void Assembler::fxsave(Address dst) { + prefixq(dst); emit_byte(0x0F); emit_byte(0xAE); emit_operand(as_Register(0), dst); } -void Assembler::fxrstor(Address src) -{ - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_WXB); - } else { - prefix(REX_WB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_WX); - } else { - prefix(REX_W); - } - } +void Assembler::fxrstor(Address src) { + prefixq(src); emit_byte(0x0F); emit_byte(0xAE); emit_operand(as_Register(1), src); } -void Assembler::ldmxcsr(Address src) -{ +void Assembler::ldmxcsr(Address src) { InstructionMark im(this); - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(src); emit_byte(0x0F); emit_byte(0xAE); emit_operand(as_Register(2), src); } -void Assembler::stmxcsr(Address dst) -{ +void Assembler::stmxcsr(Address dst) { InstructionMark im(this); - if (dst.base_needs_rex()) { - if (dst.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (dst.index_needs_rex()) { - prefix(REX_X); - } - } + prefix(dst); emit_byte(0x0F); emit_byte(0xAE); emit_operand(as_Register(3), dst); } -void Assembler::addss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::addss(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x58); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::addss(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::addss(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF3); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x58); emit_operand(dst, src); } -void Assembler::subss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::subss(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::subss(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::subss(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF3); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x5C); emit_operand(dst, src); } -void Assembler::mulss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::mulss(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x59); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::mulss(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::mulss(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF3); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x59); emit_operand(dst, src); } -void Assembler::divss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::divss(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5E); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::divss(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::divss(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF3); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x5E); emit_operand(dst, src); } -void Assembler::addsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::addsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x58); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::addsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::addsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x58); emit_operand(dst, src); } -void Assembler::subsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::subsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::subsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::subsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x5C); emit_operand(dst, src); } -void Assembler::mulsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::mulsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x59); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::mulsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::mulsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x59); emit_operand(dst, src); } -void Assembler::divsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::divsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5E); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::divsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::divsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x5E); emit_operand(dst, src); } -void Assembler::sqrtsd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); +void Assembler::sqrtsd(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x51); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::sqrtsd(FloatRegister dst, Address src) -{ + emit_byte(0xC0 | encode); +} + +void Assembler::sqrtsd(FloatRegister dst, Address src) { InstructionMark im(this); emit_byte(0xF2); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + prefix(src, dst); emit_byte(0x0F); emit_byte(0x51); emit_operand(dst, src); } -void Assembler::xorps(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } +void Assembler::xorps(FloatRegister dst, FloatRegister src) { + int encode = prefix_and_encode(dst->encoding(), src->encoding()); + emit_byte(0x0F); + emit_byte(0x57); + emit_byte(0xC0 | encode); +} + +void Assembler::xorps(FloatRegister dst, Address src) { + InstructionMark im(this); + prefix(src, dst); emit_byte(0x0F); emit_byte(0x57); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::xorps(FloatRegister dst, Address src) -{ + emit_operand(dst, src); +} + +void Assembler::xorpd(FloatRegister dst, FloatRegister src) { + emit_byte(0x66); + xorps(dst, src); +} + +void Assembler::xorpd(FloatRegister dst, Address src) { InstructionMark im(this); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } + emit_byte(0x66); + prefix(src, dst); emit_byte(0x0F); emit_byte(0x57); emit_operand(dst, src); } -void Assembler::xorpd(FloatRegister dst, FloatRegister src) -{ - emit_byte(0x66); - xorps(dst, src); -} - -void Assembler::xorpd(FloatRegister dst, Address src) -{ - InstructionMark im(this); - emit_byte(0x66); - if (dst->encoding() < 8) { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_XB); - } else { - prefix(REX_B); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_X); - } - } - } else { - if (src.base_needs_rex()) { - if (src.index_needs_rex()) { - prefix(REX_RXB); - } else { - prefix(REX_RB); - } - } else { - if (src.index_needs_rex()) { - prefix(REX_RX); - } else { - prefix(REX_R); - } - } - } +void Assembler::cvtsi2ssl(FloatRegister dst, Register src) { + emit_byte(0xF3); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); - emit_byte(0x57); - emit_operand(dst, src); -} - -void Assembler::cvtsi2ssl(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0x2A); + emit_byte(0xC0 | encode); +} + +void Assembler::cvtsi2ssq(FloatRegister dst, Register src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2A); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvtsi2ssq(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + emit_byte(0xC0 | encode); +} + +void Assembler::cvtsi2sdl(FloatRegister dst, Register src) { + emit_byte(0xF2); + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2A); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvtsi2sdl(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvtsi2sdq(FloatRegister dst, Register src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } - emit_byte(0x0F); - emit_byte(0x2A); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvtsi2sdq(FloatRegister dst, Register src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); - emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2A); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvttss2sil(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvttss2sil(Register dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvttss2siq(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvttss2siq(Register dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvttsd2sil(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvttsd2sil(Register dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvttsd2siq(Register dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvttsd2siq(Register dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc < 8) { - prefix(REX_W); - } else { - prefix(REX_WB); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_WR); - } else { - prefix(REX_WRB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x2C); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvtss2sd(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvtss2sd(FloatRegister dst, FloatRegister src) { emit_byte(0xF3); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5A); - emit_byte(0xC0 | dstenc << 3 | srcenc); -} - -void Assembler::cvtsd2ss(FloatRegister dst, FloatRegister src) -{ - int dstenc = dst->encoding(); - int srcenc = src->encoding(); + emit_byte(0xC0 | encode); +} + +void Assembler::cvtsd2ss(FloatRegister dst, FloatRegister src) { emit_byte(0xF2); - if (dstenc < 8) { - if (srcenc >= 8) { - prefix(REX_B); - srcenc -= 8; - } - } else { - if (srcenc < 8) { - prefix(REX_R); - } else { - prefix(REX_RB); - srcenc -= 8; - } - dstenc -= 8; - } + int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_byte(0x0F); emit_byte(0x5A); - emit_byte(0xC0 | dstenc << 3 | srcenc); + emit_byte(0xC0 | encode); } // Implementation of MacroAssembler -void MacroAssembler::fat_nop() -{ +// On 32 bit it returns a vanilla displacement on 64 bit is a rip relative displacement +Address MacroAssembler::as_Address(AddressLiteral adr) { + assert(!adr.is_lval(), "must be rval"); + assert(reachable(adr), "must be"); + return Address((int)(intptr_t)(adr.target() - pc()), adr.target(), adr.reloc()); +} + +Address MacroAssembler::as_Address(ArrayAddress adr) { +#ifdef _LP64 + AddressLiteral base = adr.base(); + lea(rscratch1, base); + Address index = adr.index(); + assert(index._disp == 0, "must not have disp"); // maybe it can? + Address array(rscratch1, index._index, index._scale, index._disp); + return array; +#else + return Address::make_array(adr); +#endif // _LP64 + +} + +void MacroAssembler::fat_nop() { // A 5 byte nop that is safe for patching (see patch_verified_entry) // Recommened sequence from 'Software Optimization Guide for the AMD // Hammer Processor' @@ -6106,31 +3178,350 @@ }; -void MacroAssembler::jcc(Condition cc, address dst, relocInfo::relocType rtype) -{ - Address dest(dst, rtype); - if (check_reach(dest)) { - Assembler::jcc(cc, dst, rtype); - } - else { +// 32bit can do a case table jump in one instruction but we no longer allow the base +// to be installed in the Address class +void MacroAssembler::jump(ArrayAddress entry) { +#ifdef _LP64 + lea(rscratch1, entry.base()); + Address dispatch = entry.index(); + assert(dispatch._base == noreg, "must be"); + dispatch._base = rscratch1; + jmp(dispatch); +#else + jmp(as_Address(entry)); +#endif // _LP64 +} + +void MacroAssembler::jump(AddressLiteral dst) { + if (reachable(dst)) { + jmp_literal(dst.target(), dst.rspec()); + } else { + lea(rscratch1, dst); + jmp(rscratch1); + } +} + +void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) { + if (reachable(dst)) { + InstructionMark im(this); + relocate(dst.reloc()); + const int short_size = 2; + const int long_size = 6; + int offs = (intptr_t)dst.target() - ((intptr_t)_code_pos); + if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) { + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + } else { + // 0000 1111 1000 tttn #32-bit disp + emit_byte(0x0F); + emit_byte(0x80 | cc); + emit_long(offs - long_size); + } + } else { #ifdef ASSERT warning("reversing conditional branch"); #endif /* ASSERT */ Label skip; - Assembler::jccb(reverse[cc], skip); - Assembler::movq(rscratch1, dst, rtype); - jmp(rscratch1); + jccb(reverse[cc], skip); + lea(rscratch1, dst); + Assembler::jmp(rscratch1); bind(skip); } } -void MacroAssembler::null_check(Register reg, int offset) -{ +// Wouldn't need if AddressLiteral version had new name +void MacroAssembler::call(Label& L, relocInfo::relocType rtype) { + Assembler::call(L, rtype); +} + +// Wouldn't need if AddressLiteral version had new name +void MacroAssembler::call(Register entry) { + Assembler::call(entry); +} + +void MacroAssembler::call(AddressLiteral entry) { + if (reachable(entry)) { + Assembler::call_literal(entry.target(), entry.rspec()); + } else { + lea(rscratch1, entry); + Assembler::call(rscratch1); + } +} + +void MacroAssembler::cmp8(AddressLiteral src1, int8_t src2) { + if (reachable(src1)) { + cmpb(as_Address(src1), src2); + } else { + lea(rscratch1, src1); + cmpb(Address(rscratch1, 0), src2); + } +} + +void MacroAssembler::cmp32(AddressLiteral src1, int32_t src2) { + if (reachable(src1)) { + cmpl(as_Address(src1), src2); + } else { + lea(rscratch1, src1); + cmpl(Address(rscratch1, 0), src2); + } +} + +void MacroAssembler::cmp32(Register src1, AddressLiteral src2) { + if (reachable(src2)) { + cmpl(src1, as_Address(src2)); + } else { + lea(rscratch1, src2); + cmpl(src1, Address(rscratch1, 0)); + } +} + +void MacroAssembler::cmpptr(Register src1, AddressLiteral src2) { +#ifdef _LP64 + if (src2.is_lval()) { + movptr(rscratch1, src2); + Assembler::cmpq(src1, rscratch1); + } else if (reachable(src2)) { + cmpq(src1, as_Address(src2)); + } else { + lea(rscratch1, src2); + Assembler::cmpq(src1, Address(rscratch1, 0)); + } +#else + if (src2.is_lval()) { + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); + } else { + cmpl(src1, as_Address(src2)); + } +#endif // _LP64 +} + +void MacroAssembler::cmpptr(Address src1, AddressLiteral src2) { + assert(src2.is_lval(), "not a mem-mem compare"); +#ifdef _LP64 + // moves src2's literal address + movptr(rscratch1, src2); + Assembler::cmpq(src1, rscratch1); +#else + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); +#endif // _LP64 +} + +void MacroAssembler::cmp64(Register src1, AddressLiteral src2) { + assert(!src2.is_lval(), "should use cmpptr"); + + if (reachable(src2)) { +#ifdef _LP64 + cmpq(src1, as_Address(src2)); +#else + ShouldNotReachHere(); +#endif // _LP64 + } else { + lea(rscratch1, src2); + Assembler::cmpq(src1, Address(rscratch1, 0)); + } +} + +void MacroAssembler::cmpxchgptr(Register reg, AddressLiteral adr) { + if (reachable(adr)) { +#ifdef _LP64 + cmpxchgq(reg, as_Address(adr)); +#else + cmpxchgl(reg, as_Address(adr)); +#endif // _LP64 + } else { + lea(rscratch1, adr); + cmpxchgq(reg, Address(rscratch1, 0)); + } +} + +void MacroAssembler::incrementl(AddressLiteral dst) { + if (reachable(dst)) { + incrementl(as_Address(dst)); + } else { + lea(rscratch1, dst); + incrementl(Address(rscratch1, 0)); + } +} + +void MacroAssembler::incrementl(ArrayAddress dst) { + incrementl(as_Address(dst)); +} + +void MacroAssembler::lea(Register dst, Address src) { +#ifdef _LP64 + leaq(dst, src); +#else + leal(dst, src); +#endif // _LP64 +} + +void MacroAssembler::lea(Register dst, AddressLiteral src) { +#ifdef _LP64 + mov_literal64(dst, (intptr_t)src.target(), src.rspec()); +#else + mov_literal32(dst, (intptr_t)src.target(), src.rspec()); +#endif // _LP64 +} + +void MacroAssembler::mov32(AddressLiteral dst, Register src) { + if (reachable(dst)) { + movl(as_Address(dst), src); + } else { + lea(rscratch1, dst); + movl(Address(rscratch1, 0), src); + } +} + +void MacroAssembler::mov32(Register dst, AddressLiteral src) { + if (reachable(src)) { + movl(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movl(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movdbl(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + if (UseXmmLoadAndClearUpper) { + movsd (dst, as_Address(src)); + } else { + movlpd(dst, as_Address(src)); + } + } else { + lea(rscratch1, src); + if (UseXmmLoadAndClearUpper) { + movsd (dst, Address(rscratch1, 0)); + } else { + movlpd(dst, Address(rscratch1, 0)); + } + } +} + +void MacroAssembler::movflt(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + movss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movss(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movoop(Register dst, jobject obj) { + mov_literal64(dst, (intptr_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movoop(Address dst, jobject obj) { + mov_literal64(rscratch1, (intptr_t)obj, oop_Relocation::spec_for_immediate()); + movq(dst, rscratch1); +} + +void MacroAssembler::movptr(Register dst, AddressLiteral src) { +#ifdef _LP64 + if (src.is_lval()) { + mov_literal64(dst, (intptr_t)src.target(), src.rspec()); + } else { + if (reachable(src)) { + movq(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movq(dst, Address(rscratch1,0)); + } + } +#else + if (src.is_lval()) { + mov_literal32(dst, (intptr_t)src.target(), src.rspec()); + } else { + movl(dst, as_Address(src)); + } +#endif // LP64 +} + +void MacroAssembler::movptr(ArrayAddress dst, Register src) { +#ifdef _LP64 + movq(as_Address(dst), src); +#else + movl(as_Address(dst), src); +#endif // _LP64 +} + +void MacroAssembler::pushoop(jobject obj) { +#ifdef _LP64 + movoop(rscratch1, obj); + pushq(rscratch1); +#else + push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); +#endif // _LP64 +} + +void MacroAssembler::pushptr(AddressLiteral src) { +#ifdef _LP64 + lea(rscratch1, src); + if (src.is_lval()) { + pushq(rscratch1); + } else { + pushq(Address(rscratch1, 0)); + } +#else + if (src.is_lval()) { + push_literal((int32_t)src.target(), src.rspec()); + else { + pushl(as_Address(src)); + } +#endif // _LP64 +} + +void MacroAssembler::ldmxcsr(AddressLiteral src) { + if (reachable(src)) { + Assembler::ldmxcsr(as_Address(src)); + } else { + lea(rscratch1, src); + Assembler::ldmxcsr(Address(rscratch1, 0)); + } +} + +void MacroAssembler::movlpd(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + movlpd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movlpd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::movss(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + movss(dst, as_Address(src)); + } else { + lea(rscratch1, src); + movss(dst, Address(rscratch1, 0)); + } +} +void MacroAssembler::xorpd(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + xorpd(dst, as_Address(src)); + } else { + lea(rscratch1, src); + xorpd(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::xorps(FloatRegister dst, AddressLiteral src) { + if (reachable(src)) { + xorps(dst, as_Address(src)); + } else { + lea(rscratch1, src); + xorps(dst, Address(rscratch1, 0)); + } +} + +void MacroAssembler::null_check(Register reg, int offset) { if (needs_explicit_null_check(offset)) { // provoke OS NULL exception if reg = NULL by // accessing M[reg] w/o changing any (non-CC) registers - cmpq(rax, Address(reg)); - // Note: should probably use testl(rax, Address(reg)); + cmpq(rax, Address(reg, 0)); + // Note: should probably use testl(rax, Address(reg, 0)); // may be shorter code (however, this version of // testl needs to be implemented first) } else { @@ -6139,36 +3530,31 @@ } } -int MacroAssembler::load_unsigned_byte(Register dst, Address src) -{ +int MacroAssembler::load_unsigned_byte(Register dst, Address src) { int off = offset(); movzbl(dst, src); return off; } -int MacroAssembler::load_unsigned_word(Register dst, Address src) -{ +int MacroAssembler::load_unsigned_word(Register dst, Address src) { int off = offset(); movzwl(dst, src); return off; } -int MacroAssembler::load_signed_byte(Register dst, Address src) -{ +int MacroAssembler::load_signed_byte(Register dst, Address src) { int off = offset(); movsbl(dst, src); return off; } -int MacroAssembler::load_signed_word(Register dst, Address src) -{ +int MacroAssembler::load_signed_word(Register dst, Address src) { int off = offset(); movswl(dst, src); return off; } -void MacroAssembler::incrementl(Register reg, int value) -{ +void MacroAssembler::incrementl(Register reg, int value) { if (value == min_jint) { addl(reg, value); return; } if (value < 0) { decrementl(reg, -value); return; } if (value == 0) { ; return; } @@ -6176,8 +3562,7 @@ /* else */ { addl(reg, value) ; return; } } -void MacroAssembler::decrementl(Register reg, int value) -{ +void MacroAssembler::decrementl(Register reg, int value) { if (value == min_jint) { subl(reg, value); return; } if (value < 0) { incrementl(reg, -value); return; } if (value == 0) { ; return; } @@ -6185,8 +3570,7 @@ /* else */ { subl(reg, value) ; return; } } -void MacroAssembler::incrementq(Register reg, int value) -{ +void MacroAssembler::incrementq(Register reg, int value) { if (value == min_jint) { addq(reg, value); return; } if (value < 0) { decrementq(reg, -value); return; } if (value == 0) { ; return; } @@ -6194,8 +3578,7 @@ /* else */ { addq(reg, value) ; return; } } -void MacroAssembler::decrementq(Register reg, int value) -{ +void MacroAssembler::decrementq(Register reg, int value) { if (value == min_jint) { subq(reg, value); return; } if (value < 0) { incrementq(reg, -value); return; } if (value == 0) { ; return; } @@ -6203,8 +3586,7 @@ /* else */ { subq(reg, value) ; return; } } -void MacroAssembler::incrementl(Address dst, int value) -{ +void MacroAssembler::incrementl(Address dst, int value) { if (value == min_jint) { addl(dst, value); return; } if (value < 0) { decrementl(dst, -value); return; } if (value == 0) { ; return; } @@ -6212,8 +3594,7 @@ /* else */ { addl(dst, value) ; return; } } -void MacroAssembler::decrementl(Address dst, int value) -{ +void MacroAssembler::decrementl(Address dst, int value) { if (value == min_jint) { subl(dst, value); return; } if (value < 0) { incrementl(dst, -value); return; } if (value == 0) { ; return; } @@ -6221,8 +3602,7 @@ /* else */ { subl(dst, value) ; return; } } -void MacroAssembler::incrementq(Address dst, int value) -{ +void MacroAssembler::incrementq(Address dst, int value) { if (value == min_jint) { addq(dst, value); return; } if (value < 0) { decrementq(dst, -value); return; } if (value == 0) { ; return; } @@ -6230,8 +3610,7 @@ /* else */ { addq(dst, value) ; return; } } -void MacroAssembler::decrementq(Address dst, int value) -{ +void MacroAssembler::decrementq(Address dst, int value) { if (value == min_jint) { subq(dst, value); return; } if (value < 0) { incrementq(dst, -value); return; } if (value == 0) { ; return; } @@ -6239,21 +3618,18 @@ /* else */ { subq(dst, value) ; return; } } -void MacroAssembler::align(int modulus) -{ +void MacroAssembler::align(int modulus) { if (offset() % modulus != 0) { nop(modulus - (offset() % modulus)); } } -void MacroAssembler::enter() -{ +void MacroAssembler::enter() { pushq(rbp); movq(rbp, rsp); } -void MacroAssembler::leave() -{ +void MacroAssembler::leave() { emit_byte(0xC9); // LEAVE } @@ -6314,8 +3690,7 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_java_fp, - address last_java_pc) -{ + address last_java_pc) { // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; @@ -6329,38 +3704,34 @@ // last_java_pc is optional if (last_java_pc != NULL) { - Assembler::movq(rscratch1, last_java_pc, relocInfo::internal_word_type); - - movq(Address(r15_thread, - JavaThread::frame_anchor_offset() + - JavaFrameAnchor::last_Java_pc_offset()), - rscratch1); + Address java_pc(r15_thread, + JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); + lea(rscratch1, InternalAddress(last_java_pc)); + movq(java_pc, rscratch1); } movq(Address(r15_thread, JavaThread::last_Java_sp_offset()), last_java_sp); } void MacroAssembler::reset_last_Java_frame(bool clear_fp, - bool clear_pc) -{ + bool clear_pc) { // we must set sp to zero to clear frame - movq(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_sp_offset()), NULL_WORD); // must clear fp, so that compiled frames are not confused; it is // possible that we need it only for debugging if (clear_fp) { - movq(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_fp_offset()), NULL_WORD); } if (clear_pc) { - movq(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); } } // Implementation of call_VM versions -void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) -{ +void MacroAssembler::call_VM_leaf_base(address entry_point, int num_args) { Label L, E; #ifdef _WIN64 @@ -6374,12 +3745,16 @@ jcc(Assembler::zero, L); subq(rsp, 8); - call(entry_point, relocInfo::runtime_call_type); + { + call(RuntimeAddress(entry_point)); + } addq(rsp, 8); jmp(E); bind(L); - call(entry_point, relocInfo::runtime_call_type); + { + call(RuntimeAddress(entry_point)); + } bind(E); @@ -6396,8 +3771,7 @@ Register last_java_sp, address entry_point, int num_args, - bool check_exceptions) -{ + bool check_exceptions) { // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; @@ -6432,13 +3806,17 @@ jcc(Assembler::zero, L); subq(rsp, 8); - call(entry_point, relocInfo::runtime_call_type); + { + call(RuntimeAddress(entry_point)); + } addq(rsp, 8); jmp(E); bind(L); - call(entry_point, relocInfo::runtime_call_type); + { + call(RuntimeAddress(entry_point)); + } bind(E); @@ -6476,14 +3854,14 @@ // around so we can always reach Label ok; jcc(Assembler::equal, ok); - jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + jump(RuntimeAddress(StubRoutines::forward_exception_entry())); bind(ok); } // get oop result if there is one and reset the value in the thread if (oop_result->is_valid()) { movq(oop_result, Address(r15_thread, JavaThread::vm_result_offset())); - movq(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); + movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); verify_oop(oop_result); } } @@ -6494,8 +3872,7 @@ void MacroAssembler::call_VM_helper(Register oop_result, address entry_point, int num_args, - bool check_exceptions) -{ + bool check_exceptions) { // Java thread becomes first argument of C function movq(c_rarg0, r15_thread); @@ -6509,8 +3886,7 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, - bool check_exceptions) -{ + bool check_exceptions) { Label C, E; Assembler::call(C, relocInfo::none); jmp(E); @@ -6526,8 +3902,7 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, - bool check_exceptions) -{ + bool check_exceptions) { assert(rax != arg_1, "smashed argument"); assert(c_rarg0 != arg_1, "smashed argument"); @@ -6550,8 +3925,7 @@ address entry_point, Register arg_1, Register arg_2, - bool check_exceptions) -{ + bool check_exceptions) { assert(rax != arg_1, "smashed argument"); assert(rax != arg_2, "smashed argument"); assert(c_rarg0 != arg_1, "smashed argument"); @@ -6583,8 +3957,7 @@ Register arg_1, Register arg_2, Register arg_3, - bool check_exceptions) -{ + bool check_exceptions) { assert(rax != arg_1, "smashed argument"); assert(rax != arg_2, "smashed argument"); assert(rax != arg_3, "smashed argument"); @@ -6623,8 +3996,7 @@ Register last_java_sp, address entry_point, int num_args, - bool check_exceptions) -{ + bool check_exceptions) { call_VM_base(oop_result, noreg, last_java_sp, entry_point, num_args, check_exceptions); } @@ -6633,8 +4005,7 @@ Register last_java_sp, address entry_point, Register arg_1, - bool check_exceptions) -{ + bool check_exceptions) { assert(c_rarg0 != arg_1, "smashed argument"); assert(c_rarg1 != last_java_sp, "smashed argument"); // c_rarg0 is reserved for thread @@ -6649,8 +4020,7 @@ address entry_point, Register arg_1, Register arg_2, - bool check_exceptions) -{ + bool check_exceptions) { assert(c_rarg0 != arg_1, "smashed argument"); assert(c_rarg0 != arg_2, "smashed argument"); assert(c_rarg1 != arg_2, "smashed argument"); @@ -6674,8 +4044,7 @@ Register arg_1, Register arg_2, Register arg_3, - bool check_exceptions) -{ + bool check_exceptions) { assert(c_rarg0 != arg_1, "smashed argument"); assert(c_rarg0 != arg_2, "smashed argument"); assert(c_rarg0 != arg_3, "smashed argument"); @@ -6701,13 +4070,11 @@ call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); } -void MacroAssembler::call_VM_leaf(address entry_point, int num_args) -{ +void MacroAssembler::call_VM_leaf(address entry_point, int num_args) { call_VM_leaf_base(entry_point, num_args); } -void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1) -{ +void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1) { if (c_rarg0 != arg_1) { movq(c_rarg0, arg_1); } @@ -6716,8 +4083,7 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, - Register arg_2) -{ + Register arg_2) { assert(c_rarg0 != arg_2, "smashed argument"); assert(c_rarg1 != arg_1, "smashed argument"); if (c_rarg0 != arg_1) { @@ -6732,8 +4098,7 @@ void MacroAssembler::call_VM_leaf(address entry_point, Register arg_1, Register arg_2, - Register arg_3) -{ + Register arg_3) { assert(c_rarg0 != arg_2, "smashed argument"); assert(c_rarg0 != arg_3, "smashed argument"); assert(c_rarg1 != arg_1, "smashed argument"); @@ -6759,40 +4124,36 @@ // be recorded in the (thread-local) JavaThread object. When leaving C // land, the last Java fp has to be reset to 0. This is required to // allow proper stack traversal. -void MacroAssembler::store_check(Register obj) -{ +void MacroAssembler::store_check(Register obj) { // Does a store check for the oop in register obj. The content of // register obj is destroyed afterwards. store_check_part_1(obj); store_check_part_2(obj); } -void MacroAssembler::store_check(Register obj, Address dst) -{ +void MacroAssembler::store_check(Register obj, Address dst) { store_check(obj); } // split the store check operation so that other instructions can be // scheduled inbetween -void MacroAssembler::store_check_part_1(Register obj) -{ +void MacroAssembler::store_check_part_1(Register obj) { BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); shrq(obj, CardTableModRefBS::card_shift); } -void MacroAssembler::store_check_part_2(Register obj) -{ +void MacroAssembler::store_check_part_2(Register obj) { BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - movq(r10, (int64_t) ct->byte_map_base); - movb(Address(r10, obj, Address::times_1), 0); -} - -void MacroAssembler::c2bool(Register x) -{ + ExternalAddress cardtable((address)ct->byte_map_base); + Address index(noreg, obj, Address::times_1); + movb(as_Address(ArrayAddress(cardtable, index)), 0); +} + +void MacroAssembler::c2bool(Register x) { // implements x == 0 ? 0 : 1 // note: must only look at least-significant byte of x // since C-style booleans are stored in one byte @@ -6801,8 +4162,7 @@ setb(Assembler::notZero, x); } -int MacroAssembler::corrected_idivl(Register reg) -{ +int MacroAssembler::corrected_idivl(Register reg) { // Full implementation of Java idiv and irem; checks for special // case as described in JVM spec., p.243 & p.271. The function // returns the (pc) offset of the idivl instruction - may be needed @@ -6839,8 +4199,7 @@ return idivl_offset; } -int MacroAssembler::corrected_idivq(Register reg) -{ +int MacroAssembler::corrected_idivq(Register reg) { // Full implementation of Java ldiv and lrem; checks for special // case as described in JVM spec., p.243 & p.271. The function // returns the (pc) offset of the idivl instruction - may be needed @@ -6858,7 +4217,7 @@ Label normal_case, special_case; // check for special case - cmpq(rax, Address((address) &min_long, relocInfo::none)); + cmp64(rax, ExternalAddress((address) &min_long)); jcc(Assembler::notEqual, normal_case); xorl(rdx, rdx); // prepare rdx for possible special case (where // remainder = 0) @@ -6891,11 +4250,11 @@ void MacroAssembler::push_FPU_state() { subq(rsp, FPUStateSizeInWords * wordSize); - fxsave(Address(rsp)); + fxsave(Address(rsp, 0)); } void MacroAssembler::pop_FPU_state() { - fxrstor(Address(rsp)); + fxrstor(Address(rsp, 0)); addq(rsp, FPUStateSizeInWords * wordSize); } @@ -6911,18 +4270,15 @@ pop_IU_state(); } -void MacroAssembler::sign_extend_short(Register reg) -{ +void MacroAssembler::sign_extend_short(Register reg) { movswl(reg, reg); } -void MacroAssembler::sign_extend_byte(Register reg) -{ +void MacroAssembler::sign_extend_byte(Register reg) { movsbl(reg, reg); } -void MacroAssembler::division_with_shift(Register reg, int shift_value) -{ +void MacroAssembler::division_with_shift(Register reg, int shift_value) { assert (shift_value > 0, "illegal shift value"); Label _is_positive; testl (reg, reg); @@ -6939,20 +4295,17 @@ sarl(reg, shift_value); } -void MacroAssembler::round_to_l(Register reg, int modulus) -{ +void MacroAssembler::round_to_l(Register reg, int modulus) { addl(reg, modulus - 1); andl(reg, -modulus); } -void MacroAssembler::round_to_q(Register reg, int modulus) -{ +void MacroAssembler::round_to_q(Register reg, int modulus) { addq(reg, modulus - 1); andq(reg, -modulus); } -void MacroAssembler::verify_oop(Register reg, const char* s) -{ +void MacroAssembler::verify_oop(Register reg, const char* s) { if (!VerifyOops) { return; } @@ -6965,11 +4318,12 @@ // pass args on stack, only touch rax pushq(reg); - pushq(Address((address) b, relocInfo::none)); + ExternalAddress buffer((address) b); + pushptr(buffer.addr()); // call indirectly to solve generation ordering problem - movq(rax, (int64_t) StubRoutines::verify_oop_subroutine_entry_address()); - Assembler::call(rax); // no alignment requirement + movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(rax); // no alignment requirement // everything popped by receiver } @@ -6981,35 +4335,35 @@ pushq(rax); // save rax movq(addr, rax); pushq(rax); // pass register argument - pushq((intptr_t)b); // pass msg argument + ExternalAddress buffer((address) b); + // pass msg argument + pushptr(buffer.addr()); + // call indirectly to solve generation ordering problem - movq(rax, (int64_t)StubRoutines::verify_oop_subroutine_entry_address()); - Assembler::call(rax); // no alignment requirement + movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(rax); // no alignment requirement // everything popped by receiver } -void MacroAssembler::stop(const char* msg) -{ +void MacroAssembler::stop(const char* msg) { address rip = pc(); pushaq(); // get regs on stack - movq(c_rarg0, (int64_t) msg); - leaq(c_rarg1, Address(rip, relocInfo::none)); // get pc + lea(c_rarg0, ExternalAddress((address) msg)); + lea(c_rarg1, InternalAddress(rip)); movq(c_rarg2, rsp); // pass pointer to regs array andq(rsp, -16); // align stack as required by ABI - call(CAST_FROM_FN_PTR(address, MacroAssembler::debug), - relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); hlt(); } -void MacroAssembler::warn(const char* msg) -{ +void MacroAssembler::warn(const char* msg) { pushq(r12); movq(r12, rsp); andq(rsp, -16); // align stack as required by push_CPU_state and call push_CPU_state(); // keeps alignment at 16 bytes - movq(c_rarg0, (int64_t) msg); + lea(c_rarg0, ExternalAddress((address) msg)); call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); pop_CPU_state(); @@ -7017,8 +4371,7 @@ popq(r12); } -void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) -{ +void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) { // In order to get locks to work, we need to fake a in_VM state if (ShowMessageBoxOnError ) { JavaThread* thread = JavaThread::current(); @@ -7060,13 +4413,11 @@ } } -void MacroAssembler::os_breakpoint() -{ +void MacroAssembler::os_breakpoint() { // instead of directly emitting a breakpoint, call os:breakpoint for // better debugability // This shouldn't need alignment, it's an empty function - call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } // Write serialization page so VM thread can do a pseudo remote membar. @@ -7074,18 +4425,19 @@ // offset to write to within the page. This minimizes bus traffic // due to cache line collision. void MacroAssembler::serialize_memory(Register thread, - Register tmp1, - Register tmp2) -{ - movq(tmp2, thread); - shrq(tmp2, os::get_serialize_page_shift_count()); - movq(tmp1, (int64_t)os::get_memory_serialize_page()); - andq(tmp2, (os::vm_page_size() - sizeof(int))); - movl(Address(tmp2, tmp1,Address::times_1), tmp2); -} - -void MacroAssembler::verify_tlab() -{ + Register tmp) { + + movl(tmp, thread); + shrl(tmp, os::get_serialize_page_shift_count()); + andl(tmp, (os::vm_page_size() - sizeof(int))); + + Address index(noreg, tmp, Address::times_1); + ExternalAddress page(os::get_memory_serialize_page()); + + movptr(ArrayAddress(page, index), tmp); +} + +void MacroAssembler::verify_tlab() { #ifdef ASSERT if (UseTLAB) { Label next, ok; @@ -7118,14 +4470,14 @@ Register var_size_in_bytes, int con_size_in_bytes, Register t1, - Label& slow_case) -{ + Label& slow_case) { assert(obj == rax, "obj must be in rax for cmpxchg"); assert_different_registers(obj, var_size_in_bytes, t1); Register end = t1; Label retry; bind(retry); - movq(obj, Address((address) Universe::heap()->top_addr(), relocInfo::none)); + ExternalAddress heap_top((address) Universe::heap()->top_addr()); + movptr(obj, heap_top); if (var_size_in_bytes == noreg) { leaq(end, Address(obj, con_size_in_bytes)); } else { @@ -7134,7 +4486,8 @@ // if end < obj then we wrapped around => object too long => slow case cmpq(end, obj); jcc(Assembler::below, slow_case); - cmpq(end, Address((address) Universe::heap()->end_addr(), relocInfo::none)); + cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); + jcc(Assembler::above, slow_case); // Compare obj with the top addr, and if still equal, store the new // top addr in end at the address of the top addr pointer. Sets ZF @@ -7143,8 +4496,7 @@ if (os::is_MP()) { lock(); } - cmpxchgq(end, - Address((address) Universe::heap()->top_addr(), relocInfo::none)); + cmpxchgptr(end, heap_top); // if someone beat us on the allocation, try again, otherwise continue jcc(Assembler::notEqual, retry); } @@ -7155,8 +4507,7 @@ int con_size_in_bytes, Register t1, Register t2, - Label& slow_case) -{ + Label& slow_case) { assert_different_registers(obj, t1, t2); assert_different_registers(obj, var_size_in_bytes, t1); Register end = t2; @@ -7185,8 +4536,7 @@ // Preserves rbx and rdx. void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, - Label& slow_case) -{ + Label& slow_case) { Register top = rax; Register t1 = rcx; Register t2 = rsi; @@ -7215,7 +4565,7 @@ jcc(Assembler::lessEqual, discard_tlab); // Retain - movq(t2, ThreadLocalAllocBuffer::refill_waste_limit_increment()); + mov64(t2, ThreadLocalAllocBuffer::refill_waste_limit_increment()); addq(Address(thread_reg, // size_t in_bytes(JavaThread::tlab_refill_waste_limit_offset())), t2); @@ -7245,7 +4595,7 @@ jcc(Assembler::zero, do_refill); // set up the mark word - movq(t3, (int64_t) markOopDesc::prototype()->copy_set_hash(0x2)); + mov64(t3, (int64_t) markOopDesc::prototype()->copy_set_hash(0x2)); movq(Address(top, oopDesc::mark_offset_in_bytes()), t3); // set the length to the remaining space subq(t1, typeArrayOopDesc::header_size(T_INT)); @@ -7253,8 +4603,7 @@ shlq(t1, log2_intptr(HeapWordSize / sizeof(jint))); movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); // set klass to intArrayKlass - movq(t1, - Address((address) Universe::intArrayKlassObj_addr(), relocInfo::none)); + movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); movq(Address(top, oopDesc::klass_offset_in_bytes()), t1); // refill the tlab with an eden allocation @@ -7303,7 +4652,7 @@ assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); - Address saved_mark_addr(lock_reg); + Address saved_mark_addr(lock_reg, 0); if (PrintBiasedLockingStatistics && counters == NULL) counters = BiasedLocking::counters(); @@ -7332,7 +4681,8 @@ xorq(tmp_reg, swap_reg); andq(tmp_reg, ~((int) markOopDesc::age_mask_in_place)); if (counters != NULL) { - cond_incl(Assembler::zero, Address((address) counters->biased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); } jcc(Assembler::equal, done); @@ -7376,13 +4726,14 @@ if (os::is_MP()) { lock(); } - cmpxchgq(tmp_reg, Address(obj_reg)); + cmpxchgq(tmp_reg, Address(obj_reg, 0)); // If the biasing toward our thread failed, this means that // another thread succeeded in biasing it toward itself and we // need to revoke that bias. The revocation will occur in the // interpreter runtime in the slow case. if (counters != NULL) { - cond_incl(Assembler::zero, Address((address) counters->anonymously_biased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->anonymously_biased_lock_entry_count_addr())); } if (slow_case != NULL) { jcc(Assembler::notZero, *slow_case); @@ -7405,12 +4756,13 @@ if (os::is_MP()) { lock(); } - cmpxchgq(tmp_reg, Address(obj_reg)); + cmpxchgq(tmp_reg, Address(obj_reg, 0)); // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. if (counters != NULL) { - cond_incl(Assembler::zero, Address((address) counters->rebiased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->rebiased_lock_entry_count_addr())); } if (slow_case != NULL) { jcc(Assembler::notZero, *slow_case); @@ -7434,12 +4786,13 @@ if (os::is_MP()) { lock(); } - cmpxchgq(tmp_reg, Address(obj_reg)); + cmpxchgq(tmp_reg, Address(obj_reg, 0)); // Fall through to the normal CAS-based lock, because no matter what // the result of the above CAS, some thread must have succeeded in // removing the bias bit from the object's header. if (counters != NULL) { - cond_incl(Assembler::zero, Address((address) counters->revoked_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) counters->revoked_lock_entry_count_addr())); } bind(cas_label); @@ -7488,7 +4841,7 @@ } -void MacroAssembler::cond_incl(Condition cond, Address counter_addr) { +void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) { Condition negated_cond = negate_condition(cond); Label L; jcc(negated_cond, L); @@ -7496,7 +4849,7 @@ bind(L); } -void MacroAssembler::atomic_incl(Address counter_addr) { +void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { pushfq(); if (os::is_MP()) lock(); @@ -7507,8 +4860,7 @@ SkipIfEqual::SkipIfEqual( MacroAssembler* masm, const bool* flag_addr, bool value) { _masm = masm; - _masm->movq(rscratch1, (address)flag_addr, relocInfo::none); - _masm->cmpb(rscratch1, value); + _masm->cmp8(ExternalAddress((address)flag_addr), value); _masm->jcc(Assembler::equal, _label); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/assembler_amd64.hpp --- a/hotspot/src/cpu/amd64/vm/assembler_amd64.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/assembler_amd64.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)assembler_amd64.hpp 1.41 07/06/13 16:23:17 JVM" +#pragma ident "@(#)assembler_amd64.hpp 1.42 07/06/19 09:08:00 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -29,9 +29,9 @@ // Contains all the definitions needed for amd64 assembly code generation. +#ifdef _LP64 // Calling convention -class Argument VALUE_OBJ_CLASS_SPEC -{ +class Argument VALUE_OBJ_CLASS_SPEC { public: enum { #ifdef _WIN64 @@ -125,6 +125,7 @@ REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved +#endif // _LP64 // Address is an abstraction used to represent a memory location // using any of the amd64 addressing modes with one object. @@ -132,6 +133,8 @@ // Note: A register location is represented via a Register, not // via an address for efficiency & simplicity reasons. +class ArrayAddress; + class Address VALUE_OBJ_CLASS_SPEC { public: enum ScaleFactor { @@ -149,7 +152,9 @@ int _disp; RelocationHolder _rspec; - address _target; // only used for RIP-relative addressing + // Easily misused constructors make them private + Address::Address(int disp, address loc, relocInfo::relocType rtype); + Address::Address(int disp, address loc, RelocationHolder spec); public: // creation @@ -157,46 +162,24 @@ : _base(noreg), _index(noreg), _scale(no_scale), - _disp(0), - _target(NULL) - {} + _disp(0) { + } - // NOTE: this constructor takes a dummy argument so that we don't - // have implicit type conversion going on behind our pack. Possibly - // could be private instead. - Address(int disp, bool dummy) - : _base(noreg), - _index(noreg), - _scale(no_scale), - _disp(disp), - _target(NULL) - {} + // No default displacement otherwise Register can be implicitly + // converted to 0(Register) which is quite a different animal. - Address(address target, relocInfo::relocType rtype); - - Address(address target, RelocationHolder const& rspec) - : _base(noreg), - _index(noreg), - _scale(no_scale), - _rspec(rspec), - _disp(0), - _target(target) - {} - - Address(Register base, int disp = 0) + Address(Register base, int disp) : _base(base), _index(noreg), _scale(no_scale), - _disp(disp), - _target(NULL) - {} + _disp(disp) { + } Address(Register base, Register index, ScaleFactor scale, int disp = 0) : _base (base), _index(index), _scale(scale), - _disp (disp), - _target(NULL) { + _disp (disp) { assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address"); } @@ -217,16 +200,14 @@ : _base(base), _index(noreg), _scale(no_scale), - _disp(in_bytes(disp)), - _target(NULL) - {} + _disp(in_bytes(disp)) { + } Address(Register base, Register index, ScaleFactor scale, ByteSize disp) : _base(base), _index(index), _scale(scale), - _disp(in_bytes(disp)), - _target(NULL) { + _disp(in_bytes(disp)) { assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address"); } @@ -237,6 +218,7 @@ return _base == reg || _index == reg; } + static Address make_array(ArrayAddress); private: bool base_needs_rex() const { @@ -247,24 +229,126 @@ return _index != noreg &&_index->encoding() >= 8; } - bool is_rip_relative() const { - return _target != NULL; - } - - // Return true if the relocation is such that it will deserve a 64-bit - // relocation. We assume that everything in the code cache is reachable - // from everything else in the code cache but that from the code cache - // to external_word or runtime_call is too far. - bool is_far() const { - relocInfo::relocType r = _rspec.type(); - return r == relocInfo::runtime_call_type || r == relocInfo::external_word_type; - } relocInfo::relocType reloc() const { return _rspec.type(); } friend class Assembler; friend class MacroAssembler; + friend class LIR_Assembler; // base/index/scale/disp }; +// +// AddressLiteral has been split out from Address because operands of this type +// need to be treated specially on 32bit vs. 64bit platforms. By splitting it out +// the few instructions that need to deal with address literals are unique and the +// MacroAssembler does not have to implement every instruction in the Assembler +// in order to search for address literals that may need special handling depending +// on the instruction and the platform. As small step on the way to merging i486/amd64 +// directories. +// +class AddressLiteral VALUE_OBJ_CLASS_SPEC { + friend class ArrayAddress; + RelocationHolder _rspec; + // Typically we use AddressLiterals we want to use their rval + // However in some situations we want the lval (effect address) of the item. + // We provide a special factory for making those lvals. + bool _is_lval; + + // If the target is far we'll need to load the ea of this to + // a register to reach it. Otherwise if near we can do rip + // relative addressing. + + address _target; + + protected: + // creation + AddressLiteral() + : _is_lval(false), + _target(NULL) + {} + + public: + + + AddressLiteral(address target, relocInfo::relocType rtype); + + AddressLiteral(address target, RelocationHolder const& rspec) + : _rspec(rspec), + _is_lval(false), + _target(target) + {} + + AddressLiteral addr() { + AddressLiteral ret = *this; + ret._is_lval = true; + return ret; + } + + + private: + + address target() { return _target; } + bool is_lval() { return _is_lval; } + + relocInfo::relocType reloc() const { return _rspec.type(); } + const RelocationHolder& rspec() const { return _rspec; } + + friend class Assembler; + friend class MacroAssembler; + friend class Address; + friend class LIR_Assembler; +}; + +// Convience classes +class RuntimeAddress: public AddressLiteral { + + public: + + RuntimeAddress(address target) : AddressLiteral(target, relocInfo::runtime_call_type) {} + +}; + +class OopAddress: public AddressLiteral { + + public: + + OopAddress(address target) : AddressLiteral(target, relocInfo::oop_type){} + +}; + +class ExternalAddress: public AddressLiteral { + + public: + + ExternalAddress(address target) : AddressLiteral(target, relocInfo::external_word_type){} + +}; + +class InternalAddress: public AddressLiteral { + + public: + + InternalAddress(address target) : AddressLiteral(target, relocInfo::internal_word_type) {} + +}; + +// x86 can do array addressing as a single operation since disp can be an absolute +// address but amd64 can't [e.g. array_base(rx, ry:width) ]. We create a class +// that expresses the concept but does extra magic on amd64 to get the final result + +class ArrayAddress VALUE_OBJ_CLASS_SPEC { + private: + + AddressLiteral _base; + Address _index; + + public: + + ArrayAddress() {}; + ArrayAddress(AddressLiteral base, Address index): _base(base), _index(index) {}; + AddressLiteral base() { return _base; } + Address index() { return _index; } + +}; // The amd64 Assembler: Pure assembler doing NO optimizations on // the instruction level (e.g. mov rax, 0 is not translated into xor @@ -273,11 +357,10 @@ const int FPUStateSizeInWords = 512 / wordSize; -class Assembler - : public AbstractAssembler -{ +class Assembler : public AbstractAssembler { friend class AbstractAssembler; // for the non-virtual hack friend class StubGenerator; + protected: #ifdef ASSERT @@ -286,8 +369,8 @@ inline void emit_long64(jlong x); - void emit_data(jint data, relocInfo::relocType rtype, int format = 1); - void emit_data(jint data, RelocationHolder const& rspec, int format = 1); + void emit_data(jint data, relocInfo::relocType rtype, int format /* = 1 */); + void emit_data(jint data, RelocationHolder const& rspec, int format /* = 1 */); void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); @@ -295,12 +378,13 @@ void emit_arith_b(int op1, int op2, Register dst, int imm8); void emit_arith(int op1, int op2, Register dst, int imm32); + // only x86?? + void emit_arith(int op1, int op2, Register dst, jobject obj); void emit_arith(int op1, int op2, Register dst, Register src); void emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, - address target, RelocationHolder const& rspec, int rip_relative_correction = 0); void emit_operand(Register reg, Address adr, @@ -308,7 +392,6 @@ void emit_operand(FloatRegister reg, Register base, Register index, Address::ScaleFactor scale, int disp, - address target, RelocationHolder const& rspec, int rip_relative_correction = 0); void emit_operand(FloatRegister reg, Address adr, @@ -319,11 +402,30 @@ void emit_farith(int b1, int b2, int i); - // Helper routine used to determined if we can reach - // an address via rip relative addressing. - // As a convienence, we return true if the argument is - // not a rip address, since it will be reachable. - bool is_reachable(Address adr); + bool reachable(AddressLiteral adr); + + // These are all easily abused and hence protected + + // Make these disappear in 64bit mode since they would never be correct +#ifndef _LP64 + void cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec); + void cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec); + + void mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec); + void mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec); + + void push_literal32(int32_t imm32, RelocationHolder const& rspec); +#endif // _LP64 + + + void mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec); + + // These are unique in that we are ensured by the caller that the 32bit + // relative in these instructions will always be able to reach the potentially + // 64bit address described by entry. Since they can take a 64bit address they + // don't have the 32 suffix like the other instructions in this class. + void jmp_literal(address entry, RelocationHolder const& rspec); + void call_literal(address entry, RelocationHolder const& rspec); public: enum Condition { // The amd64 condition codes used for conditional jumps/moves. @@ -388,10 +490,12 @@ _WhichOperand_limit = 3 }; + public: + // Creation Assembler(CodeBuffer* code) - : AbstractAssembler(code) - {} + : AbstractAssembler(code) { + } // Decoding static address locate_operand(address inst, WhichOperand which); @@ -411,6 +515,7 @@ void popfq(); void pushq(int imm32); + void pushq(Register src); void pushq(Address src); @@ -420,6 +525,21 @@ // Instruction prefixes void prefix(Prefix p); + int prefix_and_encode(int reg_enc, bool byteinst = false); + int prefixq_and_encode(int reg_enc); + + int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false); + int prefixq_and_encode(int dst_enc, int src_enc); + + void prefix(Register reg); + void prefix(Address adr); + void prefixq(Address adr); + + void prefix(Address adr, Register reg, bool byteinst = false); + void prefixq(Address adr, Register reg); + + void prefix(Address adr, FloatRegister reg); + // Moves void movb(Register dst, Address src); void movb(Address dst, int imm8); @@ -435,13 +555,16 @@ void movl(Address dst, int imm32); void movl(Address dst, Register src); - void movq(Register dst, int64_t imm64); - void movq(Register dst, address imm64, relocInfo::relocType rtype); void movq(Register dst, Register src); - void movq(Register dst, jobject obj); void movq(Register dst, Address src); - void movq(Address dst, int64_t imm64); void movq(Address dst, Register src); + // These prevent using movq from converting a zero (like NULL) into Register + // by giving the compiler two choices it can't resolve + void movq(Address dst, void* dummy); + void movq(Register dst, void* dummy); + + void mov64(Register dst, intptr_t imm64); + void mov64(Address dst, intptr_t imm64); void movsbl(Register dst, Address src); void movsbl(Register dst, Register src); @@ -524,6 +647,7 @@ void cmpl(Register dst, Register src); void cmpl(Register dst, Address src); void cmpq(Address dst, int imm32); + void cmpq(Address dst, Register src); void cmpq(Register dst, int imm32); void cmpq(Register dst, Register src); void cmpq(Register dst, Address src); @@ -648,7 +772,6 @@ void cmpxchgq(Register reg, Address adr); void hlt(); - void int3(); void nop(int i = 1); void ret(int imm16); void smovl(); @@ -668,8 +791,7 @@ }; // Serializes memory. - void membar(Membar_mask_bits order_constraint) - { + void membar(Membar_mask_bits order_constraint) { // We only have to handle StoreLoad and LoadLoad if (order_constraint & StoreLoad) { // MFENCE subsumes LFENCE @@ -679,54 +801,46 @@ } */ } - void lfence() - { + void lfence() { emit_byte(0x0F); emit_byte(0xAE); emit_byte(0xE8); } - void mfence() - { + void mfence() { emit_byte(0x0F); emit_byte(0xAE); emit_byte(0xF0); } // Identify processor type and features - void cpuid() - { + void cpuid() { emit_byte(0x0F); emit_byte(0xA2); } - void cld() { - emit_byte(0xfc); + void cld() { emit_byte(0xfc); } - void std() { - emit_byte(0xfd); + void std() { emit_byte(0xfd); } // Calls + void call(Label& L, relocInfo::relocType rtype); - void call(address entry, relocInfo::relocType rtype); - void call(address entry, RelocationHolder const& rspec); - void call(Register reg, relocInfo::relocType rtype); + void call(Register reg); void call(Address adr); // Jumps - void jmp(address entry, relocInfo::relocType rtype); - void jmp(Register reg, relocInfo::relocType rtype = relocInfo::none); + + void jmp(Register reg); void jmp(Address adr); // Label operations & relative jumps (PPUM Appendix D) // unconditional jump to L void jmp(Label& L, relocInfo::relocType rtype = relocInfo::none); - // Force an 8-bit jump offset - void jmpb(address entry); // Unconditional 8-bit offset jump to L. // WARNING: be very careful using this for forward jumps. If the label is @@ -749,14 +863,9 @@ // Note: The same Label can be used for forward and backward branches // but it may be bound only once. - void jcc(Condition cc, address dst, - relocInfo::relocType rtype = relocInfo::runtime_call_type); void jcc(Condition cc, Label& L, relocInfo::relocType rtype = relocInfo::none); - // Force an 8-bit jump offset - void jccb(Condition cc, address dst); - // Conditional jump to a 8-bit offset to L. // WARNING: be very careful using this for forward jumps. If the label is // not bound within an 8-bit offset of this instruction, a run-time error @@ -814,10 +923,13 @@ // Instructions for which a 'better' code sequence exists depending // on arguments should also go in here. -class MacroAssembler - : public Assembler -{ +class MacroAssembler : public Assembler { + friend class LIR_Assembler; protected: + + Address as_Address(AddressLiteral adr); + Address as_Address(ArrayAddress adr); + // Support for VM calls // // This is the base routine called by the different versions of @@ -868,7 +980,7 @@ address entry_point, int number_of_arguments, bool check_exceptions = true); - + public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} @@ -920,690 +1032,36 @@ if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; } else { movss (dst, src); return; } } + void movflt(FloatRegister dst, Address src) { movss(dst, src); } + + void movflt(FloatRegister dst, AddressLiteral src); + void movflt(Address dst, FloatRegister src) { movss(dst, src); } void movdbl(FloatRegister dst, FloatRegister src) { if (UseXmmRegToRegMoveAll) { movapd(dst, src); return; } else { movsd (dst, src); return; } } + + void movdbl(FloatRegister dst, AddressLiteral src); + void movdbl(FloatRegister dst, Address src) { if (UseXmmLoadAndClearUpper) { movsd (dst, src); return; } else { movlpd(dst, src); return; } } + void movdbl(Address dst, FloatRegister src) { movsd(dst, src); } + void incrementl(AddressLiteral dst); + void incrementl(ArrayAddress dst); + // Alignment void align(int modulus); // Misc void fat_nop(); // 5 byte nop - // If we can reach the address with a 32 bit displacement - // return true otherwise load the address into the scratch register - // and return false. - inline bool check_reach(Address adr) - { - if (is_reachable(adr)) - return true; - // Must make it relocatable if it was relocatable in the first place - Assembler::movq(rscratch1, adr._target, adr.reloc()); - return false; - } - - void pushq(Address src) - { - check_reach(src)? Assembler::pushq(src) : - Assembler::pushq(Address(rscratch1)); - } - - void popq(Address dst) - { - check_reach(dst)? Assembler::popq(dst) : - Assembler::popq(Address(rscratch1)); - } - - // Moves - void movb(Register dst, Address src) - { - check_reach(dst) ? Assembler::movb(dst, src) : - Assembler::movb(dst, Address(rscratch1)); - } - void movb(Address dst, int imm8) - { - check_reach(dst) ? Assembler::movb(dst, imm8) : - Assembler::movb(Address(rscratch1), imm8); - } - void movb(Address dst, Register src) - { - check_reach(dst) ? Assembler::movb(dst, src) : - Assembler::movb(Address(rscratch1), src); - } - - void movw(Address dst, int imm16) - { - check_reach(dst) ? Assembler::movw(dst, imm16) : - Assembler::movw(Address(rscratch1), imm16); - } - void movw(Register dst, Address src) - { - check_reach(src) ? Assembler::movw(dst, src) : - Assembler::movw(dst, Address(rscratch1)); - } - void movw(Address dst, Register src) - { - check_reach(dst) ? Assembler::movw(dst, src) : - Assembler::movw(Address(rscratch1), src); - } - - void movl(Register dst, Address src) - { - check_reach(src) ? Assembler::movl(dst, src) : - Assembler::movl(dst, Address(rscratch1)); - } - void movl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::movl(dst, imm32) : - Assembler::movl(Address(rscratch1), imm32); - } - void movl(Address dst, Register src) - { - check_reach(dst) ? Assembler::movl(dst, src) : - Assembler::movl(Address(rscratch1), src); - } - - void movq(Register dst, Address src) - { - check_reach(src) ? Assembler::movq(dst, src) : - Assembler::movq(dst, Address(rscratch1)); - } - void movq(Address dst, int64_t imm64) - { - if (check_reach(dst)) { - if (is_simm32(imm64)) { - Assembler::movq(dst, (int) imm64); - } else { - Assembler::movq(rscratch1, imm64); - Assembler::movq(dst, rscratch1); - } - } else { - if (is_simm32(imm64)) { - Assembler::movq(Address(rscratch1), (int) imm64); - } else { - Assembler::movq(rscratch2, imm64); - Assembler::movq(Address(rscratch1), rscratch2); - } - } - } - void movq(Address dst, Register src) - { - check_reach(dst) ? Assembler::movq(dst, src) : - Assembler::movq(Address(rscratch1), src); - } - - void movsbl(Register dst, Address src) - { - check_reach(src) ? Assembler::movsbl(dst, src) : - Assembler::movsbl(dst, Address(rscratch1)); - } - void movswl(Register dst, Address src) - { - check_reach(dst) ? Assembler::movswl(dst, src) : - Assembler::movswl(dst, Address(rscratch1)); - } - void movslq(Register dst, Address src) - { - check_reach(dst) ? Assembler::movslq(dst, src) : - Assembler::movslq(dst, Address(rscratch1)); - } - - void movzbl(Register dst, Address src) - { - check_reach(dst) ? Assembler::movzbl(dst, src) : - Assembler::movzbl(dst, Address(rscratch1)); - } - void movzwl(Register dst, Address src) - { - check_reach(dst) ? Assembler::movzwl(dst, src) : - Assembler::movzwl(dst, Address(rscratch1)); - } - -private: - void movss(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::movss(dst, src) : - Assembler::movss(dst, Address(rscratch1)); - } - void movss(Address dst, FloatRegister src) - { - check_reach(dst) ? Assembler::movss(dst, src) : - Assembler::movss(Address(rscratch1), src); - } - void movlpd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::movlpd(dst, src) : - Assembler::movlpd(dst, Address(rscratch1)); - } - void movsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::movsd(dst, src) : - Assembler::movsd(dst, Address(rscratch1)); - } - void movsd(Address dst, FloatRegister src) - { - check_reach(dst) ? Assembler::movsd(dst, src) : - Assembler::movsd(Address(rscratch1), src); - } - -public: - void cmovl(Condition cc, Register dst, Address src) - { - check_reach(src) ? Assembler::cmovl(cc, dst, src) : - Assembler::cmovl(cc, dst, Address(rscratch1)); - } - void cmovq(Condition cc, Register dst, Address src) - { - check_reach(src) ? Assembler::cmovq(cc, dst, src) : - Assembler::cmovq(cc, dst, Address(rscratch1)); - } - - // Arithmetics - void adcl(Register dst, Address src) - { - check_reach(src) ? Assembler::adcl(dst, src) : - Assembler::adcl(dst, Address(rscratch1)); - } - void adcq(Register dst, Address src) - { - check_reach(src) ? Assembler::adcq(dst, src) : - Assembler::adcq(dst, Address(rscratch1)); - } - - void addl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::addl(dst, imm32) : - Assembler::addl(Address(rscratch1), imm32); - } - void addl(Address dst, Register src) - { - check_reach(dst) ? Assembler::addl(dst, src) : - Assembler::addl(Address(rscratch1), src); - } - void addl(Register dst, Address src) - { - check_reach(src) ? Assembler::addl(dst, src) : - Assembler::addl(dst, Address(rscratch1)); - } - void addq(Address dst, int imm32) - { - check_reach(dst) ? Assembler::addq(dst, imm32) : - Assembler::addq(Address(rscratch1), imm32); - } - void addq(Address dst, Register src) - { - check_reach(dst) ? Assembler::addq(dst, src) : - Assembler::addq(Address(rscratch1), src); - } - void addq(Register dst, Address src) - { - check_reach(src) ? Assembler::addq(dst, src) : - Assembler::addq(dst, Address(rscratch1)); - } - - void andl(Register dst, Address src) - { - check_reach(src) ? Assembler::andl(dst, src) : - Assembler::andl(dst, Address(rscratch1)); - } - void andq(Register dst, Address src) - { - check_reach(src) ? Assembler::andq(dst, src) : - Assembler::andq(dst, Address(rscratch1)); - } - - void cmpb(Address dst, int imm8) - { - check_reach(dst) ? Assembler::cmpb(dst, imm8) : - Assembler::cmpb(Address(rscratch1), imm8); - } - void cmpl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::cmpl(dst, imm32) : - Assembler::cmpl(Address(rscratch1), imm32); - } - void cmpl(Register dst, Address src) - { - check_reach(src) ? Assembler::cmpl(dst, src) : - Assembler::cmpl(dst, Address(rscratch1)); - } - void cmpq(Address dst, int imm32) - { - check_reach(dst) ? Assembler::cmpq(dst, imm32) : - Assembler::cmpq(Address(rscratch1), imm32); - } - void cmpq(Register dst, Address src) - { - check_reach(src) ? Assembler::cmpq(dst, src) : - Assembler::cmpq(dst, Address(rscratch1)); - } - - void decl(Address dst) - { - check_reach(dst) ? Assembler::decl(dst) : - Assembler::decl(Address(rscratch1)); - } - void decq(Address dst) - { - check_reach(dst) ? Assembler::decq(dst) : - Assembler::decq(Address(rscratch1)); - } - - void incl(Address dst) - { - check_reach(dst) ? Assembler::incl(dst) : - Assembler::incl(Address(rscratch1)); - } - void incq(Address dst) - { - check_reach(dst) ? Assembler::incq(dst) : - Assembler::incq(Address(rscratch1)); - } - - void leal(Register dst, Address src) - { - check_reach(src) ? Assembler::leal(dst, src) : - Assembler::leal(dst, Address(rscratch1)); - } - void leaq(Register dst, Address src) - { - check_reach(src) ? Assembler::leaq(dst, src) : - Assembler::leaq(dst, Address(rscratch1)); - } - - void mull(Address src) - { - check_reach(src) ? Assembler::mull(src) : - Assembler::mull(Address(rscratch1)); - } - - void orl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::orl(dst, imm32) : - Assembler::orl(Address(rscratch1), imm32); - } - void orl(Register dst, Address src) - { - check_reach(src) ? Assembler::orl(dst, src) : - Assembler::orl(dst, Address(rscratch1)); - } - void orq(Address dst, int imm32) - { - check_reach(dst) ? Assembler::orq(dst, imm32) : - Assembler::orq(Address(rscratch1), imm32); - } - void orq(Register dst, Address src) - { - check_reach(src) ? Assembler::orq(dst, src) : - Assembler::orq(dst, Address(rscratch1)); - } - - void sbbl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::sbbl(dst, imm32) : - Assembler::sbbl(Address(rscratch1), imm32); - } - void sbbl(Register dst, Address src) - { - check_reach(src) ? Assembler::sbbl(dst, src) : - Assembler::sbbl(dst, Address(rscratch1)); - } - void sbbq(Address dst, int imm32) - { - check_reach(dst) ? Assembler::sbbq(dst, imm32) : - Assembler::sbbq(Address(rscratch1), imm32); - } - void sbbq(Register dst, Address src) - { - check_reach(src) ? Assembler::sbbq(dst, src) : - Assembler::sbbq(dst, Address(rscratch1)); - } - - void subl(Address dst, int imm32) - { - check_reach(dst) ? Assembler::subl(dst, imm32) : - Assembler::subl(Address(rscratch1), imm32); - } - void subl(Address dst, Register src) - { - check_reach(dst) ? Assembler::subl(dst, src) : - Assembler::subl(Address(rscratch1), src); - } - void subl(Register dst, Address src) - { - check_reach(src) ? Assembler::subl(dst, src) : - Assembler::subl(dst, Address(rscratch1)); - } - void subq(Address dst, int imm32) - { - check_reach(dst) ? Assembler::subq(dst, imm32) : - Assembler::subq(Address(rscratch1), imm32); - } - void subq(Address dst, Register src) - { - check_reach(dst) ? Assembler::subq(dst, src) : - Assembler::subq(Address(rscratch1), src); - } - void subq(Register dst, Address src) - { - check_reach(src) ? Assembler::subq(dst, src) : - Assembler::subq(dst, Address(rscratch1)); - } - - void xaddl(Address dst, Register src) - { - check_reach(dst) ? Assembler::xaddl(dst, src) : - Assembler::xaddl(Address(rscratch1), src); - } - void xaddq(Address dst, Register src) - { - check_reach(dst) ? Assembler::xaddq(dst, src) : - Assembler::xaddq(Address(rscratch1), src); - } - - void xorl(Register dst, Address src) - { - check_reach(src) ? Assembler::xorl(dst, src) : - Assembler::xorl(dst, Address(rscratch1)); - } - void xorq(Register dst, Address src) - { - check_reach(src) ? Assembler::xorq(dst, src) : - Assembler::xorq(dst, Address(rscratch1)); - } - - void xchgl(Register reg, Address adr) - { - check_reach(adr) ? Assembler::xchgl(reg, adr) : - Assembler::xchgl(reg, Address(rscratch1)); - } - void xchgq(Register reg, Address adr) - { - check_reach(adr) ? Assembler::xchgq(reg, adr) : - Assembler::xchgq(reg, Address(rscratch1)); - } - - void cmpxchgl(Register reg, Address adr) - { - check_reach(adr) ? Assembler::cmpxchgl(reg, adr) : - Assembler::cmpxchgl(reg, Address(rscratch1)); - } - void cmpxchgq(Register reg, Address adr) - { - check_reach(adr) ? Assembler::cmpxchgq(reg, adr) : - Assembler::cmpxchgq(reg, Address(rscratch1)); - } - - // Calls - void call(Label& L, relocInfo::relocType rtype) - { - Assembler::call(L, rtype); - } - - void call(address entry, relocInfo::relocType rtype) - { - Address dest(entry, rtype); - check_reach(dest) ? Assembler::call(entry, rtype) : - Assembler::call(rscratch1, relocInfo::none); - } - void call(address entry, RelocationHolder const& rspec) - { - Address dest(entry, rspec); - check_reach(dest) ? Assembler::call(entry, rspec) : - Assembler::call(rscratch1, relocInfo::none); - } - void call(Address adr) - { - check_reach(adr) ? Assembler::call(adr) : - Assembler::call(rscratch1, relocInfo::none); - } - - // Jumps - void jmp(address entry, relocInfo::relocType rtype) - { - Address dest(entry, rtype); - check_reach(dest) ? Assembler::jmp(entry, rtype) : - Assembler::jmp(rscratch1, relocInfo::none); - } - void jmp(Address adr) - { - check_reach(adr) ? Assembler::jmp(adr) : - Assembler::jmp(rscratch1); - } - - // Label operations & relative jumps (PPUM Appendix D) - // unconditional jump to L - void jmp(Label& L, relocInfo::relocType rtype = relocInfo::none) - { - Assembler::jmp(L, rtype); - } - - void jcc(Condition cc, address dst, - relocInfo::relocType rtype = relocInfo::runtime_call_type); - - void jcc(Condition cc, Label& L, - relocInfo::relocType rtype = relocInfo::none) - { - Assembler::jcc(cc, L, rtype); - } - - - // Floating-point operations - - void fxsave(Address dst) - { - check_reach(dst) ? Assembler::fxsave(dst) : - Assembler::fxsave(Address(rscratch1)); - } - void fxrstor(Address src) - { - check_reach(src) ? Assembler::fxrstor(src) : - Assembler::fxrstor(Address(rscratch1)); - } - void ldmxcsr(Address src) - { - check_reach(src) ? Assembler::ldmxcsr(src) : - Assembler::ldmxcsr(Address(rscratch1)); - } - void stmxcsr(Address dst) - { - check_reach(dst) ? Assembler::stmxcsr(dst) : - Assembler::stmxcsr(Address(rscratch1)); - } - - void addss(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::addss(dst, src) : - Assembler::addss(dst, Address(rscratch1)); - } - void subss(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::subss(dst, src) : - Assembler::subss(dst, Address(rscratch1)); - } - void mulss(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::mulss(dst, src) : - Assembler::mulss(dst, Address(rscratch1)); - } - void divss(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::divss(dst, src) : - Assembler::divss(dst, Address(rscratch1)); - } - void addsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::addsd(dst, src) : - Assembler::addsd(dst, Address(rscratch1)); - } - void subsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::subsd(dst, src) : - Assembler::subsd(dst, Address(rscratch1)); - } - void mulsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::mulsd(dst, src) : - Assembler::mulsd(dst, Address(rscratch1)); - } - void divsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::divsd(dst, src) : - Assembler::divsd(dst, Address(rscratch1)); - } - - // We only need the double form - void sqrtsd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::sqrtsd(dst, src) : - Assembler::sqrtsd(dst, Address(rscratch1)); - } - - void xorps(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::xorps(dst, src) : - Assembler::xorps(dst, Address(rscratch1)); - } - void xorpd(FloatRegister dst, Address src) - { - check_reach(src) ? Assembler::xorpd(dst, src) : - Assembler::xorpd(dst, Address(rscratch1)); - } - - // Entrypoints which only call to the super class. - // Needed here to satisfy the C++ compiler - // Since we are overriding some of the methods which take - // an Address as an argument. - - void pushq(int imm32) { Assembler::pushq(imm32); } - void pushq(Register src) { Assembler::pushq(src); } - void popq(Register dst) { Assembler::popq(dst); } - void movl(Register dst, int imm32) { Assembler::movl(dst, imm32); } - void movl(Register dst, Register src) { Assembler::movl(dst, src); } - void movq(Register dst, int64_t imm64) { Assembler::movq(dst, imm64); } - void movq(Register dst, address imm64, relocInfo::relocType rtype) { Assembler::movq(dst, imm64, rtype); } - void movq(Register dst, Register src) { Assembler::movq(dst, src); } - void movq(Register dst, jobject obj) { Assembler::movq(dst, obj); } - void movsbl(Register dst, Register src) { Assembler::movsbl(dst, src); } - void movswl(Register dst, Register src) { Assembler::movswl(dst, src); } - void movslq(Register dst, Register src) { Assembler::movslq(dst, src); } - void movzbl(Register dst, Register src) { Assembler::movzbl(dst, src); } - void movzwl(Register dst, Register src) { Assembler::movzwl(dst, src); } -private: - void movss(FloatRegister dst, FloatRegister src) { Assembler::movss(dst, src); } - void movsd(FloatRegister dst, FloatRegister src) { Assembler::movsd(dst, src); } - -public: - void movdl(FloatRegister dst, Register src) { Assembler::movdl(dst, src); } - void movdl(Register dst, FloatRegister src) { Assembler::movdl(dst, src); } - void movdq(FloatRegister dst, Register src) { Assembler::movdq(dst, src); } - void movdq(Register dst, FloatRegister src) { Assembler::movdq(dst, src); } - void cmovl(Condition cc, Register dst, Register src) { Assembler::cmovl(cc, dst, src); } - void cmovq(Condition cc, Register dst, Register src) { Assembler::cmovq(cc, dst, src); } - void adcl(Register dst, int imm32) { Assembler::adcl(dst, imm32); } - void adcl(Register dst, Register src) { Assembler::adcl(dst, src); } - void adcq(Register dst, int imm32) { Assembler::adcq(dst, imm32); } - void adcq(Register dst, Register src) { Assembler::adcq(dst, src); } - void addl(Register dst, int imm32) { Assembler::addl(dst, imm32); } - void addl(Register dst, Register src) { Assembler::addl(dst, src); } - void addq(Register dst, int imm32) { Assembler::addq(dst, imm32); } - void addq(Register dst, Register src) { Assembler::addq(dst, src); } - void andl(Register dst, int imm32) { Assembler::andl(dst, imm32); } - void andl(Register dst, Register src) { Assembler::andl(dst, src); } - void andq(Register dst, int imm32) { Assembler::andq(dst, imm32); } - void andq(Register dst, Register src) { Assembler::andq(dst, src); } - void cmpl(Register dst, int imm32) { Assembler::cmpl(dst, imm32); } - void cmpl(Register dst, Register src) { Assembler::cmpl(dst, src); } - void cmpq(Register dst, int imm32) { Assembler::cmpq(dst, imm32); } - void cmpq(Register dst, Register src) { Assembler::cmpq(dst, src); } - void ucomiss(FloatRegister dst, FloatRegister src) { Assembler::ucomiss(dst, src); } - void ucomisd(FloatRegister dst, FloatRegister src) { Assembler::ucomisd(dst, src); } - void decl(Register dst) { Assembler::decl(dst); } - void decq(Register dst) { Assembler::decq(dst); } - void idivl(Register src) { Assembler::idivl(src); } - void idivq(Register src) { Assembler::idivq(src); } - void imull(Register dst, Register src) { Assembler::imull(dst, src); } - void imull(Register dst, Register src, int value) { Assembler::imull(dst, src, value); } - void imulq(Register dst, Register src) { Assembler::imulq(dst, src); } - void imulq(Register dst, Register src, int value) { Assembler::imulq(dst, src, value); } - void incl(Register dst) { Assembler::incl(dst); } - void incq(Register dst) { Assembler::incq(dst); } - void mull(Register src) { Assembler::mull(src); } - void negl(Register dst) { Assembler::negl(dst); } - void negq(Register dst) { Assembler::negq(dst); } - void notl(Register dst) { Assembler::notl(dst); } - void notq(Register dst) { Assembler::notq(dst); } - void orl(Register dst, int imm32) { Assembler::orl(dst, imm32); } - void orl(Register dst, Register src) { Assembler::orl(dst, src); } - void orq(Register dst, int imm32) { Assembler::orq(dst, imm32); } - void orq(Register dst, Register src) { Assembler::orq(dst, src); } - void rcll(Register dst, int imm8) { Assembler::rcll(dst, imm8); } - void rclq(Register dst, int imm8) { Assembler::rclq(dst, imm8); } - void sarl(Register dst, int imm8) { Assembler::sarl(dst, imm8); } - void sarl(Register dst) { Assembler::sarl(dst); } - void sarq(Register dst, int imm8) { Assembler::sarq(dst, imm8); } - void sarq(Register dst) { Assembler::sarq(dst); } - void sbbl(Register dst, int imm32) { Assembler::sbbl(dst, imm32); } - void sbbl(Register dst, Register src) { Assembler::sbbl(dst, src); } - void sbbq(Register dst, int imm32) { Assembler::sbbq(dst, imm32); } - void sbbq(Register dst, Register src) { Assembler::sbbq(dst, src); } - void shll(Register dst, int imm8) { Assembler::shll(dst, imm8); } - void shll(Register dst) { Assembler::shll(dst); } - void shlq(Register dst, int imm8) { Assembler::shlq(dst, imm8); } - void shlq(Register dst) { Assembler::shlq(dst); } - void shrl(Register dst, int imm8) { Assembler::shrl(dst, imm8); } - void shrl(Register dst) { Assembler::shrl(dst); } - void shrq(Register dst, int imm8) { Assembler::shrq(dst, imm8); } - void shrq(Register dst) { Assembler::shrq(dst); } - void subl(Register dst, int imm32) { Assembler::subl(dst, imm32); } - void subl(Register dst, Register src) { Assembler::subl(dst, src); } - void subq(Register dst, int imm32) { Assembler::subq(dst, imm32); } - void subq(Register dst, Register src) { Assembler::subq(dst, src); } - void testb(Register dst, int imm8) { Assembler::testb(dst, imm8); } - void testl(Register dst, int imm32) { Assembler::testl(dst, imm32); } - void testl(Register dst, Register src) { Assembler::testl(dst, src); } - void testq(Register dst, int imm32) { Assembler::testq(dst, imm32); } - void testq(Register dst, Register src) { Assembler::testq(dst, src); } - void xorl(Register dst, int imm32) { Assembler::xorl(dst, imm32); } - void xorl(Register dst, Register src) { Assembler::xorl(dst, src); } - void xorq(Register dst, int imm32) { Assembler::xorq(dst, imm32); } - void xorq(Register dst, Register src) { Assembler::xorq(dst, src); } - void bswapl(Register reg) { Assembler::bswapl(reg); } - void bswapq(Register reg) { Assembler::bswapq(reg); } - void xchgl(Register dst, Register src) { Assembler::xchgl(dst, src); } - void xchgq(Register dst, Register src) { Assembler::xchgq(dst, src); } - void call(Register reg, relocInfo::relocType rtype) { Assembler::call(reg, rtype); } - void jmp(Register reg, relocInfo::relocType rtype = relocInfo::none) { Assembler::jmp(reg, rtype); } - void addss(FloatRegister dst, FloatRegister src) { Assembler::addss(dst, src); } - void subss(FloatRegister dst, FloatRegister src) { Assembler::subss(dst, src); } - void mulss(FloatRegister dst, FloatRegister src) { Assembler::mulss(dst, src); } - void divss(FloatRegister dst, FloatRegister src) { Assembler::divss(dst, src); } - void addsd(FloatRegister dst, FloatRegister src) { Assembler::addsd(dst, src); } - void subsd(FloatRegister dst, FloatRegister src) { Assembler::subsd(dst, src); } - void mulsd(FloatRegister dst, FloatRegister src) { Assembler::mulsd(dst, src); } - void divsd(FloatRegister dst, FloatRegister src) { Assembler::divsd(dst, src); } - void sqrtsd(FloatRegister dst, FloatRegister src) { Assembler::sqrtsd(dst, src); } - void xorps(FloatRegister dst, FloatRegister src) { Assembler::xorps(dst, src); } - void xorpd(FloatRegister dst, FloatRegister src) { Assembler::xorpd(dst, src); } - void cvtsi2ssl(FloatRegister dst, Register src) { Assembler::cvtsi2ssl(dst, src); } - void cvtsi2ssq(FloatRegister dst, Register src) { Assembler::cvtsi2ssq(dst, src); } - void cvtsi2sdl(FloatRegister dst, Register src) { Assembler::cvtsi2sdl(dst, src); } - void cvtsi2sdq(FloatRegister dst, Register src) { Assembler::cvtsi2sdq(dst, src); } - void cvttss2sil(Register dst, FloatRegister src) { Assembler::cvttss2sil(dst, src); } - void cvttss2siq(Register dst, FloatRegister src) { Assembler::cvttss2siq(dst, src); } - void cvttsd2sil(Register dst, FloatRegister src) { Assembler::cvttsd2sil(dst, src); } - void cvttsd2siq(Register dst, FloatRegister src) { Assembler::cvttsd2siq(dst, src); } - void cvtss2sd(FloatRegister dst, FloatRegister src) { Assembler::cvtss2sd(dst, src); } - void cvtsd2ss(FloatRegister dst, FloatRegister src) { Assembler::cvtsd2ss(dst, src); } // C++ bool manipulation @@ -1621,6 +1079,8 @@ // thread register. void get_thread(Register thread); + void int3(); + // Support for VM calls // // It is imperative that all calls into the VM are handled via the @@ -1804,7 +1264,7 @@ void bang_stack_size(Register offset, Register tmp); // Support for serializing memory accesses between threads. - void serialize_memory(Register thread, Register tmp1, Register tmp2); + void serialize_memory(Register thread, Register tmp); void verify_tlab(); @@ -1828,11 +1288,112 @@ Condition negate_condition(Condition cond); + // Instructions that use AddressLiteral operands. These instruction can handle 32bit/64bit + // operands. In general the names are modified to avoid hiding the instruction in Assembler + // so that we don't need to implement all the varieties in the Assembler with trivial wrappers + // here in MacroAssembler. The major exception to this rule is call + + // Arithmetics + + void cmp8(AddressLiteral src1, int8_t imm32); + + void cmp32(AddressLiteral src1, int32_t src2); + // compare reg - mem, or reg - &mem + void cmp32(Register src1, AddressLiteral src2); + + void cmp32(Register src1, Address src2); + +#ifndef _LP64 + void cmpoop(Address dst, jobject obj); + void cmpoop(Register dst, jobject obj); +#endif // _LP64 + + // NOTE src2 must be the lval. This is NOT an mem-mem compare + void cmpptr(Address src1, AddressLiteral src2); + + void cmpptr(Register src1, AddressLiteral src); + + // will be cmpreg(?) + void cmp64(Register src1, AddressLiteral src); + + void cmpxchgptr(Register reg, Address adr); + void cmpxchgptr(Register reg, AddressLiteral adr); + // Helper functions for statistics gathering. // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. - void cond_incl(Condition cond, Address counter_addr); + void cond_inc32(Condition cond, AddressLiteral counter_addr); // Unconditional atomic increment. - void atomic_incl(Address counter_addr); + void atomic_incl(AddressLiteral counter_addr); + + + void lea(Register dst, AddressLiteral src); + void lea(Register dst, Address src); + + + // Calls + void call(Label& L, relocInfo::relocType rtype); + void call(Register entry); + void call(AddressLiteral entry); + + // Jumps + + // 32bit can do a case table jump in one instruction but we no longer allow the base + // to be installed in the Address class + void jump(ArrayAddress entry); + + void jump(AddressLiteral entry); + void jump_cc(Condition cc, AddressLiteral dst); + + // Floating + + void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } + void ldmxcsr(AddressLiteral src); + +private: + // these are private because users should be doing movflt/movdbl + + void movss(FloatRegister dst, FloatRegister src) { Assembler::movss(dst, src); } + void movss(Address dst, FloatRegister src) { Assembler::movss(dst, src); } + void movss(FloatRegister dst, Address src) { Assembler::movss(dst, src); } + void movss(FloatRegister dst, AddressLiteral src); + + void movlpd(FloatRegister dst, Address src) {Assembler::movlpd(dst, src); } + void movlpd(FloatRegister dst, AddressLiteral src); + +public: + + + void xorpd(FloatRegister dst, FloatRegister src) {Assembler::xorpd(dst, src); } + void xorpd(FloatRegister dst, Address src) {Assembler::xorpd(dst, src); } + void xorpd(FloatRegister dst, AddressLiteral src); + + void xorps(FloatRegister dst, FloatRegister src) {Assembler::xorps(dst, src); } + void xorps(FloatRegister dst, Address src) {Assembler::xorps(dst, src); } + void xorps(FloatRegister dst, AddressLiteral src); + + + // Data + + void movoop(Register dst, jobject obj); + void movoop(Address dst, jobject obj); + + void movptr(ArrayAddress dst, Register src); + void movptr(Register dst, AddressLiteral src); + + void movptr(Register dst, intptr_t src); + void movptr(Address dst, intptr_t src); + + void movptr(Register dst, ArrayAddress src); + + // to avoid hiding movl + void mov32(AddressLiteral dst, Register src); + void mov32(Register dst, AddressLiteral src); + + void pushoop(jobject obj); + + // Can push value or effective address + void pushptr(AddressLiteral src); + }; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/assembler_amd64.inline.hpp --- a/hotspot/src/cpu/amd64/vm/assembler_amd64.inline.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/assembler_amd64.inline.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)assembler_amd64.inline.hpp 1.13 07/05/05 17:04:04 JVM" +#pragma ident "@(#)assembler_amd64.inline.hpp 1.14 07/06/19 09:08:00 JVM" #endif /* * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -25,36 +25,12 @@ * */ -inline void Assembler::emit_long64(jlong x) -{ +inline void Assembler::emit_long64(jlong x) { *(jlong*) _code_pos = x; _code_pos += sizeof(jlong); code_section()->set_end(_code_pos); } -inline bool Assembler::is_reachable(Address adr) -{ - if ( !adr.is_rip_relative() ) return true; - int64_t disp; - if (adr.is_far()) { - if (adr.reloc() != relocInfo::external_word_type && - adr.reloc() != relocInfo::runtime_call_type ) { - return false; - } - // For external_word_type/runtime_call_type if it is reachable from where we - // are now (possibly a temp buffer) and where we might end up - // anywhere in the codeCache then we are always reachable. - // This would have to change if we ever save/restore shared code - // to be more pessimistic. - disp = (int64_t)adr._target - ((int64_t)CodeCache::low_bound() + sizeof(int)); - if (!is_simm32(disp)) return false; - disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int)); - if (!is_simm32(disp)) return false; - } - disp = (int64_t)adr._target - ((int64_t)_code_pos + sizeof(int)); - return is_simm32(disp); -} - inline void MacroAssembler::pd_patch_instruction(address branch, address target) { unsigned char op = branch[0]; assert(op == 0xE8 /* call */ || @@ -95,3 +71,19 @@ tty->print("%s (unresolved)", s); } #endif // ndef PRODUCT + +inline void MacroAssembler::movptr(Address dst, intptr_t src) { +#ifdef _LP64 + Assembler::mov64(dst, src); +#else + Assembler::movl(dst, src); +#endif // _LP64 +} + +inline void MacroAssembler::movptr(Register dst, intptr_t src) { +#ifdef _LP64 + Assembler::mov64(dst, src); +#else + Assembler::movl(dst, src); +#endif // _LP64 +} diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/dump_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/dump_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/dump_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)dump_amd64.cpp 1.11 07/05/05 17:04:04 JVM" +#pragma ident "@(#)dump_amd64.cpp 1.12 07/06/19 09:08:00 JVM" #endif /* * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -98,9 +98,9 @@ __ movq(c_rarg0, rax); __ shrq(c_rarg0, 8); // isolate vtable identifier. __ shlq(c_rarg0, LogBytesPerWord); - __ movq(c_rarg1, (int64_t)vtbl_list); // ptr to correct vtable list. + __ lea(c_rarg1, ExternalAddress((address)vtbl_list)); // ptr to correct vtable list. __ addq(c_rarg1, c_rarg0); // ptr to list entry. - __ movq(c_rarg1, Address(c_rarg1)); // get correct vtable address. + __ movq(c_rarg1, Address(c_rarg1, 0)); // get correct vtable address. __ popq(c_rarg0); // restore "this" __ movq(Address(c_rarg0, 0), c_rarg1); // update vtable pointer. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/icBuffer_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/icBuffer_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/icBuffer_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)icBuffer_amd64.cpp 1.11 07/05/05 17:04:06 JVM" +#pragma ident "@(#)icBuffer_amd64.cpp 1.12 07/06/19 09:08:00 JVM" #endif /* * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -28,8 +28,7 @@ #include "incls/_precompiled.incl" #include "incls/_icBuffer_amd64.cpp.incl" -int InlineCacheBuffer::ic_stub_code_size() -{ +int InlineCacheBuffer::ic_stub_code_size() { return NativeMovConstReg::instruction_size + NativeJump::instruction_size + 1; @@ -38,8 +37,7 @@ void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, oop cached_oop, - address entry_point) -{ + address entry_point) { ResourceMark rm; CodeBuffer code(code_begin, ic_stub_code_size()); MacroAssembler* masm = new MacroAssembler(&code); @@ -49,13 +47,12 @@ // (2) these ICStubs are removed *before* a GC happens, so the roots // disappear assert(cached_oop == NULL || cached_oop->is_perm(), "must be perm oop"); - masm->movq(rax, (int64_t) cached_oop); - masm->jmp(entry_point, relocInfo::none); + masm->lea(rax, OopAddress((address) cached_oop)); + masm->jump(ExternalAddress(entry_point)); } -address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) -{ +address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { // creation also verifies the object NativeMovConstReg* move = nativeMovConstReg_at(code_begin); NativeJump* jump = nativeJump_at(move->next_instruction_address()); @@ -63,8 +60,7 @@ } -oop InlineCacheBuffer::ic_buffer_cached_oop(address code_begin) -{ +oop InlineCacheBuffer::ic_buffer_cached_oop(address code_begin) { // creation also verifies the object NativeMovConstReg* move = nativeMovConstReg_at(code_begin); return (oop) move->data(); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/icache_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/icache_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/icache_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)icache_amd64.cpp 1.13 07/05/17 15:39:46 JVM" +#pragma ident "@(#)icache_amd64.cpp 1.14 07/06/19 09:08:00 JVM" #endif /* * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -51,7 +51,7 @@ __ mfence(); __ bind(flush_line); - __ clflush(Address(addr)); + __ clflush(Address(addr, 0)); __ addq(addr, ICache::line_size); __ decrementl(lines); __ jcc(Assembler::notZero, flush_line); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/interp_masm_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/interp_masm_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/interp_masm_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interp_masm_amd64.cpp 1.44 07/06/08 18:13:30 JVM" +#pragma ident "@(#)interp_masm_amd64.cpp 1.45 07/06/19 09:08:00 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -42,7 +42,7 @@ save_bcp(); { Label L; - cmpq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + cmpq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int)NULL_WORD); jcc(Assembler::equal, L); stop("InterpreterMacroAssembler::call_VM_leaf_base:" " last_sp != NULL"); @@ -89,7 +89,7 @@ #ifdef ASSERT { Label L; - cmpq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + cmpq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int)NULL_WORD); jcc(Assembler::equal, L); stop("InterpreterMacroAssembler::call_VM_leaf_base:" " last_sp != NULL"); @@ -123,7 +123,7 @@ // Call Interpreter::remove_activation_preserving_args_entry() to get the // address of the same-named entrypoint in the generated interpreter code. call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); - jmp(rax, relocInfo::runtime_call_type); + jmp(rax); bind(L); } } @@ -136,7 +136,7 @@ const Address val_addr(rcx, JvmtiThreadState::earlyret_value_offset()); switch (state) { case atos: movq(rax, oop_addr); - movq(oop_addr, NULL_WORD); + movptr(oop_addr, NULL_WORD); verify_oop(rax, state); break; case ltos: movq(rax, val_addr); break; case btos: // fall through @@ -173,7 +173,7 @@ movq(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_tos_offset())); call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), c_rarg0); - jmp(rax, relocInfo::runtime_call_type); + jmp(rax); bind(L); } } @@ -304,7 +304,7 @@ jcc(Assembler::equal, okay); // Also compare if the stack value is zero, then the tag might // not have been set coming from deopt. - cmpq(Address(rsp), 0); + cmpq(Address(rsp, 0), 0); jcc(Assembler::equal, okay); stop("Java Expression stack tag value is bad"); bind(okay); @@ -326,27 +326,27 @@ void InterpreterMacroAssembler::pop_i(Register r) { // XXX can't use popq currently, upper half non clean debug_only(verify_stack_tag(frame::TagValue)); - movl(r, Address(rsp)); + movl(r, Address(rsp, 0)); addq(rsp, wordSize); if (TaggedStackInterpreter) addq(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_l(Register r) { debug_only(verify_stack_tag(frame::TagCategory2)); - movq(r, Address(rsp)); + movq(r, Address(rsp, 0)); addq(rsp, 2 * Interpreter::stackElementSize()); } void InterpreterMacroAssembler::pop_f(FloatRegister r) { debug_only(verify_stack_tag(frame::TagValue)); - movflt(r, Address(rsp)); + movflt(r, Address(rsp, 0)); addq(rsp, wordSize); if (TaggedStackInterpreter) addq(rsp, 1 * wordSize); } void InterpreterMacroAssembler::pop_d(FloatRegister r) { debug_only(verify_stack_tag(frame::TagCategory2)); - movdbl(r, Address(rsp)); + movdbl(r, Address(rsp, 0)); addq(rsp, 2 * Interpreter::stackElementSize()); } @@ -374,13 +374,13 @@ } else { subq(rsp, 2 * wordSize); } - movq(Address(rsp), r); + movq(Address(rsp, 0), r); } void InterpreterMacroAssembler::push_f(FloatRegister r) { if (TaggedStackInterpreter) pushq(frame::TagValue); subq(rsp, wordSize); - movflt(Address(rsp), r); + movflt(Address(rsp, 0), r); } void InterpreterMacroAssembler::push_d(FloatRegister r) { @@ -392,7 +392,7 @@ } else { subq(rsp, 2 * wordSize); } - movdbl(Address(rsp), r); + movdbl(Address(rsp, 0), r); } void InterpreterMacroAssembler::pop(TosState state) { @@ -450,12 +450,12 @@ void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { if (TaggedStackInterpreter) { if (tag == frame::TagCategory2) { - movq(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), + mov64(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), (intptr_t)frame::TagValue); - movq(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), + mov64(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (intptr_t)frame::TagValue); } else { - movq(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (intptr_t)tag); + mov64(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (intptr_t)tag); } } } @@ -463,12 +463,12 @@ void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { if (TaggedStackInterpreter) { if (tag == frame::TagCategory2) { - movq(Address(r14, idx, Address::times_8, + mov64(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(1)), (intptr_t)frame::TagValue); - movq(Address(r14, idx, Address::times_8, + mov64(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), (intptr_t)frame::TagValue); } else { - movq(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), + mov64(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), (intptr_t)tag); } } @@ -617,8 +617,7 @@ // The following two routines provide a hook so that an implementation // can schedule the dispatch in two parts. amd64 does not do this. -void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) -{ +void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { // Nothing amd64 specific to be done here } @@ -645,7 +644,7 @@ if (verifyoop) { verify_oop(rax, state); } - movq(rscratch1,(int64_t) table); + lea(rscratch1, ExternalAddress((address)table)); jmp(Address(rscratch1, rbx, Address::times_8)); } @@ -672,7 +671,7 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { // load current bytecode - load_unsigned_byte(rbx, Address(r13)); + load_unsigned_byte(rbx, Address(r13, 0)); dispatch_base(state, table); } @@ -873,7 +872,7 @@ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax - orq(swap_reg, Address(obj_reg)); + orq(swap_reg, Address(obj_reg, 0)); // Save (object->mark() | 1) into BasicLock's displaced header movq(Address(lock_reg, mark_offset), swap_reg); @@ -882,9 +881,10 @@ "displached header must be first word in BasicObjectLock"); if (os::is_MP()) lock(); - cmpxchgq(lock_reg, Address(obj_reg)); + cmpxchgq(lock_reg, Address(obj_reg, 0)); if (PrintBiasedLockingStatistics) { - cond_incl(Assembler::zero, Address((address) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); } jcc(Assembler::zero, done); @@ -904,7 +904,8 @@ movq(Address(lock_reg, mark_offset), swap_reg); if (PrintBiasedLockingStatistics) { - cond_incl(Assembler::zero, Address((address) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); } jcc(Assembler::zero, done); @@ -955,8 +956,7 @@ movq(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // Free entry - movq(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), - NULL_WORD); + movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); if (UseBiasedLocking) { biased_locking_exit(obj_reg, header_reg, done); @@ -974,7 +974,7 @@ // Atomic swap back the old header if (os::is_MP()) lock(); - cmpxchgq(header_reg, Address(obj_reg)); + cmpxchgq(header_reg, Address(obj_reg, 0)); // zero for recursive case jcc(Assembler::zero, done); @@ -1469,8 +1469,7 @@ } -void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) -{ +void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { if (ProfileInterpreter) { Label profile_continue; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/interp_masm_amd64.hpp --- a/hotspot/src/cpu/amd64/vm/interp_masm_amd64.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/interp_masm_amd64.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)interp_masm_amd64.hpp 1.21 07/05/17 15:39:50 JVM" +#pragma ident "@(#)interp_masm_amd64.hpp 1.22 07/06/19 09:08:01 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -29,8 +29,7 @@ class InterpreterMacroAssembler - : public MacroAssembler -{ + : public MacroAssembler { protected: // Interpreter specific version of call_VM_base virtual void call_VM_leaf_base(address entry_point, @@ -142,7 +141,7 @@ movq(rsp, Address(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize)); // NULL last_sp until next java call - movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); } // Super call_VM calls - correspond to MacroAssembler::call_VM(_leaf) calls diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/interpreterRT_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/interpreterRT_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/interpreterRT_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interpreterRT_amd64.cpp 1.23 07/06/08 18:13:30 JVM" +#pragma ident "@(#)interpreterRT_amd64.cpp 1.24 07/06/19 09:08:01 JVM" #endif /* * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -36,8 +36,7 @@ Register InterpreterRuntime::SignatureHandlerGenerator::to() { return rsp; } Register InterpreterRuntime::SignatureHandlerGenerator::temp() { return rscratch1; } -void InterpreterRuntime::SignatureHandlerGenerator::pass_int() -{ +void InterpreterRuntime::SignatureHandlerGenerator::pass_int() { const Address src(from(), Interpreter::local_offset_in_bytes(offset())); #ifdef _WIN64 @@ -91,8 +90,7 @@ #endif } -void InterpreterRuntime::SignatureHandlerGenerator::pass_long() -{ +void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); #ifdef _WIN64 @@ -147,8 +145,7 @@ #endif } -void InterpreterRuntime::SignatureHandlerGenerator::pass_float() -{ +void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { const Address src(from(), Interpreter::local_offset_in_bytes(offset())); #ifdef _WIN64 @@ -170,8 +167,7 @@ #endif } -void InterpreterRuntime::SignatureHandlerGenerator::pass_double() -{ +void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); #ifdef _WIN64 @@ -193,8 +189,7 @@ #endif } -void InterpreterRuntime::SignatureHandlerGenerator::pass_object() -{ +void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { const Address src(from(), Interpreter::local_offset_in_bytes(offset())); #ifdef _WIN64 @@ -274,15 +269,12 @@ #endif } -void InterpreterRuntime::SignatureHandlerGenerator::generate( - uint64_t fingerprint) -{ +void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprint) { // generate code to handle arguments iterate(fingerprint); // return result handler - __ movq(rax, (int64_t) AbstractInterpreter:: - result_handler(method()->result_type())); + __ lea(rax, ExternalAddress(AbstractInterpreter::result_handler(method()->result_type()))); __ ret(0); __ flush(); @@ -296,8 +288,7 @@ #ifdef _WIN64 class SlowSignatureHandler - : public NativeSignatureIterator -{ + : public NativeSignatureIterator { private: address _from; intptr_t* _to; @@ -399,8 +390,7 @@ }; #else class SlowSignatureHandler - : public NativeSignatureIterator -{ + : public NativeSignatureIterator { private: address _from; intptr_t* _to; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/interpreter_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/interpreter_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/interpreter_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interpreter_amd64.cpp 1.63 07/06/08 18:13:30 JVM" +#pragma ident "@(#)interpreter_amd64.cpp 1.64 07/06/19 09:08:01 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -36,8 +36,7 @@ //----------------------------------------------------------------------------- -address AbstractInterpreterGenerator::generate_StackOverflowError_handler() -{ +address AbstractInterpreterGenerator::generate_StackOverflowError_handler() { address entry = __ pc(); #ifdef ASSERT @@ -68,15 +67,14 @@ } address AbstractInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler( - const char* name) -{ + const char* name) { address entry = __ pc(); // expression stack must be empty before entering the VM if an // exception happened __ empty_expression_stack(); // setup parameters // ??? convention: expect aberrant index in register ebx - __ movq(c_rarg1, (int64_t) name); + __ lea(c_rarg1, ExternalAddress((address)name)); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime:: @@ -85,8 +83,7 @@ return entry; } -address AbstractInterpreterGenerator::generate_ClassCastException_handler() -{ +address AbstractInterpreterGenerator::generate_ClassCastException_handler() { address entry = __ pc(); // object is at TOS @@ -105,8 +102,7 @@ } address AbstractInterpreterGenerator::generate_exception_handler_common( - const char* name, const char* message, bool pass_oop) -{ + const char* name, const char* message, bool pass_oop) { assert(!pass_oop || message == NULL, "either oop or message but not both"); address entry = __ pc(); if (pass_oop) { @@ -117,37 +113,41 @@ // exception happened __ empty_expression_stack(); // setup parameters - __ movq(c_rarg1, (int64_t) name); + __ lea(c_rarg1, ExternalAddress((address)name)); if (pass_oop) { __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime:: create_klass_exception), c_rarg1, c_rarg2); } else { - __ movq(c_rarg2, (int64_t) message); + // kind of lame ExternalAddress can't take NULL because + // external_word_Relocation will assert. + if (message != NULL) { + __ lea(c_rarg2, ExternalAddress((address)message)); + } else { + __ movptr(c_rarg2, NULL_WORD); + } __ call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), c_rarg1, c_rarg2); } // throw exception - __ jmp(Interpreter::throw_exception_entry(), relocInfo::none); + __ jump(ExternalAddress(Interpreter::throw_exception_entry())); return entry; } -address AbstractInterpreterGenerator::generate_continuation_for(TosState state) -{ +address AbstractInterpreterGenerator::generate_continuation_for(TosState state) { address entry = __ pc(); // NULL last_sp until next java call - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ dispatch_next(state); return entry; } address AbstractInterpreterGenerator::generate_return_entry_for(TosState state, - int step) -{ + int step) { // amd64 doesn't need to do anything special about compiled returns // to the interpreter so the code that exists on x86 to place a sentinel @@ -158,7 +158,7 @@ // Restore stack bottom in case i2c adjusted stack __ movq(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); // and NULL it as marker that esp is now tos until next java call - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); __ restore_locals(); @@ -176,11 +176,10 @@ address AbstractInterpreterGenerator::generate_deopt_entry_for(TosState state, - int step) -{ + int step) { address entry = __ pc(); // NULL last_sp until next java call - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); __ restore_locals(); // handle exceptions @@ -198,8 +197,7 @@ return entry; } -int AbstractInterpreter::BasicType_as_index(BasicType type) -{ +int AbstractInterpreter::BasicType_as_index(BasicType type) { int i = 0; switch (type) { case T_BOOLEAN: i = 0; break; @@ -222,8 +220,7 @@ address AbstractInterpreterGenerator::generate_result_handler_for( - BasicType type) -{ + BasicType type) { address entry = __ pc(); switch (type) { case T_BOOLEAN: __ c2bool(rax); break; @@ -248,8 +245,7 @@ } #ifdef _WIN64 -address AbstractInterpreterGenerator::generate_slow_signature_handler() -{ +address AbstractInterpreterGenerator::generate_slow_signature_handler() { address entry = __ pc(); // rbx: method @@ -290,7 +286,7 @@ case 0: __ movl(rscratch1, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(rscratch1, JVM_ACC_STATIC); - __ cmovq(Assembler::zero, c_rarg1, Address(rsp)); + __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); break; case 1: __ movq(c_rarg2, Address(rsp, wordSize)); @@ -328,8 +324,7 @@ return entry; } #else -address AbstractInterpreterGenerator::generate_slow_signature_handler() -{ +address AbstractInterpreterGenerator::generate_slow_signature_handler() { address entry = __ pc(); // rbx: method @@ -376,7 +371,7 @@ // Now handle integrals. Only do c_rarg1 if not static. __ movl(c_rarg3, Address(rbx, methodOopDesc::access_flags_offset())); __ testl(c_rarg3, JVM_ACC_STATIC); - __ cmovq(Assembler::zero, c_rarg1, Address(rsp)); + __ cmovq(Assembler::zero, c_rarg1, Address(rsp, 0)); __ movq(c_rarg2, Address(rsp, wordSize)); __ movq(c_rarg3, Address(rsp, 2 * wordSize)); @@ -394,8 +389,7 @@ address AbstractInterpreterGenerator::generate_safept_entry_for( TosState state, - address runtime_entry) -{ + address runtime_entry) { address entry = __ pc(); __ push(state); __ call_VM(noreg, runtime_entry); @@ -420,8 +414,7 @@ void InterpreterGenerator::generate_counter_incr( Label* overflow, Label* profile_method, - Label* profile_method_continue) -{ + Label* profile_method_continue) { const Address invocation_counter(rbx, methodOopDesc::invocation_counter_offset() + @@ -449,22 +442,18 @@ if (ProfileInterpreter && profile_method != NULL) { // Test to see if we should create a method data oop - __ cmpl(rcx, Address((address) &InvocationCounter::InterpreterProfileLimit, - relocInfo::none)); + __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit)); __ jcc(Assembler::less, *profile_method_continue); // if no method data exists, go to profile_method __ test_method_data_pointer(rax, *profile_method); } - __ cmpl(rcx, Address((address) - &InvocationCounter::InterpreterInvocationLimit, - relocInfo::none)); + __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit)); __ jcc(Assembler::aboveEqual, *overflow); } -void InterpreterGenerator::generate_counter_overflow(Label* do_continue) -{ +void InterpreterGenerator::generate_counter_overflow(Label* do_continue) { // Asm interpreter on entry // r14 - locals @@ -513,8 +502,7 @@ // // Kills: // rax -void InterpreterGenerator::generate_stack_overflow_check(void) -{ +void InterpreterGenerator::generate_stack_overflow_check(void) { // monitor entry size: see picture of stack set // (generate_method_entry) and frame_amd64.hpp @@ -573,8 +561,7 @@ __ jcc(Assembler::above, after_frame_check); __ popq(rax); // get return address - __ jmp(Interpreter::throw_StackOverflowError_entry(), - relocInfo::runtime_call_type); + __ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry())); // all done with frame size check __ bind(after_frame_check); @@ -590,8 +577,7 @@ // rax // c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs) // rscratch1, rscratch2 (scratch regs) -void InterpreterGenerator::lock_method(void) -{ +void InterpreterGenerator::lock_method(void) { // synchronize method const Address access_flags(rbx, methodOopDesc::access_flags_offset()); const Address monitor_block_top( @@ -656,8 +642,7 @@ // r14: pointer to locals // r13: sender sp // rdx: cp cache -void InterpreterGenerator::generate_fixed_frame(bool native_call) -{ +void InterpreterGenerator::generate_fixed_frame(bool native_call) { // initialize fixed part of activation frame __ pushq(rax); // save return address __ enter(); // save old & set new rbp @@ -688,7 +673,7 @@ __ pushq(r13); // set bcp } __ pushq(0); // reserve word for pointer to expression stack bottom - __ movq(Address(rsp), rsp); // set expression stack bottom + __ movq(Address(rsp, 0), rsp); // set expression stack bottom } // End of helpers @@ -698,8 +683,7 @@ // address InterpreterGenerator::generate_math_entry( - AbstractInterpreter::MethodKind kind) -{ + AbstractInterpreter::MethodKind kind) { // rbx: methodOop // r13: previous interpreter state (C++ interpreter) must preserve @@ -753,8 +737,7 @@ // Abstract method entry // Attempt to execute abstract method. Throw exception -address InterpreterGenerator::generate_abstract_entry(void) -{ +address InterpreterGenerator::generate_abstract_entry(void) { // rbx: methodOop // r13: sender SP @@ -780,8 +763,7 @@ // Empty method, generate a very fast return. -address InterpreterGenerator::generate_empty_entry(void) -{ +address InterpreterGenerator::generate_empty_entry(void) { // rbx: methodOop // r13: sender sp must set sp to this value on return @@ -793,9 +775,8 @@ // If we need a safepoint check, generate full interpreter entry. Label slow_path; - __ cmpl(Address(SafepointSynchronize::address_of_state(), - relocInfo::none), - SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); __ jcc(Assembler::notEqual, slow_path); // do nothing for empty methods (do not even increment invocation counter) @@ -814,8 +795,7 @@ // Call an accessor method (assuming it is resolved, otherwise drop // into vanilla (slow path) entry -address InterpreterGenerator::generate_accessor_entry(void) -{ +address InterpreterGenerator::generate_accessor_entry(void) { // rbx: methodOop // r13: senderSP must preserver for slow path, set SP to it on fast path @@ -832,9 +812,8 @@ // these conditions first and use slow path if necessary. Label slow_path; // If we need a safepoint check, generate full interpreter entry. - __ cmpl(Address(SafepointSynchronize::address_of_state(), - relocInfo::none), - SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); __ jcc(Assembler::notEqual, slow_path); // rbx: method @@ -959,8 +938,7 @@ // Interpreter stub for calling a native method. (asm interpreter) // This sets up a somewhat different looking stack for calling the // native method than the typical interpreter frame setup. -address InterpreterGenerator::generate_native_entry(bool synchronized) -{ +address InterpreterGenerator::generate_native_entry(bool synchronized) { // determine code generation flags bool inc_counter = UseCompiler || CountCompiledCalls; @@ -1130,7 +1108,7 @@ // However, large signatures cannot be cached and are generated // each time here. The slow-path generator can do a GC on return, // so we must reload it after the call. - __ call(t, relocInfo::none); + __ call(t); __ get_method(method); // slow path can do a GC, reload RBX @@ -1165,8 +1143,8 @@ { Label L; __ movq(rax, Address(method, methodOopDesc::native_function_offset())); - __ movq(rscratch2, (int64_t) - SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + __ movptr(rscratch2, unsatisfied.addr()); __ cmpq(rax, rscratch2); __ jcc(Assembler::notEqual, L); __ call_VM(noreg, @@ -1204,18 +1182,17 @@ _thread_in_native); // Call the native method. - __ call(rax, relocInfo::none); + __ call(rax); // result potentially in rax or xmm0 // Depending on runtime options, either restore the MXCSR // register after returning from the JNI Call or verify that // it wasn't changed during -Xcheck:jni. if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(Address(StubRoutines::amd64::mxcsr_std(), relocInfo::none)); + __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); } else if (CheckJNICalls) { - __ call(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); } // NOTE: The order of these pushes is known to frame::interpreter_frame_result @@ -1241,16 +1218,15 @@ // We use the current thread pointer to calculate a thread specific // offset to write to within the page. This minimizes bus traffic // due to cache line collision. - __ serialize_memory(r15_thread, rscratch1, rscratch2); + __ serialize_memory(r15_thread, rscratch2); } } // check for safepoint operation in progress and/or pending suspend requests { Label Continue; - __ cmpl(Address(SafepointSynchronize::address_of_state(), - relocInfo::none), - SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); Label L; __ jcc(Assembler::notEqual, L); @@ -1269,9 +1245,7 @@ __ movq(r12, rsp); // remember sp __ subq(rsp, frame::arg_reg_save_area_bytes); // windows __ andq(rsp, -16); // align stack as required by ABI - __ call(CAST_FROM_FN_PTR(address, - JavaThread::check_special_condition_for_native_trans), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ movq(rsp, r12); // restore sp __ bind(Continue); } @@ -1284,21 +1258,21 @@ // reset handle block __ movq(t, Address(r15_thread, JavaThread::active_handles_offset())); - __ movq(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movptr(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); // If result is an oop unbox and store it in frame where gc will see it // and result handler will pick it up { Label no_oop, store_result; - __ movq(t, (int64_t)AbstractInterpreter::result_handler(T_OBJECT)); + __ lea(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT))); __ cmpq(t, Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize)); __ jcc(Assembler::notEqual, no_oop); // retrieve result __ pop(ltos); __ testq(rax, rax); __ jcc(Assembler::zero, store_result); - __ movq(rax, Address(rax)); + __ movq(rax, Address(rax, 0)); __ bind(store_result); __ movq(Address(rbp, frame::interpreter_frame_oop_temp_offset*wordSize), rax); // keep stack depth as expected by pushing oop which will eventually be discarde @@ -1317,8 +1291,7 @@ __ movq(r12, rsp); // remember sp __ subq(rsp, frame::arg_reg_save_area_bytes); // windows __ andq(rsp, -16); // align stack as required by ABI - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ movq(rsp, r12); // restore sp __ popaq(); // XXX only restore smashed registers @@ -1403,7 +1376,7 @@ __ movq(t, Address(rbp, (frame::interpreter_frame_result_handler_offset) * wordSize)); - __ call(t, relocInfo::none); + __ call(t); // remove activation __ movq(t, Address(rbp, @@ -1426,8 +1399,7 @@ // // Generic interpreted method entry to (asm) interpreter // -address InterpreterGenerator::generate_asm_interpreter_entry(bool synchronized) -{ +address InterpreterGenerator::generate_asm_interpreter_entry(bool synchronized) { // determine code generation flags bool inc_counter = UseCompiler || CountCompiledCalls; @@ -1659,8 +1631,7 @@ // [ parameter 1 ] <--- r14 address AbstractInterpreterGenerator::generate_method_entry( - AbstractInterpreter::MethodKind kind) -{ + AbstractInterpreter::MethodKind kind) { // determine code generation flags bool synchronized = false; address entry_point = NULL; @@ -1692,8 +1663,7 @@ } // How much stack a method activation needs in words. -int AbstractInterpreter::size_top_interpreter_activation(methodOop method) -{ +int AbstractInterpreter::size_top_interpreter_activation(methodOop method) { const int entry_size = frame::interpreter_frame_monitor_size(); // total overhead size: entry_size + (saved rbp thru expr stack @@ -1715,8 +1685,7 @@ int moncount, int callee_param_count, int callee_locals, - bool is_top_frame) -{ + bool is_top_frame) { return layout_activation(method, tempcount, popframe_extra_args, moncount, callee_param_count, callee_locals, @@ -1732,8 +1701,7 @@ int callee_locals, frame* caller, frame* interpreter_frame, - bool is_top_frame) -{ + bool is_top_frame) { // Note: This calculation must exactly parallel the frame setup // in AbstractInterpreterGenerator::generate_method_entry. // If interpreter_frame!=NULL, set up the method, locals, and monitors. @@ -1816,14 +1784,13 @@ //----------------------------------------------------------------------------- // Exceptions -void AbstractInterpreterGenerator::generate_throw_exception() -{ +void AbstractInterpreterGenerator::generate_throw_exception() { // Entry point in previous activation (i.e., if the caller was // interpreted) Interpreter::_rethrow_exception_entry = __ pc(); // Restore sp to interpreter_frame_last_sp even though we are going // to empty the expression stack for the exception processing. - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); // rax: exception // rdx: return address/pc that threw exception __ restore_bcp(); // r13 points to call/send @@ -1950,7 +1917,7 @@ __ reset_last_Java_frame(true, true); // Restore the last_sp and null it out __ movq(rsp, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ restore_bcp(); // XXX do we need this? __ restore_locals(); // XXX do we need this? @@ -1976,7 +1943,7 @@ __ remove_activation(vtos, rdx, false, true, false); // restore exception __ movq(rax, Address(r15_thread, JavaThread::vm_result_offset())); - __ movq(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); __ verify_oop(rax); // In between activations - previous activation type unknown yet @@ -2040,8 +2007,7 @@ address& lep, address& fep, address& dep, - address& vep) -{ + address& vep) { assert(t->is_valid() && t->tos_in() == vtos, "illegal template"); Label L; aep = __ pc(); __ push_ptr(); __ jmp(L); @@ -2063,8 +2029,7 @@ InterpreterGenerator::InterpreterGenerator(StubQueue* code) - : AbstractInterpreterGenerator(code) -{ + : AbstractInterpreterGenerator(code) { generate_all(); // down here so it can be "virtual" } @@ -2072,8 +2037,7 @@ // Non-product code #ifndef PRODUCT -address AbstractInterpreterGenerator::generate_trace_code(TosState state) -{ +address AbstractInterpreterGenerator::generate_trace_code(TosState state) { address entry = __ pc(); __ push(state); @@ -2098,54 +2062,44 @@ return entry; } -void AbstractInterpreterGenerator::count_bytecode() -{ - __ incrementl(Address((address) &BytecodeCounter::_counter_value, - relocInfo::none)); +void AbstractInterpreterGenerator::count_bytecode() { + __ incrementl(ExternalAddress((address) &BytecodeCounter::_counter_value)); } -void AbstractInterpreterGenerator::histogram_bytecode(Template* t) -{ - __ incrementl(Address((address) &BytecodeHistogram::_counters[t->bytecode()], - relocInfo::none)); +void AbstractInterpreterGenerator::histogram_bytecode(Template* t) { + __ incrementl(ExternalAddress((address) &BytecodeHistogram::_counters[t->bytecode()])); } -void AbstractInterpreterGenerator::histogram_bytecode_pair(Template* t) -{ - __ movl(rbx, Address((address) &BytecodePairHistogram::_index, - relocInfo::none)); +void AbstractInterpreterGenerator::histogram_bytecode_pair(Template* t) { + __ mov32(rbx, ExternalAddress((address) &BytecodePairHistogram::_index)); __ shrl(rbx, BytecodePairHistogram::log2_number_of_codes); __ orl(rbx, ((int) t->bytecode()) << BytecodePairHistogram::log2_number_of_codes); - __ movl(Address((address) &BytecodePairHistogram::_index, - relocInfo::none), - rbx); - __ movq(rscratch1, (int64_t) BytecodePairHistogram::_counters); + __ mov32(ExternalAddress((address) &BytecodePairHistogram::_index), rbx); + __ lea(rscratch1, ExternalAddress((address) BytecodePairHistogram::_counters)); __ incrementl(Address(rscratch1, rbx, Address::times_4)); } -void AbstractInterpreterGenerator::trace_bytecode(Template* t) -{ +void AbstractInterpreterGenerator::trace_bytecode(Template* t) { // Call a little run-time stub to avoid blow-up for each bytecode. // The run-time runtime saves the right registers, depending on // the tosca in-state for the given template. - address entry = Interpreter::trace_code(t->tos_in()); - assert(entry != NULL, "entry must have been generated"); + + assert(Interpreter::trace_code(t->tos_in()) != NULL, + "entry must have been generated"); __ movq(r12, rsp); // remember sp __ andq(rsp, -16); // align stack as required by ABI - __ call(entry, relocInfo::none); + __ call(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); __ movq(rsp, r12); // restore sp } -void AbstractInterpreterGenerator::stop_interpreter_at() -{ +void AbstractInterpreterGenerator::stop_interpreter_at() { Label L; - __ cmpl(Address((address) &BytecodeCounter::_counter_value, - relocInfo::none), - StopInterpreterAt); + __ cmp32(ExternalAddress((address) &BytecodeCounter::_counter_value), + StopInterpreterAt); __ jcc(Assembler::notEqual, L); __ int3(); __ bind(L); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/jniFastGetField_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/jniFastGetField_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/jniFastGetField_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)jniFastGetField_amd64.cpp 1.12 07/06/08 18:13:31 JVM" +#pragma ident "@(#)jniFastGetField_amd64.cpp 1.13 07/06/19 09:08:01 JVM" #endif /* * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -68,9 +68,8 @@ Label slow; - address counter_addr = SafepointSynchronize::safepoint_counter_addr(); - Address ca(counter_addr, relocInfo::none); - __ movl (rcounter, ca); + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); + __ mov32 (rcounter, counter); __ movq (robj, c_rarg1); __ testb (rcounter, 1); __ jcc (Assembler::notZero, slow); @@ -80,7 +79,7 @@ // robj ^ rcounter ^ rcounter == robj // robj is data dependent on rcounter. } - __ movq (robj, Address(robj)); // *obj + __ movq (robj, Address(robj, 0)); // *obj __ movq (roffset, c_rarg2); __ shrq (roffset, 2); // offset @@ -96,13 +95,15 @@ default: ShouldNotReachHere(); } - __ movq (rcounter_addr, (int64_t)counter_addr); - ca = Address(rcounter_addr); if (os::is_MP()) { + __ lea(rcounter_addr, counter); + // ca is data dependent on rax. + __ xorq (rcounter_addr, rax); __ xorq (rcounter_addr, rax); - __ xorq (rcounter_addr, rax); // ca is data dependent on rax. + __ cmpl (rcounter, Address(rcounter_addr, 0)); + } else { + __ cmp32 (rcounter, counter); } - __ cmpl (rcounter, ca); __ jcc (Assembler::notEqual, slow); __ ret (0); @@ -119,7 +120,7 @@ case T_LONG: slow_case_addr = jni_GetLongField_addr(); } // tail call - __ jmp (slow_case_addr, relocInfo::none); + __ jump (ExternalAddress(slow_case_addr)); __ flush (); @@ -165,9 +166,8 @@ Label slow; - address counter_addr = SafepointSynchronize::safepoint_counter_addr(); - Address ca(counter_addr, relocInfo::none); - __ movl (rcounter, ca); + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); + __ mov32 (rcounter, counter); __ movq (robj, c_rarg1); __ testb (rcounter, 1); __ jcc (Assembler::notZero, slow); @@ -177,7 +177,7 @@ // robj ^ rcounter ^ rcounter == robj // robj is data dependent on rcounter. } - __ movq (robj, Address(robj)); // *obj + __ movq (robj, Address(robj, 0)); // *obj __ movq (roffset, c_rarg2); __ shrq (roffset, 2); // offset @@ -189,14 +189,16 @@ default: ShouldNotReachHere(); } - __ movq (rcounter_addr, (int64_t)counter_addr); - ca = Address(rcounter_addr); if (os::is_MP()) { + __ lea(rcounter_addr, counter); __ movdq (rax, xmm0); + // counter address is data dependent on xmm0. __ xorq (rcounter_addr, rax); - __ xorq (rcounter_addr, rax); // ca is data dependent on xmm0. + __ xorq (rcounter_addr, rax); + __ cmpl (rcounter, Address(rcounter_addr, 0)); + } else { + __ cmp32 (rcounter, counter); } - __ cmpl (rcounter, ca); __ jcc (Assembler::notEqual, slow); __ ret (0); @@ -209,7 +211,7 @@ case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); } // tail call - __ jmp (slow_case_addr, relocInfo::none); + __ jump (ExternalAddress(slow_case_addr)); __ flush (); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/sharedRuntime_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/sharedRuntime_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/sharedRuntime_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)sharedRuntime_amd64.cpp 1.40 07/06/08 18:13:31 JVM" +#pragma ident "@(#)sharedRuntime_amd64.cpp 1.41 07/06/19 09:08:02 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -410,7 +410,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { Label L; __ verify_oop(rbx); - __ cmpq(Address(rbx, in_bytes(methodOopDesc::code_offset())), NULL_WORD); + __ cmpq(Address(rbx, in_bytes(methodOopDesc::code_offset())), (int)NULL_WORD); __ jcc(Assembler::equal, L); // Save the current stack pointer @@ -437,8 +437,7 @@ } __ movq(c_rarg0, rbx); __ movq(c_rarg1, rax); - __ movq(rscratch1, CAST_FROM_FN_PTR(int64_t, SharedRuntime::fixup_callers_callsite)); - __ call(rscratch1, relocInfo::none); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite))); // De-allocate argument register save area if (frame::arg_reg_save_area_bytes != 0) { @@ -456,13 +455,13 @@ if (TaggedStackInterpreter) { int tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(0); if (sig == T_OBJECT || sig == T_ARRAY) { - __ movq(Address(rsp, tag_offset), frame::TagReference); + __ mov64(Address(rsp, tag_offset), frame::TagReference); } else if (sig == T_LONG || sig == T_DOUBLE) { int next_tag_offset = st_off + Interpreter::expr_tag_offset_in_bytes(1); - __ movq(Address(rsp, next_tag_offset), frame::TagValue); - __ movq(Address(rsp, tag_offset), frame::TagValue); + __ mov64(Address(rsp, next_tag_offset), frame::TagValue); + __ mov64(Address(rsp, tag_offset), frame::TagValue); } else { - __ movq(Address(rsp, tag_offset), frame::TagValue); + __ mov64(Address(rsp, tag_offset), frame::TagValue); } } } @@ -556,7 +555,7 @@ __ movq(Address(rsp, next_off), rax); #ifdef ASSERT // Overwrite the unused slot with known junk - __ movq(rax, CONST64(0xdeadffffdeadaaaa)); + __ mov64(rax, CONST64(0xdeadffffdeadaaaa)); __ movq(Address(rsp, st_off), rax); #endif /* ASSERT */ tag_stack(masm, sig_bt[i], next_off); @@ -579,7 +578,7 @@ // long/double in gpr #ifdef ASSERT // Overwrite the unused slot with known junk - __ movq(rax, CONST64(0xdeadffffdeadaaab)); + __ mov64(rax, CONST64(0xdeadffffdeadaaab)); __ movq(Address(rsp, st_off), rax); #endif /* ASSERT */ __ movq(Address(rsp, next_off), r); @@ -598,7 +597,7 @@ } else { #ifdef ASSERT // Overwrite the unused slot with known junk - __ movq(rax, CONST64(0xdeadffffdeadaaac)); + __ mov64(rax, CONST64(0xdeadffffdeadaaac)); __ movq(Address(rsp, st_off), rax); #endif /* ASSERT */ __ movdbl(Address(rsp, next_off), r_1->as_FloatRegister()); @@ -635,7 +634,7 @@ // save code can segv when fxsave instructions find improperly // aligned stack pointer. - __ movq(rax, Address(rsp)); + __ movq(rax, Address(rsp, 0)); // Cut-out for having no stack args. Since up to 2 int/oop args are passed // in registers, we will occasionally have no stack args. @@ -792,8 +791,6 @@ Register temp = rbx; { - address ic_miss = SharedRuntime::get_ic_miss_stub(); - __ verify_oop(holder); __ movq(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); __ verify_oop(temp); @@ -801,19 +798,15 @@ __ cmpq(temp, Address(holder, compiledICHolderOopDesc::holder_klass_offset())); __ movq(rbx, Address(holder, compiledICHolderOopDesc::holder_method_offset())); __ jcc(Assembler::equal, ok); - // Must have a long jump here. Code is relocated unknown amount - __ movq(rscratch1, (int64_t) ic_miss); - __ jmp(rscratch1); + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); __ bind(ok); // Method might have been compiled since the call site was patched to // interpreted if that is the case treat it as a miss so we can get // the call site corrected. - __ cmpq(Address(rbx, in_bytes(methodOopDesc::code_offset())), NULL_WORD); + __ cmpq(Address(rbx, in_bytes(methodOopDesc::code_offset())), (int)NULL_WORD); __ jcc(Assembler::equal, skip_fixup); - // Must have a long jump here. Code is relocated unknown amount - __ movq(rscratch1, (int64_t) ic_miss); - __ jmp(rscratch1); + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); } address c2i_entry = __ pc(); @@ -990,7 +983,7 @@ *receiver_offset = (offset_in_older_frame + framesize_in_slots) * VMRegImpl::stack_slot_size; } - __ cmpq(Address(rbp, reg2offset_in(src.first())), NULL_WORD); + __ cmpq(Address(rbp, reg2offset_in(src.first())), (int)NULL_WORD); __ leaq(rHandle, Address(rbp, reg2offset_in(src.first()))); // conditionally move a NULL __ cmovq(Assembler::equal, rHandle, Address(rbp, reg2offset_in(src.first()))); @@ -1299,7 +1292,6 @@ // First thing make an ic check to see if we should even be here - address ic_miss = SharedRuntime::get_ic_miss_stub(); // We are free to use all registers as temps without saving them and // restoring them except rbp. rbp is the only callee save register @@ -1316,7 +1308,7 @@ __ cmpq(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); __ jcc(Assembler::equal, ok); - __ jmp(ic_miss, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); // Verified entry point must be aligned __ align(8); @@ -1470,7 +1462,7 @@ if (method->is_static()) { // load oop into a register - __ movq(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); + __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); // Now handlize the static class mirror it's known not-null. __ movq(Address(rsp, klass_offset), oop_handle_reg); @@ -1502,7 +1494,7 @@ SkipIfEqual skip(masm, &DTraceMethodProbes, false); // protect the args we've loaded save_args(masm, total_c_args, c_arg, out_regs); - __ movq(c_rarg1, JNIHandles::make_local(method())); + __ movoop(c_rarg1, JNIHandles::make_local(method())); __ call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), r15_thread, c_rarg1); @@ -1544,7 +1536,7 @@ __ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax - __ orq(swap_reg, Address(obj_reg)); + __ orq(swap_reg, Address(obj_reg, 0)); // Save (object->mark() | 1) into BasicLock's displaced header __ movq(Address(lock_reg, mark_word_offset), swap_reg); @@ -1554,7 +1546,7 @@ } // src -> dest iff dest == rax else rax <- dest - __ cmpxchgq(lock_reg, Address(obj_reg)); + __ cmpxchgq(lock_reg, Address(obj_reg, 0)); __ jcc(Assembler::equal, lock_done); // Hmm should this move to the slow path code area??? @@ -1589,19 +1581,18 @@ __ leaq(c_rarg0, Address(r15_thread, in_bytes(JavaThread::jni_environment_offset()))); // Now set thread in native - __ movq(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native); - - __ call(method->native_function(), relocInfo::runtime_call_type); + __ mov64(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native); + + __ call(RuntimeAddress(method->native_function())); // Either restore the MXCSR register after returning from the JNI Call // or verify that it wasn't changed. if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(Address(StubRoutines::amd64::mxcsr_std(), relocInfo::external_word_type)); + __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); } else if (CheckJNICalls ) { - __ call(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); } @@ -1631,7 +1622,7 @@ // VM thread changes sync state to synchronizing and suspends threads for GC. // Thread A is resumed to finish this native method, but doesn't block here since it // didn't see any synchronization is progress, and escapes. - __ movq(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans); + __ mov64(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native_trans); if(os::is_MP()) { if (UseMembar) { @@ -1644,7 +1635,7 @@ // We use the current thread pointer to calculate a thread specific // offset to write to within the page. This minimizes bus traffic // due to cache line collision. - __ serialize_memory(r15_thread, r8, rcx); + __ serialize_memory(r15_thread, rcx); } } @@ -1653,8 +1644,8 @@ { Label Continue; - __ cmpl(Address((address)SafepointSynchronize::address_of_state(), relocInfo::external_word_type), - SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress((address)SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); Label L; __ jcc(Assembler::notEqual, L); @@ -1673,9 +1664,7 @@ __ movq(r12, rsp); // remember sp __ subq(rsp, frame::arg_reg_save_area_bytes); // windows __ andq(rsp, -16); // align stack as required by ABI - __ call(CAST_FROM_FN_PTR(address, - JavaThread::check_special_condition_for_native_trans), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ movq(rsp, r12); // restore sp // Restore any method result value restore_native_result(masm, ret_type, stack_slots); @@ -1709,7 +1698,7 @@ // Simple recursive lock? - __ cmpq(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), NULL_WORD); + __ cmpq(Address(rsp, lock_slot_offset * VMRegImpl::stack_slot_size), (int)NULL_WORD); __ jcc(Assembler::equal, done); // Must save rax if if it is live now because cmpxchg must use it @@ -1727,7 +1716,7 @@ if (os::is_MP()) { __ lock(); } - __ cmpxchgq(old_hdr, Address(obj_reg)); + __ cmpxchgq(old_hdr, Address(obj_reg, 0)); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -1743,7 +1732,7 @@ { SkipIfEqual skip(masm, &DTraceMethodProbes, false); save_native_result(masm, ret_type, stack_slots); - __ movq(c_rarg1, JNIHandles::make_local(method())); + __ movoop(c_rarg1, JNIHandles::make_local(method())); __ call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), r15_thread, c_rarg1); @@ -1757,21 +1746,21 @@ Label L; __ testq(rax, rax); __ jcc(Assembler::zero, L); - __ movq(rax, Address(rax)); + __ movq(rax, Address(rax, 0)); __ bind(L); __ verify_oop(rax); } // reset handle block __ movq(rcx, Address(r15_thread, JavaThread::active_handles_offset())); - __ movq(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int)NULL_WORD); // pop our frame __ leave(); // Any exception pending? - __ cmpq(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); + __ cmpq(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), (int)NULL_WORD); __ jcc(Assembler::notEqual, exception_pending); // Return @@ -1784,7 +1773,7 @@ __ bind(exception_pending); // and forward the exception - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); // Slow path locking & unlocking @@ -1839,14 +1828,14 @@ // Save pending exception around call to VM (which contains an EXCEPTION_MARK) // NOTE that obj_reg == rbx currently __ movq(rbx, Address(r15_thread, in_bytes(Thread::pending_exception_offset()))); - __ movq(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); - - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), relocInfo::runtime_call_type); + __ movptr(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), (int)NULL_WORD); + + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C))); __ movq(rsp, r12); // restore sp #ifdef ASSERT { Label L; - __ cmpq(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), NULL_WORD); + __ cmpq(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), (int)NULL_WORD); __ jcc(Assembler::equal, L); __ stop("no pending exception allowed on exit complete_monitor_unlocking_C"); __ bind(L); @@ -1871,7 +1860,7 @@ __ movq(r12, rsp); // remember sp __ subq(rsp, frame::arg_reg_save_area_bytes); // windows __ andq(rsp, -16); // align stack as required by ABI - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ movq(rsp, r12); // restore sp restore_native_result(masm, ret_type, stack_slots); // and continue @@ -1906,8 +1895,7 @@ //------------------------------generate_deopt_blob---------------------------- -void SharedRuntime::generate_deopt_blob() -{ +void SharedRuntime::generate_deopt_blob() { // Allocate space for the code ResourceMark rm; // Setup code generation tools @@ -1993,8 +1981,7 @@ } #endif // ASSERT __ movq(c_rarg0, r15_thread); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info))); // Need to have an oopmap that tells fetch_unroll_info where to // find any register it might need. @@ -2067,21 +2054,21 @@ // Push interpreter frames in a loop Label loop; __ bind(loop); - __ movq(rbx, Address(rsi)); // Load frame size + __ movq(rbx, Address(rsi, 0)); // Load frame size __ subq(rbx, 2*wordSize); // We'll push pc and ebp by hand - __ pushq(Address(rcx)); // Save return address + __ pushq(Address(rcx, 0)); // Save return address __ enter(); // Save old & set new ebp __ subq(rsp, rbx); // Prolog __ movq(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), sender_sp); // Make it walkable // This value is corrected by layout_activation_impl - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int)NULL_WORD ); __ movq(sender_sp, rsp); // Pass sender_sp to next frame __ addq(rsi, wordSize); // Bump array pointer (sizes) __ addq(rcx, wordSize); // Bump array pointer (pcs) __ decrementl(rdx); // Decrement counter __ jcc(Assembler::notZero, loop); - __ pushq(Address(rcx)); // Save final return address + __ pushq(Address(rcx, 0)); // Save final return address // Re-push self-frame __ enter(); // Save old & set new ebp @@ -2105,8 +2092,7 @@ __ movq(c_rarg0, r15_thread); __ movl(c_rarg1, r12); // second arg: exec_mode - __ call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); // Set an oopmap for the call site oop_maps->add_gc_map(__ pc() - start, @@ -2164,8 +2150,7 @@ // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index); __ movq(c_rarg0, r15_thread); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); // Set an oopmap for the call site OopMapSet* oop_maps = new OopMapSet(); @@ -2243,21 +2228,21 @@ // Push interpreter frames in a loop Label loop; __ bind(loop); - __ movq(rbx, Address(rsi)); // Load frame size + __ movq(rbx, Address(rsi, 0)); // Load frame size __ subq(rbx, 2 * wordSize); // We'll push pc and rbp by hand - __ pushq(Address(rcx)); // Save return address + __ pushq(Address(rcx, 0)); // Save return address __ enter(); // Save old & set new rbp __ subq(rsp, rbx); // Prolog __ movq(Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize), sender_sp); // Make it walkable // This value is corrected by layout_activation_impl - __ movq(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD ); + __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int)NULL_WORD ); __ movq(sender_sp, rsp); // Pass sender_sp to next frame __ addq(rsi, wordSize); // Bump array pointer (sizes) __ addq(rcx, wordSize); // Bump array pointer (pcs) __ decrementl(rdx); // Decrement counter __ jcc(Assembler::notZero, loop); - __ pushq(Address(rcx)); // Save final return address + __ pushq(Address(rcx, 0)); // Save final return address // Re-push self-frame __ enter(); // Save old & set new rbp @@ -2276,8 +2261,7 @@ __ movq(c_rarg0, r15_thread); __ movl(c_rarg1, Deoptimization::Unpack_uncommon_trap); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); // Set an oopmap for the call site oop_maps->add_gc_map(__ pc() - start, new OopMap(SimpleRuntimeFrame::framesize, 0)); @@ -2304,8 +2288,7 @@ // Generate a special Compile2Runtime blob that saves all registers, // and setup oopmap. // -static SafepointBlob* generate_handler_blob(address call_ptr, bool cause_return) -{ +static SafepointBlob* generate_handler_blob(address call_ptr, bool cause_return) { assert(StubRoutines::forward_exception_entry() != NULL, "must be generated before"); @@ -2346,7 +2329,7 @@ // Do the call __ movq(c_rarg0, r15_thread); - __ call(call_ptr, relocInfo::runtime_call_type); + __ call(RuntimeAddress(call_ptr)); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -2359,14 +2342,14 @@ __ reset_last_Java_frame(false, false); - __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), NULL_WORD); + __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); __ jcc(Assembler::equal, noException); // Exception pending RegisterSaver::restore_live_registers(masm); - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); // No exception case __ bind(noException); @@ -2415,7 +2398,7 @@ __ movq(c_rarg0, r15_thread); - __ call(destination, relocInfo::runtime_call_type); + __ call(RuntimeAddress(destination)); // Set an oopmap for the call site. @@ -2430,7 +2413,7 @@ __ reset_last_Java_frame(false, false); // check for pending exceptions Label pending; - __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), NULL_WORD); + __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); __ jcc(Assembler::notEqual, pending); // get the returned methodOop @@ -2453,10 +2436,10 @@ // exception pending => remove activation and forward to exception handler - __ movq(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::vm_result_offset()), (int)NULL_WORD); __ movq(rax, Address(r15_thread, Thread::pending_exception_offset())); - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); // ------------- // make sure all code is generated @@ -2527,8 +2510,7 @@ // Registers rax, rdx, rcx, rsi, rdi, r8-r11 are not callee saved. // -void OptoRuntime::generate_exception_blob() -{ +void OptoRuntime::generate_exception_blob() { assert(!OptoRuntime::is_callee_saved_register(RDX_num), ""); assert(!OptoRuntime::is_callee_saved_register(RAX_num), ""); assert(!OptoRuntime::is_callee_saved_register(RCX_num), ""); @@ -2573,8 +2555,7 @@ __ set_last_Java_frame(noreg, noreg, NULL); __ movq(c_rarg0, r15_thread); - __ call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); // Set an oopmap for the call site. This oopmap will only be used if we // are unwinding the stack. Hence, all locations will be dead. @@ -2609,11 +2590,11 @@ // Get the exception pc in case we are deoptimized __ movq(rdx, Address(r15_thread, JavaThread::exception_pc_offset())); #ifdef ASSERT - __ movq(Address(r15_thread, JavaThread::exception_handler_pc_offset()), NULL_WORD); - __ movq(Address(r15_thread, JavaThread::exception_pc_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::exception_handler_pc_offset()), (int)NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::exception_pc_offset()), (int)NULL_WORD); #endif // Clear the exception oop so GC no longer processes it as a root. - __ movq(Address(r15_thread, JavaThread::exception_oop_offset()), NULL_WORD); + __ movptr(Address(r15_thread, JavaThread::exception_oop_offset()), (int)NULL_WORD); // rax: exception oop // r8: exception handler diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/stubGenerator_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/stubGenerator_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/stubGenerator_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)stubGenerator_amd64.cpp 1.42 07/06/08 18:13:31 JVM" +#pragma ident "@(#)stubGenerator_amd64.cpp 1.43 07/06/19 09:08:02 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -67,8 +67,7 @@ #define inc_counter_np(counter) (0) #else void inc_counter_np_(int& counter) { - Address counter_addr((address) &counter, relocInfo::none); - __ incrementl(counter_addr); + __ incrementl(ExternalAddress((address)&counter)); } #define inc_counter_np(counter) \ BLOCK_COMMENT("inc_counter " #counter); \ @@ -246,9 +245,10 @@ __ stmxcsr(mxcsr_save); __ movl(rax, mxcsr_save); __ andl(rax, MXCSR_MASK); // Only check control and mask bits - __ cmpl(rax, *(int *)(StubRoutines::amd64::mxcsr_std())); + ExternalAddress mxcsr_std(StubRoutines::amd64::mxcsr_std()); + __ cmp32(rax, mxcsr_std); __ jcc(Assembler::equal, skip_ldmx); - __ ldmxcsr(Address(StubRoutines::amd64::mxcsr_std(), relocInfo::none)); + __ ldmxcsr(mxcsr_std); __ bind(skip_ldmx); } #endif @@ -260,7 +260,7 @@ // make sure we have no pending exceptions { Label L; - __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), NULL_WORD); + __ cmpq(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); __ jcc(Assembler::equal, L); __ stop("StubRoutines::call_stub: entered with pending exception"); __ bind(L); @@ -279,11 +279,11 @@ __ movl(c_rarg1, c_rarg3); // parameter counter is in c_rarg1 __ BIND(loop); if (TaggedStackInterpreter) { - __ movq(rax, Address(c_rarg2)); // get tag + __ movq(rax, Address(c_rarg2, 0)); // get tag __ addq(c_rarg2, wordSize); // advance to next tag - __ pushq(rax); // pass tag + __ pushq(rax); // pass tag } - __ movq(rax, Address(c_rarg2)); // get parameter + __ movq(rax, Address(c_rarg2, 0)); // get parameter __ addq(c_rarg2, wordSize); // advance to next parameter __ decrementl(c_rarg1); // decrement counter __ pushq(rax); // pass parameter @@ -295,7 +295,7 @@ __ movq(c_rarg1, entry_point); // get entry_point __ movq(r13, rsp); // set sender sp BLOCK_COMMENT("call Java function"); - __ call(c_rarg1, relocInfo::none); + __ call(c_rarg1); BLOCK_COMMENT("call_stub_return_address:"); return_address = __ pc(); @@ -315,7 +315,7 @@ __ jcc(Assembler::equal, is_double); // handle T_INT case - __ movl(Address(c_rarg0), rax); + __ movl(Address(c_rarg0, 0), rax); __ BIND(exit); @@ -361,15 +361,15 @@ // handle return types different from T_INT __ BIND(is_long); - __ movq(Address(c_rarg0), rax); + __ movq(Address(c_rarg0, 0), rax); __ jmp(exit); __ BIND(is_float); - __ movflt(Address(c_rarg0), xmm0); + __ movflt(Address(c_rarg0, 0), xmm0); __ jmp(exit); __ BIND(is_double); - __ movdbl(Address(c_rarg0), xmm0); + __ movdbl(Address(c_rarg0, 0), xmm0); __ jmp(exit); return start; @@ -414,14 +414,14 @@ __ verify_oop(rax); __ movq(Address(r15_thread, Thread::pending_exception_offset()), rax); - __ movq(rscratch1, (int64_t) __FILE__); + __ lea(rscratch1, ExternalAddress((address)__FILE__)); __ movq(Address(r15_thread, Thread::exception_file_offset()), rscratch1); __ movl(Address(r15_thread, Thread::exception_line_offset()), (int) __LINE__); // complete return to VM assert(StubRoutines::_call_stub_return_address != NULL, "_call_stub_return_address must have been generated before"); - __ jmp(StubRoutines::_call_stub_return_address, relocInfo::none); + __ jump(RuntimeAddress(StubRoutines::_call_stub_return_address)); return start; } @@ -462,7 +462,7 @@ #endif // compute exception handler into rbx - __ movq(c_rarg0, Address(rsp)); + __ movq(c_rarg0, Address(rsp, 0)); BLOCK_COMMENT("call exception_handler_for_return_address"); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), @@ -472,7 +472,7 @@ // setup rax & rdx, remove return address & clear pending exception __ popq(rdx); __ movq(rax, Address(r15_thread, Thread::pending_exception_offset())); - __ movq(Address(r15_thread, Thread::pending_exception_offset()), NULL_WORD); + __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int)NULL_WORD); #ifdef ASSERT // make sure exception is set @@ -508,7 +508,7 @@ address start = __ pc(); __ movl(rax, c_rarg0); // Copy to eax we need a return value anyhow - __ xchgl(rax, Address(c_rarg1)); // automatic LOCK + __ xchgl(rax, Address(c_rarg1, 0)); // automatic LOCK __ ret(0); return start; @@ -527,7 +527,7 @@ address start = __ pc(); __ movq(rax, c_rarg0); // Copy to eax we need a return value anyhow - __ xchgq(rax, Address(c_rarg1)); // automatic LOCK + __ xchgq(rax, Address(c_rarg1, 0)); // automatic LOCK __ ret(0); return start; @@ -553,7 +553,7 @@ __ movl(rax, c_rarg2); if ( os::is_MP() ) __ lock(); - __ cmpxchgl(c_rarg0, Address(c_rarg1)); + __ cmpxchgl(c_rarg0, Address(c_rarg1, 0)); __ ret(0); return start; @@ -579,7 +579,7 @@ __ movq(rax, c_rarg2); if ( os::is_MP() ) __ lock(); - __ cmpxchgq(c_rarg0, Address(c_rarg1)); + __ cmpxchgq(c_rarg0, Address(c_rarg1, 0)); __ ret(0); return start; @@ -600,7 +600,7 @@ __ movl(rax, c_rarg0); if ( os::is_MP() ) __ lock(); - __ xaddl(Address(c_rarg1), c_rarg0); + __ xaddl(Address(c_rarg1, 0), c_rarg0); __ addl(rax, c_rarg0); __ ret(0); @@ -622,7 +622,7 @@ __ movq(rax, c_rarg0); // Copy to eax we need a return value anyhow if ( os::is_MP() ) __ lock(); - __ xaddl(Address(c_rarg1), c_rarg0); + __ xaddl(Address(c_rarg1, 0), c_rarg0); __ addl(rax, c_rarg0); __ ret(0); @@ -675,7 +675,7 @@ StubCodeMark mark(this, "StubRoutines", "verify_mxcsr"); address start = __ pc(); - const Address mxcsr_save(rsp); + const Address mxcsr_save(rsp, 0); if (CheckJNICalls) { Label ok_ret; @@ -689,7 +689,7 @@ __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall"); - __ ldmxcsr(Address(StubRoutines::amd64::mxcsr_std(), relocInfo::none)); + __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); __ bind(ok_ret); __ addq(rsp, wordSize); @@ -759,8 +759,8 @@ __ cmpl(rax, c_rarg1); // NaN? -> 0 __ jcc(Assembler::negative, L); __ testl(c_rarg2, c_rarg2); // signed ? min_jlong : max_jlong - __ movq(c_rarg3, 0x8000000000000000); - __ movq(rax, 0x7fffffffffffffff); + __ mov64(c_rarg3, 0x8000000000000000); + __ mov64(rax, 0x7fffffffffffffff); __ cmovq(Assembler::positive, c_rarg3, rax); __ bind(L); @@ -852,8 +852,8 @@ __ cmpl(rax, c_rarg1); __ jcc(Assembler::negative, L); // NaN -> 0 __ testq(c_rarg0, c_rarg0); // signed ? min_jlong : max_jlong - __ movq(c_rarg2, 0x8000000000000000); - __ movq(rax, 0x7fffffffffffffff); + __ mov64(c_rarg2, 0x8000000000000000); + __ mov64(rax, 0x7fffffffffffffff); __ cmovq(Assembler::positive, c_rarg2, rax); __ bind(L); @@ -896,8 +896,7 @@ __ subq(rsp, frame::arg_reg_save_area_bytes); BLOCK_COMMENT("call handle_unsafe_access"); - __ call(CAST_FROM_FN_PTR(address, handle_unsafe_access), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access))); __ addq(rsp, frame::arg_reg_save_area_bytes); __ movq(next_pc, rax); // stuff next address @@ -928,8 +927,7 @@ Label exit, error; __ pushfq(); - __ incrementl(Address((address) StubRoutines::verify_oop_count_addr(), - relocInfo::none)); + __ incrementl(ExternalAddress((address) StubRoutines::verify_oop_count_addr())); // save c_rarg2 and c_rarg3 __ pushq(c_rarg2); @@ -943,9 +941,9 @@ __ jcc(Assembler::zero, exit); // if obj is NULL it is OK // Check if the oop is in the right area of memory __ movq(c_rarg2, rax); - __ movq(c_rarg3, (int64_t) Universe::verify_oop_mask()); + __ movptr(c_rarg3, (int64_t) Universe::verify_oop_mask()); __ andq(c_rarg2, c_rarg3); - __ movq(c_rarg3, (int64_t) Universe::verify_oop_bits()); + __ movptr(c_rarg3, (int64_t) Universe::verify_oop_bits()); __ cmpq(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); @@ -955,9 +953,9 @@ __ jcc(Assembler::zero, error); // if klass is NULL it is broken // Check if the klass is in the right area of memory __ movq(c_rarg2, rax); - __ movq(c_rarg3, (int64_t) Universe::verify_klass_mask()); + __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); __ andq(c_rarg2, c_rarg3); - __ movq(c_rarg3, (int64_t) Universe::verify_klass_bits()); + __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); __ cmpq(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); @@ -966,9 +964,9 @@ __ testq(rax, rax); __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken // Check if the klass' klass is in the right area of memory - __ movq(c_rarg3, (int64_t) Universe::verify_klass_mask()); + __ movptr(c_rarg3, (int64_t) Universe::verify_klass_mask()); __ andq(rax, c_rarg3); - __ movq(c_rarg3, (int64_t) Universe::verify_klass_bits()); + __ movptr(c_rarg3, (int64_t) Universe::verify_klass_bits()); __ cmpq(rax, c_rarg3); __ jcc(Assembler::notZero, error); @@ -1004,8 +1002,7 @@ __ subq(rsp, frame::arg_reg_save_area_bytes);// windows __ andq(rsp, -16); // align stack as required by ABI BLOCK_COMMENT("call MacroAssembler::debug"); - __ call(CAST_FROM_FN_PTR(address, MacroAssembler::debug), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); __ movq(rsp, r12); // restore rsp __ popaq(); // pop registers __ ret(3 * wordSize); // pop caller saved stuff @@ -1072,15 +1069,16 @@ __ cmpq(to, from); __ leaq(end_from, Address(from, count, sf, 0)); - if (NOLp == NULL) - __ jcc(Assembler::belowEqual, no_overlap_target); - else + if (NOLp == NULL) { + ExternalAddress no_overlap(no_overlap_target); + __ jump_cc(Assembler::belowEqual, no_overlap); + __ cmpq(to, end_from); + __ jump_cc(Assembler::aboveEqual, no_overlap); + } else { __ jcc(Assembler::belowEqual, (*NOLp)); - __ cmpq(to, end_from); - if (NOLp == NULL) - __ jcc(Assembler::aboveEqual, no_overlap_target); - else + __ cmpq(to, end_from); __ jcc(Assembler::aboveEqual, (*NOLp)); + } } // Shuffle first three arg regs on Windows into Linux/Solaris locations. @@ -1149,7 +1147,7 @@ __ subq(end, start); // number of bytes to copy const Register count = end; // 'end' register contains bytes count now - __ movq(scratch, (int64_t) ct->byte_map_base); + __ lea(scratch, ExternalAddress((address)ct->byte_map_base)); __ addq(start, scratch); __ BIND(L_loop); __ movb(Address(start, count, Address::times_1), 0); @@ -2220,19 +2218,19 @@ __ jccb(Assembler::zero, L_int_aligned); __ testb(bits, BytesPerShort-1); - __ jcc(Assembler::notZero, byte_copy_entry, relocInfo::runtime_call_type); + __ jump_cc(Assembler::notZero, RuntimeAddress(byte_copy_entry)); __ BIND(L_short_aligned); __ shrq(size, LogBytesPerShort); // size => short_count - __ jmp(short_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(short_copy_entry)); __ BIND(L_int_aligned); __ shrq(size, LogBytesPerInt); // size => int_count - __ jmp(int_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(int_copy_entry)); __ BIND(L_long_aligned); __ shrq(size, LogBytesPerLong); // size => qword_count - __ jmp(long_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(long_copy_entry)); return start; } @@ -2441,7 +2439,7 @@ __ leaq(from, Address(src, src_pos, Address::times_1, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_1, 0));// dst_addr __ movslq(count, r11_length); // length - __ jmp(byte_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(byte_copy_entry)); __ BIND(L_copy_shorts); __ cmpl(rax_elsize, LogBytesPerShort); @@ -2449,7 +2447,7 @@ __ leaq(from, Address(src, src_pos, Address::times_2, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_2, 0));// dst_addr __ movslq(count, r11_length); // length - __ jmp(short_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(short_copy_entry)); __ BIND(L_copy_ints); __ cmpl(rax_elsize, LogBytesPerInt); @@ -2457,7 +2455,7 @@ __ leaq(from, Address(src, src_pos, Address::times_4, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_4, 0));// dst_addr __ movslq(count, r11_length); // length - __ jmp(int_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(int_copy_entry)); __ BIND(L_copy_longs); #ifdef ASSERT @@ -2471,7 +2469,7 @@ __ leaq(from, Address(src, src_pos, Address::times_8, 0));// src_addr __ leaq(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr __ movslq(count, r11_length); // length - __ jmp(long_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(long_copy_entry)); // objArrayKlass __ BIND(L_objArray); @@ -2492,7 +2490,7 @@ arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr __ movslq(count, r11_length); // length __ BIND(L_plain_copy); - __ jmp(oop_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(oop_copy_entry)); __ BIND(L_checkcast_copy); // live at this point: r10_src_klass, !r11_length @@ -2544,7 +2542,7 @@ // the checkcast_copy loop needs two extra arguments: assert(c_rarg3 == sco_temp, "#3 already in place"); __ movq(C_RARG4, r11_dst_klass); // dst.klass.element_klass - __ jmp(checkcast_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(checkcast_copy_entry)); } __ BIND(L_failed); @@ -2667,7 +2665,7 @@ // Call runtime __ movq(c_rarg0, r15_thread); BLOCK_COMMENT("call runtime_entry"); - __ call(runtime_entry, relocInfo::runtime_call_type); + __ call(RuntimeAddress(runtime_entry)); // Generate oop map OopMap* map = new OopMap(framesize, 0); @@ -2687,8 +2685,7 @@ __ should_not_reach_here(); __ bind(L); #endif // ASSERT - __ jmp(StubRoutines::forward_exception_entry(), - relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); // codeBlob framesize is in words (not VMRegImpl::slot_size) diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/templateTable_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/templateTable_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/templateTable_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)templateTable_amd64.cpp 1.55 07/06/08 18:13:32 JVM" +#pragma ident "@(#)templateTable_amd64.cpp 1.56 07/06/19 09:08:02 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -32,66 +32,54 @@ // Platform-dependent initialization -void TemplateTable::pd_initialize() -{ +void TemplateTable::pd_initialize() { // No amd64 specific initialization } // Address computation: local variables -static inline Address iaddress(int n) -{ +static inline Address iaddress(int n) { return Address(r14, Interpreter::local_offset_in_bytes(n)); } -static inline Address laddress(int n) -{ +static inline Address laddress(int n) { return iaddress(n + 1); } -static inline Address faddress(int n) -{ +static inline Address faddress(int n) { return iaddress(n); } -static inline Address daddress(int n) -{ +static inline Address daddress(int n) { return laddress(n); } -static inline Address aaddress(int n) -{ +static inline Address aaddress(int n) { return iaddress(n); } -static inline Address iaddress(Register r) -{ +static inline Address iaddress(Register r) { return Address(r14, r, Address::times_8, Interpreter::value_offset_in_bytes()); } -static inline Address laddress(Register r) -{ +static inline Address laddress(Register r) { return Address(r14, r, Address::times_8, Interpreter::local_offset_in_bytes(1)); } -static inline Address faddress(Register r) -{ +static inline Address faddress(Register r) { return iaddress(r); } -static inline Address daddress(Register r) -{ +static inline Address daddress(Register r) { return laddress(r); } -static inline Address aaddress(Register r) -{ +static inline Address aaddress(Register r) { return iaddress(r); } -static inline Address at_rsp() -{ - return Address(rsp); +static inline Address at_rsp() { + return Address(rsp, 0); } // At top of Java expression stack which may be different than esp(). It @@ -113,8 +101,7 @@ } // Condition conversion -static Assembler::Condition j_not(TemplateTable::Condition cc) -{ +static Assembler::Condition j_not(TemplateTable::Condition cc) { switch (cc) { case TemplateTable::equal : return Assembler::notEqual; case TemplateTable::not_equal : return Assembler::equal; @@ -130,16 +117,14 @@ // Miscelaneous helper routines -Address TemplateTable::at_bcp(int offset) -{ +Address TemplateTable::at_bcp(int offset) { assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); return Address(r13, offset); } void TemplateTable::patch_bytecode(Bytecodes::Code bytecode, Register bc, Register scratch, - bool load_bc_into_scratch/*=true*/) -{ + bool load_bc_into_scratch/*=true*/) { if (!RewriteBytecodes) { return; } @@ -185,26 +170,22 @@ // Individual instructions -void TemplateTable::nop() -{ +void TemplateTable::nop() { transition(vtos, vtos); // nothing to do } -void TemplateTable::shouldnotreachhere() -{ +void TemplateTable::shouldnotreachhere() { transition(vtos, vtos); __ stop("shouldnotreachhere bytecode"); } -void TemplateTable::aconst_null() -{ +void TemplateTable::aconst_null() { transition(vtos, atos); __ xorl(rax, rax); } -void TemplateTable::iconst(int value) -{ +void TemplateTable::iconst(int value) { transition(vtos, itos); if (value == 0) { __ xorl(rax, rax); @@ -213,8 +194,7 @@ } } -void TemplateTable::lconst(int value) -{ +void TemplateTable::lconst(int value) { transition(vtos, ltos); if (value == 0) { __ xorl(rax, rax); @@ -223,8 +203,7 @@ } } -void TemplateTable::fconst(int value) -{ +void TemplateTable::fconst(int value) { transition(vtos, ftos); static float one = 1.0f, two = 2.0f; switch (value) { @@ -232,10 +211,10 @@ __ xorps(xmm0, xmm0); break; case 1: - __ movflt(xmm0, Address((address) &one, relocInfo::none)); + __ movflt(xmm0, ExternalAddress((address) &one)); break; case 2: - __ movflt(xmm0, Address((address) &two, relocInfo::none)); + __ movflt(xmm0, ExternalAddress((address) &two)); break; default: ShouldNotReachHere(); @@ -243,8 +222,7 @@ } } -void TemplateTable::dconst(int value) -{ +void TemplateTable::dconst(int value) { transition(vtos, dtos); static double one = 1.0; switch (value) { @@ -252,7 +230,7 @@ __ xorpd(xmm0, xmm0); break; case 1: - __ movdbl(xmm0, Address((address) &one, relocInfo::none)); + __ movdbl(xmm0, ExternalAddress((address) &one)); break; default: ShouldNotReachHere(); @@ -260,22 +238,19 @@ } } -void TemplateTable::bipush() -{ +void TemplateTable::bipush() { transition(vtos, itos); __ load_signed_byte(rax, at_bcp(1)); } -void TemplateTable::sipush() -{ +void TemplateTable::sipush() { transition(vtos, itos); __ load_unsigned_word(rax, at_bcp(1)); __ bswapl(rax); __ sarl(rax, 16); } -void TemplateTable::ldc(bool wide) -{ +void TemplateTable::ldc(bool wide) { transition(vtos, vtos); Label call_ldc, notFloat, notClass, Done; @@ -355,8 +330,7 @@ __ bind(Done); } -void TemplateTable::ldc2_w() -{ +void TemplateTable::ldc2_w() { transition(vtos, vtos); Label Long, Done; __ get_unsigned_2_byte_index_at_bcp(rbx, 1); @@ -382,15 +356,13 @@ __ bind(Done); } -void TemplateTable::locals_index(Register reg, int offset) -{ +void TemplateTable::locals_index(Register reg, int offset) { __ load_unsigned_byte(reg, at_bcp(offset)); __ negq(reg); if (TaggedStackInterpreter) __ shlq(reg, 1); // index = index*2 } -void TemplateTable::iload() -{ +void TemplateTable::iload() { transition(vtos, itos); if (RewriteFrequentPairs) { Label rewrite, done; @@ -430,8 +402,7 @@ debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::fast_iload2() -{ +void TemplateTable::fast_iload2() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); @@ -442,48 +413,42 @@ debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::fast_iload() -{ +void TemplateTable::fast_iload() { transition(vtos, itos); locals_index(rbx); __ movl(rax, iaddress(rbx)); debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::lload() -{ +void TemplateTable::lload() { transition(vtos, ltos); locals_index(rbx); __ movq(rax, laddress(rbx)); debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } -void TemplateTable::fload() -{ +void TemplateTable::fload() { transition(vtos, ftos); locals_index(rbx); __ movflt(xmm0, faddress(rbx)); debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::dload() -{ +void TemplateTable::dload() { transition(vtos, dtos); locals_index(rbx); __ movdbl(xmm0, daddress(rbx)); debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } -void TemplateTable::aload() -{ +void TemplateTable::aload() { transition(vtos, atos); locals_index(rbx); __ movq(rax, aaddress(rbx)); debug_only(__ verify_local_tag(frame::TagReference, rbx)); } -void TemplateTable::locals_index_wide(Register reg) -{ +void TemplateTable::locals_index_wide(Register reg) { __ movl(reg, at_bcp(2)); __ bswapl(reg); __ shrl(reg, 16); @@ -491,48 +456,42 @@ if (TaggedStackInterpreter) __ shlq(reg, 1); // index = index*2 } -void TemplateTable::wide_iload() -{ +void TemplateTable::wide_iload() { transition(vtos, itos); locals_index_wide(rbx); __ movl(rax, iaddress(rbx)); debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::wide_lload() -{ +void TemplateTable::wide_lload() { transition(vtos, ltos); locals_index_wide(rbx); __ movq(rax, laddress(rbx)); debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } -void TemplateTable::wide_fload() -{ +void TemplateTable::wide_fload() { transition(vtos, ftos); locals_index_wide(rbx); __ movflt(xmm0, faddress(rbx)); debug_only(__ verify_local_tag(frame::TagValue, rbx)); } -void TemplateTable::wide_dload() -{ +void TemplateTable::wide_dload() { transition(vtos, dtos); locals_index_wide(rbx); __ movdbl(xmm0, daddress(rbx)); debug_only(__ verify_local_tag(frame::TagCategory2, rbx)); } -void TemplateTable::wide_aload() -{ +void TemplateTable::wide_aload() { transition(vtos, atos); locals_index_wide(rbx); __ movq(rax, aaddress(rbx)); debug_only(__ verify_local_tag(frame::TagReference, rbx)); } -void TemplateTable::index_check(Register array, Register index) -{ +void TemplateTable::index_check(Register array, Register index) { // destroys rbx // check array __ null_check(array, arrayOopDesc::length_offset_in_bytes()); @@ -545,13 +504,11 @@ assert(rbx != array, "different registers"); __ movl(rbx, index); } - __ jcc(Assembler::aboveEqual, - Interpreter::_throw_ArrayIndexOutOfBoundsException_entry, - relocInfo::none); + __ jump_cc(Assembler::aboveEqual, + ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); } -void TemplateTable::iaload() -{ +void TemplateTable::iaload() { transition(itos, itos); __ pop_ptr(rdx); // eax: index @@ -562,8 +519,7 @@ arrayOopDesc::base_offset_in_bytes(T_INT))); } -void TemplateTable::laload() -{ +void TemplateTable::laload() { transition(itos, ltos); __ pop_ptr(rdx); // eax: index @@ -574,8 +530,7 @@ arrayOopDesc::base_offset_in_bytes(T_LONG))); } -void TemplateTable::faload() -{ +void TemplateTable::faload() { transition(itos, ftos); __ pop_ptr(rdx); // eax: index @@ -586,8 +541,7 @@ arrayOopDesc::base_offset_in_bytes(T_FLOAT))); } -void TemplateTable::daload() -{ +void TemplateTable::daload() { transition(itos, dtos); __ pop_ptr(rdx); // eax: index @@ -598,8 +552,7 @@ arrayOopDesc::base_offset_in_bytes(T_DOUBLE))); } -void TemplateTable::aaload() -{ +void TemplateTable::aaload() { transition(itos, atos); __ pop_ptr(rdx); // eax: index @@ -610,8 +563,7 @@ arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } -void TemplateTable::baload() -{ +void TemplateTable::baload() { transition(itos, itos); __ pop_ptr(rdx); // eax: index @@ -623,8 +575,7 @@ arrayOopDesc::base_offset_in_bytes(T_BYTE))); } -void TemplateTable::caload() -{ +void TemplateTable::caload() { transition(itos, itos); __ pop_ptr(rdx); // eax: index @@ -637,8 +588,7 @@ } // iload followed by caload frequent pair -void TemplateTable::fast_icaload() -{ +void TemplateTable::fast_icaload() { transition(vtos, itos); // load index out of locals locals_index(rbx); @@ -655,8 +605,7 @@ arrayOopDesc::base_offset_in_bytes(T_CHAR))); } -void TemplateTable::saload() -{ +void TemplateTable::saload() { transition(itos, itos); __ pop_ptr(rdx); // eax: index @@ -668,43 +617,37 @@ arrayOopDesc::base_offset_in_bytes(T_SHORT))); } -void TemplateTable::iload(int n) -{ +void TemplateTable::iload(int n) { transition(vtos, itos); __ movl(rax, iaddress(n)); debug_only(__ verify_local_tag(frame::TagValue, n)); } -void TemplateTable::lload(int n) -{ +void TemplateTable::lload(int n) { transition(vtos, ltos); __ movq(rax, laddress(n)); debug_only(__ verify_local_tag(frame::TagCategory2, n)); } -void TemplateTable::fload(int n) -{ +void TemplateTable::fload(int n) { transition(vtos, ftos); __ movflt(xmm0, faddress(n)); debug_only(__ verify_local_tag(frame::TagValue, n)); } -void TemplateTable::dload(int n) -{ +void TemplateTable::dload(int n) { transition(vtos, dtos); __ movdbl(xmm0, daddress(n)); debug_only(__ verify_local_tag(frame::TagCategory2, n)); } -void TemplateTable::aload(int n) -{ +void TemplateTable::aload(int n) { transition(vtos, atos); __ movq(rax, aaddress(n)); debug_only(__ verify_local_tag(frame::TagReference, n)); } -void TemplateTable::aload_0() -{ +void TemplateTable::aload_0() { transition(vtos, atos); // According to bytecode histograms, the pairs: // @@ -781,40 +724,35 @@ } } -void TemplateTable::istore() -{ +void TemplateTable::istore() { transition(itos, vtos); locals_index(rbx); __ movl(iaddress(rbx), rax); __ tag_local(frame::TagValue, rbx); } -void TemplateTable::lstore() -{ +void TemplateTable::lstore() { transition(ltos, vtos); locals_index(rbx); __ movq(laddress(rbx), rax); __ tag_local(frame::TagCategory2, rbx); } -void TemplateTable::fstore() -{ +void TemplateTable::fstore() { transition(ftos, vtos); locals_index(rbx); __ movflt(faddress(rbx), xmm0); __ tag_local(frame::TagValue, rbx); } -void TemplateTable::dstore() -{ +void TemplateTable::dstore() { transition(dtos, vtos); locals_index(rbx); __ movdbl(daddress(rbx), xmm0); __ tag_local(frame::TagCategory2, rbx); } -void TemplateTable::astore() -{ +void TemplateTable::astore() { transition(vtos, vtos); __ pop_ptr(rax, rdx); // will need to pop tag too locals_index(rbx); @@ -822,8 +760,7 @@ __ tag_local(rdx, rbx); // store tag from stack, might be returnAddr } -void TemplateTable::wide_istore() -{ +void TemplateTable::wide_istore() { transition(vtos, vtos); __ pop_i(); locals_index_wide(rbx); @@ -831,8 +768,7 @@ __ tag_local(frame::TagValue, rbx); } -void TemplateTable::wide_lstore() -{ +void TemplateTable::wide_lstore() { transition(vtos, vtos); __ pop_l(); locals_index_wide(rbx); @@ -840,8 +776,7 @@ __ tag_local(frame::TagCategory2, rbx); } -void TemplateTable::wide_fstore() -{ +void TemplateTable::wide_fstore() { transition(vtos, vtos); __ pop_f(); locals_index_wide(rbx); @@ -849,8 +784,7 @@ __ tag_local(frame::TagValue, rbx); } -void TemplateTable::wide_dstore() -{ +void TemplateTable::wide_dstore() { transition(vtos, vtos); __ pop_d(); locals_index_wide(rbx); @@ -858,8 +792,7 @@ __ tag_local(frame::TagCategory2, rbx); } -void TemplateTable::wide_astore() -{ +void TemplateTable::wide_astore() { transition(vtos, vtos); __ pop_ptr(rax, rdx); // will need to pop tag too locals_index_wide(rbx); @@ -867,8 +800,7 @@ __ tag_local(rdx, rbx); // store tag from stack, might be returnAddr } -void TemplateTable::iastore() -{ +void TemplateTable::iastore() { transition(itos, vtos); __ pop_i(rbx); __ pop_ptr(rdx); @@ -882,8 +814,7 @@ rax); } -void TemplateTable::lastore() -{ +void TemplateTable::lastore() { transition(ltos, vtos); __ pop_i(rbx); __ pop_ptr(rdx); @@ -897,8 +828,7 @@ rax); } -void TemplateTable::fastore() -{ +void TemplateTable::fastore() { transition(ftos, vtos); __ pop_i(rbx); __ pop_ptr(rdx); @@ -912,8 +842,7 @@ xmm0); } -void TemplateTable::dastore() -{ +void TemplateTable::dastore() { transition(dtos, vtos); __ pop_i(rbx); __ pop_ptr(rdx); @@ -927,8 +856,7 @@ xmm0); } -void TemplateTable::aastore() -{ +void TemplateTable::aastore() { Label is_null, ok_is_subtype, done; transition(vtos, vtos); // stack: ..., array, index, value @@ -958,12 +886,12 @@ // Come here on failure // object is at TOS - __ jmp(Interpreter::_throw_ArrayStoreException_entry, relocInfo::none); + __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); // Come here on success __ bind(ok_is_subtype); __ movq(rax, at_tos()); // Value - __ movq(Address(rdx), rax); + __ movq(Address(rdx, 0), rax); __ store_check(rdx); __ jmp(done); @@ -980,8 +908,7 @@ __ addq(rsp, 3 * Interpreter::stackElementSize()); } -void TemplateTable::bastore() -{ +void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(rbx); __ pop_ptr(rdx); @@ -1009,69 +936,59 @@ rax); } -void TemplateTable::sastore() -{ +void TemplateTable::sastore() { castore(); } -void TemplateTable::istore(int n) -{ +void TemplateTable::istore(int n) { transition(itos, vtos); __ movl(iaddress(n), rax); __ tag_local(frame::TagValue, n); } -void TemplateTable::lstore(int n) -{ +void TemplateTable::lstore(int n) { transition(ltos, vtos); __ movq(laddress(n), rax); __ tag_local(frame::TagCategory2, n); } -void TemplateTable::fstore(int n) -{ +void TemplateTable::fstore(int n) { transition(ftos, vtos); __ movflt(faddress(n), xmm0); __ tag_local(frame::TagValue, n); } -void TemplateTable::dstore(int n) -{ +void TemplateTable::dstore(int n) { transition(dtos, vtos); __ movdbl(daddress(n), xmm0); __ tag_local(frame::TagCategory2, n); } -void TemplateTable::astore(int n) -{ +void TemplateTable::astore(int n) { transition(vtos, vtos); __ pop_ptr(rax, rdx); __ movq(aaddress(n), rax); __ tag_local(rdx, n); } -void TemplateTable::pop() -{ +void TemplateTable::pop() { transition(vtos, vtos); __ addq(rsp, Interpreter::stackElementSize()); } -void TemplateTable::pop2() -{ +void TemplateTable::pop2() { transition(vtos, vtos); __ addq(rsp, 2 * Interpreter::stackElementSize()); } -void TemplateTable::dup() -{ +void TemplateTable::dup() { transition(vtos, vtos); __ load_ptr_and_tag(0, rax, rdx); __ push_ptr(rax, rdx); // stack: ..., a, a } -void TemplateTable::dup_x1() -{ +void TemplateTable::dup_x1() { transition(vtos, vtos); // stack: ..., a, b __ load_ptr_and_tag(0, rax, rdx); // load b @@ -1082,8 +999,7 @@ // stack: ..., b, a, b } -void TemplateTable::dup_x2() -{ +void TemplateTable::dup_x2() { transition(vtos, vtos); // stack: ..., a, b, c __ load_ptr_and_tag(0, rax, rdx); // load c @@ -1098,8 +1014,7 @@ // stack: ..., c, a, b, c } -void TemplateTable::dup2() -{ +void TemplateTable::dup2() { transition(vtos, vtos); // stack: ..., a, b __ load_ptr_and_tag(1, rax, rdx); // load a @@ -1109,8 +1024,7 @@ // stack: ..., a, b, a, b } -void TemplateTable::dup2_x1() -{ +void TemplateTable::dup2_x1() { transition(vtos, vtos); // stack: ..., a, b, c __ load_ptr_and_tag(0, rcx, rbx); // load c @@ -1127,8 +1041,7 @@ // stack: ..., b, c, a, b, c } -void TemplateTable::dup2_x2() -{ +void TemplateTable::dup2_x2() { transition(vtos, vtos); // stack: ..., a, b, c, d __ load_ptr_and_tag(0, rcx, rbx); // load d @@ -1147,8 +1060,7 @@ // stack: ..., c, d, a, b, c, d } -void TemplateTable::swap() -{ +void TemplateTable::swap() { transition(vtos, vtos); // stack: ..., a, b __ load_ptr_and_tag(1, rcx, rbx); // load a @@ -1158,8 +1070,7 @@ // stack: ..., b, a } -void TemplateTable::iop2(Operation op) -{ +void TemplateTable::iop2(Operation op) { transition(itos, itos); switch (op) { case add : __ pop_i(rdx); __ addl (rax, rdx); break; @@ -1175,8 +1086,7 @@ } } -void TemplateTable::lop2(Operation op) -{ +void TemplateTable::lop2(Operation op) { transition(ltos, ltos); switch (op) { case add : __ pop_l(rdx); __ addq (rax, rdx); break; @@ -1188,8 +1098,7 @@ } } -void TemplateTable::idiv() -{ +void TemplateTable::idiv() { transition(itos, itos); __ movl(rcx, rax); __ pop_i(rax); @@ -1200,8 +1109,7 @@ __ corrected_idivl(rcx); } -void TemplateTable::irem() -{ +void TemplateTable::irem() { transition(itos, itos); __ movl(rcx, rax); __ pop_i(rax); @@ -1213,22 +1121,20 @@ __ movl(rax, rdx); } -void TemplateTable::lmul() -{ +void TemplateTable::lmul() { transition(ltos, ltos); __ pop_l(rdx); __ imulq(rax, rdx); } -void TemplateTable::ldiv() -{ +void TemplateTable::ldiv() { transition(ltos, ltos); __ movq(rcx, rax); __ pop_l(rax); // generate explicit div0 check __ testq(rcx, rcx); - __ jcc(Assembler::zero, - Interpreter::_throw_ArithmeticException_entry, relocInfo::none); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); // Note: could xor rax and rcx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. @@ -1236,14 +1142,13 @@ __ corrected_idivq(rcx); // kills rbx } -void TemplateTable::lrem() -{ +void TemplateTable::lrem() { transition(ltos, ltos); __ movq(rcx, rax); __ pop_l(rax); __ testq(rcx, rcx); - __ jcc(Assembler::zero, - Interpreter::_throw_ArithmeticException_entry, relocInfo::none); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); // Note: could xor rax and rcx and compare with (-1 ^ min_int). If // they are not equal, one could do a normal division (no correction // needed), which may speed up this implementation for the common case. @@ -1252,32 +1157,28 @@ __ movq(rax, rdx); } -void TemplateTable::lshl() -{ +void TemplateTable::lshl() { transition(itos, ltos); __ movl(rcx, rax); // get shift count __ pop_l(rax); // get shift value __ shlq(rax); } -void TemplateTable::lshr() -{ +void TemplateTable::lshr() { transition(itos, ltos); __ movl(rcx, rax); // get shift count __ pop_l(rax); // get shift value __ sarq(rax); } -void TemplateTable::lushr() -{ +void TemplateTable::lushr() { transition(itos, ltos); __ movl(rcx, rax); // get shift count __ pop_l(rax); // get shift value __ shrq(rax); } -void TemplateTable::fop2(Operation op) -{ +void TemplateTable::fop2(Operation op) { transition(ftos, ftos); switch (op) { case add: @@ -1309,8 +1210,7 @@ } } -void TemplateTable::dop2(Operation op) -{ +void TemplateTable::dop2(Operation op) { transition(dtos, dtos); switch (op) { case add: @@ -1342,14 +1242,12 @@ } } -void TemplateTable::ineg() -{ +void TemplateTable::ineg() { transition(itos, itos); __ negl(rax); } -void TemplateTable::lneg() -{ +void TemplateTable::lneg() { transition(ltos, ltos); __ negq(rax); } @@ -1369,30 +1267,26 @@ static jlong float_signflip_pool[2*2]; static jlong double_signflip_pool[2*2]; -void TemplateTable::fneg() -{ +void TemplateTable::fneg() { transition(ftos, ftos); static jlong *float_signflip = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000); - __ xorps(xmm0, Address((address) float_signflip, relocInfo::none)); + __ xorps(xmm0, ExternalAddress((address) float_signflip)); } -void TemplateTable::dneg() -{ +void TemplateTable::dneg() { transition(dtos, dtos); static jlong *double_signflip = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000); - __ xorpd(xmm0, Address((address) double_signflip, relocInfo::none)); + __ xorpd(xmm0, ExternalAddress((address) double_signflip)); } -void TemplateTable::iinc() -{ +void TemplateTable::iinc() { transition(vtos, vtos); __ load_signed_byte(rdx, at_bcp(2)); // get constant locals_index(rbx); __ addl(iaddress(rbx), rdx); } -void TemplateTable::wide_iinc() -{ +void TemplateTable::wide_iinc() { transition(vtos, vtos); __ movl(rdx, at_bcp(4)); // get constant locals_index_wide(rbx); @@ -1403,8 +1297,7 @@ // the index and the constant -> fix this } -void TemplateTable::convert() -{ +void TemplateTable::convert() { // Checking #ifdef ASSERT { @@ -1496,7 +1389,7 @@ Label L; __ cvttss2siq(rax, xmm0); // NaN or overflow/underflow? - __ cmpq(rax, Address((address) &is_nan, relocInfo::none)); + __ cmp64(rax, ExternalAddress((address) &is_nan)); __ jcc(Assembler::notEqual, L); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); __ bind(L); @@ -1520,7 +1413,7 @@ Label L; __ cvttsd2siq(rax, xmm0); // NaN or overflow/underflow? - __ cmpq(rax, Address((address) &is_nan, relocInfo::none)); + __ cmp64(rax, ExternalAddress((address) &is_nan)); __ jcc(Assembler::notEqual, L); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 1); __ bind(L); @@ -1534,8 +1427,7 @@ } } -void TemplateTable::lcmp() -{ +void TemplateTable::lcmp() { transition(ltos, itos); Label done; __ pop_l(rdx); @@ -1547,8 +1439,7 @@ __ bind(done); } -void TemplateTable::float_cmp(bool is_float, int unordered_result) -{ +void TemplateTable::float_cmp(bool is_float, int unordered_result) { Label done; if (is_float) { // XXX get rid of pop here, use ... reg, mem32 @@ -1576,8 +1467,7 @@ __ bind(done); } -void TemplateTable::branch(bool is_jsr, bool is_wide) -{ +void TemplateTable::branch(bool is_jsr, bool is_wide) { __ get_method(rcx); // rcx holds method __ profile_taken_branch(rax, rbx); // rax holds updated MDP, rbx // holds bumped taken count @@ -1649,9 +1539,8 @@ if (ProfileInterpreter) { // Test to see if we should create a method data oop - __ cmpl(rax, Address((address) - &InvocationCounter::InterpreterProfileLimit, - relocInfo::none)); + __ cmp32(rax, + ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit)); __ jcc(Assembler::less, dispatch); // if no method data exists, go to profile method @@ -1659,9 +1548,8 @@ if (UseOnStackReplacement) { // check for overflow against ebx which is the MDO taken count - __ cmpl(rbx, Address((address) &InvocationCounter:: - InterpreterBackwardBranchLimit, - relocInfo::none)); + __ cmp32(rbx, + ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit)); __ jcc(Assembler::below, dispatch); // When ProfileInterpreter is on, the backedge_count comes @@ -1679,9 +1567,8 @@ if (UseOnStackReplacement) { // check for overflow against eax, which is the sum of the // counters - __ cmpl(rax, Address((address) &InvocationCounter:: - InterpreterBackwardBranchLimit, - relocInfo::none)); + __ cmp32(rax, + ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit)); __ jcc(Assembler::aboveEqual, backedge_counter_overflow); } @@ -1690,7 +1577,7 @@ } // Pre-load the next target bytecode into rbx - __ load_unsigned_byte(rbx, Address(r13)); + __ load_unsigned_byte(rbx, Address(r13, 0)); // continue with the bytecode @ target // eax: return bci for jsr's, unused otherwise @@ -1705,7 +1592,7 @@ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), r13); - __ load_unsigned_byte(rbx, Address(r13)); // restore target bytecode + __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode __ movq(rcx, Address(rbp, method_offset)); __ movq(rcx, Address(rcx, in_bytes(methodOopDesc::method_data_offset()))); @@ -1730,7 +1617,7 @@ CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx); - __ load_unsigned_byte(rbx, Address(r13)); // restore target bytecode + __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode // rax: osr nmethod (osr ok) or NULL (osr not possible) // ebx: target bytecode @@ -1783,8 +1670,7 @@ } -void TemplateTable::if_0cmp(Condition cc) -{ +void TemplateTable::if_0cmp(Condition cc) { transition(itos, vtos); // assume branch is more often taken than not (loops use backward branches) Label not_taken; @@ -1795,8 +1681,7 @@ __ profile_not_taken_branch(rax); } -void TemplateTable::if_icmp(Condition cc) -{ +void TemplateTable::if_icmp(Condition cc) { transition(itos, vtos); // assume branch is more often taken than not (loops use backward branches) Label not_taken; @@ -1808,8 +1693,7 @@ __ profile_not_taken_branch(rax); } -void TemplateTable::if_nullcmp(Condition cc) -{ +void TemplateTable::if_nullcmp(Condition cc) { transition(atos, vtos); // assume branch is more often taken than not (loops use backward branches) Label not_taken; @@ -1820,8 +1704,7 @@ __ profile_not_taken_branch(rax); } -void TemplateTable::if_acmp(Condition cc) -{ +void TemplateTable::if_acmp(Condition cc) { transition(atos, vtos); // assume branch is more often taken than not (loops use backward branches) Label not_taken; @@ -1833,8 +1716,7 @@ __ profile_not_taken_branch(rax); } -void TemplateTable::ret() -{ +void TemplateTable::ret() { transition(vtos, vtos); locals_index(rbx); __ movq(rbx, aaddress(rbx)); // get return bci, compute return bcp @@ -1846,8 +1728,7 @@ __ dispatch_next(vtos); } -void TemplateTable::wide_ret() -{ +void TemplateTable::wide_ret() { transition(vtos, vtos); locals_index_wide(rbx); __ movq(rbx, aaddress(rbx)); // get return bci, compute return bcp @@ -1858,8 +1739,7 @@ __ dispatch_next(vtos); } -void TemplateTable::tableswitch() -{ +void TemplateTable::tableswitch() { Label default_case, continue_execution; transition(itos, vtos); // align r13 @@ -1889,18 +1769,16 @@ // handle default __ bind(default_case); __ profile_switch_default(rax); - __ movl(rdx, Address(rbx)); + __ movl(rdx, Address(rbx, 0)); __ jmp(continue_execution); } -void TemplateTable::lookupswitch() -{ +void TemplateTable::lookupswitch() { transition(itos, itos); __ stop("lookupswitch bytecode should have been rewritten"); } -void TemplateTable::fast_linearswitch() -{ +void TemplateTable::fast_linearswitch() { transition(itos, vtos); Label loop_entry, loop, found, continue_execution; // bswap rax so we can avoid bswapping the table entries @@ -1923,7 +1801,7 @@ __ jcc(Assembler::greaterEqual, loop); // default case __ profile_switch_default(rax); - __ movl(rdx, Address(rbx)); + __ movl(rdx, Address(rbx, 0)); __ jmp(continue_execution); // entry found -> get offset __ bind(found); @@ -1938,8 +1816,7 @@ __ dispatch_only(vtos); } -void TemplateTable::fast_binaryswitch() -{ +void TemplateTable::fast_binaryswitch() { transition(itos, vtos); // Implementation using the following core algorithm: // @@ -2048,8 +1925,7 @@ } -void TemplateTable::_return(TosState state) -{ +void TemplateTable::_return(TosState state) { transition(state, state); assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation @@ -2101,8 +1977,7 @@ // volatile-stores although it could just as well go before // volatile-loads. void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits - order_constraint) -{ + order_constraint) { // Helper function to insert a is-volatile test and memory barrier if (os::is_MP()) { // Not needed on single CPU __ membar(order_constraint); @@ -2111,8 +1986,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, - Register index) -{ + Register index) { assert(byte_no == 1 || byte_no == 2, "byte_no out of range"); const Register temp = rbx; @@ -2164,8 +2038,7 @@ Register index, Register off, Register flags, - bool is_static = false) -{ + bool is_static = false) { assert_different_registers(cache, index, flags, off); ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); @@ -2191,8 +2064,7 @@ Register itable_index, Register flags, bool is_invokevirtual, - bool is_invokevfinal /*unused*/) -{ + bool is_invokevfinal /*unused*/) { // setup registers const Register cache = rcx; const Register index = rdx; @@ -2236,8 +2108,7 @@ // take the time to call into the VM. Label L1; assert_different_registers(cache, index, rax); - __ movl(rax, Address((address) JvmtiExport::get_field_access_count_addr(), - relocInfo::none)); + __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); __ testl(rax, rax); __ jcc(Assembler::zero, L1); @@ -2270,8 +2141,7 @@ __ verify_oop(r); } -void TemplateTable::getfield_or_static(int byte_no, bool is_static) -{ +void TemplateTable::getfield_or_static(int byte_no, bool is_static) { transition(vtos, vtos); const Register cache = rcx; @@ -2405,20 +2275,17 @@ } -void TemplateTable::getfield(int byte_no) -{ +void TemplateTable::getfield(int byte_no) { getfield_or_static(byte_no, false); } -void TemplateTable::getstatic(int byte_no) -{ +void TemplateTable::getstatic(int byte_no) { getfield_or_static(byte_no, true); } // The registers cache and index expected to be set before call. // The function may destroy various registers, just not the cache and index registers. -void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) -{ +void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { transition(vtos, vtos); ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); @@ -2428,9 +2295,7 @@ // we take the time to call into the VM. Label L1; assert_different_registers(cache, index, rax); - __ movl(rax, Address((address) - JvmtiExport::get_field_modification_count_addr(), - relocInfo::none)); + __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); __ testl(rax, rax); __ jcc(Assembler::zero, L1); @@ -2478,8 +2343,7 @@ } } -void TemplateTable::putfield_or_static(int byte_no, bool is_static) -{ +void TemplateTable::putfield_or_static(int byte_no, bool is_static) { transition(vtos, vtos); const Register cache = rcx; @@ -2624,24 +2488,20 @@ __ bind(notVolatile); } -void TemplateTable::putfield(int byte_no) -{ +void TemplateTable::putfield(int byte_no) { putfield_or_static(byte_no, false); } -void TemplateTable::putstatic(int byte_no) -{ +void TemplateTable::putstatic(int byte_no) { putfield_or_static(byte_no, true); } -void TemplateTable::jvmti_post_fast_field_mod() -{ +void TemplateTable::jvmti_post_fast_field_mod() { if (JvmtiExport::can_post_field_modification()) { // Check to see if a field modification watch has been set before // we take the time to call into the VM. Label L2; - __ movl(c_rarg3, Address(JvmtiExport::get_field_modification_count_addr(), - relocInfo::none)); + __ mov32(c_rarg3, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); __ testl(c_rarg3, c_rarg3); __ jcc(Assembler::zero, L2); __ pop_ptr(rbx); // copy the object pointer from tos @@ -2649,7 +2509,7 @@ __ push_ptr(rbx); // put the object pointer back on tos __ subq(rsp, sizeof(jvalue)); // add space for a jvalue object __ movq(c_rarg3, rsp); - const Address field(c_rarg3); + const Address field(c_rarg3, 0); switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: // fall through @@ -2683,8 +2543,7 @@ } } -void TemplateTable::fast_storefield(TosState state) -{ +void TemplateTable::fast_storefield(TosState state) { transition(state, vtos); ByteSize base = constantPoolCacheOopDesc::base_offset(); @@ -2756,8 +2615,7 @@ } -void TemplateTable::fast_accessfield(TosState state) -{ +void TemplateTable::fast_accessfield(TosState state) { transition(atos, state); // Do the JVMTI work here to avoid disturbing the register state below @@ -2765,8 +2623,7 @@ // Check to see if a field access watch has been set before we // take the time to call into the VM. Label L1; - __ movl(rcx, Address((address) JvmtiExport::get_field_access_count_addr(), - relocInfo::none)); + __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); __ testl(rcx, rcx); __ jcc(Assembler::zero, L1); // access constant pool cache entry @@ -2844,8 +2701,7 @@ //}; } -void TemplateTable::fast_xaccess(TosState state) -{ +void TemplateTable::fast_xaccess(TosState state) { transition(vtos, state); // get receiver @@ -2897,8 +2753,7 @@ //----------------------------------------------------------------------------- // Calls -void TemplateTable::count_calls(Register method, Register temp) -{ +void TemplateTable::count_calls(Register method, Register temp) { // implemented elsewhere ShouldNotReachHere(); } @@ -2906,8 +2761,7 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no, - Bytecodes::Code code) -{ + Bytecodes::Code code) { // determine flags const bool is_invokeinterface = code == Bytecodes::_invokeinterface; const bool is_invokevirtual = code == Bytecodes::_invokevirtual; @@ -2949,11 +2803,9 @@ ConstantPoolCacheEntry::verify_tosBits(); // load return address { - const int64_t table = - is_invokeinterface - ? (int64_t) Interpreter::return_5_addrs_by_index_table() - : (int64_t) Interpreter::return_3_addrs_by_index_table(); - __ movq(rscratch1, table); + ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table()); + ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table()); + __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3)); __ movq(flags, Address(rscratch1, flags, Address::times_8)); } @@ -2971,8 +2823,7 @@ void TemplateTable::invokevirtual_helper(Register index, Register recv, - Register flags) -{ + Register flags) { // Uses temporary registers rax, rdx assert_different_registers(index, recv, rax, rdx); // Test for an invoke of a final method @@ -3019,8 +2870,7 @@ } -void TemplateTable::invokevirtual(int byte_no) -{ +void TemplateTable::invokevirtual(int byte_no) { transition(vtos, vtos); prepare_invoke(rbx, noreg, byte_no, bytecode()); @@ -3032,8 +2882,7 @@ } -void TemplateTable::invokespecial(int byte_no) -{ +void TemplateTable::invokespecial(int byte_no) { transition(vtos, vtos); prepare_invoke(rbx, noreg, byte_no, bytecode()); // do the call @@ -3043,8 +2892,7 @@ } -void TemplateTable::invokestatic(int byte_no) -{ +void TemplateTable::invokestatic(int byte_no) { transition(vtos, vtos); prepare_invoke(rbx, noreg, byte_no, bytecode()); // do the call @@ -3053,14 +2901,12 @@ __ jump_from_interpreted(rbx, rax); } -void TemplateTable::fast_invokevfinal(int byte_no) -{ +void TemplateTable::fast_invokevfinal(int byte_no) { transition(vtos, vtos); __ stop("fast_invokevfinal not used on amd64"); } -void TemplateTable::invokeinterface(int byte_no) -{ +void TemplateTable::invokeinterface(int byte_no) { transition(vtos, vtos); prepare_invoke(rax, rbx, byte_no, bytecode()); @@ -3183,8 +3029,7 @@ //----------------------------------------------------------------------------- // Allocation -void TemplateTable::_new() -{ +void TemplateTable::_new() { transition(vtos, atos); __ get_unsigned_2_byte_index_at_bcp(rdx, 1); Label slow_case; @@ -3192,6 +3037,8 @@ Label initialize_header; Label initialize_object; // including clearing the fields Label allocate_shared; + ExternalAddress top((address)Universe::heap()->top_addr()); + ExternalAddress end((address)Universe::heap()->end_addr()); __ get_cpool_and_tags(rsi, rax); // get instanceKlass @@ -3255,15 +3102,15 @@ const Register RtopAddr = rscratch1; const Register RendAddr = rscratch2; - __ movq(RtopAddr, (int64_t) Universe::heap()->top_addr()); - __ movq(RendAddr, (int64_t) Universe::heap()->end_addr()); - __ movq(rax, Address(RtopAddr)); + __ lea(RtopAddr, top); + __ lea(RendAddr, end); + __ movq(rax, Address(RtopAddr, 0)); // For retries rax gets set by cmpxchgq Label retry; __ bind(retry); __ leaq(rbx, Address(rax, rdx, Address::times_1)); - __ cmpq(rbx, Address(RendAddr)); + __ cmpq(rbx, Address(RendAddr, 0)); __ jcc(Assembler::above, slow_case); // Compare rax with the top addr, and if still equal, store the new @@ -3276,7 +3123,7 @@ if (os::is_MP()) { __ lock(); } - __ cmpxchgq(rbx, Address(RtopAddr)); + __ cmpxchgq(rbx, Address(RtopAddr, 0)); // if someone beat us on the allocation, try again, otherwise continue __ jcc(Assembler::notEqual, retry); @@ -3308,8 +3155,8 @@ __ movq(rscratch1, Address(rsi, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); __ movq(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1); } else { - __ movq(Address(rax, oopDesc::mark_offset_in_bytes()), - (intptr_t) markOopDesc::prototype()); // header (address 0x1) + __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), + (intptr_t) markOopDesc::prototype()); // header (address 0x1) } __ movq(Address(rax, oopDesc::klass_offset_in_bytes()), rsi); // klass __ jmp(done); @@ -3335,8 +3182,7 @@ __ bind(done); } -void TemplateTable::newarray() -{ +void TemplateTable::newarray() { transition(itos, atos); __ load_unsigned_byte(c_rarg1, at_bcp(1)); __ movl(c_rarg2, rax); @@ -3344,8 +3190,7 @@ c_rarg1, c_rarg2); } -void TemplateTable::anewarray() -{ +void TemplateTable::anewarray() { transition(itos, atos); __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1); __ get_constant_pool(c_rarg1); @@ -3354,15 +3199,13 @@ c_rarg1, c_rarg2, c_rarg3); } -void TemplateTable::arraylength() -{ +void TemplateTable::arraylength() { transition(atos, itos); __ null_check(rax, arrayOopDesc::length_offset_in_bytes()); __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes())); } -void TemplateTable::checkcast() -{ +void TemplateTable::checkcast() { transition(atos, atos); Label done, is_null, ok_is_subtype, quicked, resolved; __ testq(rax, rax); // object is in rax @@ -3401,7 +3244,7 @@ // Come here on failure __ push_ptr(rdx); // object is at TOS - __ jmp(Interpreter::_throw_ClassCastException_entry, relocInfo::none); + __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); // Come here on success __ bind(ok_is_subtype); @@ -3418,8 +3261,7 @@ __ bind(done); } -void TemplateTable::instanceof() -{ +void TemplateTable::instanceof() { transition(atos, itos); Label done, is_null, ok_is_subtype, quicked, resolved; __ testq(rax, rax); @@ -3477,8 +3319,7 @@ //----------------------------------------------------------------------------- // Breakpoints -void TemplateTable::_breakpoint() -{ +void TemplateTable::_breakpoint() { // Note: We get here even if we are single stepping.. // jbug inists on setting breakpoints at every bytecode // even if we are in single step mode. @@ -3506,11 +3347,10 @@ //----------------------------------------------------------------------------- // Exceptions -void TemplateTable::athrow() -{ +void TemplateTable::athrow() { transition(atos, vtos); __ null_check(rax); - __ jmp(Interpreter::throw_exception_entry(), relocInfo::none); + __ jump(ExternalAddress(Interpreter::throw_exception_entry())); } //----------------------------------------------------------------------------- @@ -3530,8 +3370,7 @@ // [frame data ] <--- monitor block bot // ... // [saved rbp ] <--- rbp -void TemplateTable::monitorenter() -{ +void TemplateTable::monitorenter() { transition(atos, vtos); // check for NULL object @@ -3593,10 +3432,10 @@ __ bind(loop); __ movq(c_rarg2, Address(c_rarg3, entry_size)); // load expression stack // word from old location - __ movq(Address(c_rarg3), c_rarg2); // and store it at new location - __ addq(c_rarg3, wordSize); // advance to next word + __ movq(Address(c_rarg3, 0), c_rarg2); // and store it at new location + __ addq(c_rarg3, wordSize); // advance to next word __ bind(entry); - __ cmpq(c_rarg3, c_rarg1); // check if bottom reached + __ cmpq(c_rarg3, c_rarg1); // check if bottom reached __ jcc(Assembler::notEqual, loop); // if not at bottom then // copy next word } @@ -3625,8 +3464,7 @@ } -void TemplateTable::monitorexit() -{ +void TemplateTable::monitorexit() { transition(atos, vtos); // check for NULL object @@ -3678,11 +3516,10 @@ // Wide instructions -void TemplateTable::wide() -{ +void TemplateTable::wide() { transition(vtos, vtos); __ load_unsigned_byte(rbx, at_bcp(1)); - __ movq(rscratch1, (int64_t) Interpreter::_wentry_point); + __ lea(rscratch1, ExternalAddress((address)Interpreter::_wentry_point)); __ jmp(Address(rscratch1, rbx, Address::times_8)); // Note: the r13 increment step is part of the individual wide // bytecode implementations @@ -3690,8 +3527,7 @@ // Multi arrays -void TemplateTable::multianewarray() -{ +void TemplateTable::multianewarray() { transition(vtos, atos); __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions // last dim is on top of stack; we want address of first one: diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/amd64/vm/vtableStubs_amd64.cpp --- a/hotspot/src/cpu/amd64/vm/vtableStubs_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/amd64/vm/vtableStubs_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)vtableStubs_amd64.cpp 1.20 07/05/17 15:46:10 JVM" +#pragma ident "@(#)vtableStubs_amd64.cpp 1.21 07/06/19 09:08:02 JVM" #endif /* * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -48,8 +48,7 @@ #ifndef PRODUCT if (CountCompiledCalls) { - __ incrementl(Address((address) SharedRuntime::nof_megamorphic_calls_addr(), - relocInfo::none)); + __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); } #endif @@ -90,7 +89,7 @@ Label L; __ cmpq(method, (int)NULL); __ jcc(Assembler::equal, L); - __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), NULL_WORD); + __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD); __ jcc(Assembler::notZero, L); __ stop("Vtable entry is NULL"); __ bind(L); @@ -119,8 +118,7 @@ #ifndef PRODUCT if (CountCompiledCalls) { - __ incrementl(Address((address) SharedRuntime::nof_megamorphic_calls_addr(), - relocInfo::none)); + __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); } #endif @@ -212,7 +210,7 @@ Label L2; __ cmpq(method, (int)NULL); __ jcc(Assembler::equal, L2); - __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), NULL_WORD); + __ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD); __ jcc(Assembler::notZero, L2); __ stop("compiler entrypoint is null"); __ bind(L2); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/assembler_i486.cpp --- a/hotspot/src/cpu/i486/vm/assembler_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/assembler_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_i486.cpp 1.236 07/06/12 12:32:42 JVM" +#pragma ident "@(#)assembler_i486.cpp 1.238 07/06/28 10:31:47 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -28,59 +28,79 @@ #include "incls/_precompiled.incl" #include "incls/_assembler_i486.cpp.incl" +// Implementation of AddressLiteral + +AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { + _is_lval = false; + _target = target; + switch (rtype) { + case relocInfo::oop_type: + // Oops are a special case. Normally they would be their own section + // but in cases like icBuffer they are literals in the code stream that + // we don't have a section for. We use none so that we get a literal address + // which is always patchable. + break; + case relocInfo::external_word_type: + _rspec = external_word_Relocation::spec(target); + break; + case relocInfo::internal_word_type: + _rspec = internal_word_Relocation::spec(target); + break; + case relocInfo::opt_virtual_call_type: + _rspec = opt_virtual_call_Relocation::spec(); + break; + case relocInfo::static_call_type: + _rspec = static_call_Relocation::spec(); + break; + case relocInfo::runtime_call_type: + _rspec = runtime_call_Relocation::spec(); + break; + case relocInfo::poll_type: + case relocInfo::poll_return_type: + _rspec = Relocation::spec_simple(rtype); + break; + case relocInfo::none: + break; + default: + ShouldNotReachHere(); + break; + } +} // Implementation of Address -// -// Note: For now an address simply stores all its attributes in individual fields. A better solution would -// do the conversion into a byte stream (currently performed by Assembler::emit_operand) when creating -// an address. The byte stream & some management information could be easily compressed into a two word -// object, making the use of addresses both faster & more lightweight (addresses are used frequently & -// often the same address is used several times. Doing the conversion when creating the address saves -// repeated conversion by the assembler). - -Address::Address(int disp, relocInfo::relocType rtype) { + +Address Address::make_array(ArrayAddress adr) { +#ifdef _LP64 + // Not implementable on 64bit machines + // Should have been handled higher up the call chain. + ShouldNotReachHere(); +#else + AddressLiteral base = adr.base(); + Address index = adr.index(); + assert(index._disp == 0, "must not have disp"); // maybe it can? + Address array(index._base, index._index, index._scale, (intptr_t) base.target()); + array._rspec = base._rspec; + return array; +#endif // _LP64 +} + +#ifndef _LP64 + +// exceedingly dangerous constructor +Address::Address(address loc, RelocationHolder spec) { _base = noreg; _index = noreg; _scale = no_scale; - _disp = disp; - switch (rtype) { - case relocInfo::external_word_type: - _rspec = external_word_Relocation::spec((address)disp); - break; - case relocInfo::internal_word_type: - _rspec = internal_word_Relocation::spec((address)disp); - break; - case relocInfo::none: - break; - default: - ShouldNotReachHere(); - } -} - -Address::Address(Register base, Register index, ScaleFactor scale, relocInfo::relocType rtype, int disp) { - _base = base; - _index = index; - _scale = scale; - _disp = disp; - switch (rtype) { - case relocInfo::external_word_type: - _rspec = external_word_Relocation::spec((address)disp); - break; - case relocInfo::internal_word_type: - _rspec = internal_word_Relocation::spec((address)disp); - break; - case relocInfo::none: - break; - default: - ShouldNotReachHere(); - } -} + _disp = (intptr_t) loc; + _rspec = spec; +} +#endif // _LP64 // Convert the raw encoding form into the form expected by the constructor for // Address. An index of 4 (esp) corresponds to having no index, so convert // that to noreg for the Address constructor. Address Address::make_raw(int base, int index, int scale, int disp) { - bool valid_index = index != 0x4; + bool valid_index = index != esp->encoding(); if (valid_index) { Address madr(as_Register(base), as_Register(index), (Address::ScaleFactor)scale, in_ByteSize(disp)); return madr; @@ -96,7 +116,7 @@ return (u_char)'\xF4'; // hlt } - +// make this go away someday void Assembler::emit_data(jint data, relocInfo::relocType rtype, int format) { if (rtype == relocInfo::none) emit_long(data); @@ -107,12 +127,19 @@ void Assembler::emit_data(jint data, RelocationHolder const& rspec, int format) { assert(imm32_operand == 0, "default format must be imm32 in this file"); assert(inst_mark() != NULL, "must be inside InstructionMark"); - // Do not use AbstractAssembler::relocate, which is not intended for - // embedded words. Instead, relocate to the enclosing instruction. - code_section()->relocate(inst_mark(), rspec, format); - #ifdef ASSERT - check_relocation(rspec, format); - #endif + if (rspec.type() != relocInfo::none) { + #ifdef ASSERT + check_relocation(rspec, format); + #endif + // Do not use AbstractAssembler::relocate, which is not intended for + // embedded words. Instead, relocate to the enclosing instruction. + + // hack. call32 is too wide for mask so use disp32 + if (format == call32_operand) + code_section()->relocate(inst_mark(), rspec, disp32_operand); + else + code_section()->relocate(inst_mark(), rspec, format); + } emit_long(data); } @@ -165,7 +192,7 @@ InstructionMark im(this); emit_byte(op1); emit_byte(op2 | dst->encoding()); - emit_data((int)obj, relocInfo::oop_type); + emit_data((int)obj, relocInfo::oop_type, 0); } @@ -176,7 +203,13 @@ } -void Assembler::emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, RelocationHolder const& rspec) { +void Assembler::emit_operand(Register reg, + Register base, + Register index, + Address::ScaleFactor scale, + int disp, + RelocationHolder const& rspec) { + relocInfo::relocType rtype = (relocInfo::relocType) rspec.type(); if (base->is_valid()) { if (index->is_valid()) { @@ -353,8 +386,13 @@ case 0x57: // xorps case 0x6E: // movd case 0x7E: // movd + case 0xAE: // ldmxcsr a + // amd side says it these have both operands but that doesn't + // appear to be true. + // debug_only(has_imm32 = true); // has both kinds of operands! + break; + case 0xAD: // shrd r, a, %cl - case 0xAE: // ldmxcsr a case 0xAF: // imul r, a case 0xBE: // movsxb r, a case 0xBF: // movsxw r, a @@ -387,6 +425,9 @@ debug_only(has_imm32 = true); // has both kinds of operands! break; + case 0x85: // test r/m, r + break; + case 0x83: // addl a, #8; addl r, #8 // also: orl, adcl, sbbl, andl, subl, xorl, cmpl tail_size = 1; @@ -412,7 +453,6 @@ case 0xF7: // mull a case 0x8D: // leal r, a case 0x87: // xchg r, a - case 0x85: // test r, a break; case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8 @@ -525,14 +565,14 @@ Relocation* r = rspec.reloc(); if (r->type() == relocInfo::none) { return; - } else if (r->is_call()) { - assert(format == 0, "cannot specify a nonzero format"); + } else if (r->is_call() || format == call32_operand) { + // assert(format == imm32_operand, "cannot specify a nonzero format"); opnd = locate_operand(inst, call32_operand); } else if (r->is_data()) { assert(format == imm32_operand || format == disp32_operand, "format ok"); opnd = locate_operand(inst, (WhichOperand)format); } else { - assert(format == 0, "cannot specify a format"); + assert(format == imm32_operand, "cannot specify a format"); return; } assert(opnd == pc(), "must put operand where relocs can find it"); @@ -575,24 +615,13 @@ emit_long(imm32); } -void Assembler::pushl(int imm32, relocInfo::relocType rtype) { - InstructionMark im(this); - emit_byte(0x68); - emit_data(imm32, rtype); -} - -void Assembler::pushl(int imm32, RelocationHolder const& rspec) { +#ifndef _LP64 +void Assembler::push_literal32(int32_t imm32, RelocationHolder const& rspec) { InstructionMark im(this); emit_byte(0x68); - emit_data(imm32, rspec); -} - -void Assembler::pushl(jobject obj) { - InstructionMark im(this); - emit_byte(0x68); - emit_data((int)obj, relocInfo::oop_type); -} - + emit_data(imm32, rspec, 0); +} +#endif // _LP64 void Assembler::pushl(Register src) { emit_byte(0x50 | src->encoding()); @@ -605,19 +634,6 @@ emit_operand(esi, src); } - -void Assembler::pushl(Label& L, relocInfo::relocType rtype) { - if (L.is_bound()) { - int offs = (int)target(L); - InstructionMark im(this); - emit_byte(0x68); - emit_data(offs, rtype); - } else { - ShouldNotReachHere(); - } -} - - void Assembler::popl(Register dst) { emit_byte(0x58 | dst->encoding()); } @@ -690,19 +706,14 @@ emit_long(imm32); } -void Assembler::movl(Register dst, address imm32, relocInfo::relocType rtype) { +#ifndef _LP64 +void Assembler::mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); emit_byte(0xB8 | dst->encoding()); - emit_data((int)imm32, rtype); -} - - -void Assembler::movl(Register dst, jobject obj) { - InstructionMark im(this); - emit_byte(0xB8 | dst->encoding()); - emit_data((int)obj, relocInfo::oop_type); -} - + emit_data((int)imm32, rspec, 0); +} +#endif // _LP64 void Assembler::movl(Register dst, Register src) { emit_byte(0x8B); @@ -724,21 +735,14 @@ emit_long(imm32); } -void Assembler::movl(Address dst, address imm32, relocInfo::relocType rtype) { +#ifndef _LP64 +void Assembler::mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec) { InstructionMark im(this); emit_byte(0xC7); emit_operand(eax, dst); - emit_data((int)imm32, rtype); -} - - -void Assembler::movl(Address dst, jobject obj) { - InstructionMark im(this); // Note: This insn might have two relocations. - emit_byte(0xC7); - emit_operand(eax, dst); - emit_data((int)obj, relocInfo::oop_type); -} - + emit_data((int)imm32, rspec, 0); +} +#endif // _LP64 void Assembler::movl(Address dst, Register src) { InstructionMark im(this); @@ -746,7 +750,6 @@ emit_operand(src, dst); } - void Assembler::movsxb(Register dst, Address src) { InstructionMark im(this); emit_byte(0x0F); @@ -754,7 +757,6 @@ emit_operand(dst, src); } - void Assembler::movsxb(Register dst, Register src) { assert(src->has_byte_register(), "must have byte register"); emit_byte(0x0F); @@ -955,6 +957,14 @@ emit_byte(imm8); } +void Assembler::cmpw(Address dst, int imm16) { + InstructionMark im(this); + emit_byte(0x66); + emit_byte(0x81); + emit_operand(edi, dst); + emit_word(imm16); +} + void Assembler::cmpl(Address dst, int imm32) { InstructionMark im(this); emit_byte(0x81); @@ -962,13 +972,21 @@ emit_long(imm32); } - -void Assembler::cmpl(Address dst, jobject obj) { - InstructionMark im(this); // Note: This insn might have two relocations. +#ifndef _LP64 +void Assembler::cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); emit_byte(0x81); - emit_operand(edi, dst); - emit_data((int)obj, relocInfo::oop_type); -} + emit_byte(0xF8 | src1->encoding()); + emit_data(imm32, rspec, 0); +} + +void Assembler::cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec) { + InstructionMark im(this); + emit_byte(0x81); + emit_operand(edi, src1); + emit_data(imm32, rspec, 0); +} +#endif // _LP64 void Assembler::cmpl(Register dst, int imm32) { @@ -976,11 +994,6 @@ } -void Assembler::cmpl(Register dst, jobject obj) { - emit_arith(0x81, 0xF8, dst, obj); -} - - void Assembler::cmpl(Register dst, Register src) { emit_arith(0x3B, 0xC0, dst, src); } @@ -1589,7 +1602,7 @@ // flags (which we save and restore.) pushfd(); // Save eflags register lock(); - addl(Address(esp), 0); // Assert the lock# signal here + addl(Address(esp, 0), 0);// Assert the lock# signal here popfd(); // Restore eflags register } } @@ -1612,36 +1625,17 @@ InstructionMark im(this); // 1110 1000 #32-bit disp emit_byte(0xE8); - emit_data(offs - long_size, rtype); + emit_data(offs - long_size, rtype, 0); } else { InstructionMark im(this); // 1110 1000 #32-bit disp L.add_patch_at(code(), locator()); emit_byte(0xE8); - emit_data(int(0), rtype); + emit_data(int(0), rtype, 0); } } - -void Assembler::call(address entry, relocInfo::relocType rtype) { - assert(rtype != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); - assert(entry != NULL, "call most probably wrong"); - InstructionMark im(this); - emit_byte(0xE8); - emit_data((int)entry - ((int)_code_pos + sizeof(long)), rtype); -} - - -void Assembler::call(address entry, RelocationHolder const& rspec) { - assert(entry != NULL, "call most probably wrong"); - InstructionMark im(this); - emit_byte(0xE8); - emit_data((int)entry - ((int)_code_pos + sizeof(long)), rspec); -} - - -void Assembler::call(Register dst, relocInfo::relocType rtype) { - relocate(rtype); +void Assembler::call(Register dst) { emit_byte(0xFF); emit_byte(0xD0 | dst->encoding()); } @@ -1649,15 +1643,28 @@ void Assembler::call(Address adr) { InstructionMark im(this); + relocInfo::relocType rtype = adr.reloc(); + if (rtype != relocInfo::runtime_call_type) { + emit_byte(0xFF); + emit_operand(edx, adr); + } else { + assert(false, "ack"); + } + +} + +void Assembler::call_literal(address dest, RelocationHolder const& rspec) { + InstructionMark im(this); + emit_byte(0xE8); + intptr_t disp = dest - (_code_pos + sizeof(int32_t)); + assert(dest != NULL, "must have a target"); + emit_data(disp, rspec, call32_operand); + +} + +void Assembler::jmp(Register entry) { emit_byte(0xFF); - emit_operand(edx, adr); -} - - -void Assembler::jmp(Register reg, relocInfo::relocType rtype) { - relocate(rtype); - emit_byte(0xFF); - emit_byte(0xE0 | reg->encoding()); + emit_byte(0xE0 | entry->encoding()); } @@ -1667,33 +1674,29 @@ emit_operand(esp, adr); } -// relative jump -void Assembler::jmp(address entry, relocInfo::relocType rtype) { - assert(entry != NULL, "jmp most probably wrong"); +void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { InstructionMark im(this); - relocate(rtype); - const int short_size = 2; - const int long_size = 5; - int offs = (int)entry - (int)_code_pos; - if (rtype == relocInfo::none && is8bit(offs - short_size)) { - emit_byte(0xEB); - emit_byte((offs - short_size) & 0xFF); - } else { - emit_byte(0xE9); - emit_long(offs - long_size); - } -} - -void Assembler::jmpb(address entry) { - const int short_size = 2; - assert(is8bit((intptr_t)entry - ((intptr_t)_code_pos + short_size)), - "Displacement too large for short jmp"); - jmp(entry, relocInfo::none); + emit_byte(0xE9); + assert(dest != NULL, "must have a target"); + intptr_t disp = dest - (_code_pos + sizeof(int32_t)); + emit_data(disp, rspec.reloc(), call32_operand); } void Assembler::jmp(Label& L, relocInfo::relocType rtype) { if (L.is_bound()) { - jmp(target(L), rtype); + address entry = target(L); + assert(entry != NULL, "jmp most probably wrong"); + InstructionMark im(this); + const int short_size = 2; + const int long_size = 5; + intptr_t offs = entry - _code_pos; + if (relocInfo::none && is8bit(offs - short_size)) { + emit_byte(0xEB); + emit_byte((offs - short_size) & 0xFF); + } else { + emit_byte(0xE9); + emit_long(offs - long_size); + } } else { // By default, forward jumps are always 32-bit displacements, since // we can't yet know where the label will be bound. If you're sure that @@ -1709,7 +1712,14 @@ void Assembler::jmpb(Label& L) { if (L.is_bound()) { - jmpb(target(L)); + const int short_size = 2; + address entry = target(L); + assert(is8bit((entry - _code_pos) + short_size), + "Dispacement too large for a short jmp"); + assert(entry != NULL, "jmp most probably wrong"); + intptr_t offs = entry - _code_pos; + emit_byte(0xEB); + emit_byte((offs - short_size) & 0xFF); } else { InstructionMark im(this); L.add_patch_at(code(), locator()); @@ -1718,39 +1728,32 @@ } } -void Assembler::jcc(Condition cc, address dst, relocInfo::relocType rtype) { - assert((0 <= cc) && (cc < 16), "illegal cc"); - assert(dst != NULL, "jcc most probably wrong"); - +void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { InstructionMark im(this); relocate(rtype); - const int short_size = 2; - const int long_size = 6; - int offs = (int)dst - ((int)_code_pos); - if (rtype == relocInfo::none && is8bit(offs - short_size)) { - // 0111 tttn #8-bit disp - emit_byte(0x70 | cc); - emit_byte((offs - short_size) & 0xFF); - } else { - // 0000 1111 1000 tttn #32-bit disp - emit_byte(0x0F); - emit_byte(0x80 | cc); - emit_long(offs - long_size); - } -} - - -void Assembler::jcc(Condition cc, Label& L, relocInfo::relocType rtype) { assert((0 <= cc) && (cc < 16), "illegal cc"); if (L.is_bound()) { - jcc(cc, target(L), rtype); + address dst = target(L); + assert(dst != NULL, "jcc most probably wrong"); + + const int short_size = 2; + const int long_size = 6; + int offs = (int)dst - ((int)_code_pos); + if (rtype == relocInfo::none && is8bit(offs - short_size)) { + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + } else { + // 0000 1111 1000 tttn #32-bit disp + emit_byte(0x0F); + emit_byte(0x80 | cc); + emit_long(offs - long_size); + } } else { // Note: could eliminate cond. jumps to this jump if condition // is the same however, seems to be rather unlikely case. // Note: use jccb() if label to be bound is very close to get // an 8-bit displacement - InstructionMark im(this); - relocate(rtype); L.add_patch_at(code(), locator()); emit_byte(0x0F); emit_byte(0x80 | cc); @@ -1760,7 +1763,15 @@ void Assembler::jccb(Condition cc, Label& L) { if (L.is_bound()) { - jccb(cc, target(L)); + const int short_size = 2; + address entry = target(L); + assert(is8bit((intptr_t)entry - ((intptr_t)_code_pos + short_size)), + "Dispacement too large for a short jmp"); + intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos; + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + jcc(cc, L); } else { InstructionMark im(this); L.add_patch_at(code(), locator()); @@ -1769,14 +1780,6 @@ } } -void Assembler::jccb(Condition cc, address dst) { - const int short_size = 2; - assert(is8bit((intptr_t)dst - ((intptr_t)_code_pos + short_size)), - "Distance too far for short jmp"); - jcc(cc, dst, relocInfo::none); -} - - // FPU instructions void Assembler::fld1() { @@ -2569,6 +2572,19 @@ // Implementation of MacroAssembler +Address MacroAssembler::as_Address(AddressLiteral adr) { + // amd64 always does this as a pc-rel + // we can be absolute or disp based on the instruction type + // jmp/call are displacements others are absolute + assert(!adr.is_lval(), "must be rval"); + + return Address(adr.target(), adr.rspec()); +} + +Address MacroAssembler::as_Address(ArrayAddress adr) { + return Address::make_array(adr); +} + void MacroAssembler::fat_nop() { // A 5 byte nop that is safe for patching (see patch_verified_entry) emit_byte(0x26); // es: @@ -2578,12 +2594,250 @@ emit_byte(0x90); } +// 32bit can do a case table jump in one instruction but we no longer allow the base +// to be installed in the Address class +void MacroAssembler::jump(ArrayAddress entry) { + jmp(as_Address(entry)); +} + +void MacroAssembler::jump(AddressLiteral dst) { + jmp_literal(dst.target(), dst.rspec()); +} + +void MacroAssembler::jump_cc(Condition cc, AddressLiteral dst) { + assert((0 <= cc) && (cc < 16), "illegal cc"); + + InstructionMark im(this); + + relocInfo::relocType rtype = dst.reloc(); + relocate(rtype); + const int short_size = 2; + const int long_size = 6; + int offs = (int)dst.target() - ((int)_code_pos); + if (rtype == relocInfo::none && is8bit(offs - short_size)) { + // 0111 tttn #8-bit disp + emit_byte(0x70 | cc); + emit_byte((offs - short_size) & 0xFF); + } else { + // 0000 1111 1000 tttn #32-bit disp + emit_byte(0x0F); + emit_byte(0x80 | cc); + emit_long(offs - long_size); + } +} + +// Calls +void MacroAssembler::call(Label& L, relocInfo::relocType rtype) { + Assembler::call(L, rtype); +} + +void MacroAssembler::call(Register entry) { + Assembler::call(entry); +} + +void MacroAssembler::call(AddressLiteral entry) { + Assembler::call_literal(entry.target(), entry.rspec()); +} + + +void MacroAssembler::cmp8(AddressLiteral src1, int8_t imm) { + Assembler::cmpb(as_Address(src1), imm); +} + +void MacroAssembler::cmp32(AddressLiteral src1, int32_t imm) { + Assembler::cmpl(as_Address(src1), imm); +} + +void MacroAssembler::cmp32(Register src1, AddressLiteral src2) { + if (src2.is_lval()) { + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); + } else { + Assembler::cmpl(src1, as_Address(src2)); + } +} + +void MacroAssembler::cmp32(Register src1, int32_t imm) { + Assembler::cmpl(src1, imm); +} + +void MacroAssembler::cmp32(Register src1, Address src2) { + Assembler::cmpl(src1, src2); +} + +void MacroAssembler::cmpoop(Address src1, jobject obj) { + cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::cmpoop(Register src1, jobject obj) { + cmp_literal32(src1, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::cmpptr(Register src1, AddressLiteral src2) { + if (src2.is_lval()) { + // compare the effect address of src2 to src1 + cmp_literal32(src1, (int32_t)src2.target(), src2.rspec()); + } else { + Assembler::cmpl(src1, as_Address(src2)); + } +} + +void MacroAssembler::cmpptr(Address src1, AddressLiteral src2) { + assert(src2.is_lval(), "not a mem-mem compare"); + cmp_literal32(src1, (int32_t) src2.target(), src2.rspec()); +} + + +void MacroAssembler::cmpxchgptr(Register reg, AddressLiteral adr) { + cmpxchg(reg, as_Address(adr)); +} + +void MacroAssembler::increment(AddressLiteral dst) { + increment(as_Address(dst)); +} + +void MacroAssembler::increment(ArrayAddress dst) { + increment(as_Address(dst)); +} + +void MacroAssembler::lea(Register dst, AddressLiteral adr) { + // leal(dst, as_Address(adr)); + // see note in movl as to why we musr use a move + mov_literal32(dst, (int32_t) adr.target(), adr.rspec()); +} + +void MacroAssembler::lea(Address dst, AddressLiteral adr) { + // leal(dst, as_Address(adr)); + // see note in movl as to why we musr use a move + mov_literal32(dst, (int32_t) adr.target(), adr.rspec()); +} + +void MacroAssembler::mov32(AddressLiteral dst, Register src) { + Assembler::movl(as_Address(dst), src); +} + +void MacroAssembler::mov32(Register dst, AddressLiteral src) { + Assembler::movl(dst, as_Address(src)); +} + +void MacroAssembler::movoop(Address dst, jobject obj) { + mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movoop(Register dst, jobject obj) { + mov_literal32(dst, (int32_t)obj, oop_Relocation::spec_for_immediate()); +} + +void MacroAssembler::movptr(Register dst, AddressLiteral src) { + if (src.is_lval()) { + // essentially an lea + mov_literal32(dst, (int32_t) src.target(), src.rspec()); + } else { + // mov 32bits from an absolute address + movl(dst, as_Address(src)); + } +} + +void MacroAssembler::movptr(ArrayAddress dst, Register src) { + movl(as_Address(dst), src); +} + +void MacroAssembler::movptr(Register dst, ArrayAddress src) { + movl(dst, as_Address(src)); +} + +void MacroAssembler::movflt(XMMRegister dst, AddressLiteral src) { + movss(dst, as_Address(src)); +} + +void MacroAssembler::movdbl(XMMRegister dst, AddressLiteral src) { + if (UseXmmLoadAndClearUpper) { movsd (dst, as_Address(src)); return; } + else { movlpd(dst, as_Address(src)); return; } +} + +void Assembler::pushoop(jobject obj) { + push_literal32((int32_t)obj, oop_Relocation::spec_for_immediate()); +} + + +void MacroAssembler::pushptr(AddressLiteral src) { + if (src.is_lval()) { + push_literal32((int32_t)src.target(), src.rspec()); + } else { + pushl(as_Address(src)); + } +} + +void MacroAssembler::test32(Register src1, AddressLiteral src2) { + // src2 must be rval + testl(src1, as_Address(src2)); +} + +// FPU + +void MacroAssembler::fld_x(AddressLiteral src) { + Assembler::fld_x(as_Address(src)); +} + +void MacroAssembler::fld_d(AddressLiteral src) { + fld_d(as_Address(src)); +} + +void MacroAssembler::fld_s(AddressLiteral src) { + fld_s(as_Address(src)); +} + +void MacroAssembler::fldcw(AddressLiteral src) { + Assembler::fldcw(as_Address(src)); +} + +void MacroAssembler::ldmxcsr(AddressLiteral src) { + Assembler::ldmxcsr(as_Address(src)); +} + +// SSE + +void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { + andpd(dst, as_Address(src)); +} + +void MacroAssembler::comisd(XMMRegister dst, AddressLiteral src) { + comisd(dst, as_Address(src)); +} + +void MacroAssembler::comiss(XMMRegister dst, AddressLiteral src) { + comiss(dst, as_Address(src)); +} + +void MacroAssembler::movsd(XMMRegister dst, AddressLiteral src) { + movsd(dst, as_Address(src)); +} + +void MacroAssembler::movss(XMMRegister dst, AddressLiteral src) { + movss(dst, as_Address(src)); +} + +void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { + xorpd(dst, as_Address(src)); +} + +void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { + xorps(dst, as_Address(src)); +} + +void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) { + ucomisd(dst, as_Address(src)); +} + +void MacroAssembler::ucomiss(XMMRegister dst, AddressLiteral src) { + ucomiss(dst, as_Address(src)); +} + void MacroAssembler::null_check(Register reg, int offset) { if (needs_explicit_null_check(offset)) { // provoke OS NULL exception if reg = NULL by // accessing M[reg] w/o changing any (non-CC) registers - cmpl(eax, Address(reg)); - // Note: should probably use testl(eax, Address(reg)); + cmpl(eax, Address(reg, 0)); + // Note: should probably use testl(eax, Address(reg, 0)); // may be shorter code (however, this version of // testl needs to be implemented first) } else { @@ -2735,10 +2989,9 @@ // last_java_pc is optional if (last_java_pc != NULL) { - movl(Address(java_thread, + lea(Address(java_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()), - last_java_pc, - relocInfo::internal_word_type); + InternalAddress(last_java_pc)); } movl(Address(java_thread, JavaThread::last_Java_sp_offset()), last_java_sp); @@ -2769,7 +3022,7 @@ address entry_point, int number_of_arguments ) { - call(entry_point, relocInfo::runtime_call_type); + call(RuntimeAddress(entry_point)); increment(esp, number_of_arguments * wordSize); } @@ -2802,7 +3055,7 @@ // Only interpreter should have to set fp set_last_Java_frame(java_thread, last_java_sp, ebp, NULL); // do the call - call(entry_point, relocInfo::runtime_call_type); + call(RuntimeAddress(entry_point)); // restore the thread (cannot use the pushed argument since arguments // may be overwritten by C code generated by an optimizing compiler); // however can use the register value directly if it is callee saved. @@ -2835,7 +3088,8 @@ if (check_exceptions) { // check for pending exceptions (java_thread is set upon return) cmpl(Address(java_thread, Thread::pending_exception_offset()), NULL_WORD); - jcc(Assembler::notEqual, StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + jump_cc(Assembler::notEqual, + RuntimeAddress(StubRoutines::forward_exception_entry())); } // get oop result if there is one and reset the value in the thread @@ -3001,7 +3255,10 @@ assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - movb(Address(noreg, obj, Address::times_1, (int)ct->byte_map_base), 0); + ExternalAddress cardtable((address)ct->byte_map_base); + Address index(noreg, obj, Address::times_1); + + movb(as_Address(ArrayAddress(cardtable, index)), 0); } @@ -3219,7 +3476,7 @@ Label slow_case, done; // x ?<= pi/4 - fld_d(Address(int(&pi_4), relocInfo::none)); + fld_d(ExternalAddress((address)&pi_4)); fld_s(1); // Stack: X PI/4 X fabs(); // Stack: |X| PI/4 X fcmp(tmp); @@ -3257,13 +3514,13 @@ // hold the return value from dsin or dcos. for (int i = 0; i < num_fpu_regs_in_use; i++) { subl(esp, wordSize*2); - fstp_d(Address(esp)); + fstp_d(Address(esp, 0)); } incoming_argument_and_return_value_offset = 2*wordSize*(num_fpu_regs_in_use-1); fld_d(Address(esp, incoming_argument_and_return_value_offset)); } subl(esp, wordSize*2); - fstp_d(Address(esp)); + fstp_d(Address(esp, 0)); // NOTE: we must not use call_VM_leaf here because that requires a // complete interpreter frame in debug mode -- same bug as 4387334 NEEDS_CLEANUP; @@ -3272,13 +3529,19 @@ // the MacroAssembler level switch(trig) { case 's': - call( CAST_FROM_FN_PTR(address, SharedRuntime::dsin), relocInfo::runtime_call_type ); + { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); + } break; case 'c': - call( CAST_FROM_FN_PTR(address, SharedRuntime::dcos), relocInfo::runtime_call_type ); + { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); + } break; case 't': - call( CAST_FROM_FN_PTR(address, SharedRuntime::dtan), relocInfo::runtime_call_type ); + { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); + } break; default: assert(false, "bad intrinsic"); @@ -3289,7 +3552,7 @@ // Must save return value to stack and then restore entire FPU stack fstp_d(Address(esp, incoming_argument_and_return_value_offset)); for (int i = 0; i < num_fpu_regs_in_use; i++) { - fld_d(Address(esp)); + fld_d(Address(esp, 0)); addl(esp, wordSize*2); } } @@ -3542,42 +3805,59 @@ sprintf(b, "verify_oop: %s: %s", reg->name(), s); pushl(eax); // save eax pushl(reg); // pass register argument - pushl((int)b); // pass msg argument + ExternalAddress buffer((address) b); + pushptr(buffer.addr()); // call indirectly to solve generation ordering problem - movl(eax, Address((int)StubRoutines::verify_oop_subroutine_entry_address(), relocInfo::none)); - call(eax, relocInfo::none); + movptr(eax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(eax); } void MacroAssembler::verify_oop_addr(Address addr, const char* s) { if (!VerifyOops) return; - Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); + // QQQ fix this + // Address adjust(addr.base(), addr.index(), addr.scale(), addr.disp() + BytesPerWord); // Pass register number to verify_oop_subroutine char* b = new char[strlen(s) + 50]; sprintf(b, "verify_oop_addr: %s", s); pushl(eax); // save eax - movl(eax, adjust); - pushl(eax); // pass register argument - pushl((int)b); // pass msg argument + // addr may contain esp so we will have to adjust it based on the push + // we just did + if (addr.uses(esp)) { + leal(eax, addr); + pushl(Address(eax, BytesPerWord)); + } else { + pushl(addr); + } + ExternalAddress buffer((address) b); + // pass msg argument + pushptr(buffer.addr()); // call indirectly to solve generation ordering problem - movl(eax, Address((int)StubRoutines::verify_oop_subroutine_entry_address(), relocInfo::none)); - call(eax, relocInfo::none); + movptr(eax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); + call(eax); + // Caller pops the arguments and restores eax from the stack } void MacroAssembler::stop(const char* msg) { - pushl((int)msg); // push msg + ExternalAddress message((address)msg); + // push address of message + pushptr(message.addr()); { Label L; call(L, relocInfo::none); bind(L); } // push eip pushad(); // push registers - call(CAST_FROM_FN_PTR(address, MacroAssembler::debug), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); hlt(); } void MacroAssembler::warn(const char* msg) { push_CPU_state(); - pushl((int)msg); // push msg - call(CAST_FROM_FN_PTR(address, warning), relocInfo::runtime_call_type); + + ExternalAddress message((address) msg); + // push address of message + pushptr(message.addr()); + + call(RuntimeAddress(CAST_FROM_FN_PTR(address, warning))); addl(esp, wordSize); // discard argument pop_CPU_state(); } @@ -3622,18 +3902,18 @@ void MacroAssembler::os_breakpoint() { // instead of directly emitting a breakpoint, call os:breakpoint for better debugability // (e.g., MSVC can't call ps() otherwise) - call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MacroAssembler::push_fTOS() { subl(esp, 2 * wordSize); - fstp_d(Address(esp)); + fstp_d(Address(esp, 0)); } void MacroAssembler::pop_fTOS() { - fld_d(Address(esp)); + fld_d(Address(esp, 0)); addl(esp, 2 * wordSize); } @@ -3917,7 +4197,7 @@ void MacroAssembler::print_CPU_state() { push_CPU_state(); pushl(esp); // pass CPU state - call(CAST_FROM_FN_PTR(address, _print_CPU_state), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, _print_CPU_state))); addl(esp, wordSize); // discard argument pop_CPU_state(); } @@ -3984,9 +4264,11 @@ if (!VerifyFPU) return; push_CPU_state(); pushl(esp); // pass CPU state - pushl((int)s); // pass message string s + ExternalAddress msg((address) s); + // pass message string s + pushptr(msg.addr()); pushl(stack_depth); // pass stack depth - call(CAST_FROM_FN_PTR(address, _verify_FPU), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, _verify_FPU))); addl(esp, 3 * wordSize); // discard arguments // check for error { Label L; @@ -4013,13 +4295,13 @@ void MacroAssembler::push_FPU_state() { subl(esp, FPUStateSizeInWords * wordSize); - fnsave(Address(esp)); + fnsave(Address(esp, 0)); fwait(); } void MacroAssembler::pop_FPU_state() { - frstor(Address(esp)); + frstor(Address(esp, 0)); addl(esp, FPUStateSizeInWords * wordSize); } @@ -4065,7 +4347,11 @@ movl(tmp, thread); shrl(tmp, os::get_serialize_page_shift_count()); andl(tmp, (os::vm_page_size() - sizeof(int))); - movl(Address(tmp, (int)os::get_memory_serialize_page()), tmp); + + Address index(noreg, tmp, Address::times_1); + ExternalAddress page(os::get_memory_serialize_page()); + + movptr(ArrayAddress(page, index), tmp); } @@ -4109,7 +4395,8 @@ Register end = t1; Label retry; bind(retry); - movl(obj, Address((int)Universe::heap()->top_addr(), relocInfo::none)); + ExternalAddress heap_top((address) Universe::heap()->top_addr()); + movptr(obj, heap_top); if (var_size_in_bytes == noreg) { leal(end, Address(obj, con_size_in_bytes)); } else { @@ -4118,7 +4405,7 @@ // if end < obj then we wrapped around => object too long => slow case cmpl(end, obj); jcc(Assembler::below, slow_case); - cmpl(end, Address((int)Universe::heap()->end_addr(), relocInfo::none)); + cmpptr(end, ExternalAddress((address) Universe::heap()->end_addr())); jcc(Assembler::above, slow_case); // Compare obj with the top addr, and if still equal, store the new top addr in // end at the address of the top addr pointer. Sets ZF if was equal, and clears @@ -4126,7 +4413,7 @@ if (os::is_MP()) { lock(); } - cmpxchg(end, Address((int)Universe::heap()->top_addr(), relocInfo::none)); + cmpxchgptr(end, heap_top); jcc(Assembler::notEqual, retry); } @@ -4220,7 +4507,8 @@ shll(t1, log2_intptr(HeapWordSize/sizeof(jint))); movl(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); // set klass to intArrayKlass - movl(t1, Address((intptr_t)Universe::intArrayKlassObj_addr(), relocInfo::none)); + // dubious reloc why not an oop reloc? + movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); movl(Address(top, oopDesc::klass_offset_in_bytes()), t1); // refill the tlab with an eden allocation @@ -4279,7 +4567,7 @@ assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); - Address saved_mark_addr(lock_reg); + Address saved_mark_addr(lock_reg, 0); // Biased locking // See whether the lock is currently biased toward our thread and @@ -4326,7 +4614,8 @@ popl(tmp_reg); } if (counters != NULL) { - cond_incl(Assembler::zero, Address((int) counters->biased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->biased_lock_entry_count_addr())); } jcc(Assembler::equal, done); @@ -4374,7 +4663,7 @@ if (os::is_MP()) { lock(); } - cmpxchg(tmp_reg, Address(obj_reg)); + cmpxchg(tmp_reg, Address(obj_reg, 0)); if (need_tmp_reg) { popl(tmp_reg); } @@ -4383,7 +4672,8 @@ // need to revoke that bias. The revocation will occur in the // interpreter runtime in the slow case. if (counters != NULL) { - cond_incl(Assembler::zero, Address((int) counters->anonymously_biased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->anonymously_biased_lock_entry_count_addr())); } if (slow_case != NULL) { jcc(Assembler::notZero, *slow_case); @@ -4410,7 +4700,7 @@ if (os::is_MP()) { lock(); } - cmpxchg(tmp_reg, Address(obj_reg)); + cmpxchg(tmp_reg, Address(obj_reg, 0)); if (need_tmp_reg) { popl(tmp_reg); } @@ -4418,7 +4708,8 @@ // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. if (counters != NULL) { - cond_incl(Assembler::zero, Address((int) counters->rebiased_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->rebiased_lock_entry_count_addr())); } if (slow_case != NULL) { jcc(Assembler::notZero, *slow_case); @@ -4446,7 +4737,7 @@ if (os::is_MP()) { lock(); } - cmpxchg(tmp_reg, Address(obj_reg)); + cmpxchg(tmp_reg, Address(obj_reg, 0)); if (need_tmp_reg) { popl(tmp_reg); } @@ -4454,7 +4745,8 @@ // the result of the above CAS, some thread must have succeeded in // removing the bias bit from the object's header. if (counters != NULL) { - cond_incl(Assembler::zero, Address((int) counters->revoked_lock_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address)counters->revoked_lock_entry_count_addr())); } bind(cas_label); @@ -4503,7 +4795,7 @@ } -void MacroAssembler::cond_incl(Condition cond, Address counter_addr) { +void MacroAssembler::cond_inc32(Condition cond, AddressLiteral counter_addr) { Condition negated_cond = negate_condition(cond); Label L; jcc(negated_cond, L); @@ -4511,7 +4803,7 @@ bind(L); } -void MacroAssembler::atomic_incl(Address counter_addr) { +void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { pushfd(); if (os::is_MP()) lock(); @@ -4522,8 +4814,7 @@ SkipIfEqual::SkipIfEqual( MacroAssembler* masm, const bool* flag_addr, bool value) { _masm = masm; - _masm->cmpb( - Address((int32_t)flag_addr, relocInfo::none), value); + _masm->cmp8(ExternalAddress((address)flag_addr), value); _masm->jcc(Assembler::equal, _label); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/assembler_i486.hpp --- a/hotspot/src/cpu/i486/vm/assembler_i486.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/assembler_i486.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)assembler_i486.hpp 1.164 07/06/13 16:22:12 JVM" +#pragma ident "@(#)assembler_i486.hpp 1.166 07/06/28 10:31:46 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -31,19 +31,114 @@ // Calling convention class Argument VALUE_OBJ_CLASS_SPEC { -public: + public: enum { - n_register_parameters = 0 // 0 registers used to pass arguments +#ifdef _LP64 +#ifdef _WIN64 + n_int_register_parameters_c = 4, // rcx, rdx, r8, r9 (c_rarg0, c_rarg1, ...) + n_float_register_parameters_c = 4, // xmm0 - xmm3 (c_farg0, c_farg1, ... ) +#else + n_int_register_parameters_c = 6, // rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...) + n_float_register_parameters_c = 8, // xmm0 - xmm7 (c_farg0, c_farg1, ... ) +#endif // _WIN64 + n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ... + n_float_register_parameters_j = 8 // j_farg0, j_farg1, ... +#else + n_register_parameters = 0 // 0 registers used to pass arguments +#endif // _LP64 }; }; +#ifdef _LP64 +// Symbolically name the register arguments used by the c calling convention. +// Windows is different from linux/solaris. So much for standards... + +#ifdef _WIN64 + +REGISTER_DECLARATION(Register, c_rarg0, rcx); +REGISTER_DECLARATION(Register, c_rarg1, rdx); +REGISTER_DECLARATION(Register, c_rarg2, r8); +REGISTER_DECLARATION(Register, c_rarg3, r9); + +REGISTER_DECLARATION(FloatRegister, c_farg0, xmm0); +REGISTER_DECLARATION(FloatRegister, c_farg1, xmm1); +REGISTER_DECLARATION(FloatRegister, c_farg2, xmm2); +REGISTER_DECLARATION(FloatRegister, c_farg3, xmm3); + +#else + +REGISTER_DECLARATION(Register, c_rarg0, rdi); +REGISTER_DECLARATION(Register, c_rarg1, rsi); +REGISTER_DECLARATION(Register, c_rarg2, rdx); +REGISTER_DECLARATION(Register, c_rarg3, rcx); +REGISTER_DECLARATION(Register, c_rarg4, r8); +REGISTER_DECLARATION(Register, c_rarg5, r9); + +REGISTER_DECLARATION(FloatRegister, c_farg0, xmm0); +REGISTER_DECLARATION(FloatRegister, c_farg1, xmm1); +REGISTER_DECLARATION(FloatRegister, c_farg2, xmm2); +REGISTER_DECLARATION(FloatRegister, c_farg3, xmm3); +REGISTER_DECLARATION(FloatRegister, c_farg4, xmm4); +REGISTER_DECLARATION(FloatRegister, c_farg5, xmm5); +REGISTER_DECLARATION(FloatRegister, c_farg6, xmm6); +REGISTER_DECLARATION(FloatRegister, c_farg7, xmm7); + +#endif // _WIN64 + +// Symbolically name the register arguments used by the Java calling convention. +// We have control over the convention for java so we can do what we please. +// What pleases us is to offset the java calling convention so that when +// we call a suitable jni method the arguments are lined up and we don't +// have to do little shuffling. A suitable jni method is non-static and a +// small number of arguments (two fewer args on windows) +// +// |-------------------------------------------------------| +// | c_rarg0 c_rarg1 c_rarg2 c_rarg3 c_rarg4 c_rarg5 | +// |-------------------------------------------------------| +// | rcx rdx r8 r9 rdi* rsi* | windows (* not a c_rarg) +// | rdi rsi rdx rcx r8 r9 | solaris/linux +// |-------------------------------------------------------| +// | j_rarg5 j_rarg0 j_rarg1 j_rarg2 j_rarg3 j_rarg4 | +// |-------------------------------------------------------| + +REGISTER_DECLARATION(Register, j_rarg0, c_rarg1); +REGISTER_DECLARATION(Register, j_rarg1, c_rarg2); +REGISTER_DECLARATION(Register, j_rarg2, c_rarg3); +// Windows runs out of register args here +#ifdef _WIN64 +REGISTER_DECLARATION(Register, j_rarg3, rdi); +REGISTER_DECLARATION(Register, j_rarg4, rsi); +#else +REGISTER_DECLARATION(Register, j_rarg3, c_rarg4); +REGISTER_DECLARATION(Register, j_rarg4, c_rarg5); +#endif /* _WIN64 */ +REGISTER_DECLARATION(Register, j_rarg5, c_rarg0); + +REGISTER_DECLARATION(FloatRegister, j_farg0, xmm0); +REGISTER_DECLARATION(FloatRegister, j_farg1, xmm1); +REGISTER_DECLARATION(FloatRegister, j_farg2, xmm2); +REGISTER_DECLARATION(FloatRegister, j_farg3, xmm3); +REGISTER_DECLARATION(FloatRegister, j_farg4, xmm4); +REGISTER_DECLARATION(FloatRegister, j_farg5, xmm5); +REGISTER_DECLARATION(FloatRegister, j_farg6, xmm6); +REGISTER_DECLARATION(FloatRegister, j_farg7, xmm7); + +REGISTER_DECLARATION(Register, rscratch1, r10); // volatile +REGISTER_DECLARATION(Register, rscratch2, r11); // volatile + +REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved + +#endif // _LP64 + // Address is an abstraction used to represent a memory location -// using any of the x86 addressing modes with one object. +// using any of the amd64 addressing modes with one object. // // Note: A register location is represented via a Register, not // via an address for efficiency & simplicity reasons. +class ArrayAddress; + class Address VALUE_OBJ_CLASS_SPEC { public: enum ScaleFactor { @@ -61,110 +156,249 @@ int _disp; RelocationHolder _rspec; + // Easily misused constructor make them private +#ifndef _LP64 + Address::Address(address loc, RelocationHolder spec); +#endif // _LP64 + public: // creation Address() - : _base (noreg) - , _index(noreg) - , _scale(no_scale) - , _disp (0) - {} - - Address(int disp, relocInfo::relocType rtype); - Address(Register base, Register index, ScaleFactor scale, relocInfo::relocType rtype, int disp = 0); + : _base(noreg), + _index(noreg), + _scale(no_scale), + _disp(0) { + } - Address(int disp, RelocationHolder const& rspec) - : _base (noreg) - , _index(noreg) - , _scale(no_scale) - , _disp (disp) - , _rspec(rspec) - {} + // No default displacement otherwise Register can be implicitly + // converted to 0(Register) which is quite a different animal. - Address(Register base, int disp = 0) - : _base (base) - , _index(noreg) - , _scale(no_scale) - , _disp (disp) - {} + Address(Register base, int disp) + : _base(base), + _index(noreg), + _scale(no_scale), + _disp(disp) { + } Address(Register base, Register index, ScaleFactor scale, int disp = 0) - : _base (base) - , _index(index) - , _scale(scale) - , _disp (disp) - { - assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address"); + : _base (base), + _index(index), + _scale(scale), + _disp (disp) { + assert(!index->is_valid() == (scale == Address::no_scale), + "inconsistent address"); } - // The following two overloads are used in connection with the ByteSize type (see sizes.hpp). - // They simplify the use of ByteSize'd arguments in assembly code. Note that their equivalent - // for the optimized build are the member functions with int disp argument since ByteSize is - // mapped to an int type in that case. + // The following two overloads are used in connection with the + // ByteSize type (see sizes.hpp). They simplify the use of + // ByteSize'd arguments in assembly code. Note that their equivalent + // for the optimized build are the member functions with int disp + // argument since ByteSize is mapped to an int type in that case. // - // Note: DO NOT introduce similar overloaded functions for WordSize arguments as in the - // optimized mode, both ByteSize and WordSize are mapped to the same type and thus - // the compiler cannot make a distinction anymore (=> compiler errors). + // Note: DO NOT introduce similar overloaded functions for WordSize + // arguments as in the optimized mode, both ByteSize and WordSize + // are mapped to the same type and thus the compiler cannot make a + // distinction anymore (=> compiler errors). #ifdef ASSERT Address(Register base, ByteSize disp) - : _base (base) - , _index(noreg) - , _scale(no_scale) - , _disp (in_bytes(disp)) - {} + : _base(base), + _index(noreg), + _scale(no_scale), + _disp(in_bytes(disp)) { + } Address(Register base, Register index, ScaleFactor scale, ByteSize disp) - : _base (base) - , _index(index) - , _scale(scale) - , _disp (in_bytes(disp)) - { - assert(!index->is_valid() == (scale == Address::no_scale), "inconsistent address"); + : _base(base), + _index(index), + _scale(scale), + _disp(in_bytes(disp)) { + assert(!index->is_valid() == (scale == Address::no_scale), + "inconsistent address"); } #endif // ASSERT // accessors - bool uses(Register reg) const { return _base == reg || _index == reg; } - Register base() const { return _base; } - Register index() const { return _index; } - ScaleFactor scale() const { return _scale; } - int disp() const { return _disp; } + bool uses(Register reg) const { + return _base == reg || _index == reg; + } // Convert the raw encoding form into the form expected by the constructor for // Address. An index of 4 (esp) corresponds to having no index, so convert // that to noreg for the Address constructor. static Address make_raw(int base, int index, int scale, int disp); + static Address make_array(ArrayAddress); + + + private: + bool base_needs_rex() const { + return _base != noreg && _base->encoding() >= 8; + } + + bool index_needs_rex() const { + return _index != noreg &&_index->encoding() >= 8; + } + + relocInfo::relocType reloc() const { return _rspec.type(); } + friend class Assembler; friend class MacroAssembler; + friend class LIR_Assembler; // base/index/scale/disp }; -const int FPUStateSizeInWords = 27; +// +// AddressLiteral has been split out from Address because operands of this type +// need to be treated specially on 32bit vs. 64bit platforms. By splitting it out +// the few instructions that need to deal with address literals are unique and the +// MacroAssembler does not have to implement every instruction in the Assembler +// in order to search for address literals that may need special handling depending +// on the instruction and the platform. As small step on the way to merging i486/amd64 +// directories. +// +class AddressLiteral VALUE_OBJ_CLASS_SPEC { + friend class ArrayAddress; + RelocationHolder _rspec; + // Typically we use AddressLiterals we want to use their rval + // However in some situations we want the lval (effect address) of the item. + // We provide a special factory for making those lvals. + bool _is_lval; + + // If the target is far we'll need to load the ea of this to + // a register to reach it. Otherwise if near we can do rip + // relative addressing. + + address _target; + + protected: + // creation + AddressLiteral() + : _is_lval(false), + _target(NULL) + {} + + public: + + + AddressLiteral(address target, relocInfo::relocType rtype); + + AddressLiteral(address target, RelocationHolder const& rspec) + : _rspec(rspec), + _is_lval(false), + _target(target) + {} + + AddressLiteral addr() { + AddressLiteral ret = *this; + ret._is_lval = true; + return ret; + } + + + private: + + address target() { return _target; } + bool is_lval() { return _is_lval; } + + relocInfo::relocType reloc() const { return _rspec.type(); } + const RelocationHolder& rspec() const { return _rspec; } -// The Intel x86 Assembler: Pure assembler doing NO optimizations on the instruction + friend class Assembler; + friend class MacroAssembler; + friend class Address; + friend class LIR_Assembler; +}; + +// Convience classes +class RuntimeAddress: public AddressLiteral { + + public: + + RuntimeAddress(address target) : AddressLiteral(target, relocInfo::runtime_call_type) {} + +}; + +class OopAddress: public AddressLiteral { + + public: + + OopAddress(address target) : AddressLiteral(target, relocInfo::oop_type){} + +}; + +class ExternalAddress: public AddressLiteral { + + public: + + ExternalAddress(address target) : AddressLiteral(target, relocInfo::external_word_type){} + +}; + +class InternalAddress: public AddressLiteral { + + public: + + InternalAddress(address target) : AddressLiteral(target, relocInfo::internal_word_type) {} + +}; + +// x86 can do array addressing as a single operation since disp can be an absolute +// address amd64 can't. We create a class that expresses the concept but does extra +// magic on amd64 to get the final result + +class ArrayAddress VALUE_OBJ_CLASS_SPEC { + private: + + AddressLiteral _base; + Address _index; + + public: + + ArrayAddress() {}; + ArrayAddress(AddressLiteral base, Address index): _base(base), _index(index) {}; + AddressLiteral base() { return _base; } + Address index() { return _index; } + +}; + +#ifndef _LP64 +const int FPUStateSizeInWords = 27; +#else +const int FPUStateSizeInWords = 512 / wordSize; +#endif // _LP64 + +// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction // level (e.g. mov eax, 0 is not translated into xor eax, eax!); i.e., what you write // is what you get. The Assembler is generating code into a CodeBuffer. class Assembler : public AbstractAssembler { friend class AbstractAssembler; // for the non-virtual hack + friend class LIR_Assembler; // as_Address() protected: #ifdef ASSERT void check_relocation(RelocationHolder const& rspec, int format); #endif - void emit_data(jint data, relocInfo::relocType rtype, int format = 0); - void emit_data(jint data, RelocationHolder const& rspec, int format = 0); + inline void emit_long64(jlong x); + + void emit_data(jint data, relocInfo::relocType rtype, int format /* = 0 */); + void emit_data(jint data, RelocationHolder const& rspec, int format /* = 0 */); + void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0); + void emit_data64(jlong data, RelocationHolder const& rspec, int format = 0); // Helper functions for groups of instructions void emit_arith_b(int op1, int op2, Register dst, int imm8); void emit_arith(int op1, int op2, Register dst, int imm32); + // only x86?? void emit_arith(int op1, int op2, Register dst, jobject obj); void emit_arith(int op1, int op2, Register dst, Register src); - void emit_operand(Register reg, Register base, Register index, Address::ScaleFactor scale, int disp, RelocationHolder const& rspec); + void emit_operand(Register reg, + Register base, Register index, Address::ScaleFactor scale, + int disp, + RelocationHolder const& rspec); void emit_operand(Register reg, Address adr); // Immediate-to-memory forms @@ -172,6 +406,31 @@ void emit_farith(int b1, int b2, int i); + // macroassembler?? QQQ + bool reachable(AddressLiteral adr) { return true; } + + // These are all easily abused and hence protected + + // Make these disappear in 64bit mode since they would never be correct +#ifndef _LP64 + void cmp_literal32(Register src1, int32_t imm32, RelocationHolder const& rspec); + void cmp_literal32(Address src1, int32_t imm32, RelocationHolder const& rspec); + + void mov_literal32(Register dst, int32_t imm32, RelocationHolder const& rspec); + void mov_literal32(Address dst, int32_t imm32, RelocationHolder const& rspec); + + void push_literal32(int32_t imm32, RelocationHolder const& rspec); +#endif // _LP64 + + // These are unique in that we are ensured by the caller that the 32bit + // relative in these instructions will always be able to reach the potentially + // 64bit address described by entry. Since they can take a 64bit address they + // don't have the 32 suffix like the other instructions in this class. + + void call_literal(address entry, RelocationHolder const& rspec); + void jmp_literal(address entry, RelocationHolder const& rspec); + + public: enum Condition { // The x86 condition codes used for conditional jumps/moves. zero = 0x4, @@ -203,7 +462,27 @@ DS_segment = 0x3e, ES_segment = 0x26, FS_segment = 0x64, - GS_segment = 0x65 + GS_segment = 0x65, + + REX = 0x40, + + REX_B = 0x41, + REX_X = 0x42, + REX_XB = 0x43, + REX_R = 0x44, + REX_RB = 0x45, + REX_RX = 0x46, + REX_RXB = 0x47, + + REX_W = 0x48, + + REX_WB = 0x49, + REX_WX = 0x4A, + REX_WXB = 0x4B, + REX_WR = 0x4C, + REX_WRB = 0x4D, + REX_WRX = 0x4E, + REX_WRXB = 0x4F }; enum WhichOperand { @@ -214,6 +493,8 @@ _WhichOperand_limit = 3 }; + public: + // Creation Assembler(CodeBuffer* code) : AbstractAssembler(code) {} @@ -229,12 +510,14 @@ void popfd(); void pushl(int imm32); - void pushl(int imm32, relocInfo::relocType rtype); - void pushl(int imm32, RelocationHolder const& rspec); - void pushl(jobject obj); + void pushoop(jobject obj); + void pushl(Register src); void pushl(Address src); - void pushl(Label& L, relocInfo::relocType rtype); + // void pushl(Label& L, relocInfo::relocType rtype); ? needed? + + // dummy to prevent NULL being converted to Register + void pushl(void* dummy); void popl(Register dst); void popl(Address dst); @@ -251,15 +534,14 @@ void movw(Register dst, Address src); void movw(Address dst, Register src); + // these are dummies used to catch attempting to convert NULL to Register + void movl(Register dst, void* junk); + void movl(Address dst, void* junk); + void movl(Register dst, int imm32); - void movl(Register dst, address imm32, relocInfo::relocType rtype); - void movl(Register dst, jobject obj); + void movl(Address dst, int imm32); void movl(Register dst, Register src); void movl(Register dst, Address src); - - void movl(Address dst, int imm32); - void movl(Address dst, address imm32, relocInfo::relocType rtype); - void movl(Address dst, jobject obj); void movl(Address dst, Register src); void movsxb(Register dst, Address src); @@ -302,13 +584,15 @@ void andl(Register dst, Register src); void cmpb(Address dst, int imm8); + void cmpw(Address dst, int imm16); void cmpl(Address dst, int imm32); - void cmpl(Address dst, jobject obj); void cmpl(Register dst, int imm32); - void cmpl(Register dst, jobject obj); void cmpl(Register dst, Register src); void cmpl(Register dst, Address src); + // this is a dummy used to catch attempting to convert NULL to Register + void cmpl(Register dst, void* junk); + protected: // Don't use next inc() and dec() methods directly. INC & DEC instructions // could cause a partial flag stall since they don't set CF flag. @@ -383,12 +667,14 @@ // Miscellaneous void bswap(Register reg); void lock(); + void xchg (Register reg, Address adr); void xchgl(Register dst, Register src); + void cmpxchg (Register reg, Address adr); void cmpxchg8 (Address adr); + void hlt(); - void int3(); void nop(int i = 1); void ret(int imm16); void set_byte_if_not_zero(Register dst); // sets reg to 1 if not zero, otherwise 0 @@ -406,20 +692,18 @@ // Calls void call(Label& L, relocInfo::relocType rtype); - void call(address entry, relocInfo::relocType rtype); - void call(address entry, RelocationHolder const& rspec); - void call(Register reg, relocInfo::relocType rtype); - void call(Address adr); + void call(Register reg); // push pc; pc <- reg + void call(Address adr); // push pc; pc <- adr // Jumps - void jmp(address entry, relocInfo::relocType rtype); - void jmp(Register reg, relocInfo::relocType rtype = relocInfo::none); - void jmp(Address adr); + void jmp(Address entry); // pc <- entry + void jmp(Register entry); // pc <- entry + // Label operations & relative jumps (PPUM Appendix D) void jmp(Label& L, relocInfo::relocType rtype = relocInfo::none); // unconditional jump to L // Force an 8-bit jump offset - void jmpb(address entry); + // void jmpb(address entry); // Unconditional 8-bit offset jump to L. // WARNING: be very careful using this for forward jumps. If the label is @@ -442,14 +726,9 @@ // Note: The same Label can be used for forward and backward branches // but it may be bound only once. - void jcc(Condition cc, address dst, - relocInfo::relocType rtype = relocInfo::runtime_call_type); void jcc(Condition cc, Label& L, relocInfo::relocType rtype = relocInfo::none); - // Force an 8-bit jump offset - void jccb(Condition cc, address dst); - // Conditional jump to a 8-bit offset to L. // WARNING: be very careful using this for forward jumps. If the label is // not bound within an 8-bit offset of this instruction, a run-time error @@ -707,7 +986,12 @@ // on arguments should also go in here. class MacroAssembler: public Assembler { + friend class LIR_Assembler; protected: + + Address as_Address(AddressLiteral adr); + Address as_Address(ArrayAddress adr); + // Support for VM calls // // This is the base routine called by the different versions of call_VM_leaf. The interpreter @@ -794,18 +1078,26 @@ else { movss (dst, src); return; } } void movflt(XMMRegister dst, Address src) { movss(dst, src); } + void movflt(XMMRegister dst, AddressLiteral src); void movflt(Address dst, XMMRegister src) { movss(dst, src); } void movdbl(XMMRegister dst, XMMRegister src) { if (UseXmmRegToRegMoveAll) { movapd(dst, src); return; } else { movsd (dst, src); return; } } + + void movdbl(XMMRegister dst, AddressLiteral src); + void movdbl(XMMRegister dst, Address src) { if (UseXmmLoadAndClearUpper) { movsd (dst, src); return; } else { movlpd(dst, src); return; } } void movdbl(Address dst, XMMRegister src) { movsd(dst, src); } + void increment(AddressLiteral dst); + void increment(ArrayAddress dst); + + // Alignment void align(int modulus); @@ -868,6 +1160,8 @@ // returns idivl instruction offset for implicit exception handling int corrected_idivl(Register reg); + void int3(); + // Long negation for Java void lneg(Register hi, Register lo); @@ -1034,13 +1328,145 @@ BiasedLockingCounters* counters = NULL); void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done); + Condition negate_condition(Condition cond); + // Instructions that use AddressLiteral operands. These instruction can handle 32bit/64bit + // operands. In general the names are modified to avoid hiding the instruction in Assembler + // so that we don't need to implement all the varieties in the Assembler with trivial wrappers + // here in MacroAssembler. The major exception to this rule is call + + // Arithmetics + + void cmp8(AddressLiteral src1, int8_t imm); + + // QQQ renamed to drag out the casting of address to int32_t/intptr_t + void cmp32(Register src1, int32_t imm); + + void cmp32(AddressLiteral src1, int32_t imm); + // compare reg - mem, or reg - &mem + void cmp32(Register src1, AddressLiteral src2); + + void cmp32(Register src1, Address src2); + + // NOTE src2 must be the lval. This is NOT an mem-mem compare + void cmpptr(Address src1, AddressLiteral src2); + + void cmpptr(Register src1, AddressLiteral src2); + + void cmpoop(Address dst, jobject obj); + void cmpoop(Register dst, jobject obj); + + + void cmpxchgptr(Register reg, AddressLiteral adr); + // Helper functions for statistics gathering. // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. - void cond_incl(Condition cond, Address counter_addr); + void cond_inc32(Condition cond, AddressLiteral counter_addr); // Unconditional atomic increment. - void atomic_incl(Address counter_addr); + void atomic_incl(AddressLiteral counter_addr); + + void lea(Register dst, AddressLiteral adr); + void lea(Address dst, AddressLiteral adr); + + void test32(Register dst, AddressLiteral src); + + // Calls + + void call(Label& L, relocInfo::relocType rtype); + void call(Register entry); + + // NOTE: this call tranfers to the effective address of entry NOT + // the address contained by entry. This is because this is more natural + // for jumps/calls. + void call(AddressLiteral entry); + + // Jumps + + // NOTE: these jumps tranfer to the effective address of dst NOT + // the address contained by dst. This is because this is more natural + // for jumps/calls. + void jump(AddressLiteral dst); + void jump_cc(Condition cc, AddressLiteral dst); + + // 32bit can do a case table jump in one instruction but we no longer allow the base + // to be installed in the Address class. This jump will tranfers to the address + // contained in the location described by entry (not the address of entry) + void jump(ArrayAddress entry); + + // Floating + + void andpd(XMMRegister dst, Address src) { Assembler::andpd(dst, src); } + void andpd(XMMRegister dst, AddressLiteral src); + + void comiss(XMMRegister dst, Address src) { Assembler::comiss(dst, src); } + void comiss(XMMRegister dst, AddressLiteral src); + + void comisd(XMMRegister dst, Address src) { Assembler::comisd(dst, src); } + void comisd(XMMRegister dst, AddressLiteral src); + + void fldcw(Address src) { Assembler::fldcw(src); } + void fldcw(AddressLiteral src); + + void fld_s(int index) { Assembler::fld_s(index); } + void fld_s(Address src) { Assembler::fld_s(src); } + void fld_s(AddressLiteral src); + + void fld_d(Address src) { Assembler::fld_d(src); } + void fld_d(AddressLiteral src); + + void fld_x(Address src) { Assembler::fld_x(src); } + void fld_x(AddressLiteral src); + + void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } + void ldmxcsr(AddressLiteral src); + + void movss(Address dst, XMMRegister src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, XMMRegister src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, Address src) { Assembler::movss(dst, src); } + void movss(XMMRegister dst, AddressLiteral src); + + void movsd(XMMRegister dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(Address dst, XMMRegister src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); } + void movsd(XMMRegister dst, AddressLiteral src); + + void ucomiss(XMMRegister dst, XMMRegister src) { Assembler::ucomiss(dst, src); } + void ucomiss(XMMRegister dst, Address src) { Assembler::ucomiss(dst, src); } + void ucomiss(XMMRegister dst, AddressLiteral src); + + void ucomisd(XMMRegister dst, XMMRegister src) { Assembler::ucomisd(dst, src); } + void ucomisd(XMMRegister dst, Address src) { Assembler::ucomisd(dst, src); } + void ucomisd(XMMRegister dst, AddressLiteral src); + + // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values + void xorpd(XMMRegister dst, XMMRegister src) { Assembler::xorpd(dst, src); } + void xorpd(XMMRegister dst, Address src) { Assembler::xorpd(dst, src); } + void xorpd(XMMRegister dst, AddressLiteral src); + + // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values + void xorps(XMMRegister dst, XMMRegister src) { Assembler::xorps(dst, src); } + void xorps(XMMRegister dst, Address src) { Assembler::xorps(dst, src); } + void xorps(XMMRegister dst, AddressLiteral src); + + // Data + + void movoop(Register dst, jobject obj); + void movoop(Address dst, jobject obj); + + void movptr(ArrayAddress dst, Register src); + // can this do an lea? + void movptr(Register dst, ArrayAddress src); + + void movptr(Register dst, AddressLiteral src); + + // to avoid hiding movl + void mov32(AddressLiteral dst, Register src); + void mov32(Register dst, AddressLiteral src); + + // Can push value or effective address + void pushptr(AddressLiteral src); + }; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_CodeStubs_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_CodeStubs_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_CodeStubs_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_CodeStubs_i486.cpp 1.98 07/05/17 15:46:20 JVM" +#pragma ident "@(#)c1_CodeStubs_i486.cpp 1.99 07/06/19 09:08:03 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -40,9 +40,11 @@ if (input()->is_single_xmm()) { - __ comiss(input()->as_xmm_float_reg(), Address((int)&float_zero, relocInfo::none)); + __ comiss(input()->as_xmm_float_reg(), + ExternalAddress((address)&float_zero)); } else if (input()->is_double_xmm()) { - __ comisd(input()->as_xmm_double_reg(), Address((int)&double_zero, relocInfo::none)); + __ comisd(input()->as_xmm_double_reg(), + ExternalAddress((address)&double_zero)); } else { __ pushl(eax); __ ftst(); @@ -72,7 +74,7 @@ void CounterOverflowStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); ce->store_parameter(_bci, 0); - __ call(Runtime1::entry_for(Runtime1::counter_overflow_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::counter_overflow_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); @@ -99,11 +101,13 @@ } else { ce->store_parameter(_index->as_jint(), 0); } + Runtime1::StubID stub_id; if (_throw_index_out_of_bounds_exception) { - __ call(Runtime1::entry_for(Runtime1::throw_index_exception_id), relocInfo::runtime_call_type); + stub_id = Runtime1::throw_index_exception_id; } else { - __ call(Runtime1::entry_for(Runtime1::throw_range_check_failed_id), relocInfo::runtime_call_type); + stub_id = Runtime1::throw_range_check_failed_id; } + __ call(RuntimeAddress(Runtime1::entry_for(stub_id))); ce->add_call_info_here(_info); debug_only(__ should_not_reach_here()); } @@ -114,7 +118,7 @@ ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); } __ bind(_entry); - __ call(Runtime1::entry_for(Runtime1::throw_div0_exception_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_div0_exception_id))); ce->add_call_info_here(_info); debug_only(__ should_not_reach_here()); } @@ -139,7 +143,7 @@ assert(__ esp_offset() == 0, "frame size should be fixed"); __ bind(_entry); __ movl(edx, _klass_reg->as_register()); - __ call(Runtime1::entry_for(_stub_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(_stub_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == eax, "result must in eax"); @@ -162,7 +166,7 @@ __ bind(_entry); assert(_length->as_register() == ebx, "length must in ebx"); assert(_klass_reg->as_register() == edx, "klass_reg must in edx"); - __ call(Runtime1::entry_for(Runtime1::new_type_array_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_type_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == eax, "result must in eax"); @@ -185,7 +189,7 @@ __ bind(_entry); assert(_length->as_register() == ebx, "length must in ebx"); assert(_klass_reg->as_register() == edx, "klass_reg must in edx"); - __ call(Runtime1::entry_for(Runtime1::new_object_array_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::new_object_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); assert(_result->as_register() == eax, "result must in eax"); @@ -207,11 +211,13 @@ __ bind(_entry); ce->store_parameter(_obj_reg->as_register(), 1); ce->store_parameter(_lock_reg->as_register(), 0); + Runtime1::StubID enter_id; if (ce->compilation()->has_fpu_code()) { - __ call(Runtime1::entry_for(Runtime1::monitorenter_id), relocInfo::runtime_call_type); + enter_id = Runtime1::monitorenter_id; } else { - __ call(Runtime1::entry_for(Runtime1::monitorenter_nofpu_id), relocInfo::runtime_call_type); + enter_id = Runtime1::monitorenter_nofpu_id; } + __ call(RuntimeAddress(Runtime1::entry_for(enter_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); __ jmp(_continuation); @@ -226,11 +232,13 @@ } ce->store_parameter(_lock_reg->as_register(), 0); // note: non-blocking leaf routine => no call info needed + Runtime1::StubID exit_id; if (ce->compilation()->has_fpu_code()) { - __ call(Runtime1::entry_for(Runtime1::monitorexit_id), relocInfo::runtime_call_type); + exit_id = Runtime1::monitorexit_id; } else { - __ call(Runtime1::entry_for(Runtime1::monitorexit_nofpu_id), relocInfo::runtime_call_type); + exit_id = Runtime1::monitorexit_nofpu_id; } + __ call(RuntimeAddress(Runtime1::entry_for(exit_id))); __ jmp(_continuation); } @@ -273,7 +281,7 @@ // produce a copy of the load klass instruction for use by the being initialized case address start = __ pc(); jobject o = NULL; - __ movl(_obj, o); + __ movoop(_obj, o); #ifdef ASSERT for (int i = 0; i < _bytes_to_copy; i++) { address ptr = (address)(_pc_start + i); @@ -349,7 +357,7 @@ if (CommentedAssembly) { __ block_comment("patch entry point"); } - __ call(target, relocInfo::runtime_call_type); + __ call(RuntimeAddress(target)); assert(_patch_info_offset == (patch_info_pc - __ pc()), "must not change"); ce->add_call_info_here(_info); int jmp_off = __ offset(); @@ -370,7 +378,7 @@ void ImplicitNullCheckStub::emit_code(LIR_Assembler* ce) { ce->compilation()->implicit_exception_table()->append(_offset, __ offset()); __ bind(_entry); - __ call(Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_null_pointer_exception_id))); ce->add_call_info_here(_info); debug_only(__ should_not_reach_here()); } @@ -384,7 +392,7 @@ if (_obj->is_cpu_register()) { ce->store_parameter(_obj->as_register(), 0); } - __ call(Runtime1::entry_for(_stub), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(_stub))); ce->add_call_info_here(_info); debug_only(__ should_not_reach_here()); } @@ -398,7 +406,7 @@ void ArrayStoreExceptionStub::emit_code(LIR_Assembler* ce) { assert(__ esp_offset() == 0, "frame size should be fixed"); __ bind(_entry); - __ call(Runtime1::entry_for(Runtime1::throw_array_store_exception_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::throw_array_store_exception_id))); ce->add_call_info_here(_info); debug_only(__ should_not_reach_here()); } @@ -438,11 +446,13 @@ ce->align_call(lir_static_call); ce->emit_static_call_stub(); - __ call(SharedRuntime::get_resolve_static_call_stub(), relocInfo::static_call_type); + AddressLiteral resolve(SharedRuntime::get_resolve_static_call_stub(), + relocInfo::static_call_type); + __ call(resolve); ce->add_call_info_here(info()); #ifndef PRODUCT - __ increment(Address((intptr_t)&Runtime1::_arraycopy_slowcase_cnt, relocInfo::none)); + __ increment(ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt)); #endif __ jmp(_continuation); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_LIRAssembler_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_LIRAssembler_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_LIRAssembler_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRAssembler_i486.cpp 1.164 07/06/08 18:13:17 JVM" +#pragma ident "@(#)c1_LIRAssembler_i486.cpp 1.165 07/06/19 09:08:03 JVM" #endif /* * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -153,11 +153,11 @@ void LIR_Assembler::set_24bit_FPU() { - __ fldcw(Address((int)StubRoutines::addr_fpu_cntrl_wrd_24(), relocInfo::none)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); } void LIR_Assembler::reset_FPU() { - __ fldcw(Address((int)StubRoutines::addr_fpu_cntrl_wrd_std(), relocInfo::none)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } void LIR_Assembler::fpop() { @@ -215,7 +215,10 @@ Address LIR_Assembler::as_Address(LIR_Address* addr) { if (addr->base()->is_illegal()) { assert(addr->index()->is_illegal(), "must be illegal too"); - return Address(addr->disp(), relocInfo::none); + //return Address(addr->disp(), relocInfo::none); + // hack for now since this should really return an AddressLiteral + // which will have to await 64bit c1 changes. + return Address(noreg, addr->disp()); } Register base = addr->base()->as_register(); @@ -238,7 +241,7 @@ Address LIR_Assembler::as_Address_hi(LIR_Address* addr) { Address base = as_Address(addr); - return Address(base.base(), base.index(), base.scale(), base.disp() + BytesPerWord); + return Address(base._base, base._index, base._scale, base._disp + BytesPerWord); } @@ -335,7 +338,7 @@ void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) { jobject o = NULL; PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id); - __ movl(reg, o); + __ movoop(reg, o); patching_epilog(patch, lir_patch_normal, reg, info); } @@ -429,7 +432,7 @@ __ verify_not_null_oop(eax); // search an exception handler (eax: exception oop, edx: throwing pc) - __ call(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); // if the call returns here, then the exception handler for particular // exception doesn't exist -> unwind activation and forward exception to caller @@ -451,7 +454,7 @@ // unwind activation and forward exception to caller // eax: exception - __ jmp(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); assert(code_offset() - offset <= exception_handler_size, "overflow"); @@ -480,8 +483,10 @@ compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset()); - __ pushl( (intptr_t) __ pc(), relocInfo::internal_word_type); - __ jmp(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type); + InternalAddress here(__ pc()); + __ pushptr(here.addr()); + + __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); assert(code_offset() - offset <= deopt_handler_size, "overflow"); @@ -533,8 +538,8 @@ __ jcc (Assembler::zero, noLoop); // compare first characters - __ load_unsigned_word(ecx, Address(edi)); - __ load_unsigned_word(ebx, Address(esi)); + __ load_unsigned_word(ecx, Address(edi, 0)); + __ load_unsigned_word(ebx, Address(esi, 0)); __ subl(ecx, ebx); __ jcc(Assembler::notZero, haveResult); // starting loop @@ -585,19 +590,17 @@ // Note: we do not need to round double result; float result has the right precision // the poll sets the condition code, but no data registers - Address polling_page((int)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), - relocInfo::none); - - __ relocate(relocInfo::poll_return_type); - __ testl(eax, polling_page); + AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), + relocInfo::poll_return_type); + __ test32(eax, polling_page); __ ret(0); } int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { - Address polling_page((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), - relocInfo::none); + AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), + relocInfo::poll_type); if (info != NULL) { add_debug_info_for_branch(info); @@ -606,7 +609,7 @@ } int offset = __ offset(); - __ testl(eax, polling_page); + __ test32(eax, polling_page); return offset; } @@ -643,7 +646,7 @@ if (patch_code != lir_patch_none) { jobject2reg_with_patching(dest->as_register(), info); } else { - __ movl(dest->as_register(), c->as_jobject()); + __ movoop(dest->as_register(), c->as_jobject()); } break; } @@ -653,8 +656,8 @@ if (c->is_zero_float()) { __ xorps(dest->as_xmm_float_reg(), dest->as_xmm_float_reg()); } else { - address const_addr = float_constant(c->as_jfloat()); - __ movflt(dest->as_xmm_float_reg(), Address((int)const_addr, relocInfo::internal_word_type)); + __ movflt(dest->as_xmm_float_reg(), + InternalAddress(float_constant(c->as_jfloat()))); } } else { assert(dest->is_single_fpu(), "must be"); @@ -664,8 +667,7 @@ } else if (c->is_one_float()) { __ fld1(); } else { - address const_addr = float_constant(c->as_jfloat()); - __ fld_s (Address((int)const_addr, relocInfo::internal_word_type)); + __ fld_s (InternalAddress(float_constant(c->as_jfloat()))); } } break; @@ -676,8 +678,8 @@ if (c->is_zero_double()) { __ xorpd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg()); } else { - address const_addr = double_constant(c->as_jdouble()); - __ movdbl(dest->as_xmm_double_reg(), Address((int)const_addr, relocInfo::internal_word_type)); + __ movdbl(dest->as_xmm_double_reg(), + InternalAddress(double_constant(c->as_jdouble()))); } } else { assert(dest->is_double_fpu(), "must be"); @@ -687,8 +689,7 @@ } else if (c->is_one_double()) { __ fld1(); } else { - address const_addr = double_constant(c->as_jdouble()); - __ fld_d (Address((int)const_addr, relocInfo::internal_word_type)); + __ fld_d (InternalAddress(double_constant(c->as_jdouble()))); } } break; @@ -711,7 +712,7 @@ break; case T_OBJECT: - __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject()); + __ movoop(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject()); break; case T_LONG: // fall through @@ -745,7 +746,7 @@ if (c->as_jobject() == NULL) { __ movl(as_Address(addr), NULL_WORD); } else { - __ movl(as_Address(addr), c->as_jobject()); + __ movoop(as_Address(addr), c->as_jobject()); } break; @@ -806,17 +807,17 @@ // special moves from fpu-register to xmm-register // necessary for method results } else if (src->is_single_xmm() && !dest->is_single_xmm()) { - __ movflt(Address(esp), src->as_xmm_float_reg()); - __ fld_s(Address(esp)); + __ movflt(Address(esp, 0), src->as_xmm_float_reg()); + __ fld_s(Address(esp, 0)); } else if (src->is_double_xmm() && !dest->is_double_xmm()) { - __ movdbl(Address(esp), src->as_xmm_double_reg()); - __ fld_d(Address(esp)); + __ movdbl(Address(esp, 0), src->as_xmm_double_reg()); + __ fld_d(Address(esp, 0)); } else if (dest->is_single_xmm() && !src->is_single_xmm()) { - __ fstp_s(Address(esp)); - __ movflt(dest->as_xmm_float_reg(), Address(esp)); + __ fstp_s(Address(esp, 0)); + __ movflt(dest->as_xmm_float_reg(), Address(esp, 0)); } else if (dest->is_double_xmm() && !src->is_double_xmm()) { - __ fstp_d(Address(esp)); - __ movdbl(dest->as_xmm_double_reg(), Address(esp)); + __ fstp_d(Address(esp, 0)); + __ movdbl(dest->as_xmm_double_reg(), Address(esp, 0)); // move between xmm-registers } else if (dest->is_single_xmm()) { @@ -1112,7 +1113,7 @@ // patches or null checks. assert(info == NULL && patch == NULL, "must be"); __ leal(to_hi, as_Address(addr)); - __ movl(to_lo, Address(to_hi)); + __ movl(to_lo, Address(to_hi, 0)); __ movl(to_hi, Address(to_hi, BytesPerWord)); } else if (base == to_lo || index == to_lo) { assert(base != to_hi, "can't be"); @@ -1353,8 +1354,8 @@ __ cvtsi2sd(dest->as_xmm_double_reg(), src->as_register()); } else { assert(dest->fpu() == 0, "result must be on TOS"); - __ movl(Address(esp), src->as_register()); - __ fild_s(Address(esp)); + __ movl(Address(esp, 0), src->as_register()); + __ fild_s(Address(esp, 0)); } break; @@ -1366,10 +1367,10 @@ __ cvttsd2si(dest->as_register(), src->as_xmm_double_reg()); } else { assert(src->fpu() == 0, "input must be on TOS"); - __ fldcw(Address((int)StubRoutines::addr_fpu_cntrl_wrd_trunc(), relocInfo::none)); - __ fist_s(Address(esp)); - __ movl(dest->as_register(), Address(esp)); - __ fldcw(Address((int)StubRoutines::addr_fpu_cntrl_wrd_std(), relocInfo::none)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_trunc())); + __ fist_s(Address(esp, 0)); + __ movl(dest->as_register(), Address(esp, 0)); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } // IA32 conversion instructions do not match JLS for overflow, underflow and NaN -> fixup in stub @@ -1384,9 +1385,9 @@ assert(!dest->is_xmm_register(), "result in xmm register not supported (no SSE instruction present)"); assert(dest->fpu() == 0, "result must be on TOS"); - __ movl(Address(esp), src->as_register_lo()); + __ movl(Address(esp, 0), src->as_register_lo()); __ movl(Address(esp, BytesPerWord), src->as_register_hi()); - __ fild_d(Address(esp)); + __ fild_d(Address(esp, 0)); // float result is rounded later through spilling break; @@ -1397,7 +1398,9 @@ assert(dest == FrameMap::eax_edx_long_opr, "runtime stub places result in these registers"); // instruction sequence too long to inline it here - __ call(Runtime1::entry_for(Runtime1::fpu2long_stub_id), relocInfo::runtime_call_type); + { + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::fpu2long_stub_id))); + } break; default: ShouldNotReachHere(); @@ -1488,7 +1491,7 @@ __ pushl(klass_RInfo); __ pushl(k_RInfo); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ popl(klass_RInfo); __ popl(k_RInfo); __ cmpl(k_RInfo, 0); @@ -1541,7 +1544,7 @@ assert(data != NULL, "need data for checkcast"); assert(data->is_BitData(), "need BitData for checkcast"); Register mdo = klass_RInfo; - __ movl(mdo, md->encoding()); + __ movoop(mdo, md->encoding()); Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); __ orl(data_addr, header_bits); @@ -1556,7 +1559,7 @@ // get object classo // not a safepoint as obj null check happens earlier if (k->is_loaded()) { - __ cmpl(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()); + __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()); } else { __ cmpl(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); @@ -1569,19 +1572,19 @@ __ movl(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); if (k->is_loaded()) { // See if we get an immediate positive hit - __ cmpl(Address(klass_RInfo, k->super_check_offset()), k->encoding()); + __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding()); if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { __ jcc(Assembler::notEqual, *stub->entry()); } else { // See if we get an immediate positive hit __ jcc(Assembler::equal, done); // check for self - __ cmpl(klass_RInfo, k->encoding()); + __ cmpoop(klass_RInfo, k->encoding()); __ jcc(Assembler::equal, done); __ pushl(klass_RInfo); - __ pushl(k->encoding()); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); + __ pushoop(k->encoding()); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ popl(klass_RInfo); __ popl(klass_RInfo); __ cmpl(klass_RInfo, 0); @@ -1602,7 +1605,7 @@ __ pushl(klass_RInfo); __ pushl(k_RInfo); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ popl(klass_RInfo); __ popl(k_RInfo); __ cmpl(k_RInfo, 0); @@ -1642,7 +1645,7 @@ // get object class // not a safepoint as obj null check happens earlier if (k->is_loaded()) { - __ cmpl(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()); + __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()); k_RInfo = noreg; } else { __ cmpl(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); @@ -1657,15 +1660,15 @@ __ movl(klass_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); if (k->is_loaded()) { // See if we get an immediate positive hit - __ cmpl(Address(klass_RInfo, k->super_check_offset()), k->encoding()); + __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding()); __ jcc(Assembler::equal, one); if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) { // check for self - __ cmpl(klass_RInfo, k->encoding()); + __ cmpoop(klass_RInfo, k->encoding()); __ jcc(Assembler::equal, one); __ pushl(klass_RInfo); - __ pushl(k->encoding()); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); + __ pushoop(k->encoding()); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ popl(klass_RInfo); __ popl(dst); __ jmp(done); @@ -1686,7 +1689,7 @@ __ pushl(klass_RInfo); __ pushl(k_RInfo); - __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); __ popl(klass_RInfo); __ popl(dst); __ jmp(done); @@ -1716,7 +1719,7 @@ if (os::is_MP()) { __ lock(); } - __ cmpxchg8(addr); + __ cmpxchg8(Address(addr, 0)); } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { Register addr = op->addr()->as_register(); @@ -1730,7 +1733,7 @@ if (os::is_MP()) { __ lock(); } - __ cmpxchg(newval, addr); + __ cmpxchg(newval, Address(addr, 0)); } else { Unimplemented(); } @@ -1914,8 +1917,8 @@ if (right->is_single_stack()) { raddr = frame_map()->address_for_slot(right->single_stack_ix()); } else if (right->is_constant()) { - address const_addr = float_constant(right->as_jfloat()); - raddr = Address((int)const_addr, relocInfo::internal_word_type); + // hack for now + raddr = __ as_Address(InternalAddress(float_constant(right->as_jfloat()))); } else { ShouldNotReachHere(); } @@ -1950,8 +1953,8 @@ if (right->is_double_stack()) { raddr = frame_map()->address_for_slot(right->double_stack_ix()); } else if (right->is_constant()) { - address const_addr = double_constant(right->as_jdouble()); - raddr = Address((int)const_addr, relocInfo::internal_word_type); + // hack for now + raddr = __ as_Address(InternalAddress(double_constant(right->as_jdouble()))); } else { ShouldNotReachHere(); } @@ -1982,7 +1985,8 @@ } else if (right->is_constant()) { address const_addr = float_constant(right->as_jfloat()); assert(const_addr != NULL, "incorrect float/double constant maintainance"); - raddr = Address((int)const_addr, relocInfo::internal_word_type); + // hack for now + raddr = __ as_Address(InternalAddress(const_addr)); } else { ShouldNotReachHere(); } @@ -2003,7 +2007,7 @@ if (code == lir_mul_strictfp || code == lir_div_strictfp) { // Double values require special handling for strictfp mul/div on x86 - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias1(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); __ fmulp(left->fpu_regnrLo() + 1); } @@ -2018,8 +2022,8 @@ if (right->is_double_stack()) { raddr = frame_map()->address_for_slot(right->double_stack_ix()); } else if (right->is_constant()) { - address const_addr = double_constant(right->as_jdouble()); - raddr = Address((int)const_addr, relocInfo::internal_word_type); + // hack for now + raddr = __ as_Address(InternalAddress(double_constant(right->as_jdouble()))); } else { ShouldNotReachHere(); } @@ -2037,7 +2041,7 @@ if (code == lir_mul_strictfp || code == lir_div_strictfp) { // Double values require special handling for strictfp mul/div on x86 - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias2(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); __ fmulp(dest->fpu_regnrLo() + 1); } @@ -2145,10 +2149,13 @@ if (value->is_double_xmm()) { switch(code) { case lir_abs : - if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) { - __ movdbl(dest->as_xmm_double_reg(), value->as_xmm_double_reg()); + { + if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) { + __ movdbl(dest->as_xmm_double_reg(), value->as_xmm_double_reg()); + } + __ andpd(dest->as_xmm_double_reg(), + ExternalAddress((address)double_signmask_pool)); } - __ andpd(dest->as_xmm_double_reg(), Address((int)double_signmask_pool, relocInfo::none)); break; case lir_sqrt: __ sqrtsd(dest->as_xmm_double_reg(), value->as_xmm_double_reg()); break; @@ -2350,7 +2357,7 @@ if (o == NULL) { __ cmpl(reg1, NULL_WORD); } else { - __ cmpl(reg1, c->as_jobject()); + __ cmpoop(reg1, c->as_jobject()); } } else { ShouldNotReachHere(); @@ -2396,8 +2403,7 @@ __ ucomiss(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); } else if (opr2->is_constant()) { // xmm register - constant - address const_addr = float_constant(opr2->as_jfloat()); - __ ucomiss(reg1, Address((int)const_addr, relocInfo::internal_word_type)); + __ ucomiss(reg1, InternalAddress(float_constant(opr2->as_jfloat()))); } else if (opr2->is_address()) { // xmm register - address if (op->info() != NULL) { @@ -2418,8 +2424,7 @@ __ ucomisd(reg1, frame_map()->address_for_slot(opr2->double_stack_ix())); } else if (opr2->is_constant()) { // xmm register - constant - address const_addr = double_constant(opr2->as_jdouble()); - __ ucomisd(reg1, Address((int)const_addr, relocInfo::internal_word_type)); + __ ucomisd(reg1, InternalAddress(double_constant(opr2->as_jdouble()))); } else if (opr2->is_address()) { // xmm register - address if (op->info() != NULL) { @@ -2445,7 +2450,7 @@ if (c->type() == T_INT) { __ cmpl(as_Address(addr), c->as_jint()); } else if (c->type() == T_OBJECT) { - __ cmpl(as_Address(addr), c->as_jobject()); + __ cmpoop(as_Address(addr), c->as_jobject()); } else { ShouldNotReachHere(); } @@ -2508,18 +2513,18 @@ void LIR_Assembler::call(address entry, relocInfo::relocType rtype, CodeEmitInfo* info) { assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(entry, rtype); + __ call(AddressLiteral(entry, rtype)); add_call_info(code_offset(), info); } void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) { RelocationHolder rh = virtual_call_Relocation::spec(pc()); - __ movl(IC_Klass, (jobject)Universe::non_oop_word()); + __ movoop(IC_Klass, (jobject)Universe::non_oop_word()); assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); - __ call(entry, rh); + __ call(AddressLiteral(entry, rh)); add_call_info(code_offset(), info); } @@ -2546,10 +2551,10 @@ } } __ relocate(static_stub_Relocation::spec(call_pc)); - __ movl(ebx, (jobject)NULL); + __ movoop(ebx, (jobject)NULL); // must be set to -1 at code generation time assert(!os::is_MP() || ((__ offset() + 1) % BytesPerWord) == 0, "must be aligned on MP"); - __ jmp((address)-1, relocInfo::runtime_call_type); + __ jump(RuntimeAddress((address)-1)); assert(__ offset() - start <= call_stub_size, "stub too big") __ end_a_stub(); @@ -2563,25 +2568,27 @@ // exception object is not added to oop map by LinearScan // (LinearScan assumes that no oops are in fixed registers) info->add_register_oop(exceptionOop); + Runtime1::StubID unwind_id; if (!unwind) { // get current pc information // pc is only needed if the method has an exception handler, the unwind code does not need it. - int pc_for_athrow = (int)__ pc(); int pc_for_athrow_offset = __ offset(); - __ leal(exceptionPC->as_register(), Address(pc_for_athrow, relocInfo::internal_word_type)); + InternalAddress pc_for_athrow(__ pc()); + __ lea(exceptionPC->as_register(), pc_for_athrow); add_call_info(pc_for_athrow_offset, info); // for exception handler __ verify_not_null_oop(eax); // search an exception handler (eax: exception oop, edx: throwing pc) if (compilation()->has_fpu_code()) { - __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); + unwind_id = Runtime1::handle_exception_id; } else { - __ call(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id), relocInfo::runtime_call_type); + unwind_id = Runtime1::handle_exception_nofpu_id; } } else { - __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type); + unwind_id = Runtime1::unwind_exception_id; } + __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); // enough room for two byte trap __ nop(); @@ -2666,7 +2673,7 @@ assert(offset_from_esp_in_words >= 0, "invalid offset from esp"); int offset_from_esp_in_bytes = offset_from_esp_in_words * BytesPerWord; assert(offset_from_esp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); - __ movl (Address(esp, offset_from_esp_in_bytes), o); + __ movoop (Address(esp, offset_from_esp_in_bytes), o); } @@ -2815,7 +2822,7 @@ // a type check is needed then at this point the classes are known to be // the same but again which don't know which type so we can't check them. Label known_ok, halt; - __ movl(tmp, default_type->encoding()); + __ movoop(tmp, default_type->encoding()); __ cmpl(tmp, dst_klass_addr); if (basic_type != T_OBJECT) { __ jcc(Assembler::notEqual, halt); @@ -2888,7 +2895,7 @@ assert(data->is_CounterData(), "need CounterData for calls"); assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); Register mdo = op->mdo()->as_register(); - __ movl(mdo, md->encoding()); + __ movoop(mdo, md->encoding()); Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); __ addl(counter_addr, DataLayout::counter_increment); Bytecodes::Code bc = method->java_code_at_bci(bci); @@ -2928,7 +2935,7 @@ ciKlass* receiver = vc_data->receiver(i); if (receiver == NULL) { Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); - __ movl(recv_addr, known_klass->encoding()); + __ movoop(recv_addr, known_klass->encoding()); Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); __ addl(data_addr, DataLayout::counter_increment); return; @@ -3006,13 +3013,15 @@ if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) { __ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg()); } - __ xorps(dest->as_xmm_float_reg(), Address((int)float_signflip_pool, relocInfo::none)); + __ xorps(dest->as_xmm_float_reg(), + ExternalAddress((address)float_signflip_pool)); } else if (dest->is_double_xmm()) { if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) { __ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg()); } - __ xorpd(dest->as_xmm_double_reg(), Address((int)double_signflip_pool, relocInfo::none)); + __ xorpd(dest->as_xmm_double_reg(), + ExternalAddress((address)double_signflip_pool)); } else if (left->is_single_fpu() || left->is_double_fpu()) { assert(left->fpu() == 0, "arg must be on TOS"); @@ -3035,7 +3044,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { assert(!tmp->is_valid(), "don't need temporary"); - __ call(dest, relocInfo::runtime_call_type); + __ call(RuntimeAddress(dest)); if (info != NULL) { add_call_info_here(info); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_LIRGenerator_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_LIRGenerator_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_LIRGenerator_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRGenerator_i486.cpp 1.13 07/05/05 17:04:13 JVM" +#pragma ident "@(#)c1_LIRGenerator_i486.cpp 1.14 07/06/18 14:25:21 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -296,9 +296,12 @@ __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info); } - __ move(value.result(), array_addr, null_check_info); if (obj_store) { - write_barrier(LIR_OprFact::address(array_addr)); + __ move(value.result(), array_addr, null_check_info); + // Seems to be a precise + post_barrier(LIR_OprFact::address(array_addr), value.result()); + } else { + __ move(value.result(), array_addr, null_check_info); } } @@ -741,10 +744,12 @@ ShouldNotReachHere(); } - LIR_Opr addr = new_register(T_OBJECT); + LIR_Opr addr = new_pointer_register(); __ move(obj.result(), addr); __ add(addr, offset.result(), addr); + + LIR_Opr ill = LIR_OprFact::illegalOpr; // for convenience if (type == objectType) __ cas_obj(addr, cmp.result(), val.result(), ill, ill); @@ -759,8 +764,10 @@ // generate conditional move of boolean result LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); - if (type == objectType) // Write-barrier needed for Object fields. - write_barrier(addr); + if (type == objectType) { // Write-barrier needed for Object fields. + // Seems to be precise + post_barrier(addr, val.result()); + } } @@ -1244,10 +1251,14 @@ __ move(tmp, addr); } else { LIR_Address* addr = new LIR_Address(src, offset, type); - __ move(data, addr); - if (type == T_ARRAY || type == T_OBJECT) { + bool is_obj = (type == T_ARRAY || type == T_OBJECT); + if (is_obj) { + __ move(data, addr); assert(src->is_register(), "must be register"); - write_barrier(LIR_OprFact::address(addr)); + // Seems to be a precise address + post_barrier(LIR_OprFact::address(addr), data); + } else { + __ move(data, addr); } } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_LinearScan_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_LinearScan_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_LinearScan_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_LinearScan_i486.cpp 1.7 07/05/05 17:04:13 JVM" +#pragma ident "@(#)c1_LinearScan_i486.cpp 1.8 07/06/18 14:25:22 JVM" #endif /* * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. @@ -702,7 +702,7 @@ case lir_div: { assert(left->is_fpu_register(), "must be"); assert(res->is_fpu_register(), "must be"); - assert(left->is_equivalent(res), "must be"); + assert(left->is_equal(res), "must be"); // either the left-hand or the right-hand side must be on top of stack // (if right is not a register, left must be on top) @@ -743,7 +743,7 @@ assert(left->is_fpu_register(), "must be"); assert(right->is_fpu_register(), "must be"); assert(res->is_fpu_register(), "must be"); - assert(left->is_equivalent(res), "must be"); + assert(left->is_equal(res), "must be"); // Must bring both operands to top of stack with following operand ordering: // * fpu stack before rem: ... right left diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_MacroAssembler_i486.cpp 1.57 07/05/17 15:46:25 JVM" +#pragma ident "@(#)c1_MacroAssembler_i486.cpp 1.58 07/06/19 09:08:04 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -54,7 +54,7 @@ // and mark it as unlocked orl(hdr, markOopDesc::unlocked_value); // save unlocked object header into the displaced header location on the stack - movl(Address(disp_hdr), hdr); + movl(Address(disp_hdr, 0), hdr); // test if object header is still the same (i.e. unlocked), and if so, store the // displaced header address in the object header - if it is not the same, get the // object header instead @@ -62,7 +62,8 @@ cmpxchg(disp_hdr, Address(obj, hdr_offset)); // if the object header was the same, we're done if (PrintBiasedLockingStatistics) { - cond_incl(Assembler::equal, Address((int) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::equal, + ExternalAddress((address)BiasedLocking::fast_path_entry_count_addr())); } jcc(Assembler::equal, done); // if the object header was not the same, it is now in the hdr register @@ -82,7 +83,7 @@ andl(hdr, aligned_mask - os::vm_page_size()); // for recursive locking, the result is zero => save it in the displaced header // location (NULL in the displaced hdr location indicates recursive locking) - movl(Address(disp_hdr), hdr); + movl(Address(disp_hdr, 0), hdr); // otherwise we don't care about the result and handle locking via runtime call jcc(Assembler::notZero, slow_case); // done @@ -106,7 +107,7 @@ } // load displaced header - movl(hdr, Address(disp_hdr)); + movl(hdr, Address(disp_hdr, 0)); // if the loaded hdr is NULL we had recursive locking testl(hdr, hdr); // if we had recursive locking, we are done @@ -260,9 +261,7 @@ if (DTraceAllocProbes) { assert(obj == eax, "must be"); - call(CAST_FROM_FN_PTR(address, - Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), - relocInfo::runtime_call_type); + call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id))); } verify_oop(obj); @@ -295,8 +294,7 @@ if (DTraceAllocProbes) { assert(obj == eax, "must be"); - call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), - relocInfo::runtime_call_type); + call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id))); } verify_oop(obj); @@ -313,7 +311,8 @@ cmpl(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); // if icache check fails, then jump to runtime routine // Note: RECEIVER must still contain the receiver! - jcc(Assembler::notEqual, SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); + jump_cc(Assembler::notEqual, + RuntimeAddress(SharedRuntime::get_ic_miss_stub())); assert(offset() - start_offset == 9, "check alignment in emit_method_entry"); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.hpp --- a/hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_MacroAssembler_i486.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_MacroAssembler_i486.hpp 1.34 07/05/05 17:04:13 JVM" +#pragma ident "@(#)c1_MacroAssembler_i486.hpp 1.35 07/06/19 09:08:04 JVM" #endif /* * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -98,7 +98,7 @@ // This helps us to track the esp changes compared to the entry esp (->_esp_offset) void push_jint (jint i) { _esp_offset++; pushl(i); } - void push_oop (jobject o) { _esp_offset++; pushl(o); } + void push_oop (jobject o) { _esp_offset++; pushoop(o); } void push_addr (Address a) { _esp_offset++; pushl(a); } void push_reg (Register r) { _esp_offset++; pushl(r); } void pop (Register r) { _esp_offset--; popl (r); assert(_esp_offset >= 0, "stack offset underflow"); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/c1_Runtime1_i486.cpp --- a/hotspot/src/cpu/i486/vm/c1_Runtime1_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/c1_Runtime1_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_Runtime1_i486.cpp 1.193 07/06/08 18:13:17 JVM" +#pragma ident "@(#)c1_Runtime1_i486.cpp 1.195 07/06/28 10:31:46 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -46,7 +46,7 @@ set_last_Java_frame(thread, noreg, ebp, NULL); // do the call - call(entry, relocInfo::runtime_call_type); + call(RuntimeAddress(entry)); int call_offset = offset(); // verify callee-saved register #ifdef ASSERT @@ -82,11 +82,11 @@ } if (frame_size() == no_frame_size) { leave(); - jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + jump(RuntimeAddress(StubRoutines::forward_exception_entry())); } else if (_stub_id == Runtime1::forward_exception_id) { should_not_reach_here(); } else { - jmp(Runtime1::entry_for(Runtime1::forward_exception_id), relocInfo::runtime_call_type); + jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); } bind(L); } @@ -312,9 +312,22 @@ __ fnsave(Address(esp, fpu_state_off * wordSize)); __ fwait(); - // restore FPUStatusWord that was initialized by fnsave instruction - __ fldenv(Address(esp, fpu_state_off * wordSize)); +#ifdef ASSERT + Label ok; + __ cmpw(Address(esp, fpu_state_off * wordSize), StubRoutines::fpu_cntrl_wrd_std()); + __ jccb(Assembler::equal, ok); + __ stop("corrupted control word detected"); + __ bind(ok); +#endif + // Reset the control word to guard against exceptions being unmasked + // since fstp_d can cause FPU stack underflow exceptions. Write it + // into the on stack copy and then reload that to make sure that the + // current and future values are correct. + __ movw(Address(esp, fpu_state_off * wordSize), StubRoutines::fpu_cntrl_wrd_std()); + __ frstor(Address(esp, fpu_state_off * wordSize)); + + // Save the FPU registers in de-opt-able form __ fstp_d(Address(esp, float_regs_as_doubles_off * BytesPerWord + 0)); __ fstp_d(Address(esp, float_regs_as_doubles_off * BytesPerWord + 8)); __ fstp_d(Address(esp, float_regs_as_doubles_off * BytesPerWord + 16)); @@ -612,7 +625,7 @@ // leave activation of nmethod __ leave(); // store return address (is on top of stack after leave) - __ movl(exception_pc, Address(esp)); + __ movl(exception_pc, Address(esp, 0)); __ verify_oop(exception_oop); @@ -675,7 +688,7 @@ __ pushl(thread); __ set_last_Java_frame(thread, noreg, ebp, NULL); // do the call - __ call(target, relocInfo::runtime_call_type); + __ call(RuntimeAddress(target)); OopMapSet* oop_maps = new OopMapSet(); oop_maps->add_gc_map(__ offset(), oop_map); // verify callee-saved register @@ -702,8 +715,8 @@ // exception pending => remove activation and forward to exception handler __ testl(eax, eax); // have we deoptimized? - __ jcc(Assembler::equal, Runtime1::entry_for(Runtime1::forward_exception_id), - relocInfo::runtime_call_type); + __ jump_cc(Assembler::equal, + RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); // the deopt blob expects exceptions in the special fields of // JavaThread, so copy and clear pending exception. @@ -721,7 +734,7 @@ #ifdef ASSERT // check that fields in JavaThread for exception oop and issuing pc are empty Label oop_empty; - __ cmpl(Address(thread, JavaThread::exception_oop_offset()), 0); + __ cmpoop(Address(thread, JavaThread::exception_oop_offset()), 0); __ jcc(Assembler::equal, oop_empty); __ stop("exception oop must be empty"); __ bind(oop_empty); @@ -746,7 +759,7 @@ // registers and must leave throwing pc on the stack. A patch may // have values live in registers so the entry point with the // exception in tls. - __ jmp(deopt_blob->unpack_with_exception_in_tls(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls())); __ bind(L); } @@ -764,7 +777,7 @@ // registers, pop all of our frame but the return address and jump to the deopt blob restore_live_registers(sasm); __ leave(); - __ jmp(deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); __ bind(cont); restore_live_registers(sasm); @@ -1295,8 +1308,7 @@ save_live_registers(sasm, 1); __ pushl(eax); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc))); __ popl(eax); restore_live_registers(sasm); @@ -1330,14 +1342,14 @@ __ jcc(Assembler::notZero, return0); __ bind(do_convert); - __ fnstcw(Address(esp)); - __ movzxw(eax, Address(esp)); + __ fnstcw(Address(esp, 0)); + __ movzxw(eax, Address(esp, 0)); __ orl(eax, 0xc00); __ movw(Address(esp, 2), eax); __ fldcw(Address(esp, 2)); __ fwait(); __ fistp_d(result_low_word); - __ fldcw(Address(esp)); + __ fldcw(Address(esp, 0)); __ fwait(); __ movl(eax, result_low_word); __ movl(edx, result_high_word); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/dump_i486.cpp --- a/hotspot/src/cpu/i486/vm/dump_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/dump_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)dump_i486.cpp 1.11 07/05/05 17:04:15 JVM" +#pragma ident "@(#)dump_i486.cpp 1.12 07/06/19 09:08:04 JVM" #endif /* * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -106,7 +106,9 @@ __ movl(ecx, eax); __ shrl(ecx, 8); // isolate vtable identifier. __ shll(ecx, LogBytesPerWord); - __ movl(edx, Address(ecx, (int)vtbl_list)); // get correct vtable address. + Address index(noreg, ecx, Address::times_1); + ExternalAddress vtbl((address)vtbl_list); + __ movptr(edx, ArrayAddress(vtbl, index)); // get correct vtable address. #ifdef WIN32 __ popl(ecx); // restore "this" #else diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/i486.ad --- a/hotspot/src/cpu/i486/vm/i486.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/i486.ad Thu Jul 05 23:47:33 2007 +0000 @@ -548,8 +548,7 @@ // If method sets FPU control word do it now if( C->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); - Address cntrl_addr_24 = Address((int)StubRoutines::addr_fpu_cntrl_wrd_24(), relocInfo::none); - masm.fldcw(cntrl_addr_24); + masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); } int framesize = C->frame_slots() << LogBytesPerInt; @@ -646,8 +645,7 @@ // If method set FPU control word, restore to standard control word if( C->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); - Address cntrl_addr_std = Address((int)StubRoutines::addr_fpu_cntrl_wrd_std(), relocInfo::none); - masm.fldcw(cntrl_addr_std); + masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } int framesize = C->frame_slots() << LogBytesPerInt; @@ -1150,9 +1148,9 @@ if (base == NULL) return; // CodeBuffer::expand failed // static stub relocation stores the instruction address of the call __ relocate(static_stub_Relocation::spec(mark), RELOC_IMM32); - __ movl(ebx, (jobject) NULL); // method is zapped till fixup time - __ jmp((address)-1, relocInfo::runtime_call_type); // jmp entry // static stub relocation also tags the methodOop in the code-stream. + __ movoop(ebx, (jobject)NULL); // method is zapped till fixup time + __ jump(RuntimeAddress((address)-1)); __ end_a_stub(); // Update current stubs pointer and restore code_end. @@ -1184,7 +1182,8 @@ uint code_size = cbuf.code_size(); #endif masm.cmpl(eax, Address(ecx, oopDesc::klass_offset_in_bytes())); - masm.jcc(Assembler::notEqual, SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); + masm.jump_cc(Assembler::notEqual, + RuntimeAddress(SharedRuntime::get_ic_miss_stub())); /* WARNING these NOPs are critical so that verified entry point is properly aligned for patching by NativeJump::patch_verified_entry() */ int nops_cnt = 2; @@ -1221,7 +1220,7 @@ __ start_a_stub(size_exception_handler()); if (base == NULL) return 0; // CodeBuffer::expand failed int offset = __ offset(); - __ jmp(OptoRuntime::exception_blob()->instructions_begin(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(OptoRuntime::exception_blob()->instructions_begin())); assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); __ end_a_stub(); return offset; @@ -1246,8 +1245,10 @@ __ start_a_stub(size_exception_handler()); if (base == NULL) return 0; // CodeBuffer::expand failed int offset = __ offset(); - __ pushl((intptr_t)__ pc(), relocInfo::internal_word_type); - __ jmp(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type); + InternalAddress here(__ pc()); + __ pushptr(here.addr()); + + __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); __ end_a_stub(); return offset; @@ -1678,8 +1679,7 @@ __ cmpl(Reax, Resi); __ jcc(Assembler::equal, hit); #ifndef PRODUCT - int* ps_counter = &SharedRuntime::_partial_subtype_ctr; - __ increment(Address((int) ps_counter, relocInfo::none)); + __ increment(ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr)); #endif //PRODUCT __ movl(Redi,Address(Resi,sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes())); __ movl(Recx,Address(Redi,arrayOopDesc::length_offset_in_bytes())); @@ -1756,8 +1756,7 @@ // If method sets FPU control word restore it here if( Compile::current()->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); - Address cntrl_addr_std = Address((int)StubRoutines::addr_fpu_cntrl_wrd_std(), relocInfo::none); - masm.fldcw(cntrl_addr_std); + masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } %} @@ -1765,8 +1764,7 @@ // If method sets FPU control word do it here also if( Compile::current()->in_24_bit_fp_mode() ) { MacroAssembler masm(&cbuf); - Address cntrl_addr_24 = Address((int)StubRoutines::addr_fpu_cntrl_wrd_24(), relocInfo::none); - masm.fldcw(cntrl_addr_24); + masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); } %} @@ -3245,12 +3243,12 @@ MacroAssembler masm(&cbuf); if (_counters != NULL) { - masm.atomic_incl(Address((int) _counters->total_entry_count_addr(), relocInfo::none)); + masm.atomic_incl(ExternalAddress((address) _counters->total_entry_count_addr())); } if (EmitSync & 1) { // set box->dhw = unused_mark (3) // Force all sync thru slow-path: slow_enter() and slow_exit() - masm.movl (Address(boxReg), intptr_t(markOopDesc::unused_mark())) ; + masm.movl (Address(boxReg, 0), intptr_t(markOopDesc::unused_mark())) ; masm.cmpl (esp, 0) ; } else if (EmitSync & 2) { @@ -3260,16 +3258,16 @@ masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); } - masm.movl (tmpReg, Address(objReg)) ; // fetch markword + masm.movl (tmpReg, Address(objReg, 0)) ; // fetch markword masm.orl (tmpReg, 0x1); - masm.movl (Address(boxReg), tmpReg); // Anticipate successful CAS + masm.movl (Address(boxReg, 0), tmpReg); // Anticipate successful CAS if (os::is_MP()) { masm.lock(); } - masm.cmpxchg(boxReg, Address(objReg)); // Updates tmpReg + masm.cmpxchg(boxReg, Address(objReg, 0)); // Updates tmpReg masm.jcc(Assembler::equal, DONE_LABEL); // Recursive locking masm.subl(tmpReg, esp); masm.andl(tmpReg, 0xFFFFF003 ); - masm.movl(Address(boxReg), tmpReg); + masm.movl(Address(boxReg, 0), tmpReg); masm.bind(DONE_LABEL) ; } else { // Possible cases that we'll encounter in fast_lock @@ -3301,26 +3299,28 @@ masm.biased_locking_enter(boxReg, objReg, tmpReg, scrReg, false, DONE_LABEL, NULL, _counters); } - masm.movl (tmpReg, Address(objReg)) ; // [FETCH] + masm.movl (tmpReg, Address(objReg, 0)) ; // [FETCH] masm.testl (tmpReg, 0x02) ; // Inflated v (Stack-locked or neutral) masm.jccb (Assembler::notZero, IsInflated) ; // Attempt stack-locking ... masm.orl (tmpReg, 0x1); - masm.movl (Address(boxReg), tmpReg); // Anticipate successful CAS + masm.movl (Address(boxReg, 0), tmpReg); // Anticipate successful CAS if (os::is_MP()) { masm.lock(); } - masm.cmpxchg(boxReg, Address(objReg)); // Updates tmpReg + masm.cmpxchg(boxReg, Address(objReg, 0)); // Updates tmpReg if (_counters != NULL) { - masm.cond_incl(Assembler::equal, Address((int) _counters->fast_path_entry_count_addr(), relocInfo::none)); + masm.cond_inc32(Assembler::equal, + ExternalAddress((address)_counters->fast_path_entry_count_addr())); } masm.jccb (Assembler::equal, DONE_LABEL); // Recursive locking masm.subl(tmpReg, esp); masm.andl(tmpReg, 0xFFFFF003 ); - masm.movl(Address(boxReg), tmpReg); + masm.movl(Address(boxReg, 0), tmpReg); if (_counters != NULL) { - masm.cond_incl(Assembler::equal, Address((int) _counters->fast_path_entry_count_addr(), relocInfo::none)); + masm.cond_inc32(Assembler::equal, + ExternalAddress((address)_counters->fast_path_entry_count_addr())); } masm.jmp (DONE_LABEL) ; @@ -3350,7 +3350,7 @@ // additional latency as we have another ST in the store buffer that must drain. if (EmitSync & 8192) { - masm.movl (Address(boxReg), 3) ; // results in ST-before-CAS penalty + masm.movl (Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty masm.get_thread (scrReg) ; masm.movl (boxReg, tmpReg); // consider: LEA box, [tmp-2] masm.movl (tmpReg, 0); // consider: xor vs mov @@ -3391,7 +3391,7 @@ // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. if (os::is_MP()) { masm.lock(); } masm.cmpxchg (scrReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)) ; - masm.movl (Address(scrReg), 3) ; // box->_displaced_header = 3 + masm.movl (Address(scrReg, 0), 3) ; // box->_displaced_header = 3 masm.jccb (Assembler::notZero, DONE_LABEL) ; masm.get_thread (scrReg) ; // beware: clobbers ICCs masm.movl (Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2), scrReg) ; @@ -3405,7 +3405,7 @@ // Invariant: m->_recursions should already be 0, so we don't need to explicitly set it. // Intentional fall-through into DONE_LABEL ... } else { - masm.movl (Address(boxReg), 3) ; // results in ST-before-CAS penalty + masm.movl (Address(boxReg, 0), 3) ; // results in ST-before-CAS penalty masm.movl (boxReg, tmpReg) ; // Using a prefetchw helps avoid later RTS->RTO upgrades and cache probes @@ -3511,11 +3511,11 @@ masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); } // classic stack-locking code ... - masm.movl (tmpReg, Address(boxReg)) ; + masm.movl (tmpReg, Address(boxReg, 0)) ; masm.testl (tmpReg, tmpReg) ; masm.jcc (Assembler::zero, DONE_LABEL) ; if (os::is_MP()) { masm.lock(); } - masm.cmpxchg(tmpReg, Address(objReg)); // Uses EAX which is box + masm.cmpxchg(tmpReg, Address(objReg, 0)); // Uses EAX which is box masm.bind(DONE_LABEL); } else { Label DONE_LABEL, Stacked, CheckSucc, Inflated ; @@ -3526,8 +3526,8 @@ masm.biased_locking_exit(objReg, tmpReg, DONE_LABEL); } - masm.cmpl (Address(boxReg), 0) ; // Examine the displaced header - masm.movl (tmpReg, Address(objReg)) ; // Examine the object's markword + masm.cmpl (Address(boxReg, 0), 0) ; // Examine the displaced header + masm.movl (tmpReg, Address(objReg, 0)) ; // Examine the object's markword masm.jccb (Assembler::zero, DONE_LABEL) ; // 0 indicates recursive stack-lock masm.testl (tmpReg, 0x02) ; // Inflated? @@ -3642,7 +3642,7 @@ masm.emit_raw (0xAE) ; masm.emit_raw (0xF0) ; } else { - masm.lock () ; masm.addl (Address(esp), 0) ; + masm.lock () ; masm.addl (Address(esp, 0), 0) ; } } // Ratify _succ remains non-null @@ -3675,9 +3675,9 @@ // Try to reset the header to displaced header. // The "box" value on the stack is stable, so we can reload // and be assured we observe the same value as above. - masm.movl (tmpReg, Address(boxReg)) ; + masm.movl (tmpReg, Address(boxReg, 0)) ; if (os::is_MP()) { masm.lock(); } - masm.cmpxchg(tmpReg, Address(objReg)); // Uses EAX which is box + masm.cmpxchg(tmpReg, Address(objReg, 0)); // Uses EAX which is box // Intention fall-thru into DONE_LABEL @@ -3744,8 +3744,8 @@ masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL); // Load first characters - masm.load_unsigned_word(ecx, Address(ebx)); - masm.load_unsigned_word(edi, Address(eax)); + masm.load_unsigned_word(ecx, Address(ebx, 0)); + masm.load_unsigned_word(edi, Address(eax, 0)); // Compare first characters masm.subl(ecx, edi); @@ -3761,7 +3761,7 @@ masm.jcc(Assembler::notEqual, LSkip2); // Check if the length difference is zero (from stack) - masm.cmpl(Address(esp), 0x0); + masm.cmpl(Address(esp, 0), 0x0); masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL); // Strings might not be equivalent @@ -9207,7 +9207,8 @@ match(Set dst (NegD dst)); format %{ "XORPD $dst,[0x8000000000000000]\t# CHS D by sign flipping" %} ins_encode %{ - __ xorpd($dst$$XMMRegister, Address((int)double_signflip_pool, relocInfo::none)); + __ xorpd($dst$$XMMRegister, + ExternalAddress((address)double_signflip_pool)); %} ins_pipe( pipe_slow ); %} @@ -11803,7 +11804,9 @@ address table_base = __ address_table_constant(_index2label); // Jump to Address(table_base + switch_reg) - __ jmp(Address(noreg, $switch_val$$Register, Address::times_1, relocInfo::internal_word_type, (int)table_base)); + InternalAddress table(table_base); + Address index(noreg, $switch_val$$Register, Address::times_1); + __ jump(ArrayAddress(table, index)); %} ins_pc_relative(1); ins_pipe(pipe_jmp); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/icBuffer_i486.cpp --- a/hotspot/src/cpu/i486/vm/icBuffer_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/icBuffer_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)icBuffer_i486.cpp 1.23 07/05/05 17:04:16 JVM" +#pragma ident "@(#)icBuffer_i486.cpp 1.24 07/06/19 09:08:06 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -43,8 +43,8 @@ // (1) the oop is old (i.e., doesn't matter for scavenges) // (2) these ICStubs are removed *before* a GC happens, so the roots disappear assert(cached_oop == NULL || cached_oop->is_perm(), "must be perm oop"); - masm->movl(eax, (int)cached_oop); - masm->jmp (entry_point, relocInfo::none); + masm->lea(eax, OopAddress((address) cached_oop)); + masm->jump(ExternalAddress(entry_point)); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/interp_masm_i486.cpp --- a/hotspot/src/cpu/i486/vm/interp_masm_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/interp_masm_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interp_masm_i486.cpp 1.167 07/06/08 18:13:19 JVM" +#pragma ident "@(#)interp_masm_i486.cpp 1.168 07/06/19 09:08:07 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -111,7 +111,7 @@ // Call Interpreter::remove_activation_preserving_args_entry() to get the // address of the same-named entrypoint in the generated interpreter code. call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); - jmp(eax, relocInfo::runtime_call_type); + jmp(eax); bind(L); get_thread(java_thread); } @@ -168,7 +168,7 @@ movl(tmp, Address(java_thread, JavaThread::jvmti_thread_state_offset())); pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); - jmp(eax, relocInfo::runtime_call_type); + jmp(eax); bind(L); get_thread(java_thread); } @@ -259,16 +259,16 @@ void InterpreterMacroAssembler::f2ieee() { if (IEEEPrecision) { - fstp_s(Address(esp)); - fld_s(Address(esp)); + fstp_s(Address(esp, 0)); + fld_s(Address(esp, 0)); } } void InterpreterMacroAssembler::d2ieee() { if (IEEEPrecision) { - fstp_d(Address(esp)); - fld_d(Address(esp)); + fstp_d(Address(esp, 0)); + fld_d(Address(esp, 0)); } } @@ -282,7 +282,7 @@ jcc(Assembler::equal, okay); // Also compare if the stack value is zero, then the tag might // not have been set coming from deopt. - cmpl(Address(esp), 0); + cmpl(Address(esp, 0), 0); jcc(Assembler::equal, okay); stop("Java Expression stack tag value is bad"); bind(okay); @@ -319,7 +319,7 @@ void InterpreterMacroAssembler::pop_f() { debug_only(verify_stack_tag(frame::TagValue)); - fld_s(Address(esp)); + fld_s(Address(esp, 0)); addl(esp, 1 * wordSize); if (TaggedStackInterpreter) addl(esp, 1 * wordSize); } @@ -327,7 +327,7 @@ void InterpreterMacroAssembler::pop_d() { // Write double to stack contiguously and load into ST0 pop_dtos_to_esp(); - fld_d(Address(esp)); + fld_d(Address(esp, 0)); addl(esp, 2 * wordSize); } @@ -399,7 +399,7 @@ if (TaggedStackInterpreter) pushl(frame::TagValue); // Do not schedule for no AGI! Never write beyond esp! subl(esp, 1 * wordSize); - fstp_s(Address(esp)); + fstp_s(Address(esp, 0)); } void InterpreterMacroAssembler::push_d(Register r) { @@ -411,7 +411,7 @@ // low pushl(frame::TagValue); subl(esp, 3 * wordSize); - fstp_d(Address(esp)); + fstp_d(Address(esp, 0)); // move high word up to slot n-1 movl(r, Address(esp, 1*wordSize)); movl(Address(esp, 2*wordSize), r); @@ -420,7 +420,7 @@ } else { // Do not schedule for no AGI! Never write beyond esp! subl(esp, 2 * wordSize); - fstp_d(Address(esp)); + fstp_d(Address(esp, 0)); } } @@ -631,7 +631,10 @@ bind(L); } if (verifyoop) verify_oop(eax, state); - jmp(Address(noreg, ebx, Address::times_4, (int)table)); + Address index(noreg, ebx, Address::times_4); + ExternalAddress tbl((address)table); + ArrayAddress dispatch(tbl, index); + jump(dispatch); } @@ -660,7 +663,7 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { // load current bytecode - load_unsigned_byte(ebx, Address(esi)); + load_unsigned_byte(ebx, Address(esi, 0)); dispatch_base(state, table); } @@ -858,7 +861,7 @@ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %eax - orl(swap_reg, Address(obj_reg)); + orl(swap_reg, Address(obj_reg, 0)); // Save (object->mark() | 1) into BasicLock's displaced header movl(Address(lock_reg, mark_offset), swap_reg); @@ -867,9 +870,10 @@ if (os::is_MP()) { lock(); } - cmpxchg(lock_reg, Address(obj_reg)); + cmpxchg(lock_reg, Address(obj_reg, 0)); if (PrintBiasedLockingStatistics) { - cond_incl(Assembler::zero, Address((int) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); } jcc(Assembler::zero, done); @@ -889,7 +893,8 @@ movl(Address(lock_reg, mark_offset), swap_reg); if (PrintBiasedLockingStatistics) { - cond_incl(Assembler::zero, Address((int) BiasedLocking::fast_path_entry_count_addr(), relocInfo::none)); + cond_inc32(Assembler::zero, + ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); } jcc(Assembler::zero, done); @@ -948,7 +953,7 @@ // Atomic swap back the old header if (os::is_MP()) lock(); - cmpxchg(header_reg, Address(obj_reg)); + cmpxchg(header_reg, Address(obj_reg, 0)); // zero for recursive case jcc(Assembler::zero, done); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/interpreterRT_i486.cpp --- a/hotspot/src/cpu/i486/vm/interpreterRT_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/interpreterRT_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interpreterRT_i486.cpp 1.54 07/05/05 17:04:16 JVM" +#pragma ident "@(#)interpreterRT_i486.cpp 1.55 07/06/19 09:08:07 JVM" #endif /* * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -55,7 +55,8 @@ // generate code to handle arguments iterate(fingerprint); // return result handler - __ movl(eax, (int)AbstractInterpreter::result_handler(method()->result_type())); + __ lea(eax, + ExternalAddress((address)AbstractInterpreter::result_handler(method()->result_type()))); // return __ ret(0); __ flush(); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/interpreter_i486.cpp --- a/hotspot/src/cpu/i486/vm/interpreter_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/interpreter_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)interpreter_i486.cpp 1.372 07/06/08 18:13:19 JVM" +#pragma ident "@(#)interpreter_i486.cpp 1.374 07/06/28 10:31:45 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -76,7 +76,7 @@ __ empty_FPU_stack(); // setup parameters // ??? convention: expect aberrant index in register ebx - __ movl(eax, (int)name); + __ lea(eax, ExternalAddress((address)name)); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ArrayIndexOutOfBoundsException), eax, ebx); return entry; } @@ -107,15 +107,19 @@ __ empty_expression_stack(); __ empty_FPU_stack(); // setup parameters - __ movl(eax, (int)name); + __ lea(eax, ExternalAddress((address)name)); if (pass_oop) { __ call_VM(eax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_klass_exception), eax, ebx); } else { - __ movl(ebx, (int)message); + if (message != NULL) { + __ lea(ebx, ExternalAddress((address)message)); + } else { + __ movl(ebx, NULL_WORD); + } __ call_VM(eax, CAST_FROM_FN_PTR(address, InterpreterRuntime::create_exception), eax, ebx); } // throw exception - __ jmp(Interpreter::throw_exception_entry(), relocInfo::none); + __ jump(ExternalAddress(Interpreter::throw_exception_entry())); return entry; } @@ -277,7 +281,7 @@ __ movdbl(xmm0, Address(esp, 0)); } else { // restore ST0 - __ fld_d(Address(esp)); + __ fld_d(Address(esp, 0)); } // and pop the temp __ addl(esp, 2 * wordSize); @@ -353,14 +357,16 @@ if (ProfileInterpreter && profile_method != NULL) { // Test to see if we should create a method data oop - __ cmpl(ecx, Address(int(&InvocationCounter::InterpreterProfileLimit), relocInfo::none)); + __ cmp32(ecx, + ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit)); __ jcc(Assembler::less, *profile_method_continue); // if no method data exists, go to profile_method __ test_method_data_pointer(eax, *profile_method); } - __ cmpl(ecx, Address(int(&InvocationCounter::InterpreterInvocationLimit), relocInfo::none)); + __ cmp32(ecx, + ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit)); __ jcc(Assembler::aboveEqual, *overflow); } @@ -477,7 +483,7 @@ __ popl(esi); // get saved bcp __ popl(eax); // get return address - __ jmp(Interpreter::throw_StackOverflowError_entry(), relocInfo::runtime_call_type); + __ jump(ExternalAddress(Interpreter::throw_StackOverflowError_entry())); // all done with frame size check __ bind(after_frame_check_pop); @@ -561,7 +567,7 @@ __ pushl(esi); // set bcp } __ pushl(0); // reserve word for pointer to expression stack bottom - __ movl(Address(esp), esp); // set expression stack bottom + __ movl(Address(esp, 0), esp); // set expression stack bottom } @@ -622,7 +628,7 @@ if (TaggedStackInterpreter) { __ pushl(Address(esp, 3*wordSize)); // push hi (and note esp -= wordSize) __ pushl(Address(esp, 2*wordSize)); // push lo - __ fld_d(Address(esp)); // get double in ST0 + __ fld_d(Address(esp, 0)); // get double in ST0 __ addl(esp, 2*wordSize); } else { __ fld_d(Address(esp, 1*wordSize)); @@ -716,9 +722,11 @@ address entry_point = __ pc(); + // If we need a safepoint check, generate full interpreter entry. Label slow_path; - __ cmpl(Address((int)SafepointSynchronize::address_of_state(), - relocInfo::none), SafepointSynchronize::_not_synchronized); + ExternalAddress state(SafepointSynchronize::address_of_state()); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); __ jcc(Assembler::notEqual, slow_path); // do nothing for empty methods (do not even increment invocation counter) @@ -749,8 +757,11 @@ // do fastpath for resolved accessor methods if (UseFastAccessorMethods) { Label slow_path; - __ cmpl(Address((int)SafepointSynchronize::address_of_state(), - relocInfo::none), SafepointSynchronize::_not_synchronized); + // If we need a safepoint check, generate full interpreter entry. + ExternalAddress state(SafepointSynchronize::address_of_state()); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); + __ jcc(Assembler::notEqual, slow_path); // Code: _aload_0, _(i|a)getfield, _(i|a)return or any rewrites thereof; parameter size = 1 // Note: We can only use this code if the getfield has been resolved @@ -1023,7 +1034,7 @@ // However, large signatures cannot be cached and are generated // each time here. The slow-path generator will blow EBX // sometime, so we must reload it after the call. - __ call(t, relocInfo::none); + __ call(t); __ get_method(method); // slow path call blows EBX on DevStudio 5.0 // result handler is in eax @@ -1051,7 +1062,8 @@ // get native function entry point { Label L; __ movl(eax, Address(method, methodOopDesc::native_function_offset())); - __ cmpl(eax, (int)SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + ExternalAddress unsatisfied(SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); + __ cmp32(eax, unsatisfied.addr()); __ jcc(Assembler::notEqual, L); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), method); __ get_method(method); @@ -1063,7 +1075,7 @@ // pass JNIEnv __ get_thread(thread); __ leal(t, Address(thread, JavaThread::jni_environment_offset())); - __ movl(Address(esp), t); + __ movl(Address(esp, 0), t); // set_last_Java_frame_before_call // It is enough that the pc() @@ -1083,7 +1095,7 @@ // Change state to native __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); - __ call(eax, relocInfo::none); + __ call(eax); // result potentially in edx:eax or ST0 @@ -1091,18 +1103,17 @@ // or verify that it wasn't changed. if (VM_Version::supports_sse()) { if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(Address((int) StubRoutines::addr_mxcsr_std(), relocInfo::none)); + __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std())); } else if (CheckJNICalls ) { - __ call(CAST_FROM_FN_PTR(address, StubRoutines::i486::verify_mxcsr_entry()), - relocInfo::runtime_call_type); + __ call(RuntimeAddress(StubRoutines::i486::verify_mxcsr_entry())); } } // Either restore the x87 floating pointer control word after returning // from the JNI call or verify that it wasn't changed. if (CheckJNICalls) { - __ call(StubRoutines::i486::verify_fpu_cntrl_wrd_entry(), relocInfo::runtime_call_type); + __ call(RuntimeAddress(StubRoutines::i486::verify_fpu_cntrl_wrd_entry())); } // save potential result in ST(0) & edx:eax @@ -1117,11 +1128,13 @@ { Label L; Label push_double; - __ cmpl(Address(ebp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), - (int)AbstractInterpreter::result_handler(T_FLOAT)); + ExternalAddress float_handler(AbstractInterpreter::result_handler(T_FLOAT)); + ExternalAddress double_handler(AbstractInterpreter::result_handler(T_DOUBLE)); + __ cmpptr(Address(ebp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), + float_handler.addr()); __ jcc(Assembler::equal, push_double); - __ cmpl(Address(ebp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), - (int)AbstractInterpreter::result_handler(T_DOUBLE)); + __ cmpptr(Address(ebp, (frame::interpreter_frame_oop_temp_offset + 1)*wordSize), + double_handler.addr()); __ jcc(Assembler::notEqual, L); __ bind(push_double); __ push(dtos); @@ -1144,11 +1157,16 @@ } } + if (AlwaysRestoreFPU) { + // Make sure the control word is correct. + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } // check for safepoint operation in progress and/or pending suspend requests { Label Continue; - __ cmpl(Address((int)SafepointSynchronize::address_of_state(), relocInfo::none), SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress(SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); Label L; __ jcc(Assembler::notEqual, L); @@ -1163,7 +1181,8 @@ // by hand. // __ pushl(thread); - __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, + JavaThread::check_special_condition_for_native_trans))); __ increment(esp, wordSize); __ get_thread(thread); @@ -1182,15 +1201,16 @@ // If result was an oop then unbox and save it in the frame { Label L; Label no_oop, store_result; - __ cmpl(Address(ebp, frame::interpreter_frame_result_handler_offset*wordSize), - (int)AbstractInterpreter::result_handler(T_OBJECT)); + ExternalAddress handler(AbstractInterpreter::result_handler(T_OBJECT)); + __ cmpptr(Address(ebp, frame::interpreter_frame_result_handler_offset*wordSize), + handler.addr()); __ jcc(Assembler::notEqual, no_oop); - __ cmpl(Address(esp), NULL_WORD); + __ cmpl(Address(esp, 0), NULL_WORD); __ pop(ltos); __ testl(eax, eax); __ jcc(Assembler::zero, store_result); // unbox - __ movl(eax, Address(eax)); + __ movl(eax, Address(eax, 0)); __ bind(store_result); __ movl(Address(ebp, (frame::interpreter_frame_oop_temp_offset)*wordSize), eax); // keep stack depth as expected by pushing oop which will eventually be discarded @@ -1204,7 +1224,7 @@ __ jcc(Assembler::notEqual, no_reguard); __ pushad(); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ popad(); __ bind(no_reguard); @@ -1267,7 +1287,7 @@ // restore potential result in edx:eax, call result handler to restore potential result in ST0 & handle result __ pop(ltos); __ movl(t, Address(ebp, frame::interpreter_frame_result_handler_offset*wordSize)); - __ call(t, relocInfo::none); + __ call(t); // remove activation __ movl(t, Address(ebp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp @@ -1914,21 +1934,22 @@ void AbstractInterpreterGenerator::count_bytecode() { - __ increment(Address((int)&BytecodeCounter::_counter_value, relocInfo::none)); + __ increment(ExternalAddress((address) &BytecodeCounter::_counter_value)); } void AbstractInterpreterGenerator::histogram_bytecode(Template* t) { - __ increment(Address((int)&BytecodeHistogram::_counters[t->bytecode()], relocInfo::none)); + __ increment(ExternalAddress((address) &BytecodeHistogram::_counters[t->bytecode()])); } void AbstractInterpreterGenerator::histogram_bytecode_pair(Template* t) { - __ movl(ebx, Address((int)&BytecodePairHistogram::_index, relocInfo::none)); + __ mov32(ExternalAddress((address) &BytecodePairHistogram::_index), ebx); __ shrl(ebx, BytecodePairHistogram::log2_number_of_codes); __ orl(ebx, ((int)t->bytecode()) << BytecodePairHistogram::log2_number_of_codes); - __ movl(Address((int)&BytecodePairHistogram::_index, relocInfo::none), ebx); - __ increment(Address(noreg, ebx, Address::times_4, (int)BytecodePairHistogram::_counters)); + ExternalAddress table((address) BytecodePairHistogram::_counters); + Address index(noreg, ebx, Address::times_4); + __ increment(ArrayAddress(table, index)); } @@ -1936,15 +1957,16 @@ // Call a little run-time stub to avoid blow-up for each bytecode. // The run-time runtime saves the right registers, depending on // the tosca in-state for the given template. - address entry = Interpreter::trace_code(t->tos_in()); - assert(entry != NULL, "entry must have been generated"); - __ call(entry, relocInfo::none); + assert(Interpreter::trace_code(t->tos_in()) != NULL, + "entry must have been generated"); + __ call(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); } void AbstractInterpreterGenerator::stop_interpreter_at() { Label L; - __ cmpl(Address(int(&BytecodeCounter::_counter_value), relocInfo::none), StopInterpreterAt); + __ cmp32(ExternalAddress((address) &BytecodeCounter::_counter_value), + StopInterpreterAt); __ jcc(Assembler::notEqual, L); __ int3(); __ bind(L); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/jniFastGetField_i486.cpp --- a/hotspot/src/cpu/i486/vm/jniFastGetField_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/jniFastGetField_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)jniFastGetField_i486.cpp 1.10 07/05/05 17:04:18 JVM" +#pragma ident "@(#)jniFastGetField_i486.cpp 1.11 07/06/19 09:08:08 JVM" #endif /* * Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -70,9 +70,8 @@ // obj 2 // jfieldID 3 - address counter_addr = SafepointSynchronize::safepoint_counter_addr(); - Address ca((int)counter_addr, relocInfo::none); - __ movl (ecx, ca); + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); + __ mov32 (ecx, counter); __ testb (ecx, 1); __ jcc (Assembler::notZero, slow); if (os::is_MP()) { @@ -85,7 +84,7 @@ __ movl (edx, Address(esp, 2*wordSize)); // obj } __ movl (eax, Address(esp, 3*wordSize)); // jfieldID - __ movl (edx, Address(edx)); // *obj + __ movl (edx, Address(edx, 0)); // *obj __ shrl (eax, 2); // offset assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); @@ -101,16 +100,16 @@ Address ca1; if (os::is_MP()) { - __ movl (edx, eax); - __ xorl (edx, (int)counter_addr); - __ xorl (edx, eax); - ca1 = Address(edx); // ca1 is the same as ca because - // eax ^ counter_addr ^ eax = address - // ca1 is data dependent on eax. + __ lea(edx, counter); + __ xorl(edx, eax); + __ xorl(edx, eax); + __ cmp32(ecx, Address(edx, 0)); + // ca1 is the same as ca because + // eax ^ counter_addr ^ eax = address + // ca1 is data dependent on eax. } else { - ca1 = ca; + __ cmp32(ecx, counter); } - __ cmpl (ecx, ca1); __ jcc (Assembler::notEqual, slow); #ifndef _WINDOWS @@ -131,7 +130,7 @@ case T_INT: slow_case_addr = jni_GetIntField_addr(); } // tail call - __ jmp (slow_case_addr, relocInfo::none); + __ jump (ExternalAddress(slow_case_addr)); __ flush (); @@ -186,10 +185,10 @@ // obj 3 // jfieldID 4 - address counter_addr = SafepointSynchronize::safepoint_counter_addr(); - Address ca((int)counter_addr, relocInfo::none); + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); + __ pushl (esi); - __ movl (ecx, ca); + __ mov32 (ecx, counter); __ testb (ecx, 1); __ jcc (Assembler::notZero, slow); if (os::is_MP()) { @@ -202,7 +201,7 @@ __ movl (edx, Address(esp, 3*wordSize)); // obj } __ movl (esi, Address(esp, 4*wordSize)); // jfieldID - __ movl (edx, Address(edx)); // *obj + __ movl (edx, Address(edx, 0)); // *obj __ shrl (esi, 2); // offset assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); @@ -211,20 +210,19 @@ speculative_load_pclist[count] = __ pc(); __ movl (edx, Address(edx, esi, Address::times_1, 4)); - Address ca1; if (os::is_MP()) { - __ movl (esi, eax); + __ lea (esi, counter); __ xorl (esi, edx); - __ xorl (esi, (int)counter_addr); __ xorl (esi, eax); __ xorl (esi, edx); - ca1 = Address(esi); // ca1 is the same as ca because - // eax ^ edx ^ counter_addr ^ eax ^ edx = address - // ca1 is data dependent on both eax and edx. + __ xorl (esi, eax); + __ cmp32(ecx, Address(esi, 0)); + // ca1 is the same as ca because + // eax ^ edx ^ counter_addr ^ eax ^ edx = address + // ca1 is data dependent on both eax and edx. } else { - ca1 = ca; + __ cmp32(ecx, counter); } - __ cmpl (ecx, ca1); __ jcc (Assembler::notEqual, slow); __ popl (esi); @@ -242,7 +240,7 @@ __ popl (esi); address slow_case_addr = jni_GetLongField_addr();; // tail call - __ jmp (slow_case_addr, relocInfo::none); + __ jump (ExternalAddress(slow_case_addr)); __ flush (); @@ -275,9 +273,9 @@ // obj 2 // jfieldID 3 - address counter_addr = SafepointSynchronize::safepoint_counter_addr(); - Address ca((int)counter_addr, relocInfo::none); - __ movl (ecx, ca); + ExternalAddress counter(SafepointSynchronize::safepoint_counter_addr()); + + __ mov32 (ecx, counter); __ testb (ecx, 1); __ jcc (Assembler::notZero, slow); if (os::is_MP()) { @@ -290,7 +288,7 @@ __ movl (edx, Address(esp, 2*wordSize)); // obj } __ movl (eax, Address(esp, 3*wordSize)); // jfieldID - __ movl (edx, Address(edx)); // *obj + __ movl (edx, Address(edx, 0)); // *obj __ shrl (eax, 2); // offset assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); @@ -304,18 +302,17 @@ Address ca1; if (os::is_MP()) { __ fst_s (Address(esp, -4)); + __ lea(edx, counter); __ movl (eax, Address(esp, -4)); - __ movl (edx, eax); - __ xorl (edx, (int)counter_addr); - __ xorl (edx, eax); - ca1 = Address(edx); // ca1 is the same as ca because + __ xorl(edx, eax); + __ xorl(edx, eax); + __ cmp32(ecx, Address(edx, 0)); // eax ^ counter_addr ^ eax = address // ca1 is data dependent on the field // access. } else { - ca1 = ca; + __ cmp32(ecx, counter); } - __ cmpl (ecx, ca1); __ jcc (Assembler::notEqual, slow_with_pop); #ifndef _WINDOWS @@ -338,7 +335,7 @@ default: ShouldNotReachHere(); } // tail call - __ jmp (slow_case_addr, relocInfo::none); + __ jump (ExternalAddress(slow_case_addr)); __ flush (); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/runtime_i486.cpp --- a/hotspot/src/cpu/i486/vm/runtime_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/runtime_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)runtime_i486.cpp 1.110 07/05/05 17:04:19 JVM" +#pragma ident "@(#)runtime_i486.cpp 1.111 07/06/19 09:08:08 JVM" #endif /* * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -102,7 +102,8 @@ // __ movl(Address(esp, thread_off * wordSize), ecx); // Thread is first argument __ set_last_Java_frame(ecx, noreg, noreg, NULL); - __ call(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C), relocInfo::runtime_call_type); + + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C))); // No registers to map, ebp is known implicitly oop_maps->add_gc_map( __ pc() - start, new OopMap( framesize, 0 )); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/sharedRuntime_i486.cpp --- a/hotspot/src/cpu/i486/vm/sharedRuntime_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/sharedRuntime_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)sharedRuntime_i486.cpp 1.51 07/06/08 18:13:19 JVM" +#pragma ident "@(#)sharedRuntime_i486.cpp 1.53 07/06/28 10:31:45 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -84,7 +84,8 @@ public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); + static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, + int* total_frame_words, bool verify_fpu = true); static void restore_live_registers(MacroAssembler* masm); static int eax_offset() { return eax_off; } @@ -108,7 +109,8 @@ }; -OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, + int* total_frame_words, bool verify_fpu) { int frame_size_in_bytes = (reg_save_size + additional_frame_words) * wordSize; int frame_words = frame_size_in_bytes / wordSize; @@ -126,10 +128,38 @@ __ pushfd(); __ subl(esp,FPU_regs_live*sizeof(jdouble)); // Push FPU registers space __ push_FPU_state(); // Save FPU state & init - __ frstor(Address(esp)); // Restore state (but keep stack copy) + + if (verify_fpu) { + // Some stubs may have non standard FPU control word settings so + // only check and reset the value when it required to be the + // standard value. The safepoint blob in particular can be used + // in methods which are using the 24 bit control word for + // optimized float math. + +#ifdef ASSERT + // Make sure the control word has the expected value + Label ok; + __ cmpw(Address(esp, 0), StubRoutines::fpu_cntrl_wrd_std()); + __ jccb(Assembler::equal, ok); + __ stop("corrupted control word detected"); + __ bind(ok); +#endif + + // Reset the control word to guard against exceptions being unmasked + // since fstp_d can cause FPU stack underflow exceptions. Write it + // into the on stack copy and then reload that to make sure that the + // current and future values are correct. + __ movw(Address(esp, 0), StubRoutines::fpu_cntrl_wrd_std()); + } + + __ frstor(Address(esp, 0)); + if (!verify_fpu) { + // Set the control word so that exceptions are masked for the + // following code. + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } // Save the FPU registers in de-opt-able form - __ fstp_d(Address(esp, st0_off*wordSize)); // st(0) __ fstp_d(Address(esp, st1_off*wordSize)); // st(1) __ fstp_d(Address(esp, st2_off*wordSize)); // st(2) @@ -260,7 +290,7 @@ // restoration so only result registers need to be restored here. // - __ frstor(Address(esp)); // Restore fpu state + __ frstor(Address(esp, 0)); // Restore fpu state // Recover XMM & FPU state if( UseSSE == 1 ) { @@ -453,7 +483,7 @@ // VM needs target method __ pushl(ebx); __ verify_oop(ebx); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite))); __ addl(esp, 2*wordSize); if (UseSSE == 1) { @@ -657,7 +687,7 @@ // code goes non-entrant while we get args ready. // Pick up the return address - __ movl(eax, Address(esp)); + __ movl(eax, Address(esp, 0)); // If UseSSE >= 2 then no cleanup is needed on the return to the // interpreter so skip fixing up the return entry point unless @@ -667,10 +697,11 @@ // If we were called from the call stub we need to do a little bit different // cleanup than if the interpreter returned to the call stub. - __ cmpl(eax, (int)StubRoutines::_call_stub_return_address); + ExternalAddress stub_return_address(StubRoutines::_call_stub_return_address); + __ cmp32(eax, stub_return_address.addr()); __ jcc(Assembler::notEqual, chk_int); assert(StubRoutines::i486::get_call_stub_compiled_return() != NULL, "must be set"); - __ movl(eax, (intptr_t) StubRoutines::i486::get_call_stub_compiled_return()); + __ lea(eax, ExternalAddress(StubRoutines::i486::get_call_stub_compiled_return())); __ jmp(skip); // It must be the interpreter since we never get here via a c2i (unlike Azul) @@ -850,7 +881,6 @@ Register temp = ebx; { - address ic_miss = SharedRuntime::get_ic_miss_stub(); Label missed; @@ -868,7 +898,7 @@ __ jcc(Assembler::equal, skip_fixup); __ bind(missed); - __ jmp(ic_miss, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); } address c2i_entry = __ pc(); @@ -1227,7 +1257,6 @@ intptr_t start = (intptr_t)__ pc(); // First thing make an ic check to see if we should even be here - address ic_miss = SharedRuntime::get_ic_miss_stub(); // We are free to use all registers as temps without saving them and // restoring them except ebp. ebp is the only callee save register @@ -1243,7 +1272,8 @@ __ verify_oop(receiver); __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); __ jcc(Assembler::equal, hit); - __ jmp(ic_miss, relocInfo::runtime_call_type); + + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); // verified entry must be aligned for code patching. // and the first 5 bytes must be in the same cache line @@ -1419,7 +1449,7 @@ if (method->is_static()) { // load opp into a register - __ movl(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); + __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); // Now handlize the static class mirror it's known not-null. __ movl(Address(esp, klass_offset), oop_handle_reg); @@ -1447,7 +1477,7 @@ { SkipIfEqual skip_if(masm, &DTraceMethodProbes, 0); - __ movl(eax, JNIHandles::make_local(method())); + __ movoop(eax, JNIHandles::make_local(method())); __ call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), thread, eax); @@ -1487,7 +1517,7 @@ __ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %eax - __ orl(swap_reg, Address(obj_reg)); + __ orl(swap_reg, Address(obj_reg, 0)); // Save (object->mark() | 1) into BasicLock's displaced header __ movl(Address(lock_reg, mark_word_offset), swap_reg); @@ -1498,7 +1528,7 @@ // src -> dest iff dest == eax else eax <- dest // *obj_reg = lock_reg iff *obj_reg == eax else eax = *(obj_reg) - __ cmpxchg(lock_reg, Address(obj_reg)); + __ cmpxchg(lock_reg, Address(obj_reg, 0)); __ jcc(Assembler::equal, lock_done); // Test if the oopMark is an obvious stack pointer, i.e., @@ -1537,7 +1567,7 @@ // Now set thread in native __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); - __ call(method->native_function(), relocInfo::runtime_call_type); + __ call(RuntimeAddress(method->native_function())); // WARNING - on Windows Java Natives use pascal calling convention and pop the // arguments off of the stack. We could just re-adjust the stack pointer here @@ -1584,12 +1614,16 @@ } } + if (AlwaysRestoreFPU) { + // Make sure the control word is correct. + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } // check for safepoint operation in progress and/or pending suspend requests { Label Continue; - __ cmpl(Address((int)SafepointSynchronize::address_of_state(), relocInfo::none), - SafepointSynchronize::_not_synchronized); + __ cmp32(ExternalAddress((address)SafepointSynchronize::address_of_state()), + SafepointSynchronize::_not_synchronized); Label L; __ jcc(Assembler::notEqual, L); @@ -1605,7 +1639,8 @@ // save_native_result(masm, ret_type, stack_slots); __ pushl(thread); - __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, + JavaThread::check_special_condition_for_native_trans))); __ increment(esp, wordSize); // Restore any method result value restore_native_result(masm, ret_type, stack_slots); @@ -1665,7 +1700,7 @@ // src -> dest iff dest == eax else eax <- dest // *obj_reg = ebx iff *obj_reg == eax else eax = *(obj_reg) - __ cmpxchg(ebx, Address(obj_reg)); + __ cmpxchg(ebx, Address(obj_reg, 0)); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -1682,7 +1717,7 @@ SkipIfEqual skip_if(masm, &DTraceMethodProbes, 0); // Tell dtrace about this method exit save_native_result(masm, ret_type, stack_slots); - __ movl(eax, JNIHandles::make_local(method())); + __ movoop(eax, JNIHandles::make_local(method())); __ call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), thread, eax); @@ -1698,7 +1733,7 @@ Label L; __ cmpl(eax, NULL_WORD); __ jcc(Assembler::equal, L); - __ movl(eax, Address(eax)); + __ movl(eax, Address(eax, 0)); __ bind(L); __ verify_oop(eax); } @@ -1752,7 +1787,7 @@ __ pushl(thread); __ pushl(lock_reg); __ pushl(obj_reg); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C))); __ addl(esp, 3*wordSize); #ifdef ASSERT @@ -1787,7 +1822,7 @@ __ pushl(eax); __ pushl(obj_reg); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C))); __ addl(esp, 2*wordSize); #ifdef ASSERT { @@ -1813,7 +1848,9 @@ __ bind(reguard); save_native_result(masm, ret_type, stack_slots); - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), relocInfo::runtime_call_type); + { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); + } restore_native_result(masm, ret_type, stack_slots); __ jmp(reguard_done); @@ -1829,7 +1866,7 @@ // pop our frame __ leave(); // and forward the exception - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); __ flush(); @@ -1996,7 +2033,7 @@ // fetch_unroll_info needs to call last_java_frame() __ set_last_Java_frame(ecx, noreg, noreg, NULL); - __ call( CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), relocInfo::runtime_call_type ); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info))); // Need to have an oopmap that tells fetch_unroll_info where to // find any register it might need. @@ -2095,9 +2132,9 @@ // Push interpreter frames in a loop Label loop; __ bind(loop); - __ movl(ebx, Address(esi)); // Load frame size + __ movl(ebx, Address(esi, 0)); // Load frame size __ subl(ebx, 2*wordSize); // we'll push pc and ebp by hand - __ pushl(Address(ecx)); // save return address + __ pushl(Address(ecx, 0)); // save return address __ enter(); // save old & set new ebp __ subl(esp, ebx); // Prolog! __ movl(ebx, sp_temp); // sender's sp @@ -2109,7 +2146,7 @@ __ addl(ecx, 4); // Bump array pointer (pcs) __ decrement(counter); // decrement counter __ jcc(Assembler::notZero, loop); - __ pushl(Address(ecx)); // save final return address + __ pushl(Address(ecx, 0)); // save final return address // Re-push self-frame __ enter(); // save old & set new ebp @@ -2138,7 +2175,7 @@ // Call C code. Need thread but NOT official VM entry // crud. We cannot block on this call, no GC can happen. Call should // restore return values to their stack-slots with the new SP. - __ call( CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), relocInfo::runtime_call_type ); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); // Set an oopmap for the call site oop_maps->add_gc_map( __ pc()-start, new OopMap( frame_size_in_words, 0 )); @@ -2231,7 +2268,7 @@ __ movl(Address(esp, arg0_off*wordSize),edx); // argument already in ECX __ movl(Address(esp, arg1_off*wordSize),ecx); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap))); // Set an oopmap for the call site OopMapSet *oop_maps = new OopMapSet(); @@ -2297,9 +2334,9 @@ // Push interpreter frames in a loop Label loop; __ bind(loop); - __ movl(ebx, Address(esi)); // Load frame size + __ movl(ebx, Address(esi, 0)); // Load frame size __ subl(ebx, 2*wordSize); // we'll push pc and ebp by hand - __ pushl(Address(ecx)); // save return address + __ pushl(Address(ecx, 0)); // save return address __ enter(); // save old & set new ebp __ subl(esp, ebx); // Prolog! __ movl(ebx, sp_temp); // sender's sp @@ -2311,7 +2348,7 @@ __ addl(ecx, 4); // Bump array pointer (pcs) __ decrement(counter); // decrement counter __ jcc(Assembler::notZero, loop); - __ pushl(Address(ecx)); // save final return address + __ pushl(Address(ecx, 0)); // save final return address // Re-push self-frame __ enter(); // save old & set new ebp @@ -2327,7 +2364,7 @@ // restore return values to their stack-slots with the new SP. __ movl(Address(esp,arg0_off*wordSize),edi); __ movl(Address(esp,arg1_off*wordSize), Deoptimization::Unpack_uncommon_trap); - __ call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); // Set an oopmap for the call site oop_maps->add_gc_map( __ pc()-start, new OopMap( framesize, 0 ) ); @@ -2384,7 +2421,7 @@ if( !cause_return ) __ pushl(ebx); // Make room for return address (or push it again) - map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words); + map = RegisterSaver::save_live_registers(masm, additional_words, &frame_size_in_words, false); // The following is basically a call_VM. However, we need the precise // address of the call in order to generate an oopmap. Hence, we do all the @@ -2402,7 +2439,7 @@ } // do the call - __ call(call_ptr, relocInfo::runtime_call_type); + __ call(RuntimeAddress(call_ptr)); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -2427,7 +2464,7 @@ RegisterSaver::restore_live_registers(masm); - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); __ bind(noException); @@ -2480,7 +2517,7 @@ __ pushl(thread); __ set_last_Java_frame(thread, noreg, ebp, NULL); - __ call(destination, relocInfo::runtime_call_type); + __ call(RuntimeAddress(destination)); // Set an oopmap for the call site. @@ -2523,7 +2560,7 @@ __ get_thread(thread); __ movl(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); __ movl(eax, Address(thread, Thread::pending_exception_offset())); - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); // ------------- // make sure all code is generated diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/stubGenerator_i486.cpp --- a/hotspot/src/cpu/i486/vm/stubGenerator_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/stubGenerator_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)stubGenerator_i486.cpp 1.87 07/06/08 18:13:20 JVM" +#pragma ident "@(#)stubGenerator_i486.cpp 1.89 07/06/28 10:31:44 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -70,8 +70,7 @@ #define inc_counter_np(counter) (0) #else void inc_counter_np_(int& counter) { - Address counter_addr((int) &counter, relocInfo::none); - __ increment(counter_addr); + __ increment(ExternalAddress((address)&counter)); } #define inc_counter_np(counter) \ BLOCK_COMMENT("inc_counter " #counter); \ @@ -157,12 +156,16 @@ __ stmxcsr(mxcsr_save); __ movl(eax, mxcsr_save); __ andl(eax, MXCSR_MASK); // Only check control and mask bits - __ cmpl(eax, *(int *)(StubRoutines::addr_mxcsr_std())); + ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std()); + __ cmp32(eax, mxcsr_std); __ jcc(Assembler::equal, skip_ldmx); - __ ldmxcsr(Address((int)StubRoutines::addr_mxcsr_std(), relocInfo::none)); + __ ldmxcsr(mxcsr_std); __ bind(skip_ldmx); } + // make sure the control word is correct. + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + #ifdef ASSERT // make sure we have no pending exceptions { Label L; @@ -214,7 +217,7 @@ __ movl(eax, entry_point); // get entry_point __ movl(esi, esp); // set sender sp BLOCK_COMMENT("call Java function"); - __ call(eax, relocInfo::none); + __ call(eax); BLOCK_COMMENT("call_stub_return_address:"); return_address = __ pc(); @@ -236,7 +239,7 @@ __ jcc(Assembler::equal, is_double); // handle T_INT case - __ movl(Address(edi), eax); + __ movl(Address(edi, 0), eax); __ BIND(exit); // check that FPU stack is empty @@ -269,18 +272,18 @@ __ BIND(is_float); // interpreter uses xmm0 for return values if (UseSSE >= 1) { - __ movflt(Address(edi), xmm0); + __ movflt(Address(edi, 0), xmm0); } else { - __ fstp_s(Address(edi)); + __ fstp_s(Address(edi, 0)); } __ jmp(exit); __ BIND(is_double); // interpreter uses xmm0 for return values if (UseSSE >= 2) { - __ movdbl(Address(edi), xmm0); + __ movdbl(Address(edi, 0), xmm0); } else { - __ fstp_d(Address(edi)); + __ fstp_d(Address(edi, 0)); } __ jmp(exit); @@ -351,11 +354,12 @@ // set pending exception __ verify_oop(eax); __ movl(Address(ecx, Thread::pending_exception_offset()), eax ); - __ movl(Address(ecx, Thread::exception_file_offset ()), (int)__FILE__); - __ movl(Address(ecx, Thread::exception_line_offset ()), __LINE__); + __ lea(Address(ecx, Thread::exception_file_offset ()), + ExternalAddress((address)__FILE__)); + __ movl(Address(ecx, Thread::exception_line_offset ()), __LINE__ ); // complete return to VM assert(StubRoutines::_call_stub_return_address != NULL, "_call_stub_return_address must have been generated before"); - __ jmp(StubRoutines::_call_stub_return_address, relocInfo::none); + __ jump(RuntimeAddress(StubRoutines::_call_stub_return_address)); return start; } @@ -396,7 +400,7 @@ #endif // compute exception handler into ebx - __ movl(eax, Address(esp)); + __ movl(eax, Address(esp, 0)); BLOCK_COMMENT("call exception_handler_for_return_address"); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), eax); __ movl(ebx, eax); @@ -470,21 +474,22 @@ StubCodeMark mark(this, "StubRoutines", "verify_mxcsr"); address start = __ pc(); - const Address mxcsr_save(esp); + const Address mxcsr_save(esp, 0); if (CheckJNICalls && UseSSE > 0 ) { Label ok_ret; + ExternalAddress mxcsr_std(StubRoutines::addr_mxcsr_std()); __ pushl(eax); __ subl(esp, wordSize); // allocate a temp location __ stmxcsr(mxcsr_save); __ movl(eax, mxcsr_save); __ andl(eax, MXCSR_MASK); - __ cmpl(eax, *(int *)(StubRoutines::addr_mxcsr_std())); + __ cmp32(eax, mxcsr_std); __ jcc(Assembler::equal, ok_ret); __ warn("MXCSR changed by native JNI code."); - __ ldmxcsr(Address((int) StubRoutines::addr_mxcsr_std(), relocInfo::none)); + __ ldmxcsr(mxcsr_std); __ bind(ok_ret); __ addl(esp, wordSize); @@ -508,7 +513,7 @@ StubCodeMark mark(this, "StubRoutines", "verify_spcw"); address start = __ pc(); - const Address fpu_cntrl_wrd_save(esp); + const Address fpu_cntrl_wrd_save(esp, 0); if (CheckJNICalls) { Label ok_ret; @@ -517,12 +522,13 @@ __ fnstcw(fpu_cntrl_wrd_save); __ movl(eax, fpu_cntrl_wrd_save); __ andl(eax, FPU_CNTRL_WRD_MASK); - __ cmpl(eax, *(int*)(StubRoutines::addr_fpu_cntrl_wrd_std())); + ExternalAddress fpu_std(StubRoutines::addr_fpu_cntrl_wrd_std()); + __ cmp32(eax, fpu_std); __ jcc(Assembler::equal, ok_ret); __ warn("Floating point control word changed by native JNI code."); - __ fldcw(Address((int) StubRoutines::addr_fpu_cntrl_wrd_std(), relocInfo::none)); + __ fldcw(fpu_std); __ bind(ok_ret); __ addl(esp, wordSize); @@ -561,7 +567,7 @@ // Save outgoing argument to stack across push_FPU_state() __ subl(esp, wordSize * 2); - __ fstp_d(Address(esp)); + __ fstp_d(Address(esp, 0)); // Save CPU & FPU state __ pushl(ebx); @@ -576,7 +582,7 @@ __ fld_d(Address(esp, saved_argument_off * wordSize)); // Store double into stack as outgoing argument __ subl(esp, wordSize*2); - __ fst_d(Address(esp)); + __ fst_d(Address(esp, 0)); // Prepare FPU for doing math in C-land __ empty_FPU_stack(); @@ -614,7 +620,7 @@ __ pushad(); // push registers Address next_pc(esp, RegisterImpl::number_of_registers * BytesPerWord); BLOCK_COMMENT("call handle_unsafe_access"); - __ call(CAST_FROM_FN_PTR(address, handle_unsafe_access), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access))); __ movl(next_pc, eax); // stuff next address __ popad(); __ ret(0); // jump to next address @@ -641,7 +647,7 @@ Label exit, error; __ pushfd(); - __ increment(Address((int)StubRoutines::verify_oop_count_addr(), relocInfo::none)); + __ increment(ExternalAddress((address) StubRoutines::verify_oop_count_addr())); __ pushl(edx); // save edx // make sure object is 'reasonable' __ movl(eax, Address(esp, 4 * wordSize)); // get object @@ -694,7 +700,7 @@ __ popfd(); // get saved EFLAGS off stack -- will be ignored __ pushad(); // push registers (eip = return address & msg are already pushed) BLOCK_COMMENT("call MacroAssembler::debug"); - __ call(CAST_FROM_FN_PTR(address, MacroAssembler::debug), relocInfo::runtime_call_type); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); __ popad(); __ ret(3 * wordSize); // pop arguments return start; @@ -768,7 +774,7 @@ // length is too short, just copy qwords // __ BIND(L_copy_8_bytes); - __ movq(mmx0, Address(from)); + __ movq(mmx0, Address(from, 0)); __ movq(Address(from, to_from, Address::times_1), mmx0); __ addl(from, 8); __ decrement(qword_count); @@ -819,7 +825,7 @@ // One byte misalignment happens only for byte arrays __ testl(from, 1); __ jccb(Assembler::zero, L_skip_align1); - __ movb(eax, Address(from)); + __ movb(eax, Address(from, 0)); __ movb(Address(from, to_from, Address::times_1, 0), eax); __ increment(from); __ decrement(count); @@ -828,7 +834,7 @@ // Two bytes misalignment happens only for byte and short (char) arrays __ testl(from, 2); __ jccb(Assembler::zero, L_skip_align2); - __ movw(eax, Address(from)); + __ movw(eax, Address(from, 0)); __ movw(Address(from, to_from, Address::times_1, 0), eax); __ addl(from, 2); __ subl(count, 1<<(shift-1)); @@ -846,7 +852,7 @@ // align to 8 bytes, we know we are 4 byte aligned to start __ testl(from, 4); __ jccb(Assembler::zero, L_copy_64_bytes); - __ movl(eax, Address(from)); + __ movl(eax, Address(from, 0)); __ movl(Address(from, to_from, Address::times_1, 0), eax); __ addl(from, 4); __ subl(count, 1< short_count __ movl(count_arg, count); // update 'count' - __ jmp(short_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(short_copy_entry)); __ BIND(L_int_aligned); __ shrl(count, LogBytesPerInt); // size => int_count __ movl(count_arg, count); // update 'count' - __ jmp(int_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(int_copy_entry)); __ BIND(L_long_aligned); __ shrl(count, LogBytesPerLong); // size => qword_count __ movl(count_arg, count); // update 'count' __ popl(edi); // Do pops here since jlong_arraycopy stub does not do it. __ popl(esi); - __ jmp(long_copy_entry, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(long_copy_entry)); return start; } @@ -1621,7 +1629,7 @@ // if (!src->is_Array()) return -1; __ cmpl(ecx_lh, Klass::_lh_neutral_value); - __ jccb(Assembler::greaterEqual, L_failed_0); // signed cmp + __ jcc(Assembler::greaterEqual, L_failed_0); // signed cmp // At this point, it is known to be a typeArray (array_tag 0x3). #ifdef ASSERT @@ -1677,18 +1685,19 @@ BLOCK_COMMENT("choose copy loop based on element size"); __ cmpl(edi_elsize, 0); - __ jcc(Assembler::equal, entry_jbyte_arraycopy); + + __ jump_cc(Assembler::equal, RuntimeAddress(entry_jbyte_arraycopy)); __ cmpl(edi_elsize, LogBytesPerShort); - __ jcc(Assembler::equal, entry_jshort_arraycopy); + __ jump_cc(Assembler::equal, RuntimeAddress(entry_jshort_arraycopy)); __ cmpl(edi_elsize, LogBytesPerInt); - __ jcc(Assembler::equal, entry_jint_arraycopy); + __ jump_cc(Assembler::equal, RuntimeAddress(entry_jint_arraycopy)); #ifdef ASSERT __ cmpl(edi_elsize, LogBytesPerLong); __ jccb(Assembler::notEqual, L_failed); #endif __ popl(edi); // Do pops here since jlong_arraycopy stub does not do it. __ popl(esi); - __ jmp(entry_jlong_arraycopy, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(entry_jlong_arraycopy)); __ BIND(L_failed); __ xorl(eax, eax); @@ -1722,7 +1731,7 @@ __ movl(FROM, from); // src_addr __ movl(TO, to); // dst_addr __ movl(COUNT, count); // count - __ jmp(entry_oop_arraycopy, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(entry_oop_arraycopy)); __ BIND(L_checkcast_copy); // live at this point: ecx_src_klass, dst[_pos], src[_pos] @@ -1783,7 +1792,7 @@ Address DST_POS_arg(esp, 16+16); Address LENGTH_arg(esp, 16+20); // push ebx changed the incoming offsets (why not just use ebp??) - assert(SRC_POS_arg.disp() == SRC_POS.disp() + 4, ""); + // assert(SRC_POS_arg.disp() == SRC_POS.disp() + 4, ""); __ movl(ebx, Address(esi_dst_klass, ek_offset)); __ movl(length, LENGTH_arg); // reload elements count @@ -1803,7 +1812,7 @@ __ leal(to, Address(dst, dst_pos, Address::times_4, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); __ movl(to_arg, to); - __ jmp(entry_checkcast_arraycopy, relocInfo::runtime_call_type); + __ jump(RuntimeAddress(entry_checkcast_arraycopy)); } return start; @@ -1977,7 +1986,7 @@ // Call runtime BLOCK_COMMENT("call runtime_entry"); - __ call(runtime_entry, relocInfo::runtime_call_type); + __ call(RuntimeAddress(runtime_entry)); // Generate oop map OopMap* map = new OopMap(framesize, 0); oop_maps->add_gc_map(__ pc() - start, map); @@ -1999,7 +2008,7 @@ __ should_not_reach_here(); __ bind(L); #endif /* ASSERT */ - __ jmp(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &code, frame_complete, framesize, oop_maps, false); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/templateTable_i486.cpp --- a/hotspot/src/cpu/i486/vm/templateTable_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/templateTable_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)templateTable_i486.cpp 1.319 07/05/17 15:47:10 JVM" +#pragma ident "@(#)templateTable_i486.cpp 1.320 07/06/19 09:08:09 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -73,7 +73,7 @@ // data beyond the esp which is potentially unsafe in an MT environment; // an interrupt may overwrite that data.) static inline Address at_esp () { - return Address(esp); + return Address(esp, 0); } // At top of Java expression stack which may be different than esp(). It @@ -425,7 +425,7 @@ __ movl(edx, haddress(ebx)); __ pushl(edx); // push hi first __ pushl(eax); - __ fld_d(Address(esp)); + __ fld_d(Address(esp, 0)); __ addl(esp, 2*wordSize); debug_only(__ verify_local_tag(frame::TagCategory2, ebx)); } else { @@ -485,7 +485,7 @@ __ movl(edx, haddress(ebx)); __ pushl(edx); // push hi first __ pushl(eax); - __ fld_d(Address(esp)); + __ fld_d(Address(esp, 0)); __ addl(esp, 2*wordSize); debug_only(__ verify_local_tag(frame::TagCategory2, ebx)); } else { @@ -518,7 +518,8 @@ assert(ebx != array, "different registers"); __ movl(ebx, index); } - __ jcc(Assembler::aboveEqual, Interpreter::_throw_ArrayIndexOutOfBoundsException_entry, relocInfo::none); + __ jump_cc(Assembler::aboveEqual, + ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry)); } @@ -648,7 +649,7 @@ __ movl(edx, haddress(n)); __ pushl(edx); // push hi first __ pushl(eax); - __ fld_d(Address(esp)); + __ fld_d(Address(esp, 0)); __ addl(esp, 2*wordSize); // reset esp debug_only(__ verify_local_tag(frame::TagCategory2, n)); } else { @@ -761,7 +762,7 @@ if (TaggedStackInterpreter) { // Store double on stack and reload into locals nonadjacently __ subl(esp, 2 * wordSize); - __ fstp_d(Address(esp)); + __ fstp_d(Address(esp, 0)); __ popl(eax); __ popl(edx); __ movl(laddress(ebx), eax); @@ -892,12 +893,12 @@ // Come here on failure // object is at TOS - __ jmp(Interpreter::_throw_ArrayStoreException_entry, relocInfo::none); + __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry)); // Come here on success __ bind(ok_is_subtype); __ movl(eax, at_esp()); // Value - __ movl(Address(edx), eax); + __ movl(Address(edx, 0), eax); __ store_check(edx); __ jmpb(done); @@ -965,7 +966,7 @@ transition(dtos, vtos); if (TaggedStackInterpreter) { __ subl(esp, 2 * wordSize); - __ fstp_d(Address(esp)); + __ fstp_d(Address(esp, 0)); __ popl(eax); __ popl(edx); __ movl(laddress(n), eax); @@ -1170,7 +1171,8 @@ __ pushl(edx); __ pushl(eax); // check if y = 0 __ orl(eax, edx); - __ jcc(Assembler::zero, Interpreter::_throw_ArithmeticException_entry, relocInfo::none); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); __ addl(esp, 4 * wordSize); // take off temporaries } @@ -1183,7 +1185,8 @@ __ pushl(edx); __ pushl(eax); // check if y = 0 __ orl(eax, edx); - __ jcc(Assembler::zero, Interpreter::_throw_ArithmeticException_entry, relocInfo::none); + __ jump_cc(Assembler::zero, + ExternalAddress(Interpreter::_throw_ArithmeticException_entry)); __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); __ addl(esp, 4 * wordSize); } @@ -1247,10 +1250,10 @@ __ fmul_d (at_esp()); __ jmpb(L_join); __ bind(L_strict); - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias1(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); __ fmulp(); __ fmul_d (at_esp()); - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias2(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); __ fmulp(); __ bind(L_join); break; @@ -1266,10 +1269,10 @@ __ fdivr_d(at_esp()); __ jmp(L_join); __ bind(L_strict); - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias1(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); __ fmul_d (at_esp()); __ fdivrp(); - __ fld_x(Address((int)StubRoutines::addr_fpu_subnormal_bias2(), relocInfo::none)); + __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); __ fmulp(); __ bind(L_join); break; @@ -1545,8 +1548,8 @@ if (ProfileInterpreter) { // Test to see if we should create a method data oop - __ cmpl(eax, Address(int(&InvocationCounter::InterpreterProfileLimit), - relocInfo::none)); + __ cmp32(eax, + ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit)); __ jcc(Assembler::less, dispatch); // if no method data exists, go to profile method @@ -1554,8 +1557,8 @@ if (UseOnStackReplacement) { // check for overflow against ebx which is the MDO taken count - __ cmpl(ebx, Address(int(&InvocationCounter::InterpreterBackwardBranchLimit), - relocInfo::none)); + __ cmp32(ebx, + ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit)); __ jcc(Assembler::below, dispatch); // When ProfileInterpreter is on, the backedge_count comes from the @@ -1571,8 +1574,8 @@ } else { if (UseOnStackReplacement) { // check for overflow against eax, which is the sum of the counters - __ cmpl(eax, Address(int(&InvocationCounter::InterpreterBackwardBranchLimit), - relocInfo::none)); + __ cmp32(eax, + ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit)); __ jcc(Assembler::aboveEqual, backedge_counter_overflow); } @@ -1581,7 +1584,7 @@ } // Pre-load the next target bytecode into EBX - __ load_unsigned_byte(ebx, Address(esi)); + __ load_unsigned_byte(ebx, Address(esi, 0)); // continue with the bytecode @ target // eax: return bci for jsr's, unused otherwise @@ -1594,7 +1597,7 @@ // Out-of-line code to allocate method data oop. __ bind(profile_method); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), esi); - __ load_unsigned_byte(ebx, Address(esi)); // restore target bytecode + __ load_unsigned_byte(ebx, Address(esi, 0)); // restore target bytecode __ movl(ecx, Address(ebp, method_offset)); __ movl(ecx, Address(ecx, in_bytes(methodOopDesc::method_data_offset()))); __ movl(Address(ebp, frame::interpreter_frame_mdx_offset * wordSize), ecx); @@ -1613,7 +1616,7 @@ __ negl(edx); __ addl(edx, esi); // branch bcp call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), edx); - __ load_unsigned_byte(ebx, Address(esi)); // restore target bytecode + __ load_unsigned_byte(ebx, Address(esi, 0)); // restore target bytecode // eax: osr nmethod (osr ok) or NULL (osr not possible) // ebx: target bytecode @@ -1658,12 +1661,12 @@ // Are we returning to the call stub? - __ cmpl(edi, (int)StubRoutines::_call_stub_return_address); + __ cmp32(edi, ExternalAddress(StubRoutines::_call_stub_return_address)); __ jcc(Assembler::notEqual, chkint); // yes adjust to the specialized call stub return. assert(StubRoutines::i486::get_call_stub_compiled_return() != NULL, "must be set"); - __ movl(edi, (intptr_t) StubRoutines::i486::get_call_stub_compiled_return()); + __ lea(edi, ExternalAddress(StubRoutines::i486::get_call_stub_compiled_return())); __ jmp(skip); __ bind(chkint); @@ -1797,7 +1800,7 @@ // handle default __ bind(default_case); __ profile_switch_default(eax); - __ movl(edx, Address(ebx)); + __ movl(edx, Address(ebx, 0)); __ jmp(continue_execution); } @@ -1829,7 +1832,7 @@ __ jcc(Assembler::greaterEqual, loop); // default case __ profile_switch_default(eax); - __ movl(edx, Address(ebx)); + __ movl(edx, Address(ebx, 0)); __ jmpb(continue_execution); // entry found -> get offset __ bind(found); @@ -2123,7 +2126,7 @@ // the time to call into the VM. Label L1; assert_different_registers(cache, index, eax); - __ movl(eax, Address((int)JvmtiExport::get_field_access_count_addr(), relocInfo::none)); + __ mov32(eax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); __ testl(eax,eax); __ jcc(Assembler::zero, L1); @@ -2307,7 +2310,7 @@ // the time to call into the VM. Label L1; assert_different_registers(cache, index, eax); - __ movl(eax, Address((int)JvmtiExport::get_field_modification_count_addr(), relocInfo::none)); + __ mov32(eax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); __ testl(eax, eax); __ jcc(Assembler::zero, L1); @@ -2545,7 +2548,7 @@ // Check to see if a field modification watch has been set before we take // the time to call into the VM. Label L2; - __ movl(ecx, Address((int)JvmtiExport::get_field_modification_count_addr(), relocInfo::none)); + __ mov32(ecx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr())); __ testl(ecx,ecx); __ jcc(Assembler::zero, L2); __ pop_ptr(ebx); // copy the object pointer from tos @@ -2679,7 +2682,7 @@ // Check to see if a field access watch has been set before we take // the time to call into the VM. Label L1; - __ movl(ecx, Address((int)JvmtiExport::get_field_access_count_addr(), relocInfo::none)); + __ mov32(ecx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr())); __ testl(ecx,ecx); __ jcc(Assembler::zero, L1); // access constant pool cache entry @@ -3018,6 +3021,8 @@ Label initialize_object; // including clearing the fields Label allocate_shared; + ExternalAddress heap_top((address)Universe::heap()->top_addr()); + __ get_cpool_and_tags(ecx, eax); // get instanceKlass __ movl(ecx, Address(ecx, edx, Address::times_4, sizeof(constantPoolOopDesc))); @@ -3076,9 +3081,9 @@ Label retry; __ bind(retry); - __ movl(eax, Address((int)Universe::heap()->top_addr(), relocInfo::none)); + __ mov32(eax, heap_top); __ leal(ebx, Address(eax, edx, Address::times_1)); - __ cmpl(ebx, Address((int)Universe::heap()->end_addr(), relocInfo::none)); + __ cmp32(ebx, ExternalAddress((address)Universe::heap()->end_addr())); __ jcc(Assembler::above, slow_case); // Compare eax with the top addr, and if still equal, store the new @@ -3089,7 +3094,7 @@ // ebx: object end // edx: instance size in bytes if (os::is_MP()) __ lock(); - __ cmpxchg(ebx, Address((int)Universe::heap()->top_addr(), relocInfo::none)); + __ cmpxchgptr(ebx, heap_top); // if someone beat us on the allocation, try again, otherwise continue __ jcc(Assembler::notEqual, retry); @@ -3221,7 +3226,7 @@ // Come here on failure __ pushl(edx); // object is at TOS - __ jmp(Interpreter::_throw_ClassCastException_entry, relocInfo::none); + __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry)); // Come here on success __ bind(ok_is_subtype); @@ -3320,7 +3325,7 @@ void TemplateTable::athrow() { transition(atos, vtos); __ null_check(eax); - __ jmp(Interpreter::throw_exception_entry(), relocInfo::none); + __ jump(ExternalAddress(Interpreter::throw_exception_entry())); } @@ -3399,7 +3404,7 @@ // 2. move expression stack contents __ bind(loop); __ movl(ebx, Address(ecx, entry_size)); // load expression stack word from old location - __ movl(Address(ecx), ebx); // and store it at new location + __ movl(Address(ecx, 0), ebx); // and store it at new location __ addl(ecx, wordSize); // advance to next word __ bind(entry); __ cmpl(ecx, edx); // check if bottom reached diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/i486/vm/vtableStubs_i486.cpp --- a/hotspot/src/cpu/i486/vm/vtableStubs_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/i486/vm/vtableStubs_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)vtableStubs_i486.cpp 1.51 07/05/17 15:47:16 JVM" +#pragma ident "@(#)vtableStubs_i486.cpp 1.52 07/06/19 09:08:09 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -50,7 +50,10 @@ MacroAssembler* masm = new MacroAssembler(&cb); #ifndef PRODUCT - if (CountCompiledCalls) __ increment(Address((int)SharedRuntime::nof_megamorphic_calls_addr(), relocInfo::none)); + + if (CountCompiledCalls) { + __ increment(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); + } #endif /* PRODUCT */ // get receiver (need to skip return address on top of stack) @@ -113,7 +116,9 @@ // ecx: Receiver #ifndef PRODUCT - if (CountCompiledCalls) __ increment(Address((int)SharedRuntime::nof_megamorphic_calls_addr(), relocInfo::none)); + if (CountCompiledCalls) { + __ increment(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); + } #endif /* PRODUCT */ // get receiver (need to skip return address on top of stack) diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_FrameMap_sparc.cpp 1.74 07/05/05 17:04:25 JVM" +#pragma ident "@(#)c1_FrameMap_sparc.cpp 1.75 07/06/18 14:25:22 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -41,7 +41,7 @@ // The calling convention does not count the SharedRuntime::out_preserve_stack_slots() value // so we must add it in here. int st_off = (r_1->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; - opr = LIR_OprFact::address(new LIR_Address(SP_opr, st_off, type)); + opr = LIR_OprFact::address(new LIR_Address(SP_opr, st_off + STACK_BIAS, type)); } else if (r_1->is_Register()) { Register reg = r_1->as_Register(); if (outgoing) { @@ -49,7 +49,7 @@ } else { assert(!reg->is_out(), "should be using O regs"); } - if (r_2->is_Register()) { + if (r_2->is_Register() && (type == T_LONG || type == T_DOUBLE)) { opr = as_long_opr(reg); } else if (type == T_OBJECT || type == T_ARRAY) { opr = as_oop_opr(reg); @@ -308,8 +308,8 @@ I6_oop_opr = as_oop_opr(I6); I7_oop_opr = as_oop_opr(I7); - FP_opr = as_opr(FP); - SP_opr = as_opr(SP); + FP_opr = as_pointer_opr(FP); + SP_opr = as_pointer_opr(SP); F0_opr = as_float_opr(F0); F0_double_opr = as_double_opr(F0); @@ -345,14 +345,14 @@ bool FrameMap::validate_frame() { - int max_offset = in_bytes(framesize_in_bytes()) + STACK_BIAS; + int max_offset = in_bytes(framesize_in_bytes()); int java_index = 0; for (int i = 0; i < _incoming_arguments->length(); i++) { LIR_Opr opr = _incoming_arguments->at(i); if (opr->is_stack()) { - max_offset = MAX2(_argument_locations->at(java_index) + STACK_BIAS, max_offset); + max_offset = MAX2(_argument_locations->at(java_index), max_offset); } java_index += type2size[opr->type()]; } - return Assembler::is_simm13(max_offset); + return Assembler::is_simm13(max_offset + STACK_BIAS); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_FrameMap_sparc.hpp 1.43 07/05/05 17:04:25 JVM" +#pragma ident "@(#)c1_FrameMap_sparc.hpp 1.44 07/06/18 14:25:22 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -122,10 +122,16 @@ static LIR_Opr as_long_opr(Register r) { return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); } + static LIR_Opr as_pointer_opr(Register r) { + return LIR_OprFact::double_cpu(cpu_reg2rnr(r), cpu_reg2rnr(r)); + } #else static LIR_Opr as_long_opr(Register r) { return LIR_OprFact::double_cpu(cpu_reg2rnr(r->successor()), cpu_reg2rnr(r)); } + static LIR_Opr as_pointer_opr(Register r) { + return as_opr(r); + } #endif static LIR_Opr as_float_opr(FloatRegister r) { return LIR_OprFact::single_fpu(r->encoding()); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRAssembler_sparc.cpp 1.204 07/05/17 15:47:57 JVM" +#pragma ident "@(#)c1_LIRAssembler_sparc.cpp 1.205 07/06/18 14:25:22 JVM" #endif /* * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -108,7 +108,7 @@ } if (dst->is_register() && - ((src->is_register() && src->is_single_word() && src->is_type_compatible(dst)) || + ((src->is_register() && src->is_single_word() && src->is_same_type(dst)) || (src->is_constant() && LIR_Assembler::is_small_constant(op->as_Op1()->in_opr())))) { return true; } @@ -1127,6 +1127,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info ) { LIR_Const* c = src->as_constant_ptr(); LIR_Address* addr = dest->as_address_ptr(); + Register base = addr->base()->as_pointer_register(); if (info != NULL) { add_debug_info_for_null_check_here(info); @@ -1143,10 +1144,10 @@ } if (addr->index()->is_valid()) { assert(addr->disp() == 0, "must be zero"); - store(tmp, addr->base()->as_register(), addr->index()->as_register(), type); + store(tmp, base, addr->index()->as_pointer_register(), type); } else { assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses"); - store(tmp, addr->base()->as_register(), addr->disp(), type); + store(tmp, base, addr->disp(), type); } break; } @@ -1163,14 +1164,14 @@ } else { __ set(value_lo, O7); } - store(tmp, addr->base()->as_register(), addr->disp() + lo_word_offset_in_bytes, T_INT); + store(tmp, base, addr->disp() + lo_word_offset_in_bytes, T_INT); int value_hi = c->as_jint_hi_bits(); if (value_hi == 0) { tmp = G0; } else { __ set(value_hi, O7); } - store(tmp, addr->base()->as_register(), addr->disp() + hi_word_offset_in_bytes, T_INT); + store(tmp, base, addr->disp() + hi_word_offset_in_bytes, T_INT); break; } case T_OBJECT: { @@ -1185,10 +1186,10 @@ // handle either reg+reg or reg+disp address if (addr->index()->is_valid()) { assert(addr->disp() == 0, "must be zero"); - store(tmp, addr->base()->as_register(), addr->index()->as_register(), type); + store(tmp, base, addr->index()->as_pointer_register(), type); } else { assert(Assembler::is_simm13(addr->disp()), "can't handle larger addresses"); - store(tmp, addr->base()->as_register(), addr->disp(), type); + store(tmp, base, addr->disp(), type); } break; @@ -1378,7 +1379,7 @@ LIR_Address* addr = src_opr->as_address_ptr(); LIR_Opr to_reg = dest; - Register src = addr->base()->as_register(); + Register src = addr->base()->as_pointer_register(); Register disp_reg = noreg; int disp_value = addr->disp(); bool needs_patching = (patch_code != lir_patch_none); @@ -1409,7 +1410,7 @@ __ add(src, addr->index()->as_register(), O7); src = O7; } else { - disp_reg = addr->index()->as_register(); + disp_reg = addr->index()->as_pointer_register(); assert(disp_value == 0, "can't handle 3 operand addresses"); } @@ -1493,7 +1494,7 @@ } else if (!from_reg->is_float_kind() && !to_reg->is_float_kind()) { if (from_reg->is_double_cpu()) { #ifdef _LP64 - __ mov(from_reg->as_register_lo(), to_reg->as_register_lo()); + __ mov(from_reg->as_pointer_register(), to_reg->as_pointer_register()); #else assert(to_reg->is_double_cpu() && from_reg->as_register_hi() != to_reg->as_register_lo() && @@ -1503,6 +1504,11 @@ __ mov(from_reg->as_register_hi(), to_reg->as_register_hi()); __ mov(from_reg->as_register_lo(), to_reg->as_register_lo()); #endif +#ifdef _LP64 + } else if (to_reg->is_double_cpu()) { + // int to int moves + __ mov(from_reg->as_register(), to_reg->as_register_lo()); +#endif } else { // int to int moves __ mov(from_reg->as_register(), to_reg->as_register()); @@ -1521,11 +1527,15 @@ bool unaligned) { LIR_Address* addr = dest->as_address_ptr(); - Register src = addr->base()->as_register(); + Register src = addr->base()->as_pointer_register(); Register disp_reg = noreg; int disp_value = addr->disp(); bool needs_patching = (patch_code != lir_patch_none); + if (addr->base()->is_oop_register()) { + __ verify_oop(src); + } + PatchingStub* patch = NULL; if (needs_patching) { patch = new PatchingStub(_masm, PatchingStub::access_field_id); @@ -1548,7 +1558,7 @@ __ add(src, addr->index()->as_register(), O7); src = O7; } else { - disp_reg = addr->index()->as_register(); + disp_reg = addr->index()->as_pointer_register(); assert(disp_value == 0, "can't handle 3 operand addresses"); } @@ -1797,7 +1807,7 @@ assert(dest->is_register(), "wrong items state"); if (right->is_register()) { - if (right->is_float_kind()) { + if (dest->is_float_kind()) { FloatRegister lreg, rreg, res; FloatRegisterImpl::Width w; @@ -1813,9 +1823,6 @@ res = dest->as_double_reg(); } - //assert(lreg == res ^ !left->rinfo().destroys_register(), "check"); - //assert(rreg == res ^ !right->rinfo().destroys_register(), "check"); - switch (code) { case lir_add: __ fadd(w, lreg, rreg, res); break; case lir_sub: __ fsub(w, lreg, rreg, res); break; @@ -1826,8 +1833,24 @@ default: ShouldNotReachHere(); } - } else if (right->is_double_cpu()) { - + } else if (dest->is_double_cpu()) { +#ifdef _LP64 + Register dst_lo = dest->as_register_lo(); + Register op1_lo = left->as_pointer_register(); + Register op2_lo = right->as_pointer_register(); + + switch (code) { + case lir_add: + __ add(op1_lo, op2_lo, dst_lo); + break; + + case lir_sub: + __ sub(op1_lo, op2_lo, dst_lo); + break; + + default: ShouldNotReachHere(); + } +#else Register op1_lo = left->as_register_lo(); Register op1_hi = left->as_register_hi(); Register op2_lo = right->as_register_lo(); @@ -1837,25 +1860,18 @@ switch (code) { case lir_add: -#ifdef _LP64 - __ add(op1_lo, op2_lo, dst_lo); -#else __ addcc(op1_lo, op2_lo, dst_lo); __ addc (op1_hi, op2_hi, dst_hi); -#endif break; case lir_sub: -#ifdef _LP64 - __ sub(op1_lo, op2_lo, dst_lo); -#else __ subcc(op1_lo, op2_lo, dst_lo); __ subc (op1_hi, op2_hi, dst_hi); -#endif break; default: ShouldNotReachHere(); } +#endif } else { assert (right->is_single_cpu(), "Just Checking"); @@ -1869,19 +1885,32 @@ default: ShouldNotReachHere(); } } - } - else { + } else { assert (right->is_constant(), "must be constant"); - Register lreg = left->as_register(); - Register res = dest->as_register(); - int simm13 = right->as_constant_ptr()->as_jint(); - - switch (code) { - case lir_add: __ add (lreg, simm13, res); break; - case lir_sub: __ sub (lreg, simm13, res); break; - case lir_mul: __ mult (lreg, simm13, res); break; - default: ShouldNotReachHere(); + if (dest->is_single_cpu()) { + Register lreg = left->as_register(); + Register res = dest->as_register(); + int simm13 = right->as_constant_ptr()->as_jint(); + + switch (code) { + case lir_add: __ add (lreg, simm13, res); break; + case lir_sub: __ sub (lreg, simm13, res); break; + case lir_mul: __ mult (lreg, simm13, res); break; + default: ShouldNotReachHere(); + } + } else { + Register lreg = left->as_pointer_register(); + Register res = dest->as_register_lo(); + long con = right->as_constant_ptr()->as_jlong(); + assert(Assembler::is_simm13(con), "must be simm13"); + + switch (code) { + case lir_add: __ add (lreg, (int)con, res); break; + case lir_sub: __ sub (lreg, (int)con, res); break; + case lir_mul: __ mult (lreg, (int)con, res); break; + default: ShouldNotReachHere(); + } } } } @@ -1973,30 +2002,38 @@ default: ShouldNotReachHere(); } } else { +#ifdef _LP64 + Register l = (left->is_single_cpu() && left->is_oop_register()) ? left->as_register() : + left->as_register_lo(); + Register r = (right->is_single_cpu() && right->is_oop_register()) ? right->as_register() : + right->as_register_lo(); + + switch (code) { + case lir_logic_and: __ and3 (l, r, dest->as_register_lo()); break; + case lir_logic_or: __ or3 (l, r, dest->as_register_lo()); break; + case lir_logic_xor: __ xor3 (l, r, dest->as_register_lo()); break; + default: ShouldNotReachHere(); + } +#else switch (code) { case lir_logic_and: -#ifndef _LP64 __ and3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); -#endif __ and3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); break; case lir_logic_or: -#ifndef _LP64 __ or3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); -#endif __ or3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); break; case lir_logic_xor: -#ifndef _LP64 __ xor3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); -#endif __ xor3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); break; default: ShouldNotReachHere(); } +#endif } } } @@ -2199,7 +2236,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { - if (dest->is_single_cpu()) { #ifdef _LP64 if (left->type() == T_OBJECT) { @@ -2238,33 +2274,37 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { - Register value = left->as_register(); - #ifdef _LP64 if (left->type() == T_OBJECT) { + count = count & 63; // shouldn't shift by more than sizeof(intptr_t) + Register l = left->as_register(); + Register d = dest->as_register_lo(); switch (code) { - case lir_shl: __ sllx (left->as_register(), count, dest->as_register()); break; - case lir_shr: __ srax (left->as_register(), count, dest->as_register()); break; - case lir_ushr: __ srlx (left->as_register(), count, dest->as_register()); break; + case lir_shl: __ sllx (l, count, d); break; + case lir_shr: __ srax (l, count, d); break; + case lir_ushr: __ srlx (l, count, d); break; default: ShouldNotReachHere(); } return; } #endif - if ( code != lir_shlx ) + if (dest->is_single_cpu()) { count = count & 0x1F; // Java spec - - if (dest->is_single_cpu()) { switch (code) { case lir_shl: __ sll (left->as_register(), count, dest->as_register()); break; - case lir_shlx: __ sllx (left->as_register(), count, dest->as_register()); break; case lir_shr: __ sra (left->as_register(), count, dest->as_register()); break; case lir_ushr: __ srl (left->as_register(), count, dest->as_register()); break; default: ShouldNotReachHere(); } } else if (dest->is_double_cpu()) { - Unimplemented(); + count = count & 63; // Java spec + switch (code) { + case lir_shl: __ sllx (left->as_pointer_register(), count, dest->as_pointer_register()); break; + case lir_shr: __ srax (left->as_pointer_register(), count, dest->as_pointer_register()); break; + case lir_ushr: __ srlx (left->as_pointer_register(), count, dest->as_pointer_register()); break; + default: ShouldNotReachHere(); + } } else { ShouldNotReachHere(); } @@ -2334,6 +2374,8 @@ Register klass_RInfo = op->tmp2()->as_register(); Register Rtmp1 = op->tmp3()->as_register(); + __ verify_oop(value); + CodeStub* stub = op->stub(); Label done; __ cmp(value, 0); @@ -2596,7 +2638,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { if (op->code() == lir_cas_long) { assert(VM_Version::supports_cx8(), "wrong machine"); - Register addr = op->addr()->as_register(); + Register addr = op->addr()->as_pointer_register(); Register cmp_value_lo = op->cmp_value()->as_register_lo(); Register cmp_value_hi = op->cmp_value()->as_register_hi(); Register new_value_lo = op->new_value()->as_register_lo(); @@ -2622,21 +2664,27 @@ __ cmp(t1, t2); } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { - Register addr = op->addr()->as_register(); + Register addr = op->addr()->as_pointer_register(); Register cmp_value = op->cmp_value()->as_register(); Register new_value = op->new_value()->as_register(); Register t1 = op->tmp1()->as_register(); Register t2 = op->tmp2()->as_register(); __ mov(cmp_value, t1); __ mov(new_value, t2); - __ cas(addr, t1, t2); +#ifdef _LP64 + if (op->code() == lir_cas_obj) { + __ casx(addr, t1, t2); + } else +#endif + { + __ cas(addr, t1, t2); + } __ cmp(t1, t2); } else { Unimplemented(); } } - void LIR_Assembler::set_24bit_FPU() { Unimplemented(); } @@ -2884,6 +2932,12 @@ if (call_info) { add_call_info(code_offset(), call_info); } + + if (VerifyStackAtCalls) { + _masm->sub(FP, SP, O7); + _masm->cmp(O7, initial_frame_size_in_bytes()); + _masm->trap(Assembler::notEqual, Assembler::ptr_cc, G0, ST_RESERVED_FOR_USER_0+2 ); + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_LIRAssembler_sparc.hpp 1.34 07/05/05 17:04:25 JVM" +#pragma ident "@(#)c1_LIRAssembler_sparc.hpp 1.35 07/06/18 14:25:22 JVM" #endif /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -78,7 +78,12 @@ void pack64( Register rs, Register rd ); void unpack64( Register rd ); - enum { call_stub_size = 20 , +enum { +#ifdef _LP64 + call_stub_size = 68, +#else + call_stub_size = 20, +#endif // _LP64 exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4), deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4) }; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRGenerator_sparc.cpp 1.10 07/05/05 17:04:26 JVM" +#pragma ident "@(#)c1_LIRGenerator_sparc.cpp 1.11 07/06/18 14:25:22 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -195,16 +195,24 @@ base_opr = array_opr; offset = array_offset + offset; } else { - base_opr = new_register(T_INT); + base_opr = new_pointer_register(); if (Assembler::is_simm13(array_offset)) { - __ add(array_opr, LIR_OprFact::intConst(array_offset), base_opr); + __ add(array_opr, LIR_OprFact::intptrConst(array_offset), base_opr); } else { - __ move(LIR_OprFact::intConst(array_offset), base_opr); + __ move(LIR_OprFact::intptrConst(array_offset), base_opr); __ add(base_opr, array_opr, base_opr); } } } else { - base_opr = new_register(T_INT); +#ifdef _LP64 + if (index_opr->type() == T_INT) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index_opr, tmp); + index_opr = tmp; + } +#endif + + base_opr = new_pointer_register(); assert (index_opr->is_register(), "Must be register"); if (shift > 0) { __ shift_left(index_opr, shift, base_opr); @@ -214,8 +222,8 @@ } } if (needs_card_mark) { - LIR_Opr ptr = new_register(T_INT); - __ add(base_opr, LIR_OprFact::intConst(offset), ptr); + LIR_Opr ptr = new_pointer_register(); + __ add(base_opr, LIR_OprFact::intptrConst(offset), ptr); return new LIR_Address(ptr, 0, type); } else { return new LIR_Address(base_opr, offset, type); @@ -224,8 +232,8 @@ void LIRGenerator::increment_counter(address counter, int step) { - LIR_Opr pointer = new_register(T_INT); - __ move(LIR_OprFact::intConst((int)counter), pointer); + LIR_Opr pointer = new_pointer_register(); + __ move(LIR_OprFact::intptrConst(counter), pointer); LIR_Address* addr = new LIR_Address(pointer, 0, T_INT); increment_counter(addr, step); } @@ -362,7 +370,8 @@ __ move(value.result(), array_addr, null_check_info); if (obj_store) { - write_barrier(LIR_OprFact::address(array_addr)); + // Is this precise? + post_barrier(LIR_OprFact::address(array_addr), value.result()); } } @@ -647,7 +656,7 @@ // Use temps to avoid kills LIR_Opr t1 = FrameMap::G1_opr; LIR_Opr t2 = FrameMap::G3_opr; - LIR_Opr addr = new_register(T_INT); + LIR_Opr addr = new_pointer_register(); // get address of field obj.load_item(); @@ -671,7 +680,7 @@ LIR_Opr result = rlock_result(x); __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result); if (type == objectType) { // Write-barrier needed for Object fields. - write_barrier(addr); + post_barrier(obj.result(), val.result()); } } @@ -961,10 +970,10 @@ jobject2reg_with_patching(reg, x->klass(), patching_info); LIR_Opr rank = FrameMap::O1_opr; __ move(LIR_OprFact::intConst(x->rank()), rank); - LIR_Opr varargs = FrameMap::O2_opr; + LIR_Opr varargs = FrameMap::as_pointer_opr(O2); int offset_from_sp = (frame::memory_parameter_word_sp_offset * wordSize) + STACK_BIAS; __ add(FrameMap::SP_opr, - LIR_OprFact::intConst(offset_from_sp), + LIR_OprFact::intptrConst(offset_from_sp), varargs); LIR_OprList* args = new LIR_OprList(3); args->append(reg); @@ -1091,7 +1100,7 @@ LIR_Opr LIRGenerator::getThreadPointer() { - return FrameMap::G2_opr; + return FrameMap::as_pointer_opr(G2); } @@ -1107,7 +1116,7 @@ void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address, CodeEmitInfo* info) { #ifdef _LP64 - __ store_mem_reg(value, address, info); + __ store(value, address, info); #else __ volatile_store_mem_reg(value, address, info); #endif @@ -1116,7 +1125,7 @@ void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result, CodeEmitInfo* info) { #ifdef _LP64 - __ load_mem_reg(address, result, info); + __ load(address, result, info); #else __ volatile_load_mem_reg(address, result, info); #endif @@ -1128,6 +1137,7 @@ LIR_Opr base_op = src; LIR_Opr index_op = offset; + bool is_obj = (type == T_ARRAY || type == T_OBJECT); #ifndef _LP64 if (is_volatile && type == T_LONG) { __ volatile_store_unsafe_reg(data, src, offset, type, NULL, lir_patch_none); @@ -1139,7 +1149,7 @@ } LIR_Address* addr; if (type == T_ARRAY || type == T_OBJECT) { - LIR_Opr tmp = new_register(T_OBJECT); + LIR_Opr tmp = new_pointer_register(); __ add(base_op, index_op, tmp); addr = new LIR_Address(tmp, 0, type); } else { @@ -1147,8 +1157,9 @@ } __ move(data, addr); - if (type == T_ARRAY || type == T_OBJECT) { - write_barrier(LIR_OprFact::address(addr)); + if (is_obj) { + // This address is precise + post_barrier(LIR_OprFact::address(addr), data); } } } @@ -1156,9 +1167,12 @@ void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset, BasicType type, bool is_volatile) { +#ifndef _LP64 if (is_volatile && type == T_LONG) { __ volatile_load_unsafe_reg(src, offset, dst, type, NULL, lir_patch_none); - } else { + } else +#endif + { LIR_Address* addr = new LIR_Address(src, offset, type); __ load(addr, dst); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_MacroAssembler_sparc.cpp 1.64 07/05/05 17:04:26 JVM" +#pragma ident "@(#)c1_MacroAssembler_sparc.cpp 1.65 07/06/18 14:25:23 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -373,7 +373,7 @@ void C1_MacroAssembler::verify_stack_oop(int stack_offset) { if (!VerifyOops) return; - verify_oop_addr(Address(SP, 0, stack_offset)); + verify_oop_addr(Address(SP, 0, stack_offset + STACK_BIAS)); } void C1_MacroAssembler::verify_not_null_oop(Register r) { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)stubGenerator_sparc.cpp 1.230 07/05/31 18:17:41 JVM" +#pragma ident "@(#)stubGenerator_sparc.cpp 1.231 07/06/18 18:44:39 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -1336,7 +1336,7 @@ // Both array are 8 bytes aligned, copy 16 bytes at a time __ and3(count, 7, G4); // Save count - __ srlx(count, 3, count); + __ srl(count, 3, count); generate_disjoint_long_copy_core(aligned); __ mov(G4, count); // Restore count @@ -2611,7 +2611,7 @@ // if (src->klass() != dst->klass()) return -1; __ cmp(G3_src_klass, G4_dst_klass); - __ br(Assembler::notEqual, false, Assembler::pn, L_failed); + __ brx(Assembler::notEqual, false, Assembler::pn, L_failed); __ delayed()->nop(); // if (!src->is_Array()) return -1; @@ -2697,7 +2697,7 @@ Label L_plain_copy, L_checkcast_copy; // test array classes for subtyping __ cmp(G3_src_klass, G4_dst_klass); // usual case is exact equality - __ br(Assembler::notEqual, true, Assembler::pn, L_checkcast_copy); + __ brx(Assembler::notEqual, true, Assembler::pn, L_checkcast_copy); __ delayed()->lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted from below // Identically typed arrays can be copied without element-wise checks. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os/win32/vm/os_win32.cpp --- a/hotspot/src/os/win32/vm/os_win32.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os/win32/vm/os_win32.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_win32.cpp 1.527 07/05/29 13:32:15 JVM" +#pragma ident "@(#)os_win32.cpp 1.528 07/06/20 10:45:37 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -1957,8 +1957,11 @@ JavaThread* thread = (JavaThread*) t; PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if ( os::is_memory_serialize_page(thread, addr) ) + if ( os::is_memory_serialize_page(thread, addr) ) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); return EXCEPTION_CONTINUE_EXECUTION; + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_amd64/vm/assembler_linux_amd64.cpp --- a/hotspot/src/os_cpu/linux_amd64/vm/assembler_linux_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_amd64/vm/assembler_linux_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_linux_amd64.cpp 1.8 07/05/05 17:04:47 JVM" +#pragma ident "@(#)assembler_linux_amd64.cpp 1.9 07/06/19 09:08:09 JVM" #endif /* * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved. @@ -28,14 +28,11 @@ #include "incls/_precompiled.incl" #include "incls/_assembler_linux_amd64.cpp.incl" -void Assembler::int3() -{ - call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); +void MacroAssembler::int3() { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } -void MacroAssembler::get_thread(Register thread) -{ +void MacroAssembler::get_thread(Register thread) { // call pthread_getspecific // void * pthread_getspecific(pthread_key_t key); if (thread != rax) { @@ -55,8 +52,7 @@ pushq(r11); movl(rdi, ThreadLocalStorage::thread_index()); - call(CAST_FROM_FN_PTR(address, pthread_getspecific), - relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, pthread_getspecific))); popq(r11); popq(rsp); @@ -75,7 +71,6 @@ // NOTE: since the linux kernel resides at the low end of // user address space, no null pointer check is needed. -bool MacroAssembler::needs_explicit_null_check(int offset) -{ +bool MacroAssembler::needs_explicit_null_check(int offset) { return offset < 0 || offset >= 0x100000; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_amd64/vm/linux_amd64.ad --- a/hotspot/src/os_cpu/linux_amd64/vm/linux_amd64.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_amd64/vm/linux_amd64.ad Thu Jul 05 23:47:33 2007 +0000 @@ -73,8 +73,7 @@ enc_class linux_breakpoint %{ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); %} enc_class call_epilog @@ -160,27 +159,22 @@ source %{ -int MachCallRuntimeNode::ret_addr_offset() -{ +int MachCallRuntimeNode::ret_addr_offset() { return 13; // movq r10,#addr; callq (r10) } // emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer& cbuf) -{ +void emit_break(CodeBuffer& cbuf) { // Debugger doesn't really catch this but best we can do so far QQQ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } -void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const -{ +void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { emit_break(cbuf); } -uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const -{ +uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { return 5; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.cpp --- a/hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_linux_amd64.cpp 1.29 07/05/05 17:04:46 JVM" +#pragma ident "@(#)os_linux_amd64.cpp 1.30 07/06/20 10:45:18 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -346,6 +346,8 @@ // so we can just return to retry the write. if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address)info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); return true; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.hpp --- a/hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_amd64/vm/os_linux_amd64.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_linux_amd64.hpp 1.9 07/05/05 17:04:46 JVM" +#pragma ident "@(#)os_linux_amd64.hpp 1.10 07/06/28 10:31:44 JVM" #endif /* * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -25,6 +25,8 @@ * */ + static void setup_fpu() {} + // Used to register dynamic code cache area with the OS // Note: Currently only used in 64 bit Windows implementations static bool register_code_area(char *low, char *high) { return true; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_i486/vm/assembler_linux_i486.cpp --- a/hotspot/src/os_cpu/linux_i486/vm/assembler_linux_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_i486/vm/assembler_linux_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_linux_i486.cpp 1.17 07/05/05 17:04:48 JVM" +#pragma ident "@(#)assembler_linux_i486.cpp 1.18 07/06/19 09:08:10 JVM" #endif /* * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. @@ -28,14 +28,19 @@ #include "incls/_precompiled.incl" #include "incls/_assembler_linux_i486.cpp.incl" -void Assembler::int3() { - call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); +void MacroAssembler::int3() { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MacroAssembler::get_thread(Register thread) { movl(thread, esp); shrl(thread, PAGE_SHIFT); - movl(thread, Address(noreg, thread, Address::times_4, (int)ThreadLocalStorage::sp_map_addr())); + + ExternalAddress tls_base((address)ThreadLocalStorage::sp_map_addr()); + Address index(noreg, thread, Address::times_4); + ArrayAddress tls(tls_base, index); + + movptr(thread, tls); } bool MacroAssembler::needs_explicit_null_check(int offset) { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_i486/vm/linux_i486.ad --- a/hotspot/src/os_cpu/linux_i486/vm/linux_i486.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_i486/vm/linux_i486.ad Thu Jul 05 23:47:33 2007 +0000 @@ -61,7 +61,7 @@ enc_class linux_breakpoint %{ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); %} enc_class call_epilog %{ @@ -145,7 +145,7 @@ // Debugger doesn't really catch this but best we can do so far QQQ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.cpp --- a/hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_linux_i486.cpp 1.94 07/05/05 17:04:49 JVM" +#pragma ident "@(#)os_linux_i486.cpp 1.96 07/06/28 19:03:37 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -347,7 +347,9 @@ // so we can just return to retry the write. if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address) info->si_addr)) { - return true; + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return true; } } @@ -677,3 +679,9 @@ st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); print_hex_dump(st, pc - 16, pc + 16, sizeof(char)); } + +void os::setup_fpu() { + address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); + __asm__ volatile ( "fldcw (%0)" : + : "r" (fpu_cntrl) : "memory"); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.hpp --- a/hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/linux_i486/vm/os_linux_i486.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_linux_i486.hpp 1.16 07/05/05 17:04:49 JVM" +#pragma ident "@(#)os_linux_i486.hpp 1.17 07/06/28 10:31:44 JVM" #endif /* * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -25,6 +25,7 @@ * */ + static void setup_fpu(); static bool supports_sse(); static bool is_allocatable(size_t bytes); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_amd64/vm/assembler_solaris_amd64.cpp --- a/hotspot/src/os_cpu/solaris_amd64/vm/assembler_solaris_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_amd64/vm/assembler_solaris_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_solaris_amd64.cpp 1.9 07/05/05 17:04:50 JVM" +#pragma ident "@(#)assembler_solaris_amd64.cpp 1.10 07/06/19 09:08:10 JVM" #endif /* * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -28,9 +28,8 @@ #include "incls/_precompiled.incl" #include "incls/_assembler_solaris_amd64.cpp.incl" -void Assembler::int3() { - call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); +void MacroAssembler::int3() { + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MacroAssembler::get_thread(Register thread) { @@ -45,7 +44,8 @@ } else if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2 // mov r, fs:[tlsOffset] emit_byte(Assembler::FS_segment); - movq(thread, Address((address) ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none)); + ExternalAddress tls_off((address) ThreadLocalStorage::pd_getTlsOffset()); + movptr(thread, tls_off); return; } @@ -72,8 +72,7 @@ pushq(r11); movl(rdi, ThreadLocalStorage::thread_index()); - call(CAST_FROM_FN_PTR(address, thr_getspecific), - relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); popq(r11); popq(rsp); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.cpp --- a/hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_solaris_amd64.cpp 1.17 07/05/17 15:49:01 JVM" +#pragma ident "@(#)os_solaris_amd64.cpp 1.18 07/06/20 10:37:52 JVM" #endif /* * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -404,6 +404,8 @@ // so we can just return to retry the write. if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address)info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); return true; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.hpp --- a/hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_amd64/vm/os_solaris_amd64.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_solaris_amd64.hpp 1.8 07/05/05 17:04:50 JVM" +#pragma ident "@(#)os_solaris_amd64.hpp 1.9 07/06/28 10:31:44 JVM" #endif /* * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. @@ -25,6 +25,8 @@ * */ + static void setup_fpu() {} + // // NOTE: we are back in class os here, not Solaris // diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_amd64/vm/solaris_amd64.ad --- a/hotspot/src/os_cpu/solaris_amd64/vm/solaris_amd64.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_amd64/vm/solaris_amd64.ad Thu Jul 05 23:47:33 2007 +0000 @@ -73,8 +73,7 @@ enc_class solaris_breakpoint %{ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); %} enc_class call_epilog @@ -115,12 +114,10 @@ enc_class post_call_verify_mxcsr %{ MacroAssembler masm(&cbuf); if (RestoreMXCSROnJNICalls) { - Address mxcsr_std = Address(StubRoutines::amd64::mxcsr_std(), relocInfo::none); - masm.ldmxcsr(mxcsr_std); + masm.ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); } else if (CheckJNICalls) { - masm.call(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()), - relocInfo::runtime_call_type); + masm.call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); } %} %} @@ -181,8 +178,7 @@ { // Debugger doesn't really catch this but best we can do so far QQQ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), - relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_i486/vm/assembler_solaris_i486.cpp --- a/hotspot/src/os_cpu/solaris_i486/vm/assembler_solaris_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_i486/vm/assembler_solaris_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_solaris_i486.cpp 1.20 07/05/05 17:04:51 JVM" +#pragma ident "@(#)assembler_solaris_i486.cpp 1.21 07/06/19 09:08:10 JVM" #endif /* * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. @@ -29,11 +29,11 @@ #include "incls/_assembler_solaris_i486.cpp.incl" -void Assembler::int3() { +void MacroAssembler::int3() { pushl(eax); pushl(edx); pushl(ecx); - call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); popl(ecx); popl(edx); popl(eax); @@ -46,14 +46,17 @@ if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1 // Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset] emit_byte (Assembler::GS_segment) ; - movl (thread, Address(0, relocInfo::none)) ; + // ExternalAddress doesn't work because it can't take NULL + AddressLiteral null(0, relocInfo::none); + movptr (thread, null); movl (thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ; return ; } else if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2 // mov r, gs:[tlsOffset] emit_byte (Assembler::GS_segment) ; - movl (thread, Address(ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none)) ; + AddressLiteral tls((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none); + movptr (thread, tls); return ; } @@ -72,7 +75,7 @@ } pushl(thread); // and pass the address pushl(ThreadLocalStorage::thread_index()); // the key - call(CAST_FROM_FN_PTR(address, thr_getspecific), relocInfo::runtime_call_type); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); increment(esp, 2 * wordSize); popl(edx); popl(ecx); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.cpp --- a/hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_solaris_i486.cpp 1.118 07/05/17 15:49:03 JVM" +#pragma ident "@(#)os_solaris_i486.cpp 1.120 07/06/28 19:03:45 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -498,6 +498,8 @@ // so we can just return to retry the write. if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address)info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); return true; } } @@ -806,3 +808,10 @@ cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; fence_func_t* os::fence_func = os::fence_bootstrap; + +extern "C" _solaris_raw_setup_fpu(address ptr); +void os::setup_fpu() { + address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); + _solaris_raw_setup_fpu(fpu_cntrl); +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.hpp --- a/hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_i486/vm/os_solaris_i486.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_solaris_i486.hpp 1.21 07/05/05 17:04:51 JVM" +#pragma ident "@(#)os_solaris_i486.hpp 1.22 07/06/28 10:31:43 JVM" #endif /* * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -40,7 +40,9 @@ static jint atomic_add_bootstrap (jint, volatile jint*); static void fence_bootstrap (); + static void setup_fpu(); static bool supports_sse(); + static bool is_allocatable(size_t bytes); // Used to register dynamic code cache area with the OS diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.ad --- a/hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.ad Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.ad Thu Jul 05 23:47:33 2007 +0000 @@ -61,7 +61,7 @@ enc_class solaris_breakpoint %{ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); %} enc_class call_epilog %{ @@ -145,7 +145,7 @@ // Debugger doesn't really catch this but best we can do so far QQQ MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(CAST_FROM_FN_PTR(address, os::breakpoint), relocInfo::runtime_call_type); + masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.il --- a/hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.il Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_i486/vm/solaris_i486.il Thu Jul 05 23:47:33 2007 +0000 @@ -23,6 +23,12 @@ // + // Support for u8 os::setup_fpu() + .inline _solaris_raw_setup_fpu,1 + movl 0(%esp), %eax + fldcw (%eax) + .end + // The argument size of each inline directive is ignored by the compiler // and is set to 0 for compatibility reason. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_solaris_sparc.cpp 1.119 07/05/17 15:49:08 JVM" +#pragma ident "@(#)os_solaris_sparc.cpp 1.120 07/06/20 10:37:06 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -495,6 +495,8 @@ // so just return. if ((sig == SIGSEGV) && os::is_memory_serialize_page(thread, (address)info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); return true; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_solaris_sparc.hpp 1.15 07/05/05 17:04:54 JVM" +#pragma ident "@(#)os_solaris_sparc.hpp 1.16 07/06/28 10:31:43 JVM" #endif /* * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -40,6 +40,8 @@ static jint atomic_add_bootstrap (jint, volatile jint*); static void fence_bootstrap (); + static void setup_fpu() {} + static bool is_allocatable(size_t bytes); // Used to register dynamic code cache area with the OS diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_amd64/vm/assembler_win32_amd64.cpp --- a/hotspot/src/os_cpu/win32_amd64/vm/assembler_win32_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_amd64/vm/assembler_win32_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_win32_amd64.cpp 1.12 07/05/05 17:04:54 JVM" +#pragma ident "@(#)assembler_win32_amd64.cpp 1.13 07/06/19 09:08:10 JVM" #endif /* * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -29,7 +29,7 @@ #include "incls/_assembler_win32_amd64.cpp.incl" -void Assembler::int3() { +void MacroAssembler::int3() { emit_byte(0xCC); } @@ -52,7 +52,7 @@ pushq(r11); movl(c_rarg0, ThreadLocalStorage::thread_index()); - call((address)TlsGetValue, relocInfo::none); + call(RuntimeAddress((address)TlsGetValue)); popq(r11); popq(rsp); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.cpp --- a/hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_win32_amd64.cpp 1.18 07/05/05 17:04:55 JVM" +#pragma ident "@(#)os_win32_amd64.cpp 1.19 07/06/19 09:08:10 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -51,8 +51,7 @@ IN PEXCEPTION_RECORD ExceptionRecord, IN ULONG64 EstablisherFrame, IN OUT PCONTEXT ContextRecord, - IN OUT PDISPATCHER_CONTEXT DispatcherContext) -{ + IN OUT PDISPATCHER_CONTEXT DispatcherContext) { EXCEPTION_POINTERS ep; LONG result; @@ -107,7 +106,7 @@ MacroAssembler* masm = new MacroAssembler(&cb); pDCD = (pDynamicCodeData) masm->pc(); - masm->jmp((address)&HandleExceptionFromCodeCache, relocInfo::none); + masm->jump(ExternalAddress((address)&HandleExceptionFromCodeCache)); masm->flush(); // Create an Unwind Structure specifying no unwind info diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.hpp --- a/hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_amd64/vm/os_win32_amd64.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_win32_amd64.hpp 1.10 07/05/05 17:04:55 JVM" +#pragma ident "@(#)os_win32_amd64.hpp 1.11 07/06/28 10:31:43 JVM" #endif /* * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -51,6 +51,7 @@ static void fence_bootstrap (); + static void setup_fpu() {} static bool supports_sse() { return true; } static bool register_code_area(char *low, char *high); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_i486/vm/assembler_win32_i486.cpp --- a/hotspot/src/os_cpu/win32_i486/vm/assembler_win32_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_i486/vm/assembler_win32_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)assembler_win32_i486.cpp 1.15 07/05/05 17:04:56 JVM" +#pragma ident "@(#)assembler_win32_i486.cpp 1.16 07/06/19 09:08:11 JVM" #endif /* * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved. @@ -29,7 +29,7 @@ #include "incls/_assembler_win32_i486.cpp.incl" -void Assembler::int3() { +void MacroAssembler::int3() { emit_byte(0xCC); } @@ -52,7 +52,11 @@ // movl reg, [reg + thread_ptr_offset] Load thread // void MacroAssembler::get_thread(Register thread) { - prefix(FS_segment); movl(thread, Address(0, relocInfo::none)); + // can't use ExternalAddress because it can't take NULL + AddressLiteral null(0, relocInfo::none); + + prefix(FS_segment); + movptr(thread, null); assert(ThreadLocalStorage::get_thread_ptr_offset() != 0, "Thread Pointer Offset has not been initialized"); movl(thread, Address(thread, ThreadLocalStorage::get_thread_ptr_offset())); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.cpp --- a/hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os_win32_i486.cpp 1.30 07/05/05 17:04:56 JVM" +#pragma ident "@(#)os_win32_i486.cpp 1.31 07/06/28 10:31:42 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -219,3 +219,8 @@ } +void os::setup_fpu() { + int fpu_cntrl_word = StubRoutines::fpu_cntrl_wrd_std(); + __asm fldcw fpu_cntrl_word; +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.hpp --- a/hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/os_cpu/win32_i486/vm/os_win32_i486.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os_win32_i486.hpp 1.19 07/05/05 17:04:57 JVM" +#pragma ident "@(#)os_win32_i486.hpp 1.20 07/06/28 10:31:42 JVM" #endif /* * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. @@ -31,6 +31,7 @@ static jlong (*atomic_cmpxchg_long_func) (jlong, volatile jlong*, jlong); static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); + static void setup_fpu(); static bool supports_sse() { return true; } // Not used in x86 Windows diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_Compilation.cpp --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_Compilation.cpp 1.159 07/05/17 15:49:28 JVM" +#pragma ident "@(#)c1_Compilation.cpp 1.160 07/06/18 14:25:23 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -290,13 +290,16 @@ } void Compilation::install_code(int frame_size) { + // frame_size is in 32-bit words so adjust it intptr_t words + assert(frame_size == frame_map()->framesize(), "must match"); + assert(in_bytes(frame_map()->framesize_in_bytes()) % sizeof(intptr_t) == 0, "must be at least pointer aligned"); _env->register_method( method(), osr_bci(), &_offsets, in_bytes(_frame_map->sp_offset_for_orig_pc()), code(), - frame_size, + in_bytes(frame_map()->framesize_in_bytes()) / sizeof(intptr_t), debug_info_recorder()->_oopmaps, exception_handler_table(), implicit_exception_table(), diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_FrameMap.cpp --- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_FrameMap.cpp 1.37 07/05/05 17:05:06 JVM" +#pragma ident "@(#)c1_FrameMap.cpp 1.38 07/06/18 14:25:23 JVM" #endif /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -83,7 +83,8 @@ args->append(opr); if (opr->is_address()) { LIR_Address* addr = opr->as_address_ptr(); - out_preserve = MAX2(out_preserve, addr->disp() / 4); + assert(addr->disp() == (int)addr->disp(), "out of range value"); + out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); } i += type2size[t]; } @@ -128,10 +129,13 @@ // C calls are always outgoing bool outgoing = true; LIR_Opr opr = map_to_opr(t, regs + i, outgoing); + // they might be of different types if for instance floating point + // values are passed in cpu registers, but the sizes must match. + assert(type2size[opr->type()] == type2size[t], "type mismatch"); args->append(opr); if (opr->is_address()) { LIR_Address* addr = opr->as_address_ptr(); - out_preserve = MAX2(out_preserve, addr->disp() / 4); + out_preserve = MAX2(out_preserve, (intptr_t)addr->disp() / 4); } i += type2size[t]; } @@ -172,7 +176,7 @@ LIR_Opr opr = _incoming_arguments->at(i); if (opr->is_address()) { LIR_Address* address = opr->as_address_ptr(); - _argument_locations->at_put(java_index, address->disp()); + _argument_locations->at_put(java_index, address->disp() - STACK_BIAS); _incoming_arguments->args()->at_put(i, LIR_OprFact::stack(java_index, as_BasicType(as_ValueType(address->type())))); } java_index += type2size[opr->type()]; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_GraphBuilder.cpp 1.255 07/05/17 15:49:34 JVM" +#pragma ident "@(#)c1_GraphBuilder.cpp 1.256 07/06/18 14:25:23 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -88,8 +88,8 @@ , _blocks(16) , _bci2block(new BlockList(scope->method()->code_size(), NULL)) , _next_block_number(0) - , _active(NULL, 0) // size not known yet - , _visited(NULL, 0) // size not known yet + , _active() // size not known yet + , _visited() // size not known yet , _next_loop_index(0) , _loop_map() // size not known yet { @@ -413,7 +413,7 @@ if (block->is_set(BlockBegin::parser_loop_header_flag)) { int header_loop_state = _loop_map.at(block_id); - assert(is_power_of_2(header_loop_state), "exactly one bit must be set"); + assert(is_power_of_2((unsigned)header_loop_state), "exactly one bit must be set"); // If the highest bit is set (i.e. when integer value is negative), the method // has 32 or more loops. This bit is never cleared because it is used for multiple loops @@ -3666,12 +3666,14 @@ _scope_data = scope_data()->parent(); } - bool GraphBuilder::append_unsafe_get_obj(ciMethod* callee, BasicType t, bool is_volatile) { if (InlineUnsafeOps) { Values* args = state()->pop_arguments(callee->arg_size()); null_check(args->at(0)); - Instruction* offset = append(new Convert(Bytecodes::_l2i, args->at(2), as_ValueType(T_INT))); + Instruction* offset = args->at(2); +#ifndef _LP64 + offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); +#endif Instruction* op = append(new UnsafeGetObject(t, args->at(1), offset, is_volatile)); push(op->type(), op); compilation()->set_has_unsafe_access(true); @@ -3684,7 +3686,10 @@ if (InlineUnsafeOps) { Values* args = state()->pop_arguments(callee->arg_size()); null_check(args->at(0)); - Instruction* offset = append(new Convert(Bytecodes::_l2i, args->at(2), as_ValueType(T_INT))); + Instruction* offset = args->at(2); +#ifndef _LP64 + offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); +#endif Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); compilation()->set_has_unsafe_access(true); kill_all(); @@ -3725,7 +3730,10 @@ } else { null_check(args->at(0)); } - Instruction* offset = append(new Convert(Bytecodes::_l2i, args->at(obj_arg_index + 1), as_ValueType(T_INT))); + Instruction* offset = args->at(obj_arg_index + 1); +#ifndef _LP64 + offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); +#endif Instruction* op = is_store ? append(new UnsafePrefetchWrite(args->at(obj_arg_index), offset)) : append(new UnsafePrefetchRead (args->at(obj_arg_index), offset)); compilation()->set_has_unsafe_access(true); @@ -3742,7 +3750,7 @@ // Pop off some args to speically handle, then push back Value newval = args->pop(); Value cmpval = args->pop(); - Value long_offset = args->pop(); + Value offset = args->pop(); Value src = args->pop(); Value unsafe_obj = args->pop(); @@ -3750,7 +3758,9 @@ // generation, but must be null checked null_check(unsafe_obj); - Instruction* offset = append(new Convert(Bytecodes::_l2i, long_offset, as_ValueType(T_INT))); +#ifndef _LP64 + offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); +#endif args->push(src); args->push(offset); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_Instruction.hpp --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_Instruction.hpp 1.195 07/05/05 17:05:07 JVM" +#pragma ident "@(#)c1_Instruction.hpp 1.196 07/06/18 14:25:24 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -1528,16 +1528,16 @@ , _exception_handler_pco(-1) , _lir(NULL) , _loop_index(-1) - , _live_in(NULL, 0) - , _live_out(NULL, 0) - , _live_gen(NULL, 0) - , _live_kill(NULL, 0) - , _fpu_register_usage(NULL, 0) + , _live_in() + , _live_out() + , _live_gen() + , _live_kill() + , _fpu_register_usage() , _fpu_stack_state(NULL) , _first_lir_instruction_id(-1) , _last_lir_instruction_id(-1) , _total_preds(0) - , _stores_to_locals(NULL, 0) + , _stores_to_locals() { set_bci(bci); } @@ -1962,7 +1962,11 @@ LEAF(OsrEntry, Instruction) public: // creation - OsrEntry() : Instruction(intType, false) { pin(); } +#ifdef _LP64 + OsrEntry() : Instruction(longType, false) { pin(); } +#else + OsrEntry() : Instruction(intType, false) { pin(); } +#endif // generic virtual void input_values_do(void f(Value*)) { } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp --- a/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_InstructionPrinter.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_InstructionPrinter.cpp 1.125 07/05/17 15:49:39 JVM" +#pragma ident "@(#)c1_InstructionPrinter.cpp 1.126 07/06/18 14:25:24 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -269,6 +269,8 @@ void InstructionPrinter::print_unsafe_object_op(UnsafeObjectOp* op, const char* name) { print_unsafe_op(op, name); print_value(op->object()); + output()->print(", "); + print_value(op->offset()); } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LIR.cpp --- a/hotspot/src/share/vm/c1/c1_LIR.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIR.cpp 1.118 07/05/05 17:05:04 JVM" +#pragma ident "@(#)c1_LIR.cpp 1.119 07/06/18 14:25:24 JVM" #endif /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -126,10 +126,17 @@ assert(scale() == times_1, "Scaled addressing mode not available on SPARC and should not be used"); assert(disp() == 0 || index()->is_illegal(), "can't have both"); #endif +#ifdef _LP64 + assert(base()->is_cpu_register(), "wrong base operand"); + assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand"); + assert(base()->type() == T_OBJECT || base()->type() == T_LONG, + "wrong type for addresses"); +#else assert(base()->is_single_cpu(), "wrong base operand"); assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand"); assert(base()->type() == T_OBJECT || base()->type() == T_INT, "wrong type for addresses"); +#endif } #endif @@ -183,7 +190,6 @@ case T_INT: case T_OBJECT: case T_ARRAY: - case T_ADDRESS: assert((kind_field() == cpu_register || kind_field() == stack_value) && size_field() == single_size, "must match"); break; @@ -216,6 +222,15 @@ void LIR_Op2::verify() const { #ifdef ASSERT + switch (code()) { + case lir_cmove: + break; + + default: + assert(!result_opr()->is_register() || !result_opr()->is_oop_register(), + "can't produce oops from arith"); + } + if (TwoOperandLIRForm) { switch (code()) { case lir_add: @@ -229,7 +244,6 @@ case lir_logic_or: case lir_logic_xor: case lir_shl: - case lir_shlx: case lir_shr: assert(in_opr1() == result_opr(), "opr1 and result must match"); assert(in_opr1()->is_valid() && in_opr2()->is_valid(), "must be valid"); @@ -561,7 +575,6 @@ case lir_logic_or: case lir_logic_xor: case lir_shl: - case lir_shlx: case lir_shr: case lir_ushr: { @@ -1567,7 +1580,6 @@ case lir_logic_or: s = "logic_or"; break; case lir_logic_xor: s = "logic_xor"; break; case lir_shl: s = "shift_left"; break; - case lir_shlx: s = "shift_left_long";break; case lir_shr: s = "shift_right"; break; case lir_ushr: s = "ushift_right"; break; case lir_alloc_array: s = "alloc_array"; break; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LIR.hpp --- a/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_LIR.hpp 1.133 07/05/05 17:05:05 JVM" +#pragma ident "@(#)c1_LIR.hpp 1.134 07/06/18 14:25:24 JVM" #endif /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -95,6 +95,15 @@ LIR_Const(jfloat f) { _value.set_type(T_FLOAT); _value.set_jfloat(f); } LIR_Const(jdouble d) { _value.set_type(T_DOUBLE); _value.set_jdouble(d); } LIR_Const(jobject o) { _value.set_type(T_OBJECT); _value.set_jobject(o); } + LIR_Const(void* p) { +#ifdef _LP64 + assert(sizeof(jlong) >= sizeof(p), "too small");; + _value.set_type(T_LONG); _value.set_jlong((jlong)p); +#else + assert(sizeof(jint) >= sizeof(p), "too small");; + _value.set_type(T_INT); _value.set_jint((jint)p); +#endif + } virtual BasicType type() const { return _value.get_type(); } virtual LIR_Const* as_constant() { return this; } @@ -107,6 +116,13 @@ jint as_jint_lo() const { type_check(T_LONG ); return low(_value.get_jlong()); } jint as_jint_hi() const { type_check(T_LONG ); return high(_value.get_jlong()); } +#ifdef _LP64 + address as_pointer() const { type_check(T_LONG ); return (address)_value.get_jlong(); } +#else + address as_pointer() const { type_check(T_INT ); return (address)_value.get_jint(); } +#endif + + jint as_jint_bits() const { type_check(T_FLOAT, T_INT); return _value.get_jint(); } jint as_jint_lo_bits() const { if (type() == T_DOUBLE) { @@ -244,8 +260,6 @@ OprKind kind_field() const { return (OprKind)(value() & kind_mask); } OprSize size_field() const { return (OprSize)(value() & size_mask); } - intptr_t value_without_type() const { return is_illegal() ? value() : value() & no_type_mask; } - static char type_char(BasicType t); public: @@ -286,7 +300,6 @@ case T_INT: case T_OBJECT: case T_ARRAY: - case T_ADDRESS: return single_size; break; @@ -296,12 +309,6 @@ } - // returns a new LIR_Opr with the OprType of from and all other information the current LIR_Opr - LIR_Opr with_type_of(LIR_Opr from) { - assert(!is_pointer() && !from->is_pointer(), "only simple LIR_Oprs"); - return (LIR_Opr)(from->type_field() | value_without_type()); - } - void validate_type() const PRODUCT_RETURN; BasicType type() const { @@ -316,23 +323,17 @@ char type_char() const { return type_char((is_pointer()) ? pointer()->type() : type()); } - bool is_same(LIR_Opr opr) const { return this == opr; } - // checks whether types are same or one type is unknown - bool is_type_compatible(LIR_Opr opr) const { - return type_field() == unknown_type || - opr->type_field() == unknown_type || - type_field() == opr->type_field(); + bool is_equal(LIR_Opr opr) const { return this == opr; } + // checks whether types are same + bool is_same_type(LIR_Opr opr) const { + assert(type_field() != unknown_type && + opr->type_field() != unknown_type, "shouldn't see unknown_type"); + return type_field() == opr->type_field(); } - - // is_type_compatible and equal - bool is_equivalent(LIR_Opr opr) const { - if (!is_pointer()) { - if (is_type_compatible(opr) && data() == opr->data() && kind_field() == opr->kind_field() && is_xmm_register() == opr->is_xmm_register()) { - return true; - } - } - // could also do checks for other pointers types - return is_same(opr); + bool is_same_register(LIR_Opr opr) { + return (is_register() && opr->is_register() && + kind_field() == opr->kind_field() && + (value() & no_type_mask) == (opr->value() & no_type_mask)); } bool is_pointer() const { return check_value_mask(pointer_mask, pointer_value); } @@ -409,6 +410,16 @@ Register as_register_lo() const; Register as_register_hi() const; + Register as_pointer_register() { +#ifdef _LP64 + if (is_double_cpu()) { + assert(as_register_lo() == as_register_hi(), "should be a single register"); + return as_register_lo(); + } +#endif + return as_register(); + } + #ifdef IA32 XMMRegister as_xmm_float_reg() const; XMMRegister as_xmm_double_reg() const; @@ -606,6 +617,8 @@ static LIR_Opr doubleConst(jdouble d) { return (LIR_Opr)(new LIR_Const(d)); } static LIR_Opr oopConst(jobject o) { return (LIR_Opr)(new LIR_Const(o)); } static LIR_Opr address(LIR_Address* a) { return (LIR_Opr)a; } + static LIR_Opr intptrConst(void* p) { return (LIR_Opr)(new LIR_Const(p)); } + static LIR_Opr intptrConst(intptr_t v) { return (LIR_Opr)(new LIR_Const((void*)v)); } static LIR_Opr illegal() { return (LIR_Opr)-1; } static LIR_Opr value_type(ValueType* type); @@ -713,7 +726,6 @@ , lir_logic_or , lir_logic_xor , lir_shl - , lir_shlx , lir_shr , lir_ushr , lir_alloc_array @@ -1534,7 +1546,6 @@ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; - // LIR_OpProfileCall class LIR_OpProfileCall : public LIR_Op { friend class LIR_OpVisitState; @@ -1573,7 +1584,6 @@ class LIR_InsertionBuffer; - //--------------------------------LIR_List--------------------------------------------------- // Maintains a list of LIR instructions (one instance of LIR_List per basic block) // The LIR instructions are appended by the LIR_List class itself; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LIRAssembler.cpp --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRAssembler.cpp 1.133 07/05/05 17:05:08 JVM" +#pragma ident "@(#)c1_LIRAssembler.cpp 1.134 07/06/18 14:25:25 JVM" #endif /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -649,7 +649,6 @@ break; case lir_shl: - case lir_shlx: case lir_shr: case lir_ushr: if (op->in_opr2()->is_constant()) { @@ -787,7 +786,7 @@ _masm->verify_oop(r->as_Register()); #endif } else { - _masm->verify_stack_oop(r->reg2stack() * wordSize); + _masm->verify_stack_oop(r->reg2stack() * VMRegImpl::stack_slot_size); } } s.next(); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)c1_LIRGenerator.cpp 1.22 07/05/17 15:49:41 JVM" +#pragma ident "@(#)c1_LIRGenerator.cpp 1.23 07/06/18 14:25:25 JVM" #endif /* * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -810,9 +810,10 @@ LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) { + assert(type2size[t] == type2size[value->type()], "size mismatch"); if (!value->is_register()) { // force into a register - LIR_Opr r = new_register(t); + LIR_Opr r = new_register(value->type()); __ move(value, r); value = r; } @@ -991,34 +992,6 @@ } -void LIRGenerator::write_barrier(LIR_Opr addr) { - if (addr->is_address()) { - LIR_Address* address = (LIR_Address*)addr; - LIR_Opr ptr = new_register(T_OBJECT); - if (!address->index()->is_valid() && address->disp() == 0) { - __ move(address->base(), ptr); - } else { - __ leal(addr, ptr); - } - addr = ptr; - } - assert(addr->is_register(), "must be a register at this point"); - - LIR_Opr tmp = new_register(T_OBJECT); - if (TwoOperandLIRForm) { - __ move(addr, tmp); - __ unsigned_shift_right(tmp, CardTableModRefBS::card_shift, tmp); - } else { - __ unsigned_shift_right(addr, CardTableModRefBS::card_shift, tmp); - } - if (can_inline_as_constant(card_table_base())) { - __ move(LIR_OprFact::intConst(0), new LIR_Address(tmp, card_table_base()->as_jint(), T_BYTE)); - } else { - __ move(LIR_OprFact::intConst(0), new LIR_Address(tmp, load_constant(card_table_base()), T_BYTE)); - } -} - - void LIRGenerator::do_ExceptionObject(ExceptionObject* x) { assert(block()->is_set(BlockBegin::exception_entry_flag), "ExceptionObject only allowed in exception handler block"); assert(block()->next() == x, "ExceptionObject must be first instruction of block"); @@ -1267,6 +1240,58 @@ return result; } +// Various barriers + +void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { + switch (Universe::heap()->barrier_set()->kind()) { + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + CardTableModRef_post_barrier(addr, new_val); + break; + case BarrierSet::ModRef: + case BarrierSet::Other: + // No post barriers + break; + default : + ShouldNotReachHere(); + } +} + +void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { + + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(sizeof(*((CardTableModRefBS*)bs)->byte_map_base) == sizeof(jbyte), "adjust this code"); + LIR_Const* card_table_base = new LIR_Const(((CardTableModRefBS*)bs)->byte_map_base); + if (addr->is_address()) { + LIR_Address* address = addr->as_address_ptr(); + LIR_Opr ptr = new_register(T_OBJECT); + if (!address->index()->is_valid() && address->disp() == 0) { + __ move(address->base(), ptr); + } else { + assert(address->disp() != max_jint, "lea doesn't support patched addresses!"); + __ leal(addr, ptr); + } + addr = ptr; + } + assert(addr->is_register(), "must be a register at this point"); + + LIR_Opr tmp = new_pointer_register(); + if (TwoOperandLIRForm) { + __ move(addr, tmp); + __ unsigned_shift_right(tmp, CardTableModRefBS::card_shift, tmp); + } else { + __ unsigned_shift_right(addr, CardTableModRefBS::card_shift, tmp); + } + if (can_inline_as_constant(card_table_base)) { + __ move(LIR_OprFact::intConst(0), + new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE)); + } else { + __ move(LIR_OprFact::intConst(0), + new LIR_Address(tmp, load_constant(card_table_base), + T_BYTE)); + } +} + //------------------------field access-------------------------------------- @@ -1302,6 +1327,7 @@ bool needs_patching = x->needs_patching(); bool is_volatile = x->field()->is_volatile(); BasicType field_type = x->field_type(); + bool is_oop = (field_type == T_ARRAY || field_type == T_OBJECT); CodeEmitInfo* info = NULL; if (needs_patching) { @@ -1374,8 +1400,8 @@ __ store(value.result(), address, info, patch_code); } - if (field_type == T_ARRAY || field_type == T_OBJECT) { - write_barrier(object.result()); + if (is_oop) { + post_barrier(object.result(), value.result()); } if (is_volatile && os::is_MP()) { @@ -1677,12 +1703,14 @@ assert(!x->has_index() || idx.value() == x->index(), "should match"); LIR_Opr base_op = base.result(); +#ifndef _LP64 if (x->base()->type()->tag() == longTag) { base_op = new_register(T_INT); __ convert(Bytecodes::_l2i, base.result(), base_op); } else { assert(x->base()->type()->tag() == intTag, "must be"); } +#endif BasicType dst_type = x->basic_type(); LIR_Opr index_op = idx.result(); @@ -1740,8 +1768,15 @@ set_no_result(x); - LIR_Opr intBase = new_register(T_INT); - __ convert(Bytecodes::_l2i, base.result(), intBase); + LIR_Opr base_op = base.result(); +#ifndef _LP64 + if (x->base()->type()->tag() == longTag) { + base_op = new_register(T_INT); + __ convert(Bytecodes::_l2i, base.result(), base_op); + } else { + assert(x->base()->type()->tag() == intTag, "must be"); + } +#endif LIR_Opr index_op = idx.result(); if (log2_scale != 0) { @@ -1751,7 +1786,7 @@ __ shift_left(index_op, log2_scale, index_op); } - LIR_Address* addr = new LIR_Address(intBase, index_op, x->basic_type()); + LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type()); __ move(value.result(), addr); } @@ -2182,7 +2217,7 @@ // emit invoke code bool optimized = x->target_is_loaded() && x->target_is_final(); - assert(receiver->is_illegal() || receiver->is_equivalent(LIR_Assembler::receiverOpr()), "must match"); + assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match"); switch (x->code()) { case Bytecodes::_invokestatic: diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LIRGenerator.hpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_LIRGenerator.hpp 1.13 07/05/05 17:05:07 JVM" +#pragma ident "@(#)c1_LIRGenerator.hpp 1.14 07/06/18 14:25:25 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -252,6 +252,19 @@ LIR_Opr call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info); LIR_Opr call_runtime(Value arg1, Value arg2, address entry, ValueType* result_type, CodeEmitInfo* info); + // GC Barriers + + // generic interface + + void post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); + + // specific implementations + + // post barriers + + void CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val); + + static LIR_Opr result_register_for(ValueType* type, bool callee = false); ciObject* get_jobject_constant(Value value); @@ -325,8 +338,6 @@ } LIR_Address* emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr, BasicType type, bool needs_card_mark); - void write_barrier(LIR_Opr addr); - // machine preferences and characteristics bool can_inline_as_constant(Value i) const; bool can_inline_as_constant(LIR_Const* c) const; @@ -360,6 +371,15 @@ LIR_Opr new_register(Value value) { return new_register(as_BasicType(value->type())); } LIR_Opr new_register(ValueType* type) { return new_register(as_BasicType(type)); } + // returns a register suitable for doing pointer math + LIR_Opr new_pointer_register() { +#ifdef _LP64 + return new_register(T_LONG); +#else + return new_register(T_INT); +#endif + } + static LIR_Condition lir_cond(If::Condition cond) { LIR_Condition l; switch (cond) { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)c1_LinearScan.cpp 1.12 07/05/05 17:05:10 JVM" +#pragma ident "@(#)c1_LinearScan.cpp 1.13 07/06/18 14:25:25 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -2547,8 +2547,8 @@ } else { // double-size operands - LocationValue* first; - LocationValue* second; + ScopeValue* first; + ScopeValue* second; if (opr->is_double_stack()) { Location loc1, loc2; @@ -2559,6 +2559,11 @@ second = new LocationValue(loc2); } else if (opr->is_double_cpu()) { +#ifdef _LP64 + VMReg rname_first = opr->as_register_lo()->as_VMReg(); + first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first)); + second = &_int_0_scope_value; +#else VMReg rname_first = opr->as_register_lo()->as_VMReg(); VMReg rname_second = opr->as_register_hi()->as_VMReg(); @@ -2571,6 +2576,7 @@ first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first)); second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second)); +#endif #ifdef IA32 } else if (opr->is_double_xmm()) { @@ -2862,15 +2868,18 @@ op->verify(); #endif +#ifndef _LP64 // remove useless moves if (op->code() == lir_move) { assert(op->as_Op1() != NULL, "move must be LIR_Op1"); LIR_Op1* move = (LIR_Op1*)op; - if (!move->result_opr()->is_pointer() && !move->in_opr()->is_pointer() && move->in_opr()->is_equivalent(move->result_opr()->with_type_of(move->in_opr()))) { + if (!move->result_opr()->is_pointer() && !move->in_opr()->is_pointer() && + move->in_opr()->is_same_register(move->result_opr())) { instructions->at_put(j, NULL); has_dead = true; } } +#endif } if (has_dead) { @@ -6379,7 +6388,6 @@ case lir_logic_or: case lir_logic_xor: case lir_shl: - case lir_shlx: case lir_shr: case lir_ushr: inc_counter(counter_alu); break; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/code/relocInfo.hpp --- a/hotspot/src/share/vm/code/relocInfo.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/code/relocInfo.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)relocInfo.hpp 1.86 07/05/05 17:05:22 JVM" +#pragma ident "@(#)relocInfo.hpp 1.87 07/06/19 09:08:11 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -1201,10 +1201,12 @@ class poll_Relocation : public Relocation { + bool is_data() { return true; } relocInfo::relocType type() { return relocInfo::poll_type; } }; class poll_return_Relocation : public Relocation { + bool is_data() { return true; } relocInfo::relocType type() { return relocInfo::poll_return_type; } }; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)cmsOopClosures.hpp 1.2 07/05/16 16:53:01 JVM" +#pragma ident "@(#)cmsOopClosures.hpp 1.3 07/06/22 16:49:48 JVM" #endif /* * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. @@ -32,8 +32,10 @@ class CMSBitMap; class CMSMarkStack; class CMSCollector; -class OopTaskQueue; -class OopTaskQueueSet; +template class GenericTaskQueue; +typedef GenericTaskQueue OopTaskQueue; +template class GenericTaskQueueSet; +typedef GenericTaskQueueSet OopTaskQueueSet; class MarkFromRootsClosure; class Par_MarkFromRootsClosure; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)parOopClosures.hpp 1.1 07/05/16 10:51:44 JVM" +#pragma ident "@(#)parOopClosures.hpp 1.2 07/06/22 16:49:48 JVM" #endif /* * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. @@ -29,7 +29,8 @@ class ParScanThreadState; class ParNewGeneration; -typedef class OopTaskQueueSet ObjToScanQueueSet; +template class GenericTaskQueueSet; +typedef GenericTaskQueueSet ObjToScanQueueSet; class ParallelTaskTerminator; class ParScanClosure: public OopsInGenClosure { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)pcTasks.cpp 1.21 07/05/05 17:05:27 JVM" +#pragma ident "@(#)pcTasks.cpp 1.22 07/06/22 16:49:49 JVM" #endif /* * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -149,7 +149,7 @@ { ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); - GenTaskQueueSet* qset = ParCompactionManager::chunk_array()->task_queue_set(); + TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); ParallelTaskTerminator terminator(parallel_gc_threads, qset); GCTaskQueue* q = GCTaskQueue::create(); for(uint i=0; iregister_queue(i, _manager_array[i]->marking_stack()); +#ifdef USE_ChunkTaskQueueWithOverflow + chunk_array()->register_queue(i, _manager_array[i]->chunk_stack()->task_queue()); +#else chunk_array()->register_queue(i, _manager_array[i]->chunk_stack()); +#endif } // The VMThread gets its own ParCompactionManager, which is not available @@ -175,13 +179,12 @@ } bool ParCompactionManager::retrieve_for_processing(size_t& chunk_index) { - #ifdef USE_ChunkTaskQueueWithOverflow return chunk_stack()->retrieve(chunk_index); #else // Should not be used in the parallel case ShouldNotReachHere(); - return NULL; + return false; #endif } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)psParallelCompact.cpp 1.61 07/06/08 23:12:00 JVM" +#pragma ident "@(#)psParallelCompact.cpp 1.51 06/08/28 10:52:10 JVM" #endif /* * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -2372,7 +2372,7 @@ ParallelScavengeHeap* heap = gc_heap(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); - GenTaskQueueSet* qset = ParCompactionManager::chunk_array()->task_queue_set(); + TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); ParallelTaskTerminator terminator(parallel_gc_threads, qset); PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); @@ -2677,7 +2677,7 @@ PSOldGen* old_gen = heap->old_gen(); old_gen->start_array()->reset(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); - GenTaskQueueSet* qset = ParCompactionManager::chunk_array()->task_queue_set(); + TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); ParallelTaskTerminator terminator(parallel_gc_threads, qset); GCTaskQueue* q = GCTaskQueue::create(); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/includeDB_compiler2 --- a/hotspot/src/share/vm/includeDB_compiler2 Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/includeDB_compiler2 Thu Jul 05 23:47:33 2007 +0000 @@ -481,9 +481,11 @@ graphKit.hpp type.hpp idealKit.cpp addnode.hpp +idealKit.cpp callnode.hpp idealKit.cpp cfgnode.hpp idealKit.cpp idealKit.hpp +idealKit.hpp connode.hpp idealKit.hpp mulnode.hpp idealKit.hpp phaseX.hpp idealKit.hpp subnode.hpp diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/includeDB_gc_parallel --- a/hotspot/src/share/vm/includeDB_gc_parallel Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/includeDB_gc_parallel Thu Jul 05 23:47:33 2007 +0000 @@ -40,12 +40,18 @@ instanceKlass.cpp oop.pcgc.inline.hpp instanceKlass.cpp psPromotionManager.inline.hpp instanceKlass.cpp psScavenge.inline.hpp +instanceKlass.cpp parOopClosures.inline.hpp +instanceKlassKlass.cpp cardTableRS.hpp +instanceKlassKlass.cpp oop.pcgc.inline.hpp instanceKlassKlass.cpp psPromotionManager.inline.hpp instanceKlassKlass.cpp psScavenge.inline.hpp +instanceKlassKlass.cpp parOopClosures.inline.hpp +instanceRefKlass.cpp oop.pcgc.inline.hpp instanceRefKlass.cpp psPromotionManager.inline.hpp instanceRefKlass.cpp psScavenge.inline.hpp +instanceRefKlass.cpp parOopClosures.inline.hpp java.cpp concurrentMarkSweepThread.hpp java.cpp psScavenge.hpp @@ -77,6 +83,7 @@ objArrayKlass.cpp oop.pcgc.inline.hpp objArrayKlass.cpp psPromotionManager.inline.hpp objArrayKlass.cpp psScavenge.inline.hpp +objArrayKlass.cpp parOopClosures.inline.hpp oop.pcgc.inline.hpp parNewGeneration.hpp oop.pcgc.inline.hpp parallelScavengeHeap.hpp diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/interpreter/bytecodeStream.cpp --- a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)bytecodeStream.cpp 1.46 07/06/04 15:38:06 JVM" +#pragma ident "@(#)bytecodeStream.cpp 1.47 07/06/20 14:52:27 JVM" #endif /* * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -32,7 +32,7 @@ assert(!is_last_bytecode(), "should have been checked"); // set next bytecode position address bcp = RawBytecodeStream::bcp(); - int l = Bytecodes::special_length_at(bcp); + int l = Bytecodes::raw_special_length_at(bcp); if (l <= 0 || (_bci + l) > _end_bci) { code = Bytecodes::_illegal; } else { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/interpreter/bytecodeStream.hpp --- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)bytecodeStream.hpp 1.53 07/06/13 12:09:38 JVM" +#pragma ident "@(#)bytecodeStream.hpp 1.54 07/06/20 14:52:27 JVM" #endif /* * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -85,8 +85,6 @@ address bcp = RawBytecodeStream::bcp(); code = Bytecodes::code_or_bp_at(bcp); - // Assert that we find no breakpoints or rewritten code. - assert(code != Bytecodes::_breakpoint, "unexpected breakpoint"); // set next bytecode position int l = Bytecodes::length_for(code); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/interpreter/bytecodes.cpp --- a/hotspot/src/share/vm/interpreter/bytecodes.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)bytecodes.cpp 1.96 07/06/04 15:38:07 JVM" +#pragma ident "@(#)bytecodes.cpp 1.97 07/06/20 14:52:27 JVM" #endif /* * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -58,7 +58,7 @@ } int Bytecodes::special_length_at(address bcp) { - Code code = code_or_bp_at(bcp); + Code code = code_at(bcp); switch (code) { case _wide: return wide_length_for(cast(*(bcp + 1))); @@ -72,9 +72,6 @@ return (len > 0 && len == (int)len) ? len : -1; } - case _breakpoint: - return 1; - case _lookupswitch: // fall through case _fast_binaryswitch: // fall through case _fast_linearswitch: @@ -89,6 +86,25 @@ return 0; } +// At a breakpoint instruction, this returns the breakpoint's length, +// otherwise, it's the same as special_length_at(). This is used by +// the RawByteCodeStream, which wants to see the actual bytecode +// values (including breakpoint). RawByteCodeStream is used by the +// verifier when reading in bytecode to verify. Other mechanisms that +// run at runtime (such as generateOopMaps) need to iterate over the code +// and don't expect to see breakpoints: they want to see the instruction +// which was replaces so that they can get the correct length and find +// the next bytecode. +int Bytecodes::raw_special_length_at(address bcp) { + Code code = code_or_bp_at(bcp); + if (code == _breakpoint) { + return 1; + } else { + return special_length_at(bcp); + } +} + + void Bytecodes::def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap) { def(code, name, format, wide_format, result_type, depth, can_trap, code); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/interpreter/bytecodes.hpp --- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)bytecodes.hpp 1.78 07/06/13 12:09:45 JVM" +#pragma ident "@(#)bytecodes.hpp 1.79 07/06/20 14:52:28 JVM" #endif /* * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. @@ -344,6 +344,7 @@ return (wf == NULL) ? 0 : (int)strlen(wf); } static int special_length_at(address bcp); + static int raw_special_length_at(address bcp); static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); } static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)genCollectedHeap.cpp 1.189 07/06/12 09:41:51 JVM" +#pragma ident "@(#)genCollectedHeap.cpp 1.190 07/06/15 16:44:02 JVM" #endif /* * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -565,11 +565,16 @@ } } + // Update "complete" boolean wrt what actually transpired -- + // for instance, a promotion failure could have led to + // a whole heap collection. + complete = complete || (max_level_collected == n_gens() - 1); + if (PrintGCDetails) { print_heap_change(gch_prev_used); // Print perm gen info for full GC with PrintGCDetails flag. - if (full && max_level == n_gens() - 1) { + if (complete) { print_perm_heap_change(perm_prev_used); } } @@ -578,6 +583,7 @@ // Adjust generation sizes. _gens[j]->compute_new_size(); } + if (complete) { // Ask the permanent generation to adjust size for full collections perm()->compute_new_size(); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)graphKit.cpp 1.128 07/05/17 17:43:32 JVM" +#pragma ident "@(#)graphKit.cpp 1.129 07/06/18 14:25:26 JVM" #endif /* * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -541,11 +541,10 @@ // Weblogic sometimes mutates the detail message of exceptions // using reflection. int offset = java_lang_Throwable::get_detailMessage_offset(); - uint alias_idx = C->get_alias_index(ex_con->add_offset(offset)); + const TypePtr* adr_typ = ex_con->add_offset(offset); Node *adr = basic_plus_adr(ex_node, ex_node, offset); - Node *store = store_to_memory(control(), adr, null(), T_OBJECT, alias_idx, false); - store_barrier(store, T_OBJECT, ex_node, adr, null()); + Node *store = store_oop_to_object(control(), ex_node, adr, adr_typ, null(), ex_con, T_OBJECT); add_exception_state(make_exception_state(ex_node)); return; @@ -1352,6 +1351,102 @@ return st; } +void GraphKit::pre_barrier(Node* ctl, + Node* obj, + Node* adr, + uint adr_idx, + Node *val, + const Type* val_type, + BasicType bt) { + BarrierSet* bs = Universe::heap()->barrier_set(); + set_control(ctl); + switch (bs->kind()) { + + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + case BarrierSet::ModRef: + break; + + case BarrierSet::Other: + default : + ShouldNotReachHere(); + + } +} + +void GraphKit::post_barrier(Node* ctl, + Node* store, + Node* obj, + Node* adr, + uint adr_idx, + Node *val, + BasicType bt, + bool use_precise) { + BarrierSet* bs = Universe::heap()->barrier_set(); + set_control(ctl); + switch (bs->kind()) { + + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + write_barrier_post(store, obj, adr, val, use_precise); + break; + + case BarrierSet::ModRef: + break; + + case BarrierSet::Other: + default : + ShouldNotReachHere(); + + } +} + +Node* GraphKit::store_oop_to_object(Node* ctl, + Node* obj, + Node* adr, + const TypePtr* adr_type, + Node *val, + const Type* val_type, + BasicType bt) { + uint adr_idx = C->get_alias_index(adr_type); + Node* store; + pre_barrier(ctl, obj, adr, adr_idx, val, val_type, bt); + store = store_to_memory(control(), adr, val, bt, adr_idx); + post_barrier(control(), store, obj, adr, adr_idx, val, bt, false); + return store; +} + +Node* GraphKit::store_oop_to_array(Node* ctl, + Node* obj, + Node* adr, + const TypePtr* adr_type, + Node *val, + const Type* val_type, + BasicType bt) { + uint adr_idx = C->get_alias_index(adr_type); + Node* store; + pre_barrier(ctl, obj, adr, adr_idx, val, val_type, bt); + store = store_to_memory(control(), adr, val, bt, adr_idx); + post_barrier(control(), store, obj, adr, adr_idx, val, bt, true); + return store; +} + +Node* GraphKit::store_oop_to_unknown(Node* ctl, + Node* obj, + Node* adr, + const TypePtr* adr_type, + Node *val, + const Type* val_type, + BasicType bt) { + uint adr_idx = C->get_alias_index(adr_type); + Node* store; + pre_barrier(ctl, obj, adr, adr_idx, val, val_type, bt); + store = store_to_memory(control(), adr, val, bt, adr_idx); + post_barrier(control(), store, obj, adr, adr_idx, val, bt, true); + return store; +} + + //-------------------------array_element_address------------------------- Node* GraphKit::array_element_address(Node* ary, Node* idx, BasicType elembt, const TypeInt* sizetype) { @@ -1649,8 +1744,8 @@ //------------------------------store_barrier---------------------------------- // Insert a write-barrier store. This is to let generational GC work; we have // to flag all oop-stores before the next GC point. -void GraphKit::store_barrier(Node* oop_store, BasicType obj_type, - Node* obj, Node* adr, Node* val) { +void GraphKit::write_barrier_post(Node* oop_store, Node* obj, Node* adr, + Node* val, bool use_precise) { // No store check needed if we're storing a NULL or an old object // (latter case is probably a string constant). The concurrent // mark sweep garbage collector, however, needs to have all nonNull @@ -1665,11 +1760,11 @@ return; } - if (obj_type == T_OBJECT) { + if (!use_precise) { // All card marks for a (non-array) instance are in one place: adr = obj; } - // (Else it's an array, and we want more precise card marks.) + // (Else it's an array (or unknown), and we want more precise card marks.) assert(adr != NULL, ""); // Get the alias_index for raw card-mark memory @@ -1681,9 +1776,8 @@ "Only one we handle so far."); CardTableModRefBS* ct = (CardTableModRefBS*)(Universe::heap()->barrier_set()); - Node *a = _gvn.transform(new (C, 3) URShiftXNode( cast, _gvn.intcon(CardTableModRefBS::card_shift) )); + Node *b = _gvn.transform(new (C, 3) URShiftXNode( cast, _gvn.intcon(CardTableModRefBS::card_shift) )); // We store into a byte array, so do not bother to left-shift by zero - Node *b = a; // Get base of card map assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); @@ -2703,7 +2797,6 @@ Node* extra_slow_test, bool raw_mem_only, // affect only raw memory Node* *return_size_val) { - // Compute size in doublewords // The size is always an integral number of doublewords, represented // as a positive bytewise size stored in the klass's layout_helper. @@ -2713,7 +2806,6 @@ int layout_is_con = (layout_val == NULL); if (extra_slow_test == NULL) extra_slow_test = intcon(0); - // Generate the initial go-slow test. It's either ALWAYS (return a // Node for 1) or NEVER (return a NULL) or perhaps (in the reflective // case) a computed value derived from the layout_helper. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/graphKit.hpp --- a/hotspot/src/share/vm/opto/graphKit.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/graphKit.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)graphKit.hpp 1.56 07/05/17 15:58:52 JVM" +#pragma ident "@(#)graphKit.hpp 1.57 07/06/18 14:25:26 JVM" #endif /* * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -426,6 +426,51 @@ int adr_idx, bool require_atomic_access = false); + + // All in one pre-barrier, store, post_barrier + // Insert a write-barrier'd store. This is to let generational GC + // work; we have to flag all oop-stores before the next GC point. + // + // It comes in 3 flavors of store to an object, array, or unknown. + // We use precise card marks for arrays to avoid scanning the entire + // array. We use imprecise for object. We use precise for unknown + // since we don't know if we have an array or and object or even + // where the object starts. + // + // If val==NULL, it is taken to be a completely unknown value. QQQ + + Node* store_oop_to_object(Node* ctl, + Node* obj, // containing obj + Node* adr, // actual adress to store val at + const TypePtr* adr_type, + Node* val, + const Type* val_type, + BasicType bt); + + Node* store_oop_to_array(Node* ctl, + Node* obj, // containing obj + Node* adr, // actual adress to store val at + const TypePtr* adr_type, + Node* val, + const Type* val_type, + BasicType bt); + + // Could be an array or object we don't know at compile time (unsafe ref.) + Node* store_oop_to_unknown(Node* ctl, + Node* obj, // containing obj + Node* adr, // actual adress to store val at + const TypePtr* adr_type, + Node* val, + const Type* val_type, + BasicType bt); + + // For the few case where the barriers need special help + void pre_barrier(Node* ctl, Node* obj, Node* adr, uint adr_idx, + Node* val, const Type* val_type, BasicType bt); + + void post_barrier(Node* ctl, Node* store, Node* obj, Node* adr, uint adr_idx, + Node* val, BasicType bt, bool use_precise); + // Return addressing for an array element. Node* array_element_address(Node* ary, Node* idx, BasicType elembt, // Optional constraint on the array size: @@ -528,14 +573,8 @@ return C->too_many_recompiles(method(), bci(), reason); } - // Insert a write-barrier'd store. This is to let generational GC - // work; we have to flag all oop-stores before the next GC point. - // The obj_type value is one of T_OBJECT, T_ARRAY, or T_CONFLICT, - // meaning obj is an instance, an array, or either (statically unknown). - // If val==NULL, it is taken to be a completely unknown value. - void store_barrier(Node *store, BasicType obj_type, - // dest object, addr within obj, and stored value: - Node* obj, Node* adr, Node* val); + // vanilla/CMS post barrier + void write_barrier_post(Node *store, Node* obj, Node* adr, Node* val, bool use_precise); // Helper function to round double arguments before a call void round_double_arguments(ciMethod* dest_method); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/idealKit.cpp --- a/hotspot/src/share/vm/opto/idealKit.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/idealKit.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)idealKit.cpp 1.7 07/05/05 17:06:29 JVM" +#pragma ident "@(#)idealKit.cpp 1.8 07/06/18 14:25:26 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -29,15 +29,23 @@ #include "incls/_idealKit.cpp.incl" // Static initialization -const uint IdealKit::first_var = 1; + +// This declares the position where vars are kept in the cvstate +// For some degree of consistency we use the TypeFunc enum to +// soak up spots in the inputs even though we only use early Control +// and Memory slots. (So far.) +const uint IdealKit::first_var = TypeFunc::Parms + 1; //----------------------------IdealKit----------------------------------------- -IdealKit::IdealKit(PhaseGVN &gvn, Node* control, bool delay_all_transforms) : +IdealKit::IdealKit(PhaseGVN &gvn, Node* control, Node* mem, bool delay_all_transforms) : _gvn(gvn), C(gvn.C) { _initial_ctrl = control; + _initial_memory = mem; _delay_all_transforms = delay_all_transforms; _var_ct = 0; _cvstate = NULL; + // We can go memory state free or else we need the entire memory state + assert(mem == NULL || mem->Opcode() == Op_MergeMem, "memory must be pre-split"); int init_size = 5; _pending_cvstates = new (C->node_arena()) GrowableArray(C->node_arena(), init_size, 0, 0); _delay_transform = new (C->node_arena()) GrowableArray(C->node_arena(), init_size, 0, 0); @@ -52,14 +60,25 @@ void IdealKit::if_then(Node* left, BoolTest::mask relop, Node* right, float prob, float cnt, bool push_new_state) { assert((state() & (BlockS|LoopS|IfThenS|ElseS)), "bad state for new If"); - Node* bol = Bool(CmpI(left, right), relop); + Node* bol; + if (left->bottom_type()->isa_ptr() == NULL) { + if (left->bottom_type()->isa_int() != NULL) { + bol = Bool(CmpI(left, right), relop); + } else { + assert(left->bottom_type()->isa_long() != NULL, "what else?"); + bol = Bool(CmpL(left, right), relop); + } + + } else { + bol = Bool(CmpP(left, right), relop); + } // Delay gvn.tranform on if-nodes until construction is finished // to prevent a constant bool input from discarding a control output. IfNode* iff = delay_transform(new (C, 2) IfNode(ctrl(), bol, prob, cnt))->as_If(); Node* then = IfTrue(iff); Node* elsen = IfFalse(iff); Node* else_cvstate = copy_cvstate(); - else_cvstate->set_req(0, elsen); + else_cvstate->set_req(TypeFunc::Control, elsen); _pending_cvstates->push(else_cvstate); DEBUG_ONLY(if (push_new_state) _state->push(IfThenS)); set_ctrl(then); @@ -79,16 +98,42 @@ } //-------------------------------end_if------------------------------------- -// Merge the "then" and "else" cvstates from an "if" via: -// create label, generate a goto from the current cvstate to the -// new label, pop the other cvstate from the if ("else" cvstate if -// no else_() and "then" cvstate if there was), and bind the label -// to the popped cvstate. +// Merge the "then" and "else" cvstates. +// +// The if_then() pushed the current state for later use +// as the initial state for a future "else" clause. The +// current state then became the initial state for the +// then clause. If an "else" clause was encountered, it will +// pop the top state and use it for it's initial state. +// It will also push the current state (the state at the end of +// the "then" clause) for latter use at the end_if. +// +// At the endif, the states are: +// 1) else exists a) current state is end of "else" clause +// b) top stack state is end of "then" clause +// +// 2) no else: a) current state is end of "then" clause +// b) top stack state is from the "if_then" which +// would have been the initial state of the else. +// +// Merging the states is accomplished by: +// 1) make a label for the merge +// 2) terminate the current state with a goto to the label +// 3) pop the top state from the stack and make it the +// current state +// 4) bind the label at the current state. Binding a label +// terminates the current state with a goto to the +// label and makes the label's state the current state. +// void IdealKit::end_if() { assert(state() & (IfThenS|ElseS), "bad state for new Endif"); Node* lab = make_label(1); + + // Node* join_state = _pending_cvstates->pop(); + /* merging, join */ goto_(lab); _cvstate = _pending_cvstates->pop(); + bind(lab); DEBUG_ONLY(_state->pop()); } @@ -115,7 +160,7 @@ if_then(value(iv), relop, limit, prob, cnt, false /* no new state */); DEBUG_ONLY(_state->push(LoopS)); assert(ctrl()->is_IfTrue(), "true branch stays in loop"); - assert(_pending_cvstates->top()->in(0)->is_IfFalse(), "false branch exits loop"); + assert(_pending_cvstates->top()->in(TypeFunc::Control)->is_IfFalse(), "false branch exits loop"); } //-------------------------------end_loop------------------------------------- @@ -141,7 +186,7 @@ Node* lab = new_cvstate(); int sz = 1 + goto_ct + 1 /* fall thru */; Node* reg = delay_transform(new (C, sz) RegionNode(sz)); - lab->init_req(0, reg); + lab->init_req(TypeFunc::Control, reg); return lab; } @@ -160,7 +205,7 @@ // all live values have phis created. Used to create phis // at loop-top regions. void IdealKit::goto_(Node* lab, bool bind) { - Node* reg = lab->in(0); + Node* reg = lab->in(TypeFunc::Control); // find next empty slot in region uint slot = 1; while (slot < reg->req() && reg->in(slot) != NULL) slot++; @@ -170,23 +215,40 @@ reg->init_req(slot, ctrl()); assert(first_var + _var_ct == _cvstate->req(), "bad _cvstate size"); for (uint i = first_var; i < _cvstate->req(); i++) { + + // l is the value of var reaching the label. Could be a single value + // reaching the label, or a phi that merges multiples values reaching + // the label. The latter is true if the label's input: in(..) is + // a phi whose control input is the region node for the label. + Node* l = lab->in(i); + // Get the current value of the var Node* m = _cvstate->in(i); + // If the var went unused no need for a phi if (m == NULL) { continue; } else if (l == NULL || m == l) { + // Only one unique value "m" is known to reach this label so a phi + // is not yet necessary unless: + // the label is being bound and all predecessors have not been seen, + // in which case "bind" will be true. if (bind) { m = promote_to_phi(m, reg); } + // Record the phi/value used for this var in the label's cvstate lab->set_req(i, m); } else { + // More than one value for the variable reaches this label so + // a create a phi if one does not already exist. if (!was_promoted_to_phi(l, reg)) { l = promote_to_phi(l, reg); lab->set_req(i, l); } + // Record in the phi, the var's value from the current state l->set_req(slot, m); } } + do_memory_merge(_cvstate, lab); stop(); } @@ -203,6 +265,7 @@ void IdealKit::declares_done() { _cvstate = new_cvstate(); // initialize current cvstate set_ctrl(_initial_ctrl); // initialize control in current cvstate + set_all_memory(_initial_memory);// initialize memory in current cvstate DEBUG_ONLY(_state->push(BlockS)); } @@ -232,6 +295,8 @@ Node* IdealKit::copy_cvstate() { Node* ns = new_cvstate(); for (uint i = 0; i < ns->req(); i++) ns->init_req(i, _cvstate->in(i)); + // We must clone memory since it will be updated as we do stores. + ns->set_req(TypeFunc::Memory, MergeMemNode::make(C, ns->in(TypeFunc::Memory))); return ns; } @@ -256,3 +321,186 @@ k.declare(this); } +Node* IdealKit::memory(uint alias_idx) { + MergeMemNode* mem = merged_memory(); + Node* p = mem->memory_at(alias_idx); + _gvn.set_type(p, Type::MEMORY); // must be mapped + return p; +} + +void IdealKit::set_memory(Node* mem, uint alias_idx) { + merged_memory()->set_memory_at(alias_idx, mem); +} + +//----------------------------- make_load ---------------------------- +Node* IdealKit::load(Node* ctl, + Node* adr, + const Type* t, + BasicType bt, + int adr_idx, + bool require_atomic_access) { + + assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" ); + const TypePtr* adr_type = NULL; // debug-mode-only argument + debug_only(adr_type = C->get_adr_type(adr_idx)); + Node* mem = memory(adr_idx); + Node* ld; + if (require_atomic_access && bt == T_LONG) { + ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); + } else { + ld = LoadNode::make(C, ctl, mem, adr, adr_type, t, bt); + } + return transform(ld); +} + +Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt, + int adr_idx, + bool require_atomic_access) { + assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); + const TypePtr* adr_type = NULL; + debug_only(adr_type = C->get_adr_type(adr_idx)); + Node *mem = memory(adr_idx); + Node* st; + if (require_atomic_access && bt == T_LONG) { + st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); + } else { + st = StoreNode::make(C, ctl, mem, adr, adr_type, val, bt); + } + st = transform(st); + set_memory(st, adr_idx); + + return st; +} + +// Card mark store. Must be ordered so that it will come after the store of +// the oop. +Node* IdealKit::storeCM(Node* ctl, Node* adr, Node *val, Node* oop_store, + BasicType bt, + int adr_idx) { + assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" ); + const TypePtr* adr_type = NULL; + debug_only(adr_type = C->get_adr_type(adr_idx)); + Node *mem = memory(adr_idx); + + // Add required edge to oop_store, optimizer does not support precedence edges. + // Convert required edge to precedence edge before allocation. + Node* st = new (C, 5) StoreCMNode(ctl, mem, adr, adr_type, val, oop_store); + + st = transform(st); + set_memory(st, adr_idx); + + return st; +} + +//---------------------------- do_memory_merge -------------------------------- +// The memory from one merging cvstate needs to be merged with the memory for another +// join cvstate. If the join cvstate doesn't have a merged memory yet then we +// can just copy the state from the merging cvstate + +// Merge one slow path into the rest of memory. +void IdealKit::do_memory_merge(Node* merging, Node* join) { + + // Get the region for the join state + Node* join_region = join->in(TypeFunc::Control); + assert(join_region != NULL, "join region must exist"); + if (join->in(TypeFunc::Memory) == NULL ) { + join->set_req(TypeFunc::Memory, merging->in(TypeFunc::Memory)); + return; + } + + // The control flow for merging must have already been attached to the join region + // we need its index for the phis. + uint slot; + for (slot = 1; slot < join_region->req() ; slot ++ ) { + if (join_region->in(slot) == merging->in(TypeFunc::Control)) break; + } + assert(slot != join_region->req(), "edge must already exist"); + + MergeMemNode* join_m = join->in(TypeFunc::Memory)->as_MergeMem(); + MergeMemNode* merging_m = merging->in(TypeFunc::Memory)->as_MergeMem(); + + // join_m should be an ancestor mergemem of merging + // Slow path memory comes from the current map (which is from a slow call) + // Fast path/null path memory comes from the call's input + + // Merge the other fast-memory inputs with the new slow-default memory. + // for (MergeMemStream mms(merged_memory(), fast_mem->as_MergeMem()); mms.next_non_empty2(); ) { + for (MergeMemStream mms(join_m, merging_m); mms.next_non_empty2(); ) { + Node* join_slice = mms.force_memory(); + Node* merging_slice = mms.memory2(); + if (join_slice != merging_slice) { + PhiNode* phi; + // bool new_phi = false; + // Is the phi for this slice one that we created for this join region or simply + // one we copied? If it is ours then add + if (join_slice->is_Phi() && join_slice->as_Phi()->region() == join_region) { + phi = join_slice->as_Phi(); + } else { + // create the phi with join_slice filling supplying memory for all of the + // control edges to the join region + phi = PhiNode::make(join_region, join_slice, Type::MEMORY, mms.adr_type(C)); + phi = (PhiNode*) delay_transform(phi); + // gvn().set_type(phi, Type::MEMORY); + // new_phi = true; + } + // Now update the phi with the slice for the merging slice + phi->set_req(slot, merging_slice/* slow_path, slow_slice */); + // this updates join_m with the phi + mms.set_memory(phi); + } + } +} + + +//----------------------------- make_call ---------------------------- +// Trivial runtime call +void IdealKit::make_leaf_call(const TypeFunc *slow_call_type, + address slow_call, + const char *leaf_name, + Node* parm0, + Node* parm1, + Node* parm2) { + + // We only handle taking in RawMem and modifying RawMem + const TypePtr* adr_type = TypeRawPtr::BOTTOM; + uint adr_idx = C->get_alias_index(adr_type); + + // Clone initial memory + MergeMemNode* cloned_mem = MergeMemNode::make(C, merged_memory()); + + // Slow-path leaf call + int size = slow_call_type->domain()->cnt(); + CallNode *call = (CallNode*)new (C, size) CallLeafNode( slow_call_type, slow_call, leaf_name, adr_type); + + // Set fixed predefined input arguments + call->init_req( TypeFunc::Control, ctrl() ); + call->init_req( TypeFunc::I_O , top() ) ; // does no i/o + // Narrow memory as only memory input + call->init_req( TypeFunc::Memory , memory(adr_idx)); + call->init_req( TypeFunc::FramePtr, top() /* frameptr() */ ); + call->init_req( TypeFunc::ReturnAdr, top() ); + + if (parm0 != NULL) call->init_req(TypeFunc::Parms+0, parm0); + if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1); + if (parm2 != NULL) call->init_req(TypeFunc::Parms+2, parm2); + + // Node *c = _gvn.transform(call); + call = (CallNode *) _gvn.transform(call); + Node *c = call; // dbx gets confused with call call->dump() + + // Slow leaf call has no side-effects, sets few values + + set_ctrl(transform( new (C, 1) ProjNode(call,TypeFunc::Control) )); + + // Set the incoming clone of memory as current memory + set_all_memory(cloned_mem); + + // Make memory for the call + Node* mem = _gvn.transform( new (C, 1) ProjNode(call, TypeFunc::Memory) ); + + // Set the RawPtr memory state only. + set_memory(mem, adr_idx); + + assert(C->alias_type(call->adr_type()) == C->alias_type(adr_type), + "call node must be constructed correctly"); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/idealKit.hpp --- a/hotspot/src/share/vm/opto/idealKit.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/idealKit.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)idealKit.hpp 1.7 07/05/05 17:06:17 JVM" +#pragma ident "@(#)idealKit.hpp 1.8 07/06/18 14:25:26 JVM" #endif /* * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -93,17 +93,23 @@ PhaseGVN &_gvn; GrowableArray* _pending_cvstates; // stack of cvstates GrowableArray* _delay_transform; // delay invoking gvn.transform until drain - Node* _cvstate; // current cvstate (control and variables) + Node* _cvstate; // current cvstate (control, memory and variables) uint _var_ct; // number of variables bool _delay_all_transforms; // flag forcing all transforms to be delayed Node* _initial_ctrl; // saves initial control until variables declared + Node* _initial_memory; // saves initial memory until variables declared PhaseGVN& gvn() const { return _gvn; } // Create a new cvstate filled with nulls Node* new_cvstate(); // Create a new cvstate Node* cvstate() { return _cvstate; } // current cvstate Node* copy_cvstate(); // copy current cvstate - void set_ctrl(Node* ctrl) { _cvstate->set_req(0, ctrl); } + void set_ctrl(Node* ctrl) { _cvstate->set_req(TypeFunc::Control, ctrl); } + + // Should this assert this is a MergeMem??? + void set_all_memory(Node* mem){ _cvstate->set_req(TypeFunc::Memory, mem); } + void set_memory(Node* mem, uint alias_idx ); + void do_memory_merge(Node* merging, Node* join); void clear(Node* m); // clear a cvstate void stop() { clear(_cvstate); } // clear current cvstate Node* delay_transform(Node* n); @@ -113,22 +119,31 @@ return (n->is_Phi() && n->in(0) == reg); } void declare(IdealVariable* v) { v->set_id(_var_ct++); } - static const uint first_var; + // This declares the position where vars are kept in the cvstate + // For some degree of consistency we use the TypeFunc enum to + // soak up spots in the inputs even though we only use early Control + // and Memory slots. (So far.) + static const uint first_var; // = TypeFunc::Parms + 1; #ifdef ASSERT enum State { NullS=0, BlockS=1, LoopS=2, IfThenS=4, ElseS=8, EndifS= 16 }; GrowableArray* _state; State state() { return (State)(_state->top()); } #endif + + // Users should not care about slices only MergedMem so no access for them. + Node* memory(uint alias_idx); public: - IdealKit(PhaseGVN &gvn, Node* control, bool delay_all_transforms = false); + IdealKit(PhaseGVN &gvn, Node* control, Node* memory, bool delay_all_transforms = false); ~IdealKit() { stop(); drain_delay_transform(); } // Control - Node* ctrl() { return _cvstate->in(0); } + Node* ctrl() { return _cvstate->in(TypeFunc::Control); } + Node* top() { return C->top(); } + MergeMemNode* merged_memory() { return _cvstate->in(TypeFunc::Memory)->as_MergeMem(); } void set(IdealVariable& v, Node* rhs) { _cvstate->set_req(first_var + v.id(), rhs); } Node* value(IdealVariable& v) { return _cvstate->in(first_var + v.id()); } void dead(IdealVariable& v) { set(v, (Node*)NULL); } @@ -145,10 +160,14 @@ void goto_(Node* lab, bool bind = false); void declares_done(); void drain_delay_transform(); + Node* IfTrue(IfNode* iff) { return transform(new (C,1) IfTrueNode(iff)); } Node* IfFalse(IfNode* iff) { return transform(new (C,1) IfFalseNode(iff)); } + // Data Node* ConI(jint k) { return (Node*)gvn().intcon(k); } + Node* makecon(const Type *t) const { return _gvn.makecon(t); } + Node* AddI(Node* l, Node* r) { return transform(new (C,3) AddINode(l, r)); } Node* SubI(Node* l, Node* r) { return transform(new (C,3) SubINode(l, r)); } Node* AndI(Node* l, Node* r) { return transform(new (C,3) AndINode(l, r)); } @@ -158,4 +177,57 @@ Node* Bool(Node* cmp, BoolTest::mask relop) { return transform(new (C,2) BoolNode(cmp, relop)); } void increment(IdealVariable& v, Node* j) { set(v, AddI(value(v), j)); } void decrement(IdealVariable& v, Node* j) { set(v, SubI(value(v), j)); } + + Node* CmpL(Node* l, Node* r) { return transform(new (C,3) CmpLNode(l, r)); } + + // TLS + Node* thread() { return gvn().transform(new (C, 1) ThreadLocalNode()); } + + // Pointers + Node* AddP(Node *base, Node *ptr, Node *off) { return transform(new (C,4) AddPNode(base, ptr, off)); } + Node* CmpP(Node* l, Node* r) { return transform(new (C,3) CmpPNode(l, r)); } +#ifdef _LP64 + Node* XorX(Node* l, Node* r) { return transform(new (C,3) XorLNode(l, r)); } +#else // _LP64 + Node* XorX(Node* l, Node* r) { return transform(new (C,3) XorINode(l, r)); } +#endif // _LP64 + Node* URShiftX(Node* l, Node* r) { return transform(new (C,3) URShiftXNode(l, r)); } + Node* ConX(jint k) { return (Node*)gvn().MakeConX(k); } + Node* CastPX(Node* ctl, Node* p) { return transform(new (C,2) CastP2XNode(ctl, p)); } + // Add a fixed offset to a pointer + Node* basic_plus_adr(Node* base, Node* ptr, intptr_t offset); + + // Memory operations + + // This is the base version which is given an alias index. + Node* load(Node* ctl, + Node* adr, + const Type* t, + BasicType bt, + int adr_idx, + bool require_atomic_access = false); + + // Return the new StoreXNode + Node* store(Node* ctl, + Node* adr, + Node* val, + BasicType bt, + int adr_idx, + bool require_atomic_access = false); + + // Store a card mark ordered after store_oop + Node* storeCM(Node* ctl, + Node* adr, + Node* val, + Node* oop_store, + BasicType bt, + int adr_idx); + + // Trivial call + void make_leaf_call(const TypeFunc *slow_call_type, + address slow_call, + const char *leaf_name, + Node* parm0, + Node* parm1 = NULL, + Node* parm2 = NULL); }; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)library_call.cpp 1.164 07/05/17 15:59:02 JVM" +#pragma ident "@(#)library_call.cpp 1.165 07/06/18 14:25:26 JVM" #endif /* * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -862,7 +862,7 @@ const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); - IdealKit kit(gvn(), control()); + IdealKit kit(gvn(), control(), merged_memory()); #define __ kit. Node* zero = __ ConI(0); Node* one = __ ConI(1); @@ -1732,6 +1732,7 @@ Node* val; debug_only(val = (Node*)(uintptr_t)-1); + if (is_store) { // Get the value being stored. (Pop it first; it was pushed last.) switch (type) { @@ -1901,40 +1902,28 @@ val = _gvn.transform( new (C, 2) CastX2PNode(val) ); break; } - Node* store = store_to_memory(control(), adr, val, type, adr_type, is_volatile); - - if (type == T_OBJECT - && !_gvn.type(heap_base_oop)->higher_equal(TypePtr::NULL_PTR)) { + + if (type != T_OBJECT ) { + (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); + } else { + // Possibly an oop being stored to Java heap or native memory if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { - store_barrier(store, T_CONFLICT, heap_base_oop, adr, val); + // oop to Java heap. + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, val->bottom_type(), type); } else { - // Base pointer may or may not be null, so put out a conditional - // store barrier. (Yech.) - Node* oldctl = control(); - Node* cmp = _gvn.transform( new (C, 3) CmpPNode(heap_base_oop, null()) ); - Node* bol = _gvn.transform( new (C, 2) BoolNode(cmp, BoolTest::ne) ); - IfNode* iff = create_and_map_if(oldctl, bol, PROB_MAX, COUNT_UNKNOWN); - enum { - heap_store_path = 1, - null_base_path, - num_paths - }; - RegionNode* rgn = new (C, num_paths) RegionNode(num_paths); - // fall-through path (base is null, offset is memory address) - rgn->init_req(null_base_path, _gvn.transform( new (C, 1) IfFalseNode(iff) )); - Node* newrawmem = PhiNode::make(rgn, memory(Compile::AliasIdxRaw)); - set_control(_gvn.transform( new (C, 1) IfTrueNode(iff) )); - store_barrier(store, T_CONFLICT, heap_base_oop, adr, val); - if (memory(Compile::AliasIdxRaw) == newrawmem->in(null_base_path)) { - // The store barrier did nothing, after all. - set_control(oldctl); - } else { - // Finish heap_store_path: - rgn->init_req(heap_store_path, control()); - set_control(_gvn.transform(rgn)); - newrawmem->init_req(heap_store_path, memory(Compile::AliasIdxRaw)); - set_memory(_gvn.transform(newrawmem), Compile::AliasIdxRaw); - } + + // We can't tell at compile time if we are storing in the Java heap or outside + // of it. So we need to emit code to conditionally do the proper type of + // store. + + IdealKit kit(gvn(), control(), merged_memory()); + kit.declares_done(); + // QQQ who knows what probability is here?? + kit.if_then(heap_base_oop, BoolTest::ne, null(), PROB_UNLIKELY(0.999)); { + (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, val->bottom_type(), type); + } kit.else_(); { + (void) store_to_memory(control(), adr, val, type, adr_type, is_volatile); + } kit.end_if(); } } } @@ -2133,10 +2122,11 @@ cas = _gvn.transform(new (C, 5) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); break; case T_OBJECT: - cas = _gvn.transform(new (C, 5) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); // reference stores need a store barrier. // (They don't if CAS fails, but it isn't worth checking.) - store_barrier(cas, T_CONFLICT, base, adr, newval); + pre_barrier(control(), base, adr, alias_idx, newval, value_type, T_OBJECT); + cas = _gvn.transform(new (C, 5) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); + post_barrier(control(), cas, base, adr, alias_idx, newval, T_OBJECT, true); break; default: ShouldNotReachHere(); @@ -2217,11 +2207,14 @@ insert_mem_bar(Op_MemBarCPUOrder); // Ensure that the store is atomic for longs: bool require_atomic_access = true; - Node* store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); + Node* store; if (type == T_OBJECT) // reference stores need a store barrier. - store_barrier(store, T_CONFLICT, base, adr, val); + store = store_oop_to_unknown(control(), base, adr, adr_type, val, value_type, type); + else { + store = store_to_memory(control(), adr, val, type, adr_type, require_atomic_access); + } insert_mem_bar(Op_MemBarCPUOrder); - + push(store); return true; } @@ -3798,8 +3791,14 @@ if (card_mark) { Node* no_particular_value = NULL; Node* no_particular_field = NULL; - store_barrier(memory(raw_adr_type), T_OBJECT, new_obj, - no_particular_field, no_particular_value); + post_barrier(control(), + memory(raw_adr_type), + new_obj, + no_particular_field, + raw_adr_idx, + no_particular_value, + T_OBJECT, + false); } // Present the results of the slow call. result_reg->init_req(_fast_path, control()); @@ -4391,7 +4390,6 @@ return _gvn.transform(new (C, 1) ProjNode(call, TypeFunc::Parms)); } - // Helper function; generates the fast out-of-line call to an arraycopy stub. void LibraryCallKit::generate_unchecked_arraycopy(BasicType basic_elem_type, diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)loopopts.cpp 1.219 07/06/06 06:35:01 JVM" +#pragma ident "@(#)loopopts.cpp 1.220 07/06/18 14:25:27 JVM" #endif /* * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -603,6 +603,9 @@ } } + // Use same limit as split_if_with_blocks_post + if( C->unique() > 35000 ) return n; // Method too big + // Split 'n' through the merge point if it is profitable Node *phi = split_thru_phi( n, n_blk, policy ); if( !phi ) return n; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/parse.hpp --- a/hotspot/src/share/vm/opto/parse.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/parse.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)parse.hpp 1.269 07/05/05 17:06:25 JVM" +#pragma ident "@(#)parse.hpp 1.270 07/06/18 14:25:27 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -132,6 +132,7 @@ Block** _successors; // Use init_node/init_graph to initialize Blocks. + // Block() : _live_locals((uintptr_t*)NULL,0) { ShouldNotReachHere(); } Block() : _live_locals(NULL,0) { ShouldNotReachHere(); } public: diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/parse2.cpp --- a/hotspot/src/share/vm/opto/parse2.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/parse2.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)parse2.cpp 1.359 07/05/05 17:06:23 JVM" +#pragma ident "@(#)parse2.cpp 1.360 07/06/18 14:25:27 JVM" #endif /* * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -1498,9 +1498,9 @@ c = pop(); // Oop to store b = pop(); // index (already used) a = pop(); // the array itself + const Type* elemtype = _gvn.type(a)->is_aryptr()->elem(); const TypeAryPtr* adr_type = TypeAryPtr::OOPS; - Node* store = store_to_memory(control(), d, c, T_OBJECT, adr_type); - store_barrier(store, T_ARRAY, a, d, c); + Node* store = store_oop_to_array(control(), a, d, adr_type, c, elemtype, T_OBJECT); break; } case Bytecodes::_lastore: { diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/opto/parse3.cpp --- a/hotspot/src/share/vm/opto/parse3.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/opto/parse3.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)parse3.cpp 1.266 07/05/05 17:06:22 JVM" +#pragma ident "@(#)parse3.cpp 1.267 07/06/18 14:25:27 JVM" #endif /* * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -223,10 +223,25 @@ if (bt == T_DOUBLE) val = dstore_rounding(val); // Store the value. - Node* store = store_to_memory( control(), adr, val, bt, adr_type, is_vol ); - - // Object-writes need a store-barrier - if (bt == T_OBJECT) store_barrier(store, T_OBJECT, obj, adr, val); + Node* store; + if (bt == T_OBJECT) { + const TypePtr* field_type; + if (!field->type()->is_loaded()) { + field_type = TypeInstPtr::BOTTOM; + } else if (field->is_constant()) { + // This can happen if the constant oop is non-perm. + ciObject* con = field->constant_value().as_object(); + // Do not "join" in the previous type; it doesn't add value, + // and may yield a vacuous result if the field is of interface type. + field_type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); + assert(field_type != NULL, "field singleton type must be consistent"); + } else { + field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); + } + store = store_oop_to_object( control(), obj, adr, adr_type, val, field_type, bt); + } else { + store = store_to_memory( control(), adr, val, bt, adr_type, is_vol ); + } // If reference is volatile, prevent following volatiles ops from // floating up before the volatile write. diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/prims/jni.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)jni.cpp 1.434 07/05/29 10:01:44 JVM" +#pragma ident "@(#)jni.cpp 1.435 07/06/28 10:31:42 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -3433,6 +3433,9 @@ ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); + // Perform any platform dependent FPU setup + os::setup_fpu(); + return JNI_OK; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/prims/jvmtiTagMap.cpp --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)jvmtiTagMap.cpp 1.84 07/06/06 13:18:31 JVM" +#pragma ident "@(#)jvmtiTagMap.cpp 1.85 07/06/27 00:30:05 JVM" #endif /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -2251,6 +2251,15 @@ return true; } +// This mask is used to pass reference_info to a jvmtiHeapReferenceCallback +// only for ref_kinds defined by the JVM TI spec. Otherwise, NULL is passed. +#define REF_INFO_MASK ((1 << JVMTI_HEAP_REFERENCE_FIELD) \ + | (1 << JVMTI_HEAP_REFERENCE_STATIC_FIELD) \ + | (1 << JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT) \ + | (1 << JVMTI_HEAP_REFERENCE_CONSTANT_POOL) \ + | (1 << JVMTI_HEAP_REFERENCE_STACK_LOCAL) \ + | (1 << JVMTI_HEAP_REFERENCE_JNI_LOCAL)) + // invoke the object reference callback to report a reference inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeapReferenceKind ref_kind, oop referrer, @@ -2294,7 +2303,7 @@ // invoke the callback int res = (*cb)(ref_kind, - &reference_info, + (REF_INFO_MASK & (1 << ref_kind)) ? &reference_info : NULL, wrapper.klass_tag(), wrapper.referrer_klass_tag(), wrapper.obj_size(), diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)arguments.cpp 1.329 07/05/29 09:44:26 JVM" +#pragma ident "@(#)arguments.cpp 1.330 07/06/27 10:52:36 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -44,6 +44,7 @@ uintx Arguments::_min_heap_size = 0; Arguments::Mode Arguments::_mode = _mixed; bool Arguments::_java_compiler = false; +bool Arguments::_xdebug_mode = false; const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG; const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; @@ -1256,27 +1257,17 @@ } //=========================================================================================================== -// Parsing of java.compiler property and JAVA_COMPILER environment variable +// Parsing of java.compiler property void Arguments::process_java_compiler_argument(char* arg) { - // Ignore java.compiler property and JAVA_COMPILER environment variable. - // It will cause the java.lang.Compiler static initializer to try to dynamically - // link the dll, which is not going to work since HotSpot does not support the - // old JIT interface. - // For backwards compatibility, we switch to interpreted mode if "NONE" or "" is - // specified. + // For backwards compatibility, Djava.compiler=NONE or "" + // causes us to switch to -Xint mode UNLESS -Xdebug + // is also specified. if (strlen(arg) == 0 || strcasecmp(arg, "NONE") == 0) { set_java_compiler(true); // "-Djava.compiler[=...]" most recently seen. } } -void Arguments::parse_java_compiler_environment_variable() { - char buffer[64]; - if (os::getenv("JAVA_COMPILER", buffer, sizeof(buffer))) { - process_java_compiler_argument(buffer); - } -} - void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { _sun_java_launcher = strdup(launcher); } @@ -1921,7 +1912,8 @@ } // -Xdebug } else if (match_option(option, "-Xdebug", &tail)) { - // ignore + // note this flag has been used, then ignore + set_xdebug_mode(true); // -Xnoagent } else if (match_option(option, "-Xnoagent", &tail)) { // For compatibility with classic. HotSpot refuses to load the old style agent.dll. @@ -2206,8 +2198,7 @@ // This must be done after all arguments have been processed. // java_compiler() true means set to "NONE" or empty. - // The -Xdebug mini-agent sets the breakpoint capability (amongst many). - if (java_compiler() && !JvmtiExport::can_post_breakpoint()) { + if (java_compiler() && !xdebug_mode()) { // For backwards compatibility, we switch to interpreted mode if // -Djava.compiler="NONE" or "" is specified AND "-Xdebug" was // not specified. @@ -2403,9 +2394,6 @@ return result; } - // Parse JAVA_COMPILER environment variable (if present) (mimics classic VM) - parse_java_compiler_environment_variable(); - #ifndef PRODUCT if (TraceBytecodesAt != 0) { TraceBytecodes = true; diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/arguments.hpp --- a/hotspot/src/share/vm/runtime/arguments.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/arguments.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)arguments.hpp 1.102 07/05/17 16:05:17 JVM" +#pragma ident "@(#)arguments.hpp 1.103 07/06/27 10:52:36 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -281,6 +281,11 @@ static void set_java_compiler(bool arg) { _java_compiler = arg; } static bool java_compiler() { return _java_compiler; } + // -Xdebug flag + static bool _xdebug_mode; + static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; } + static bool xdebug_mode() { return _xdebug_mode; } + // Used to save default settings static bool _AlwaysCompileLoopMethods; static bool _UseOnStackReplacement; @@ -325,7 +330,6 @@ static jint parse_options_environment_variable(const char* name, SysClassPath* scp_p, bool* scp_assembly_required_p); static jint parse_java_tool_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p); static jint parse_java_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p); - static void parse_java_compiler_environment_variable(); static jint parse_vm_init_args(const JavaVMInitArgs* args); static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, FlagValueOrigin origin); static jint finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)globals.hpp 1.965 07/06/13 16:22:03 JVM" +#pragma ident "@(#)globals.hpp 1.966 07/06/28 10:31:41 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -661,6 +661,9 @@ diagnostic(bool, TraceTriggers, false, \ "Trace triggers") \ \ + product(bool, AlwaysRestoreFPU, false, \ + "Restore the FPU control word after every JNI call (expensive)") \ + \ notproduct(bool, PrintCompilation2, false, \ "Print additional statistics per compilation") \ \ diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)mutexLocker.cpp 1.177 07/05/05 17:06:53 JVM" +#pragma ident "@(#)mutexLocker.cpp 1.178 07/06/20 10:36:30 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -57,6 +57,7 @@ Monitor* VMOperationQueue_lock = NULL; Monitor* VMOperationRequest_lock = NULL; Monitor* Safepoint_lock = NULL; +Monitor* SerializePage_lock = NULL; Monitor* Threads_lock = NULL; Monitor* CGC_lock = NULL; Mutex* STS_init_lock = NULL; @@ -184,6 +185,10 @@ def(Safepoint_lock , Monitor, safepoint, true ); // locks SnippetCache_lock/Threads_lock + if (!UseMembar) { + def(SerializePage_lock , Monitor, leaf, true ); + } + def(Threads_lock , Monitor, barrier, true ); def(VMOperationQueue_lock , Monitor, nonleaf, true ); // VM_thread allowed to block on these diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)mutexLocker.hpp 1.149 07/05/17 16:06:16 JVM" +#pragma ident "@(#)mutexLocker.hpp 1.150 07/06/20 10:36:30 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -55,6 +55,7 @@ extern Monitor* VMOperationQueue_lock; // a lock on queue of vm_operations waiting to execute extern Monitor* VMOperationRequest_lock; // a lock on Threads waiting for a vm_operation to terminate extern Monitor* Safepoint_lock; // a lock used by the safepoint abstraction +extern Monitor* SerializePage_lock; // a lock used when VMThread changing serialize memory page permission during safepoint extern Monitor* Threads_lock; // a lock on the Threads table of active Java threads // (also used by Safepoints too to block threads creation/destruction) extern Monitor* CGC_lock; // used for coordination between diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/os.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)os.cpp 1.182 07/06/10 14:43:17 JVM" +#pragma ident "@(#)os.cpp 1.183 07/06/17 12:55:49 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -968,11 +968,37 @@ set_serialize_page_mask((uintptr_t)(vm_page_size() - sizeof(int32_t))); } +// This method is called from signal handler when SIGSEGV occurs while the current +// thread tries to store to the "read-only" memory serialize page during state +// transition. +void os::block_on_serialize_page_trap() { + if (TraceSafepoint) { + tty->print_cr("Block until the serialize page permission restored"); + } + // When VMThread is holding the SerializePage_lock during modifying the + // access permission of the memory serialize page, the following call + // will block until the permission of that page is restored to rw. + // Generally, it is unsafe to manipulate locks in signal handlers, but in + // this case, it's OK as the signal is synchronous and we know precisely when + // it can occur. SerializePage_lock is a transiently-held leaf lock, so + // lock_without_safepoint_check should be safe. + SerializePage_lock->lock_without_safepoint_check(); + SerializePage_lock->unlock(); +} // Serialize all thread state variables void os::serialize_thread_states() { + // On some platforms such as Solaris & Linux, the time duration of the page + // permission restoration is observed to be much longer than expected due to + // scheduler starvation problem etc. To avoid the long synchronization + // time and expensive page trap spinning, 'SerializePage_lock' is used to block + // the mutator thread if such case is encountered. Since this method is always + // called by VMThread during safepoint, lock_without_safepoint_check is used + // instead. See bug 6546278. + SerializePage_lock->lock_without_safepoint_check(); os::protect_memory( (char *)os::get_memory_serialize_page(), os::vm_page_size() ); os::unguard_memory( (char *)os::get_memory_serialize_page(), os::vm_page_size() ); + SerializePage_lock->unlock(); } // Returns true if the current stack pointer is above the stack shadow diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/os.hpp --- a/hotspot/src/share/vm/runtime/os.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/os.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)os.hpp 1.219 07/06/08 23:16:34 JVM" +#pragma ident "@(#)os.hpp 1.220 07/06/17 12:56:04 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -257,6 +257,8 @@ get_serialize_page_mask()) + (uintptr_t)_mem_serialize_page; return (thr_addr == addr); } + + static void block_on_serialize_page_trap(); // threads diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)stubRoutines.hpp 1.116 07/05/17 16:06:37 JVM" +#pragma ident "@(#)stubRoutines.hpp 1.117 07/06/28 10:31:40 JVM" #endif /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. @@ -209,6 +209,7 @@ static address d2i_wrapper() { return _d2i_wrapper; } static address d2l_wrapper() { return _d2l_wrapper; } + static jint fpu_cntrl_wrd_std() { return _fpu_cntrl_wrd_std; } static address addr_fpu_cntrl_wrd_std() { return (address)&_fpu_cntrl_wrd_std; } static address addr_fpu_cntrl_wrd_24() { return (address)&_fpu_cntrl_wrd_24; } static address addr_fpu_cntrl_wrd_64() { return (address)&_fpu_cntrl_wrd_64; } diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/utilities/bitMap.hpp --- a/hotspot/src/share/vm/utilities/bitMap.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/utilities/bitMap.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)bitMap.hpp 1.45 07/05/05 17:07:06 JVM" +#pragma ident "@(#)bitMap.hpp 1.46 07/06/18 14:25:28 JVM" #endif /* * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -116,6 +116,10 @@ } public: + + // Constructs a bitmap with no map, and size 0. + BitMap() : _map(NULL), _size(0) {} + // Construction BitMap(idx_t* map, idx_t size_in_bits); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/utilities/taskqueue.cpp --- a/hotspot/src/share/vm/utilities/taskqueue.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/utilities/taskqueue.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_SRC -#pragma ident "@(#)taskqueue.cpp 1.25 07/05/05 17:07:10 JVM" +#pragma ident "@(#)taskqueue.cpp 1.21 06/08/10 17:56:51 JVM" #endif /* * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -54,8 +54,7 @@ ParallelTaskTerminator(int n_threads, TaskQueueSetSuper* queue_set) : _n_threads(n_threads), _queue_set(queue_set), - _offered_termination(0), _terminated(0), - _term_monitor(Mutex::leaf+1, "ParTaskTerm", true) {} + _offered_termination(0) {} bool ParallelTaskTerminator::peek_in_queue_set() { return _queue_set->peek(); @@ -111,519 +110,6 @@ } } -OopTaskQueue::OopTaskQueue() : TaskQueueSuper() { - assert(sizeof(Age) == sizeof(jint), "Depends on this."); -} - -void OopTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(Task, n()); - guarantee(_elems != NULL, "Allocation failed."); -} - -bool OopTaskQueue::push_slow(Task t, juint dirty_n_elems) { - if (dirty_n_elems == n() - 1) { - // Actually means 0, so do the push. - juint localBot = _bottom; - _elems[localBot] = t; - _bottom = increment_index(localBot); - return true; - } else - return false; -} - -bool OopTaskQueue:: -pop_local_slow(juint localBot, Age oldAge) { - // This queue was observed to contain exactly one element; either this - // thread will claim it, or a competing "pop_global". In either case, - // the queue will be logically empty afterwards. Create a new Age value - // that represents the empty queue for the given value of "_bottom". (We - // must also increment "tag" because of the case where "bottom == 1", - // "top == 0". A pop_global could read the queue element in that case, - // then have the owner thread do a pop followed by another push. Without - // the incrementing of "tag", the pop_global's CAS could succeed, - // allowing it to believe it has claimed the stale element.) - Age newAge; - newAge._top = localBot; - newAge._tag = oldAge.tag() + 1; - // Perhaps a competing pop_global has already incremented "top", in which - // case it wins the element. - if (localBot == oldAge.top()) { - Age tempAge; - // No competing pop_global has yet incremented "top"; we'll try to - // install new_age, thus claiming the element. - assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), - "Assumption about CAS unit."); - *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - if (tempAge == oldAge) { - // We win. - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return true; - } - } - // We fail; a completing pop_global gets the element. But the queue is - // empty (and top is greater than bottom.) Fix this representation of - // the empty queue to become the canonical one. - set_age(newAge); - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return false; -} - -bool OopTaskQueue::pop_global(Task& t) { - Age newAge; - Age oldAge = get_age(); - juint localBot = _bottom; - juint n_elems = size(localBot, oldAge.top()); - if (n_elems == 0) { - return false; - } - t = _elems[oldAge.top()]; - newAge = oldAge; - newAge._top = increment_index(newAge.top()); - if ( newAge._top == 0 ) newAge._tag++; - Age resAge; - *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - // Note that using "_bottom" here might fail, since a pop_local might - // have decremented it. - assert(dirty_size(localBot, newAge._top) != n() - 1, - "Shouldn't be possible..."); - return (resAge == oldAge); -} - -OopTaskQueue::~OopTaskQueue() { - FREE_C_HEAP_ARRAY(Task, _elems); -} - -OopStarTaskQueue::OopStarTaskQueue() : TaskQueueSuper() { - assert(sizeof(Age) == sizeof(jint), "Depends on this."); -} - -void OopStarTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(StarTask, n()); - guarantee(_elems != NULL, "Allocation failed."); -} - -bool OopStarTaskQueue::push_slow(StarTask t, juint dirty_n_elems) { - if (dirty_n_elems == n() - 1) { - // Actually means 0, so do the push. - juint localBot = _bottom; - _elems[localBot] = t; - _bottom = increment_index(localBot); - return true; - } else - return false; -} - -bool OopStarTaskQueue:: -pop_local_slow(juint localBot, Age oldAge) { - // This queue was observed to contain exactly one element; either this - // thread will claim it, or a competing "pop_global". In either case, - // the queue will be logically empty afterwards. Create a new Age value - // that represents the empty queue for the given value of "_bottom". (We - // must also increment "tag" because of the case where "bottom == 1", - // "top == 0". A pop_global could read the queue element in that case, - // then have the owner thread do a pop followed by another push. Without - // the incrementing of "tag", the pop_global's CAS could succeed, - // allowing it to believe it has claimed the stale element.) - Age newAge; - newAge._top = localBot; - newAge._tag = oldAge.tag() + 1; - // Perhaps a competing pop_global has already incremented "top", in which - // case it wins the element. - if (localBot == oldAge.top()) { - Age tempAge; - // No competing pop_global has yet incremented "top"; we'll try to - // install new_age, thus claiming the element. - assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), - "Assumption about CAS unit."); - *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - if (tempAge == oldAge) { - // We win. - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return true; - } - } - // We fail; a completing pop_global gets the element. But the queue is - // empty (and top is greater than bottom.) Fix this representation of - // the empty queue to become the canonical one. - set_age(newAge); - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return false; -} - -bool OopStarTaskQueue::pop_global(StarTask& t) { - Age newAge; - Age oldAge = get_age(); - juint localBot = _bottom; - juint n_elems = size(localBot, oldAge.top()); - if (n_elems == 0) { - return false; - } - t = _elems[oldAge.top()]; - newAge = oldAge; - newAge._top = increment_index(newAge.top()); - if ( newAge._top == 0 ) newAge._tag++; - Age resAge; - *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - // Note that using "_bottom" here might fail, since a pop_local might - // have decremented it. - assert(dirty_size(localBot, newAge._top) != n() - 1, - "Shouldn't be possible..."); - return (resAge == oldAge); -} - -OopStarTaskQueue::~OopStarTaskQueue() { - FREE_C_HEAP_ARRAY(Task, _elems); -} - -// GenTaskQueue is an exact clone of OopTaskQueue. See -// header file for questions about why GenTaskQueue exists. - -GenTaskQueue::GenTaskQueue() : TaskQueueSuper() { - assert(sizeof(Age) == sizeof(jint), "Depends on this."); -} - -void GenTaskQueue::initialize() { - _elems = NEW_C_HEAP_ARRAY(GenTask, n()); - guarantee(_elems != NULL, "Allocation failed."); -} - -bool GenTaskQueue::push_slow(GenTask t, juint dirty_n_elems) { - if (dirty_n_elems == n() - 1) { - // Actually means 0, so do the push. - juint localBot = _bottom; - _elems[localBot] = t; - _bottom = increment_index(localBot); - return true; - } else - return false; -} - -bool GenTaskQueue:: -pop_local_slow(juint localBot, Age oldAge) { - // This queue was observed to contain exactly one element; either this - // thread will claim it, or a competing "pop_global". In either case, - // the queue will be logically empty afterwards. Create a new Age value - // that represents the empty queue for the given value of "_bottom". (We - // must also increment "tag" because of the case where "bottom == 1", - // "top == 0". A pop_global could read the queue element in that case, - // then have the owner thread do a pop followed by another push. Without - // the incrementing of "tag", the pop_global's CAS could succeed, - // allowing it to believe it has claimed the stale element.) - Age newAge; - newAge._top = localBot; - newAge._tag = oldAge.tag() + 1; - // Perhaps a competing pop_global has already incremented "top", in which - // case it wins the element. - if (localBot == oldAge.top()) { - Age tempAge; - // No competing pop_global has yet incremented "top"; we'll try to - // install new_age, thus claiming the element. - assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), - "Assumption about CAS unit."); - *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - if (tempAge == oldAge) { - // We win. - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return true; - } - } - // We fail; a completing pop_global gets the element. But the queue is - // empty (and top is greater than bottom.) Fix this representation of - // the empty queue to become the canonical one. - set_age(newAge); - assert(dirty_size(localBot, get_top()) != n() - 1, - "Shouldn't be possible..."); - return false; -} - -bool GenTaskQueue::pop_global(GenTask& t) { - Age newAge; - Age oldAge = get_age(); - juint localBot = _bottom; - juint n_elems = size(localBot, oldAge.top()); - if (n_elems == 0) { - return false; - } - t = _elems[oldAge.top()]; - newAge = oldAge; - newAge._top = increment_index(newAge.top()); - if ( newAge._top == 0 ) newAge._tag++; - Age resAge; - *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); - // Note that using "_bottom" here might fail, since a pop_local might - // have decremented it. - assert(dirty_size(localBot, newAge._top) != n() - 1, - "Shouldn't be possible..."); - return (resAge == oldAge); -} - -GenTaskQueue::~GenTaskQueue() { - FREE_C_HEAP_ARRAY(GenTask, _elems); -} -// End of GenTaskQueue clone - -void OopTaskQueueSet::register_queue(int i, OopTaskQueue* q) { - assert(0 <= i && i < _n, "index out of range."); - _queues[i] = q; -} - -OopTaskQueue* OopTaskQueueSet::queue(int i) { - return _queues[i]; -} - -bool OopTaskQueueSet::steal(int queue_num, int* seed, Task& t) { - for (int i = 0; i < 2 * _n; i++) - if (steal_best_of_2(queue_num, seed, t)) - return true; - return false; -} - -bool OopTaskQueueSet::steal_best_of_all(int queue_num, int* seed, Task& t) { - if (_n > 2) { - int best_k; - jint best_sz = 0; - for (int k = 0; k < _n; k++) { - if (k == queue_num) continue; - jint sz = _queues[k]->size(); - if (sz > best_sz) { - best_sz = sz; - best_k = k; - } - } - return best_sz > 0 && _queues[best_k]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopTaskQueueSet::steal_1_random(int queue_num, int* seed, Task& t) { - if (_n > 2) { - int k = queue_num; - while (k == queue_num) k = randomParkAndMiller(seed) % _n; - return _queues[2]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopTaskQueueSet::steal_best_of_2(int queue_num, int* seed, Task& t) { - if (_n > 2) { - int k1 = queue_num; - while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; - int k2 = queue_num; - while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; - // Sample both and try the larger. - juint sz1 = _queues[k1]->size(); - juint sz2 = _queues[k2]->size(); - if (sz2 > sz1) return _queues[k2]->pop_global(t); - else return _queues[k1]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopTaskQueueSet::peek() { - // Try all the queues. - for (int j = 0; j < _n; j++) { - if (_queues[j]->peek()) - return true; - } - return false; -} - -void OopStarTaskQueueSet::register_queue(int i, OopStarTaskQueue* q) { - assert(0 <= i && i < _n, "index out of range."); - _queues[i] = q; -} - -OopStarTaskQueue* OopStarTaskQueueSet::queue(int i) { - return _queues[i]; -} - -bool OopStarTaskQueueSet::steal(int queue_num, int* seed, StarTask& t) { - for (int i = 0; i < 2 * _n; i++) - if (steal_best_of_2(queue_num, seed, t)) - return true; - return false; -} - -bool OopStarTaskQueueSet::steal_best_of_all(int queue_num, int* seed, - StarTask& t) { - if (_n > 2) { - int best_k; - jint best_sz = 0; - for (int k = 0; k < _n; k++) { - if (k == queue_num) continue; - jint sz = _queues[k]->size(); - if (sz > best_sz) { - best_sz = sz; - best_k = k; - } - } - return best_sz > 0 && _queues[best_k]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopStarTaskQueueSet::steal_1_random(int queue_num, int* seed, - StarTask& t) { - if (_n > 2) { - int k = queue_num; - while (k == queue_num) k = randomParkAndMiller(seed) % _n; - return _queues[2]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopStarTaskQueueSet::steal_best_of_2(int queue_num, int* seed, - StarTask& t) { - if (_n > 2) { - int k1 = queue_num; - while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; - int k2 = queue_num; - while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; - // Sample both and try the larger. - juint sz1 = _queues[k1]->size(); - juint sz2 = _queues[k2]->size(); - if (sz2 > sz1) return _queues[k2]->pop_global(t); - else return _queues[k1]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool OopStarTaskQueueSet::peek() { - // Try all the queues. - for (int j = 0; j < _n; j++) { - if (_queues[j]->peek()) - return true; - } - return false; -} - -// Clone of OopTaskQueueSet for GenTask -void GenTaskQueueSet::register_queue(int i, GenTaskQueue* q) { - assert(0 <= i && i < _n, "index out of range."); - _queues[i] = q; -} - -GenTaskQueue* GenTaskQueueSet::queue(int i) { - return _queues[i]; -} - -bool GenTaskQueueSet::steal(int queue_num, int* seed, GenTask& t) { - for (int i = 0; i < 2 * _n; i++) - if (steal_best_of_all(queue_num, seed, t)) - return true; - return false; -} - -bool GenTaskQueueSet::steal_best_of_all(int queue_num, int* seed, GenTask& t) { - if (_n > 2) { - int best_k; - jint best_sz = 0; - for (int k = 0; k < _n; k++) { - if (k == queue_num) continue; - jint sz = _queues[k]->size(); - if (sz > best_sz) { - best_sz = sz; - best_k = k; - } - } - return best_sz > 0 && _queues[best_k]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool GenTaskQueueSet::steal_1_random(int queue_num, int* seed, GenTask& t) { - if (_n > 2) { - int k = queue_num; - while (k == queue_num) k = randomParkAndMiller(seed) % _n; - return _queues[2]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool GenTaskQueueSet::steal_best_of_2(int queue_num, int* seed, GenTask& t) { - if (_n > 2) { - int k1 = queue_num; - while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; - int k2 = queue_num; - while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; - // Sample both and try the larger. - juint sz1 = _queues[k1]->size(); - juint sz2 = _queues[k2]->size(); - if (sz2 > sz1) return _queues[k2]->pop_global(t); - else return _queues[k1]->pop_global(t); - } else if (_n == 2) { - // Just try the other one. - int k = (queue_num + 1) % 2; - return _queues[k]->pop_global(t); - } else { - assert(_n == 1, "can't be zero."); - return false; - } -} - -bool GenTaskQueueSet::peek() { - // Try all the queues. - for (int j = 0; j < _n; j++) { - if (_queues[j]->peek()) - return true; - } - return false; -} -// End clone of OopTaskQueueSet for GenTask - bool ChunkTaskQueueWithOverflow::is_empty() { return (_chunk_queue.size() == 0) && (_overflow_stack->length() == 0); diff -r 16f2b6c91171 -r 64ed597c0ad3 hotspot/src/share/vm/utilities/taskqueue.hpp --- a/hotspot/src/share/vm/utilities/taskqueue.hpp Fri Jun 22 00:46:43 2007 +0000 +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ #ifdef USE_PRAGMA_IDENT_HDR -#pragma ident "@(#)taskqueue.hpp 1.38 07/05/05 17:07:10 JVM" +#pragma ident "@(#)taskqueue.hpp 1.33 06/08/10 17:56:52 JVM" #endif /* * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -26,8 +26,6 @@ */ class TaskQueueSuper: public CHeapObj { - friend class ChunkTaskQueue; - protected: // The first free element after the last one pushed (mod _n). // (For now we'll assume only 32-bit CAS). @@ -131,115 +129,129 @@ }; -typedef oop Task; -class OopTaskQueue: public TaskQueueSuper { +template class GenericTaskQueue: public TaskQueueSuper { private: // Slow paths for push, pop_local. (pop_global has no fast path.) - bool push_slow(Task t, juint dirty_n_elems); + bool push_slow(E t, juint dirty_n_elems); bool pop_local_slow(juint localBot, Age oldAge); public: // Initializes the queue to empty. - OopTaskQueue(); - - void initialize(); - - // Push the task "t" on the queue. Returns "false" iff the queue is - // full. - inline bool push(Task t); - - // If succeeds in claiming a task (from the 'local' end, that is, the - // most recently pushed task), returns "true" and sets "t" to that task. - // Otherwise, the queue is empty and returns false. - inline bool pop_local(Task& t); - - // If succeeds in claiming a task (from the 'global' end, that is, the - // least recently pushed task), returns "true" and sets "t" to that task. - // Otherwise, the queue is empty and returns false. - bool pop_global(Task& t); - - // Delete any resource associated with the queue. - ~OopTaskQueue(); - -private: - // Element array. - volatile Task* _elems; - -}; - -typedef oop* StarTask; -class OopStarTaskQueue: public TaskQueueSuper { -private: - // Slow paths for push, pop_local. (pop_global has no fast path.) - bool push_slow(StarTask t, juint dirty_n_elems); - bool pop_local_slow(juint localBot, Age oldAge); - -public: - // Initializes the queue to empty. - OopStarTaskQueue(); + GenericTaskQueue(); void initialize(); // Push the task "t" on the queue. Returns "false" iff the queue is // full. - inline bool push(StarTask t); + inline bool push(E t); // If succeeds in claiming a task (from the 'local' end, that is, the // most recently pushed task), returns "true" and sets "t" to that task. // Otherwise, the queue is empty and returns false. - inline bool pop_local(StarTask& t); + inline bool pop_local(E& t); // If succeeds in claiming a task (from the 'global' end, that is, the // least recently pushed task), returns "true" and sets "t" to that task. // Otherwise, the queue is empty and returns false. - bool pop_global(StarTask& t); + bool pop_global(E& t); // Delete any resource associated with the queue. - ~OopStarTaskQueue(); + ~GenericTaskQueue(); private: // Element array. - volatile StarTask* _elems; - + volatile E* _elems; }; -// Clone of OopTaskQueue with GenTask instead of Task -typedef size_t GenTask; // Generic task -class GenTaskQueue: public TaskQueueSuper { -private: - // Slow paths for push, pop_local. (pop_global has no fast path.) - bool push_slow(GenTask t, juint dirty_n_elems); - bool pop_local_slow(juint localBot, Age oldAge); +template +GenericTaskQueue::GenericTaskQueue():TaskQueueSuper() { + assert(sizeof(Age) == sizeof(jint), "Depends on this."); +} + +template +void GenericTaskQueue::initialize() { + _elems = NEW_C_HEAP_ARRAY(E, n()); + guarantee(_elems != NULL, "Allocation failed."); +} -public: - // Initializes the queue to empty. - GenTaskQueue(); - - void initialize(); - - // Push the task "t" on the queue. Returns "false" iff the queue is - // full. - inline bool push(GenTask t); +template +bool GenericTaskQueue::push_slow(E t, juint dirty_n_elems) { + if (dirty_n_elems == n() - 1) { + // Actually means 0, so do the push. + juint localBot = _bottom; + _elems[localBot] = t; + _bottom = increment_index(localBot); + return true; + } else + return false; +} - // If succeeds in claiming a task (from the 'local' end, that is, the - // most recently pushed task), returns "true" and sets "t" to that task. - // Otherwise, the queue is empty and returns false. - inline bool pop_local(GenTask& t); - - // If succeeds in claiming a task (from the 'global' end, that is, the - // least recently pushed task), returns "true" and sets "t" to that task. - // Otherwise, the queue is empty and returns false. - bool pop_global(GenTask& t); +template +bool GenericTaskQueue:: +pop_local_slow(juint localBot, Age oldAge) { + // This queue was observed to contain exactly one element; either this + // thread will claim it, or a competing "pop_global". In either case, + // the queue will be logically empty afterwards. Create a new Age value + // that represents the empty queue for the given value of "_bottom". (We + // must also increment "tag" because of the case where "bottom == 1", + // "top == 0". A pop_global could read the queue element in that case, + // then have the owner thread do a pop followed by another push. Without + // the incrementing of "tag", the pop_global's CAS could succeed, + // allowing it to believe it has claimed the stale element.) + Age newAge; + newAge._top = localBot; + newAge._tag = oldAge.tag() + 1; + // Perhaps a competing pop_global has already incremented "top", in which + // case it wins the element. + if (localBot == oldAge.top()) { + Age tempAge; + // No competing pop_global has yet incremented "top"; we'll try to + // install new_age, thus claiming the element. + assert(sizeof(Age) == sizeof(jint) && sizeof(jint) == sizeof(juint), + "Assumption about CAS unit."); + *(jint*)&tempAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); + if (tempAge == oldAge) { + // We win. + assert(dirty_size(localBot, get_top()) != n() - 1, + "Shouldn't be possible..."); + return true; + } + } + // We fail; a completing pop_global gets the element. But the queue is + // empty (and top is greater than bottom.) Fix this representation of + // the empty queue to become the canonical one. + set_age(newAge); + assert(dirty_size(localBot, get_top()) != n() - 1, + "Shouldn't be possible..."); + return false; +} - // Delete any resource associated with the queue. - ~GenTaskQueue(); +template +bool GenericTaskQueue::pop_global(E& t) { + Age newAge; + Age oldAge = get_age(); + juint localBot = _bottom; + juint n_elems = size(localBot, oldAge.top()); + if (n_elems == 0) { + return false; + } + t = _elems[oldAge.top()]; + newAge = oldAge; + newAge._top = increment_index(newAge.top()); + if ( newAge._top == 0 ) newAge._tag++; + Age resAge; + *(jint*)&resAge = Atomic::cmpxchg(*(jint*)&newAge, (volatile jint*)&_age, *(jint*)&oldAge); + // Note that using "_bottom" here might fail, since a pop_local might + // have decremented it. + assert(dirty_size(localBot, newAge._top) != n() - 1, + "Shouldn't be possible..."); + return (resAge == oldAge); +} -private: - // Element array. - volatile GenTask* _elems; - -}; -// End clone of OopTaskQueue with GenTask instead of Task +template +GenericTaskQueue::~GenericTaskQueue() { + FREE_C_HEAP_ARRAY(E, _elems); +} // Inherits the typedef of "Task" from above. class TaskQueueSetSuper: public CHeapObj { @@ -250,100 +262,129 @@ virtual bool peek() = 0; }; -class OopTaskQueueSet: public TaskQueueSetSuper { +template class GenericTaskQueueSet: public TaskQueueSetSuper { private: int _n; - OopTaskQueue** _queues; + GenericTaskQueue** _queues; - bool steal_1_random(int queue_num, int* seed, Task& t); - bool steal_best_of_2(int queue_num, int* seed, Task& t); - bool steal_best_of_all(int queue_num, int* seed, Task& t); public: - OopTaskQueueSet(int n) : _n(n) { - typedef OopTaskQueue* OopTaskQueuePtr; - _queues = NEW_C_HEAP_ARRAY(OopTaskQueuePtr, n); + GenericTaskQueueSet(int n) : _n(n) { + typedef GenericTaskQueue* GenericTaskQueuePtr; + _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n); guarantee(_queues != NULL, "Allocation failure."); - for (int i = 0; i < n; i++) _queues[i] = NULL; + for (int i = 0; i < n; i++) { + _queues[i] = NULL; + } } - void register_queue(int i, OopTaskQueue* q); + bool steal_1_random(int queue_num, int* seed, E& t); + bool steal_best_of_2(int queue_num, int* seed, E& t); + bool steal_best_of_all(int queue_num, int* seed, E& t); - OopTaskQueue* queue(int n); + void register_queue(int i, GenericTaskQueue* q); + + GenericTaskQueue* queue(int n); // The thread with queue number "queue_num" (and whose random number seed // is at "seed") is trying to steal a task from some other queue. (It // may try several queues, according to some configuration parameter.) // If some steal succeeds, returns "true" and sets "t" the stolen task, // otherwise returns false. - bool steal(int queue_num, int* seed, Task& t); - - bool peek(); -}; - -class OopStarTaskQueueSet: public TaskQueueSetSuper { -private: - int _n; - OopStarTaskQueue** _queues; - - bool steal_1_random(int queue_num, int* seed, StarTask& t); - bool steal_best_of_2(int queue_num, int* seed, StarTask& t); - bool steal_best_of_all(int queue_num, int* seed, StarTask& t); -public: - OopStarTaskQueueSet(int n) : _n(n) { - typedef OopStarTaskQueue* OopStarTaskQueuePtr; - _queues = NEW_C_HEAP_ARRAY(OopStarTaskQueuePtr, n); - guarantee(_queues != NULL, "Allocation failure."); - for (int i = 0; i < n; i++) _queues[i] = NULL; - } - - void register_queue(int i, OopStarTaskQueue* q); - - OopStarTaskQueue* queue(int n); - - // The thread with queue number "queue_num" (and whose random number seed - // is at "seed") is trying to steal a task from some other queue. (It - // may try several queues, according to some configuration parameter.) - // If some steal succeeds, returns "true" and sets "t" the stolen task, - // otherwise returns false. - bool steal(int queue_num, int* seed, StarTask& t); + bool steal(int queue_num, int* seed, E& t); bool peek(); }; -// Clone of OopTaskQueueSet for GenTask -class GenTaskQueueSet: public TaskQueueSetSuper { - friend class ChunkTaskQueueSet; +template +void GenericTaskQueueSet::register_queue(int i, GenericTaskQueue* q) { + assert(0 <= i && i < _n, "index out of range."); + _queues[i] = q; +} + +template +GenericTaskQueue* GenericTaskQueueSet::queue(int i) { + return _queues[i]; +} + +template +bool GenericTaskQueueSet::steal(int queue_num, int* seed, E& t) { + for (int i = 0; i < 2 * _n; i++) + if (steal_best_of_2(queue_num, seed, t)) + return true; + return false; +} -private: - int _n; - GenTaskQueue** _queues; +template +bool GenericTaskQueueSet::steal_best_of_all(int queue_num, int* seed, E& t) { + if (_n > 2) { + int best_k; + jint best_sz = 0; + for (int k = 0; k < _n; k++) { + if (k == queue_num) continue; + jint sz = _queues[k]->size(); + if (sz > best_sz) { + best_sz = sz; + best_k = k; + } + } + return best_sz > 0 && _queues[best_k]->pop_global(t); + } else if (_n == 2) { + // Just try the other one. + int k = (queue_num + 1) % 2; + return _queues[k]->pop_global(t); + } else { + assert(_n == 1, "can't be zero."); + return false; + } +} -protected: - bool steal_1_random(int queue_num, int* seed, GenTask& t); - bool steal_best_of_2(int queue_num, int* seed, GenTask& t); - bool steal_best_of_all(int queue_num, int* seed, GenTask& t); -public: - GenTaskQueueSet(int n) : _n(n) { - typedef GenTaskQueue* GenTaskQueuePtr; - _queues = NEW_C_HEAP_ARRAY(GenTaskQueuePtr, n); - guarantee(_queues != NULL, "Allocation failure."); - for (int i = 0; i < n; i++) _queues[i] = NULL; +template +bool GenericTaskQueueSet::steal_1_random(int queue_num, int* seed, E& t) { + if (_n > 2) { + int k = queue_num; + while (k == queue_num) k = randomParkAndMiller(seed) % _n; + return _queues[2]->pop_global(t); + } else if (_n == 2) { + // Just try the other one. + int k = (queue_num + 1) % 2; + return _queues[k]->pop_global(t); + } else { + assert(_n == 1, "can't be zero."); + return false; } +} - void register_queue(int i, GenTaskQueue* q); - - GenTaskQueue* queue(int n); +template +bool GenericTaskQueueSet::steal_best_of_2(int queue_num, int* seed, E& t) { + if (_n > 2) { + int k1 = queue_num; + while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n; + int k2 = queue_num; + while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n; + // Sample both and try the larger. + juint sz1 = _queues[k1]->size(); + juint sz2 = _queues[k2]->size(); + if (sz2 > sz1) return _queues[k2]->pop_global(t); + else return _queues[k1]->pop_global(t); + } else if (_n == 2) { + // Just try the other one. + int k = (queue_num + 1) % 2; + return _queues[k]->pop_global(t); + } else { + assert(_n == 1, "can't be zero."); + return false; + } +} - // The thread with queue number "queue_num" (and whose random number seed - // is at "seed") is trying to steal a task from some other queue. (It - // may try several queues, according to some configuration parameter.) - // If some steal succeeds, returns "true" and sets "t" the stolen task, - // otherwise returns false. - bool steal(int queue_num, int* seed, GenTask& t); - - bool peek(); -}; -// End clone of OopTaskQueueSet for GenTask +template +bool GenericTaskQueueSet::peek() { + // Try all the queues. + for (int j = 0; j < _n; j++) { + if (_queues[j]->peek()) + return true; + } + return false; +} // A class to aid in the termination of a set of parallel tasks using // TaskQueueSet's for work stealing. @@ -353,8 +394,6 @@ int _n_threads; TaskQueueSetSuper* _queue_set; jint _offered_termination; - jint _terminated; - Monitor _term_monitor; bool peek_in_queue_set(); protected: @@ -383,7 +422,7 @@ #define SIMPLE_STACK 0 -inline bool OopTaskQueue::push(Task t) { +template inline bool GenericTaskQueue::push(E t) { #if SIMPLE_STACK juint localBot = _bottom; if (_bottom < max_elems()) { @@ -410,7 +449,7 @@ #endif } -inline bool OopTaskQueue::pop_local(Task& t) { +template inline bool GenericTaskQueue::pop_local(E& t) { #if SIMPLE_STACK juint localBot = _bottom; assert(localBot > 0, "precondition."); @@ -450,167 +489,21 @@ #endif } -inline bool OopStarTaskQueue::push(StarTask t) { -#if SIMPLE_STACK - juint localBot = _bottom; - if (_bottom < max_elems()) { - _elems[localBot] = t; - _bottom = localBot + 1; - return true; - } else { - return false; - } -#else - juint localBot = _bottom; - assert((localBot >= 0) && (localBot < n()), "_bottom out of range."); - jushort top = get_top(); - juint dirty_n_elems = dirty_size(localBot, top); - assert((dirty_n_elems >= 0) && (dirty_n_elems < n()), - "n_elems out of range."); - if (dirty_n_elems < max_elems()) { - _elems[localBot] = t; - _bottom = increment_index(localBot); - return true; - } else { - return push_slow(t, dirty_n_elems); - } -#endif -} - -inline bool OopStarTaskQueue::pop_local(StarTask& t) { -#if SIMPLE_STACK - juint localBot = _bottom; - assert(localBot > 0, "precondition."); - localBot--; - t = _elems[localBot]; - _bottom = localBot; - return true; -#else - juint localBot = _bottom; - // This value cannot be n-1. That can only occur as a result of - // the assignment to bottom in this method. If it does, this method - // resets the size( to 0 before the next call (which is sequential, - // since this is pop_local.) - juint dirty_n_elems = dirty_size(localBot, get_top()); - assert(dirty_n_elems != n() - 1, "Shouldn't be possible..."); - if (dirty_n_elems == 0) return false; - localBot = decrement_index(localBot); - _bottom = localBot; - // This is necessary to prevent any read below from being reordered - // before the store just above. - OrderAccess::fence(); - t = _elems[localBot]; - // This is a second read of "age"; the "size()" above is the first. - // If there's still at least one element in the queue, based on the - // "_bottom" and "age" we've read, then there can be no interference with - // a "pop_global" operation, and we're done. - juint tp = get_top(); - if (size(localBot, tp) > 0) { - assert(dirty_size(localBot, tp) != n() - 1, - "Shouldn't be possible..."); - return true; - } else { - // Otherwise, the queue contained exactly one element; we take the slow - // path. - return pop_local_slow(localBot, get_age()); - } -#endif -} +typedef oop Task; +typedef GenericTaskQueue OopTaskQueue; +typedef GenericTaskQueueSet OopTaskQueueSet; -// Clone of OopTaskQueue for GenTask - -inline bool GenTaskQueue::push(GenTask t) { -#if SIMPLE_STACK - juint localBot = _bottom; - if (_bottom < max_elems()) { - _elems[localBot] = t; - _bottom = localBot + 1; - return true; - } else { - return false; - } -#else - juint localBot = _bottom; - assert((localBot >= 0) && (localBot < n()), "_bottom out of range."); - jushort top = get_top(); - juint dirty_n_elems = dirty_size(localBot, top); - assert((dirty_n_elems >= 0) && (dirty_n_elems < n()), - "n_elems out of range."); - if (dirty_n_elems < max_elems()) { - _elems[localBot] = t; - _bottom = increment_index(localBot); - return true; - } else { - return push_slow(t, dirty_n_elems); - } -#endif -} - -inline bool GenTaskQueue::pop_local(GenTask& t) { -#if SIMPLE_STACK - juint localBot = _bottom; - assert(localBot > 0, "precondition."); - localBot--; - t = _elems[localBot]; - _bottom = localBot; - return true; -#else - juint localBot = _bottom; - // This value cannot be n-1. That can only occur as a result of - // the assignment to bottom in this method. If it does, this method - // resets the size( to 0 before the next call (which is sequential, - // since this is pop_local.) - juint dirty_n_elems = dirty_size(localBot, get_top()); - assert(dirty_n_elems != n() - 1, "Shouldn't be possible..."); - if (dirty_n_elems == 0) return false; - localBot = decrement_index(localBot); - _bottom = localBot; - // This is necessary to prevent any read below from being reordered - // before the store just above. - OrderAccess::fence(); - t = _elems[localBot]; - // This is a second read of "age"; the "size()" above is the first. - // If there's still at least one element in the queue, based on the - // "_bottom" and "age" we've read, then there can be no interference with - // a "pop_global" operation, and we're done. - juint tp = get_top(); - if (size(localBot, tp) > 0) { - assert(dirty_size(localBot, tp) != n() - 1, - "Shouldn't be possible..."); - return true; - } else { - // Otherwise, the queue contained exactly one element; we take the slow - // path. - return pop_local_slow(localBot, get_age()); - } -#endif -} -// End clone of OopTaskQueue for GenTask +typedef oop* StarTask; +typedef GenericTaskQueue OopStarTaskQueue; +typedef GenericTaskQueueSet OopStarTaskQueueSet; typedef size_t ChunkTask; // index for chunk - -class ChunkTaskQueue: public CHeapObj { -private: - GenTaskQueue _chunk_queue; - - public: - ChunkTaskQueue() {}; - ~ChunkTaskQueue() {}; - - bool push_slow(ChunkTask t, juint dirty_n_elems); - bool pop_local_slow(juint localBot, TaskQueueSuper::Age oldAge); - - inline void initialize() { _chunk_queue.initialize(); } - inline bool push(ChunkTask t) { return _chunk_queue.push((GenTask) t); } - inline bool pop_local(ChunkTask& t) { return _chunk_queue.pop_local((GenTask&) t); } - bool pop_global(ChunkTask& t) { return _chunk_queue.pop_global((GenTask&) t); } - juint size() { return _chunk_queue.size(); } -}; +typedef GenericTaskQueue ChunkTaskQueue; +typedef GenericTaskQueueSet ChunkTaskQueueSet; class ChunkTaskQueueWithOverflow: public CHeapObj { - friend class ChunkTaskQueueSet; protected: - GenTaskQueue _chunk_queue; + ChunkTaskQueue _chunk_queue; GrowableArray* _overflow_stack; public: @@ -629,50 +522,7 @@ bool stealable_is_empty(); bool overflow_is_empty(); juint stealable_size() { return _chunk_queue.size(); } + ChunkTaskQueue* task_queue() { return &_chunk_queue; } }; -class ChunkTaskQueueSet: public CHeapObj { -private: - GenTaskQueueSet _task_queue_set; - - bool steal_1_random(int queue_num, int* seed, GenTask& t) { - return _task_queue_set.steal_1_random(queue_num, seed, t); - } - bool steal_best_of_2(int queue_num, int* seed, GenTask& t) { - return _task_queue_set.steal_best_of_2(queue_num, seed, t); - } - bool steal_best_of_all(int queue_num, int* seed, GenTask& t) { - return _task_queue_set.steal_best_of_all(queue_num, seed, t); - } -public: - ChunkTaskQueueSet(int n) : _task_queue_set(n) {} - #define USE_ChunkTaskQueueWithOverflow - void register_queue(int i, GenTaskQueue* q) { - _task_queue_set.register_queue(i, q); - } - - void register_queue(int i, ChunkTaskQueueWithOverflow* q) { - register_queue(i, &q->_chunk_queue); - } - - ChunkTaskQueue* queue(int n) { - return (ChunkTaskQueue*) _task_queue_set.queue(n); - } - - GenTaskQueueSet* task_queue_set() { return &_task_queue_set; } - - // The thread with queue number "queue_num" (and whose random number seed - // is at "seed") is trying to steal a task from some other queue. (It - // may try several queues, according to some configuration parameter.) - // If some steal succeeds, returns "true" and sets "t" the stolen task, - // otherwise returns false. - bool steal(int queue_num, int* seed, GenTask& t) { - return _task_queue_set.steal(queue_num, seed, t); - } - - bool peek() { - return _task_queue_set.peek(); - } -}; -// End clone of OopTaskQueueSet for GenTask diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/com/sun/org/apache/regexp/Makefile --- a/j2se/make/com/sun/org/apache/regexp/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/com/sun/org/apache/regexp/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -41,7 +41,6 @@ $(PKGDIR)/regexp/internal/RE.java \ $(PKGDIR)/regexp/internal/RECompiler.java \ $(PKGDIR)/regexp/internal/REDebugCompiler.java \ - $(PKGDIR)/regexp/internal/REDemo.java \ $(PKGDIR)/regexp/internal/REProgram.java \ $(PKGDIR)/regexp/internal/RESyntaxException.java \ $(PKGDIR)/regexp/internal/RETest.java \ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/com/sun/org/apache/xalan/internal/xsltc/Makefile --- a/j2se/make/com/sun/org/apache/xalan/internal/xsltc/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/com/sun/org/apache/xalan/internal/xsltc/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -277,7 +277,6 @@ $(PKGDIR)/xsltc/runtime/SecuritySupport.java \ $(PKGDIR)/xsltc/runtime/SecuritySupport12.java \ $(PKGDIR)/xsltc/runtime/AbstractTranslet.java \ - $(PKGDIR)/xsltc/runtime/AttributeList.java \ $(PKGDIR)/xsltc/runtime/Attributes.java \ $(PKGDIR)/xsltc/runtime/BasisLibrary.java \ $(PKGDIR)/xsltc/runtime/Constants.java \ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/common/Release.gmk --- a/j2se/make/common/Release.gmk Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/common/Release.gmk Thu Jul 05 23:47:33 2007 +0000 @@ -248,16 +248,14 @@ # JavaSound closed libs closed-binaries-dir-jsound: -# windows (32bit only) & linux have additional libraries +# windows & linux have additional libraries # see /make/javax/sound/Makefile & subdir's Makefiles for more details ifeq ($(PLATFORM), windows) JSOUND_LIB=jsound.dll - ifeq ($(ARCH), i586) - # include DirectSound implementation + # include DirectSound implementation closed-binaries-dir-jsound: $(MKDIR) -p $(CLOSED_DIR) $(CP) $(LIB_LOCATION)/jsoundds.dll $(CLOSED_DIR) - endif else # !(PLATFORM windows) JSOUND_LIB=libjsound.so ifeq ($(PLATFORM), linux) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/common/shared/Defs-windows.gmk --- a/j2se/make/common/shared/Defs-windows.gmk Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/common/shared/Defs-windows.gmk Thu Jul 05 23:47:33 2007 +0000 @@ -467,7 +467,12 @@ xALT_DXSDK_LIB_PATH :="$(subst \,/,$(ALT_DXSDK_LIB_PATH))" DXSDK_LIB_PATH :=$(call FullPath,$(xALT_DXSDK_LIB_PATH)) else - DXSDK_LIB_PATH =$(subst //,/,$(DXSDK_PATH)/Lib) + ifeq ($(ARCH_DATA_MODEL), 64) + # 64bit libs are located in "Lib/x64" subdir + DXSDK_LIB_PATH =$(subst //,/,$(DXSDK_PATH)/Lib/x64) + else + DXSDK_LIB_PATH =$(subst //,/,$(DXSDK_PATH)/Lib) + endif endif # DEPLOY_MSSDK: Microsoft SDK for this platform (for deploy) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/common/shared/Sanity.gmk --- a/j2se/make/common/shared/Sanity.gmk Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/common/shared/Sanity.gmk Thu Jul 05 23:47:33 2007 +0000 @@ -838,10 +838,10 @@ fi endif endif - @if [ ! -r $(MOTIF_INCLUDE)/Xm/AccColorT.h ]; then \ + @if [ ! -r $(MOTIF_INCLUDE)/Xm/AccTextT.h ]; then \ $(ECHO) "ERROR: You do not have access to valid Motif 2.1 header files. \n" \ " Please check your access to (for example) \n" \ - " $(MOTIF_INCLUDE)/Xm/AccColorT.h \n" \ + " $(MOTIF_INCLUDE)/Xm/AccTextT.h \n" \ " and/or check your value of ALT_MOTIF_DIR. \n" \ "" >> $(ERROR_FILE) ; \ fi diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/java/java/FILES_java.gmk --- a/j2se/make/java/java/FILES_java.gmk Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/java/java/FILES_java.gmk Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ # -# Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -449,6 +449,7 @@ $(TARGDIR)sun/misc/Service.java \ $(TARGDIR)sun/misc/JavaLangAccess.java \ $(TARGDIR)sun/misc/JavaIOAccess.java \ - $(TARGDIR)sun/misc/JavaIODeleteOnExitAccess.java + $(TARGDIR)sun/misc/JavaIODeleteOnExitAccess.java \ + $(TARGDIR)sun/misc/JavaIOFileDescriptorAccess.java FILES_java = $(JAVA_JAVA_java) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/java/net/FILES_c.gmk --- a/j2se/make/java/net/FILES_c.gmk Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/java/net/FILES_c.gmk Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ # -# Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ $(CTARGDIR)InetAddressImplFactory.c \ $(CTARGDIR)Inet4AddressImpl.c \ $(CTARGDIR)Inet6AddressImpl.c \ - $(CTARGDIR)PlainDatagramSocketImpl.c \ - $(CTARGDIR)PlainSocketImpl.c \ $(CTARGDIR)SocketInputStream.c \ $(CTARGDIR)SocketOutputStream.c \ $(CTARGDIR)net_util.c \ @@ -44,3 +42,14 @@ ifeq ($(PLATFORM), linux) FILES_c += $(CTARGDIR)linux_close.c endif + +ifeq ($(PLATFORM), windows) + FILES_c += $(CTARGDIR)TwoStacksPlainSocketImpl.c + FILES_c += $(CTARGDIR)DualStackPlainSocketImpl.c + FILES_c += $(CTARGDIR)TwoStacksPlainDatagramSocketImpl.c + FILES_c += $(CTARGDIR)DualStackPlainDatagramSocketImpl.c +else + FILES_c += $(CTARGDIR)PlainSocketImpl.c + FILES_c += $(CTARGDIR)PlainDatagramSocketImpl.c +endif + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/java/net/Makefile --- a/j2se/make/java/net/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/java/net/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ # -# Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ java/net/Socket.java \ java/net/SocketOptions.java \ java/net/SocketImpl.java \ + java/net/AbstractPlainSocketImpl.java \ java/net/PlainSocketImpl.java \ java/net/ServerSocket.java \ java/net/InetAddress.java \ @@ -61,15 +62,25 @@ java/net/NetworkInterface.java \ java/net/SocketInputStream.java \ java/net/SocketOutputStream.java \ + java/net/DefaultDatagramSocketImplFactory.java \ java/net/DatagramPacket.java \ java/net/DatagramSocket.java \ java/net/DatagramSocketImpl.java \ - java/net/PlainDatagramSocketImpl.java \ + java/net/AbstractPlainDatagramSocketImpl.java \ java/net/MulticastSocket.java \ java/net/UnknownHostException.java \ java/net/ProtocolException.java \ sun/net/spi/DefaultProxySelector.java +ifeq ($(PLATFORM), windows) + FILES_export += java/net/TwoStacksPlainSocketImpl.java + FILES_export += java/net/DualStackPlainSocketImpl.java + FILES_export += java/net/TwoStacksPlainDatagramSocketImpl.java + FILES_export += java/net/DualStackPlainDatagramSocketImpl.java +else + FILES_export += java/net/PlainDatagramSocketImpl.java +endif + # # Find platform specific native code # diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/javax/sound/Makefile --- a/j2se/make/javax/sound/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/javax/sound/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -94,15 +94,10 @@ INCLUDE_MIDI = TRUE INCLUDE_PORTS = TRUE - # for now, only compile DirectSound for i586 - ifeq ($(ARCH), i586) - SUBDIRS += jsoundds - EXTRA_SOUND_JNI_LIBS += jsoundds - #MXSPP_ADD = $(PLATFORM)-$(ARCH)/ - else - # otherwise, build with empty direct audio - INCLUDE_DAUDIO = TRUE - endif + # DirectSound handles directaudio (both i586 and amd64) + SUBDIRS += jsoundds + EXTRA_SOUND_JNI_LIBS += jsoundds + #MXSPP_ADD = $(PLATFORM)-$(ARCH)/ endif # PLATFORM win32 ifeq ($(PLATFORM), linux) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/javax/sound/jsoundds/Makefile --- a/j2se/make/javax/sound/jsoundds/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/javax/sound/jsoundds/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -50,7 +50,8 @@ $(DAUDIOFILES_export) LDLIBS += dsound.lib -CPPFLAGS += -DUSE_DAUDIO=TRUE +CPPFLAGS += -DUSE_DAUDIO=TRUE \ + -I$(DXSDK_INCLUDE_PATH) ifdef OPENJDK diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/javax/sound/mapfile-vers --- a/j2se/make/javax/sound/mapfile-vers Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/javax/sound/mapfile-vers Thu Jul 05 23:47:33 2007 +0000 @@ -397,6 +397,27 @@ Java_com_sun_media_sound_DirectAudioDevice_nWrite; Java_com_sun_media_sound_DirectAudioDeviceProvider_nGetNumDevices; Java_com_sun_media_sound_DirectAudioDeviceProvider_nNewDirectAudioDeviceInfo; + Java_com_sun_media_sound_MidiInDevice_nClose; + Java_com_sun_media_sound_MidiInDevice_nGetMessages; + Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp; + Java_com_sun_media_sound_MidiInDevice_nOpen; + Java_com_sun_media_sound_MidiInDevice_nStart; + Java_com_sun_media_sound_MidiInDevice_nStop; + Java_com_sun_media_sound_MidiInDeviceProvider_nGetDescription; + Java_com_sun_media_sound_MidiInDeviceProvider_nGetName; + Java_com_sun_media_sound_MidiInDeviceProvider_nGetNumDevices; + Java_com_sun_media_sound_MidiInDeviceProvider_nGetVendor; + Java_com_sun_media_sound_MidiInDeviceProvider_nGetVersion; + Java_com_sun_media_sound_MidiOutDevice_nClose; + Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp; + Java_com_sun_media_sound_MidiOutDevice_nOpen; + Java_com_sun_media_sound_MidiOutDevice_nSendLongMessage; + Java_com_sun_media_sound_MidiOutDevice_nSendShortMessage; + Java_com_sun_media_sound_MidiOutDeviceProvider_nGetDescription; + Java_com_sun_media_sound_MidiOutDeviceProvider_nGetName; + Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices; + Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor; + Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion; Java_com_sun_media_sound_HeadspaceMixer_nAllocateVoices; Java_com_sun_media_sound_HeadspaceMixer_nCloseMixer; Java_com_sun_media_sound_HeadspaceMixer_nCreateLinkedStreams; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/make/mkdemo/Makefile --- a/j2se/make/mkdemo/Makefile Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/make/mkdemo/Makefile Thu Jul 05 23:47:33 2007 +0000 @@ -42,6 +42,11 @@ ( $(CD) $(SHARE_SRC)/demo && $(TAR) -cf - \ `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ ( $(CD) $(DEMODIR) && $(TAR) -xf - ) +ifndef OPENJDK + ( $(CD) $(CLOSED_SHARE_SRC)/demo && $(TAR) -cf - \ + `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ + ( $(CD) $(DEMODIR) && $(TAR) -xf - ) +endif clean clobber:: $(SUBDIRS-loop) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/beans/ObjectHandler.java --- a/j2se/src/share/classes/com/sun/beans/ObjectHandler.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/beans/ObjectHandler.java Thu Jul 05 23:47:33 2007 +0000 @@ -204,7 +204,7 @@ private Class classForName2(String name) { try { - return ClassFinder.findClass(name, this.ldr); + return ClassFinder.resolveClass(name, this.ldr); } catch (ClassNotFoundException e) { if (is != null) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/beans/TypeResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/com/sun/beans/TypeResolver.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,411 @@ +/* + * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans; + +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.HashMap; +import java.util.Map; + +import sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; + +/** + * This is utility class to resolve types. + * + * @since 1.7 + * + * @version 1.1 06/06/07 + * @author Eamonn McManus + * @author Sergey Malenkov + */ +public final class TypeResolver { + /** + * Replaces the given {@code type} in an inherited method + * with the actual type it has in the given {@code inClass}. + * + *

Although type parameters are not inherited by subclasses in the Java + * language, they are effectively inherited when using reflection. + * For example, if you declare an interface like this...

+ * + *
+     * public interface StringToIntMap extends Map<String,Integer> {}
+     * 
+ * + *

...then StringToIntMap.class.getMethods() will show that it has methods + * like put(K,V) even though StringToIntMap has no type parameters. The K + * and V variables are the ones declared by Map, so + * {@link TypeVariable#getGenericDeclaration()} will return Map.class.

+ * + *

The purpose of this method is to take a Type from a possibly-inherited + * method and replace it with the correct Type for the inheriting class. + * So given parameters of K and StringToIntMap.class in the above example, + * this method will return String.

+ * + * @param inClass the base class used to resolve + * @param type the type to resolve + * @return a resolved type + * + * @see #getActualType(Class) + * @see #resolve(Type,Type) + */ + public static Type resolveInClass(Class inClass, Type type) { + return resolve(getActualType(inClass), type); + } + + /** + * Replaces all {@code types} in the given array + * with the actual types they have in the given {@code inClass}. + * + * @param inClass the base class used to resolve + * @param types the array of types to resolve + * @return an array of resolved types + * + * @see #getActualType(Class) + * @see #resolve(Type,Type[]) + */ + public static Type[] resolveInClass(Class inClass, Type[] types) { + return resolve(getActualType(inClass), types); + } + + /** + * Replaces type variables of the given {@code formal} type + * with the types they stand for in the given {@code actual} type. + * + *

A ParameterizedType is a class with type parameters, and the values + * of those parameters. For example, Map<K,V> is a generic class, and + * a corresponding ParameterizedType might look like + * Map<K=String,V=Integer>. Given such a ParameterizedType, this method + * will replace K with String, or List<K> with List<String;, or + * List<? super K> with List<? super String>.

+ * + *

The {@code actual} argument to this method can also be a Class. + * In this case, either it is equivalent to a ParameterizedType with + * no parameters (for example, Integer.class), or it is equivalent to + * a "raw" ParameterizedType (for example, Map.class). In the latter + * case, every type parameter declared or inherited by the class is replaced + * by its "erasure". For a type parameter declared as <T>, the erasure + * is Object. For a type parameter declared as <T extends Number>, + * the erasure is Number.

+ * + *

Although type parameters are not inherited by subclasses in the Java + * language, they are effectively inherited when using reflection. + * For example, if you declare an interface like this...

+ * + *
+     * public interface StringToIntMap extends Map<String,Integer> {}
+     * 
+ * + *

...then StringToIntMap.class.getMethods() will show that it has methods + * like put(K,V) even though StringToIntMap has no type parameters. The K + * and V variables are the ones declared by Map, so + * {@link TypeVariable#getGenericDeclaration()} will return {@link Map Map.class}.

+ * + *

For this reason, this method replaces inherited type parameters too. + * Therefore if this method is called with {@code actual} being + * StringToIntMap.class and {@code formal} being the K from Map, + * it will return {@link String String.class}.

+ * + *

In the case where {@code actual} is a "raw" ParameterizedType, the + * inherited type parameters will also be replaced by their erasures. + * The erasure of a Class is the Class itself, so a "raw" subinterface of + * StringToIntMap will still show the K from Map as String.class. But + * in a case like this... + * + *

+     * public interface StringToIntListMap extends Map<String,List<Integer>> {}
+     * public interface RawStringToIntListMap extends StringToIntListMap {}
+     * 
+ * + *

...the V inherited from Map will show up as List<Integer> in + * StringToIntListMap, but as plain List in RawStringToIntListMap.

+ * + * @param actual the type that supplies bindings for type variables + * @param formal the type where occurrences of the variables + * in {@code actual} will be replaced by the corresponding bound values + * @return a resolved type + * + * @see #TypeResolver(Type) + * @see #resolve(Type) + */ + public static Type resolve(Type actual, Type formal) { + return new TypeResolver(actual).resolve(formal); + } + + /** + * Replaces type variables of all formal types in the given array + * with the types they stand for in the given {@code actual} type. + * + * @param actual the type that supplies bindings for type variables + * @param formals the array of types to resolve + * @return an array of resolved types + * + * @see #TypeResolver(Type) + * @see #resolve(Type[]) + */ + public static Type[] resolve(Type actual, Type[] formals) { + return new TypeResolver(actual).resolve(formals); + } + + /** + * Converts the given {@code type} to the corresponding class. + * This method implements the concept of type erasure, + * that is described in section 4.6 + * of Java Language Specification. + * + * @param type the array of types to convert + * @return a corresponding class + */ + public static Class erase(Type type) { + if (type instanceof Class) { + return (Class) type; + } + if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + return (Class) pt.getRawType(); + } + if (type instanceof TypeVariable) { + TypeVariable tv = (TypeVariable)type; + Type[] bounds = tv.getBounds(); + return (0 < bounds.length) + ? erase(bounds[0]) + : Object.class; + } + if (type instanceof WildcardType) { + WildcardType wt = (WildcardType)type; + Type[] bounds = wt.getUpperBounds(); + return (0 < bounds.length) + ? erase(bounds[0]) + : Object.class; + } + if (type instanceof GenericArrayType) { + GenericArrayType gat = (GenericArrayType)type; + return Array.newInstance(erase(gat.getGenericComponentType()), 0).getClass(); + } + throw new IllegalArgumentException("Unknown Type kind: " + type.getClass()); + } + + /** + * Converts all {@code types} in the given array + * to the corresponding classes. + * + * @param types the array of types to convert + * @return an array of corresponding classes + * + * @see #erase(Type) + */ + public static Class[] erase(Type[] types) { + int length = types.length; + Class[] classes = new Class[length]; + for (int i = 0; i < length; i++) { + classes[i] = TypeResolver.erase(types[i]); + } + return classes; + } + + + private final Map, Type> map + = new HashMap, Type>(); + + /** + * Constructs the type resolver for the given actual type. + * + * @param actual the type that supplies bindings for type variables + * + * @see #prepare(Type) + */ + private TypeResolver(Type actual) { + prepare(actual); + } + + /** + * Fills the map from type parameters + * to types as seen by the given {@code type}. + * The method is recursive because the {@code type} + * inherits mappings from its parent classes and interfaces. + * The {@code type} can be either a {@link Class Class} + * or a {@link ParameterizedType ParameterizedType}. + * If it is a {@link Class Class}, it is either equivalent + * to a {@link ParameterizedType ParameterizedType} with no parameters, + * or it represents the erasure of a {@link ParameterizedType ParameterizedType}. + * + * @param type the next type in the hierarchy + */ + private void prepare(Type type) { + Class raw = (Class)((type instanceof Class) + ? type + : ((ParameterizedType)type).getRawType()); + + TypeVariable[] formals = raw.getTypeParameters(); + + Type[] actuals = (type instanceof Class) + ? formals + : ((ParameterizedType)type).getActualTypeArguments(); + + assert formals.length == actuals.length; + for (int i = 0; i < formals.length; i++) { + this.map.put(formals[i], actuals[i]); + } + Type gSuperclass = raw.getGenericSuperclass(); + if (gSuperclass != null) { + prepare(gSuperclass); + } + for (Type gInterface : raw.getGenericInterfaces()) { + prepare(gInterface); + } + // If type is the raw version of a parameterized class, we type-erase + // all of its type variables, including inherited ones. + if (type instanceof Class && formals.length > 0) { + for (Map.Entry, Type> entry : this.map.entrySet()) { + entry.setValue(erase(entry.getValue())); + } + } + } + + /** + * Replaces the given {@code formal} type + * with the type it stand for in this type resolver. + * + * @param formal the array of types to resolve + * @return a resolved type + */ + private Type resolve(Type formal) { + if (formal instanceof Class) { + return formal; + } + if (formal instanceof GenericArrayType) { + Type comp = ((GenericArrayType)formal).getGenericComponentType(); + comp = resolve(comp); + return (comp instanceof Class) + ? Array.newInstance((Class)comp, 0).getClass() + : GenericArrayTypeImpl.make(comp); + } + if (formal instanceof ParameterizedType) { + ParameterizedType fpt = (ParameterizedType)formal; + Type[] actuals = resolve(fpt.getActualTypeArguments()); + return ParameterizedTypeImpl.make( + (Class)fpt.getRawType(), actuals, fpt.getOwnerType()); + } + if (formal instanceof WildcardType) { + WildcardType fwt = (WildcardType)formal; + Type[] upper = resolve(fwt.getUpperBounds()); + Type[] lower = resolve(fwt.getLowerBounds()); + return new WildcardTypeImpl(upper, lower); + } + if (!(formal instanceof TypeVariable)) { + throw new IllegalArgumentException("Bad Type kind: " + formal.getClass()); + } + Type actual = this.map.get((TypeVariable) formal); + if (actual == null || actual.equals(formal)) { + return formal; + } + actual = fixGenericArray(actual); + return resolve(actual); + // A variable can be bound to another variable that is itself bound + // to something. For example, given: + // class Super {...} + // class Mid extends Super {...} + // class Sub extends Mid + // the variable T is bound to X, which is in turn bound to String. + // So if we have to resolve T, we need the tail recursion here. + } + + /** + * Replaces all formal types in the given array + * with the types they stand for in this type resolver. + * + * @param formals the array of types to resolve + * @return an array of resolved types + * + * @see #resolve(Type) + */ + private Type[] resolve(Type[] formals) { + int length = formals.length; + Type[] actuals = new Type[length]; + for (int i = 0; i < length; i++) { + actuals[i] = resolve(formals[i]); + } + return actuals; + } + + /** + * Replaces a {@link GenericArrayType GenericArrayType} + * with plain array class where it is possible. + * Bug 5041784 + * is that arrays of non-generic type sometimes show up + * as {@link GenericArrayType GenericArrayType} when using reflection. + * For example, a {@code String[]} might show up + * as a {@link GenericArrayType GenericArrayType} + * where {@link GenericArrayType#getGenericComponentType getGenericComponentType} + * is {@code String.class}. This violates the specification, + * which says that {@link GenericArrayType GenericArrayType} + * is used when the component type is a type variable or parameterized type. + * We fit the specification here. + * + * @param type the type to fix + * @return a corresponding type for the generic array type, + * or the same type as {@code type} + */ + private static Type fixGenericArray(Type type) { + if (type instanceof GenericArrayType) { + Type comp = ((GenericArrayType)type).getGenericComponentType(); + comp = fixGenericArray(comp); + if (comp instanceof Class) { + return Array.newInstance((Class)comp, 0).getClass(); + } + } + return type; + } + + /** + * Replaces a {@link Class Class} with type parameters + * with a {@link ParameterizedType ParameterizedType} + * where every parameter is bound to itself. + * When calling {@link #resolveInClass} in the context of {@code inClass}, + * we can't just pass {@code inClass} as the {@code actual} parameter, + * because if {@code inClass} has type parameters + * that would be interpreted as accessing the raw type, + * so we would get unwanted erasure. + * This is why we bind each parameter to itself. + * If {@code inClass} does have type parameters and has methods + * where those parameters appear in the return type or argument types, + * we will correctly leave those types alone. + * + * @param inClass the base class used to resolve + * @return a parameterized type for the class, + * or the same class as {@code inClass} + */ + private static Type getActualType(Class inClass) { + Type[] params = inClass.getTypeParameters(); + return (params.length == 0) + ? inClass + : ParameterizedTypeImpl.make( + inClass, params, inClass.getEnclosingClass()); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/beans/WildcardTypeImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/com/sun/beans/WildcardTypeImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,162 @@ +/* + * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package com.sun.beans; + +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.Arrays; + +/** + * This class implements {@link WildcardType WildcardType} compatibly with the JDK's + * {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}. + * Unfortunately we can't use the JDK's + * {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl} here as we do for + * {@link sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl ParameterizedTypeImpl} and + * {@link sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl GenericArrayTypeImpl}, + * because {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}'s + * constructor takes parameters representing intermediate structures obtained during class-file parsing. + * We could reconstruct versions of those structures but it would be more trouble than it's worth. + * + * @since 1.7 + * + * @version 1.1 06/06/07 + * @author Eamonn McManus + * @author Sergey Malenkov + */ +final class WildcardTypeImpl implements WildcardType { + private final Type[] upperBounds; + private final Type[] lowerBounds; + + /** + * Creates a wildcard type with the requested bounds. + * Note that the array arguments are not cloned + * because instances of this class are never constructed + * from outside the containing package. + * + * @param upperBounds the array of types representing + * the upper bound(s) of this type variable + * @param lowerBounds the array of types representing + * the lower bound(s) of this type variable + */ + WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { + this.upperBounds = upperBounds; + this.lowerBounds = lowerBounds; + } + + /** + * Returns an array of {@link Type Type} objects + * representing the upper bound(s) of this type variable. + * Note that if no upper bound is explicitly declared, + * the upper bound is {@link Object Object}. + * + * @return an array of types representing + * the upper bound(s) of this type variable + */ + public Type[] getUpperBounds() { + return this.upperBounds.clone(); + } + + /** + * Returns an array of {@link Type Type} objects + * representing the lower bound(s) of this type variable. + * Note that if no lower bound is explicitly declared, + * the lower bound is the type of {@code null}. + * In this case, a zero length array is returned. + * + * @return an array of types representing + * the lower bound(s) of this type variable + */ + public Type[] getLowerBounds() { + return this.lowerBounds.clone(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * It is implemented compatibly with the JDK's + * {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}. + * + * @param object the reference object with which to compare + * @return {@code true} if this object is the same as the object argument; + * {@code false} otherwise + * @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#equals + */ + @Override + public boolean equals(Object object) { + if (object instanceof WildcardType) { + WildcardType type = (WildcardType) object; + return Arrays.equals(this.upperBounds, type.getUpperBounds()) + && Arrays.equals(this.lowerBounds, type.getLowerBounds()); + } + return false; + } + + /** + * Returns a hash code value for the object. + * It is implemented compatibly with the JDK's + * {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}. + * + * @return a hash code value for this object + * @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#hashCode + */ + @Override + public int hashCode() { + return Arrays.hashCode(this.upperBounds) + ^ Arrays.hashCode(this.lowerBounds); + } + + /** + * Returns a string representation of the object. + * It is implemented compatibly with the JDK's + * {@link sun.reflect.generics.reflectiveObjects.WildcardTypeImpl WildcardTypeImpl}. + * + * @return a string representation of the object + * @see sun.reflect.generics.reflectiveObjects.WildcardTypeImpl#toString + */ + @Override + public String toString() { + StringBuilder sb; + Type[] bounds; + if (this.lowerBounds.length == 0) { + if (this.upperBounds.length == 0 || Object.class == this.upperBounds[0]) { + return "?"; + } + bounds = this.upperBounds; + sb = new StringBuilder("? extends "); + } + else { + bounds = this.lowerBounds; + sb = new StringBuilder("? super "); + } + for (int i = 0; i < bounds.length; i++) { + if (i > 0) { + sb.append(" & "); + } + sb.append((bounds[i] instanceof Class) + ? ((Class) bounds[i]).getName() + : bounds[i].toString()); + } + return sb.toString(); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/corba/se/impl/activation/CommandHandler.java --- a/j2se/src/share/classes/com/sun/corba/se/impl/activation/CommandHandler.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/corba/se/impl/activation/CommandHandler.java Thu Jul 05 23:47:33 2007 +0000 @@ -29,7 +29,7 @@ import java.io.PrintStream; /** - * @version 1.21, 07/06/21 + * @version 1.21, 07/07/05 * @author Rohit Garg * @since JDK1.2 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java Thu Jul 05 23:47:33 2007 +0000 @@ -52,7 +52,7 @@ * Finally, finishPainting() should be called. It fills the data buffer passed * in with the image data. * - * @version 1.18, 05/05/07 + * @version 1.19, 05/09/07 * @author Josh Outwater */ class GTKEngine { @@ -411,8 +411,7 @@ } public void paintCheck(Graphics g, SynthContext context, - Region id, int state, ShadowType shadowType, String detail, - int x, int y, int w, int h) { + Region id, String detail, int x, int y, int w, int h) { int synthState = context.getComponentState(); int widget = getWidgetType(context.getComponent(), id).ordinal(); @@ -477,8 +476,7 @@ } public void paintOption(Graphics g, SynthContext context, - Region id, int state, ShadowType shadowType, String detail, - int x, int y, int w, int h) { + Region id, String detail, int x, int y, int w, int h) { int synthState = context.getComponentState(); int widget = getWidgetType(context.getComponent(), id).ordinal(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java Thu Jul 05 23:47:33 2007 +0000 @@ -38,9 +38,14 @@ import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType; /** - * @version 1.40, 05/05/07 + * @version 1.41, 05/09/07 */ class GTKIconFactory { + static final int CHECK_ICON_EXTRA_INSET = 1; + static final int DEFAULT_ICON_SPACING = 2; + static final int DEFAULT_ICON_SIZE = 13; + static final int DEFAULT_TOGGLE_MENU_ITEM_SIZE = 12; // For pre-gtk2.4 + private static final String RADIO_BUTTON_ICON = "paintRadioButtonIcon"; private static final String CHECK_BOX_ICON = "paintCheckBoxIcon"; private static final String MENU_ARROW_ICON = "paintMenuArrowIcon"; @@ -147,8 +152,6 @@ private static class DelegatingIcon extends SynthIcon implements UIResource { - static final int DEFAULT_ICON_DIMENSION = 13; - private static final Class[] PARAM_TYPES = new Class[] { SynthContext.class, Graphics.class, int.class, int.class, int.class, int.class, int.class @@ -207,32 +210,23 @@ } if (context == null) { - return DEFAULT_ICON_DIMENSION; + return DEFAULT_ICON_SIZE; } Region region = context.getRegion(); GTKStyle style = (GTKStyle) context.getStyle(); - Object propValue = style.getClassSpecificValue("indicator-size"); + iconDimension = style.getClassSpecificIntValue(context, + "indicator-size", + (region == Region.CHECK_BOX_MENU_ITEM || + region == Region.RADIO_BUTTON_MENU_ITEM) ? + DEFAULT_TOGGLE_MENU_ITEM_SIZE : DEFAULT_ICON_SIZE); - if (propValue != null) { - iconDimension = ((Number)propValue).intValue(); - } else if (region == Region.CHECK_BOX || - region == Region.RADIO_BUTTON) { - iconDimension = DEFAULT_ICON_DIMENSION; - } else { - return (iconDimension = DEFAULT_ICON_DIMENSION); - } - if (region == Region.CHECK_BOX || region == Region.RADIO_BUTTON) { - propValue = style.getClassSpecificValue("indicator-spacing"); - if (propValue != null) { - iconDimension += 2 * ((Number) propValue).intValue(); - } else { - iconDimension += 2 * 2; - } + iconDimension += 2 * style.getClassSpecificIntValue(context, + "indicator-spacing", DEFAULT_ICON_SPACING); } else if (region == Region.CHECK_BOX_MENU_ITEM || region == Region.RADIO_BUTTON_MENU_ITEM) { - iconDimension++; + iconDimension += 2 * CHECK_ICON_EXTRA_INSET; } return iconDimension; } @@ -253,7 +247,7 @@ int getIconDimension(SynthContext context) { updateSizeIfNecessary(context); - return (iconDimension == -1) ? DEFAULT_ICON_DIMENSION : + return (iconDimension == -1) ? DEFAULT_ICON_SIZE : iconDimension; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -32,10 +32,8 @@ import java.lang.ref.*; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.HashMap; import java.util.Locale; import javax.swing.*; -import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.colorchooser.*; import javax.swing.plaf.*; import javax.swing.plaf.synth.*; @@ -45,12 +43,13 @@ import com.sun.java.swing.plaf.gtk.GTKConstants.StateType; import sun.awt.SunToolkit; import sun.awt.UNIXToolkit; +import sun.awt.OSInfo; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; import sun.swing.SwingUtilities2; /** - * @version 1.116, 05/05/07 + * @version 1.117, 06/07/07 * @author Scott Violet */ public class GTKLookAndFeel extends SynthLookAndFeel { @@ -109,7 +108,7 @@ static { // Backup for specifying the version, this isn't currently documented. // If you pass in anything but 2.2 you got the 2.0 colors/look. - String version = (String)java.security.AccessController.doPrivileged( + String version = AccessController.doPrivileged( new GetPropertyAction("swing.gtk.version")); if (version != null) { IS_22 = version.equals("2.2"); @@ -126,21 +125,20 @@ if (cjkLocale) { boolean isSunDesktop = false; - String osName = System.getProperty("os.name"); - if (osName != null) { - if (osName.equals("SunOS")) { + switch (OSInfo.getOSType()) { + case SOLARIS: isSunDesktop = true; - } else if (osName.equals("Linux")) { - Boolean val = - (Boolean)java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - File f = new File("/etc/sun-release"); - return Boolean.valueOf(f.exists()); - } - }); + break; + + case LINUX: + Boolean val = AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { + File f = new File("/etc/sun-release"); + return Boolean.valueOf(f.exists()); + } + }); isSunDesktop = val.booleanValue(); - } } if (isSunDesktop) { isSunCJK = true; @@ -1637,8 +1635,8 @@ return false; } - int w = 0; - int h = 0; + int w; + int h; try { w = Integer.parseInt(width); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Thu Jul 05 23:47:33 2007 +0000 @@ -41,7 +41,7 @@ import java.lang.reflect.Method; /** - * @version 1.92, 05/05/07 + * @version 1.93, 05/09/07 * @author Joshua Outwater * @author Scott Violet */ @@ -1283,30 +1283,26 @@ public void paintCheckBoxIcon(SynthContext context, Graphics g, int state, int x, int y, int w, int h) { - ShadowType shadowType = ShadowType.OUT; - if (((JCheckBox)context.getComponent()).isSelected()) { - shadowType = ShadowType.IN; - } - ENGINE.paintCheck(g, context, Region.CHECK_BOX, - GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state), - shadowType, "checkbutton", x, y, w, h); + GTKStyle style = (GTKStyle)context.getStyle(); + int size = style.getClassSpecificIntValue(context, + "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE); + int offset = style.getClassSpecificIntValue(context, + "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING); + + ENGINE.paintCheck(g, context, Region.CHECK_BOX, "checkbutton", + x+offset, y+offset, size, size); } public void paintRadioButtonIcon(SynthContext context, Graphics g, int state, int x, int y, int w, int h) { - int gtkState = GTKLookAndFeel.synthStateToGTKState( - context.getRegion(), state); - ShadowType shadowType = ShadowType.OUT; - // RadioButton painting appears to be special cased to pass - // SELECTED into the ENGINE even though text colors are PRESSED. - if ((state & SynthConstants.SELECTED) != 0) { - gtkState = SynthConstants.SELECTED; - } - if (gtkState == SynthConstants.SELECTED) { - shadowType = ShadowType.IN; - } - ENGINE.paintOption(g, context, Region.RADIO_BUTTON, gtkState, - shadowType, "radiobutton", x, y, w, h); + GTKStyle style = (GTKStyle)context.getStyle(); + int size = style.getClassSpecificIntValue(context, + "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE); + int offset = style.getClassSpecificIntValue(context, + "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING); + + ENGINE.paintOption(g, context, Region.RADIO_BUTTON, "radiobutton", + x+offset, y+offset, size, size); } public void paintMenuArrowIcon(SynthContext context, Graphics g, @@ -1323,32 +1319,28 @@ public void paintCheckBoxMenuItemCheckIcon(SynthContext context, Graphics g, int state, int x, int y, int w, int h) { - ShadowType shadowType = ShadowType.OUT; - int gtkState = GTKLookAndFeel.synthStateToGTKState( - context.getRegion(), state); - if ((state & SynthConstants.MOUSE_OVER) != 0) { - gtkState = SynthConstants.MOUSE_OVER; - } - if ((state & SynthConstants.SELECTED) != 0) { - shadowType = ShadowType.IN; - } - ENGINE.paintCheck(g, context, Region.CHECK_BOX_MENU_ITEM, - gtkState, shadowType, "check", x, y, w, h); + + GTKStyle style = (GTKStyle)context.getStyle(); + int size = style.getClassSpecificIntValue(context,"indicator-size", + GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE); + + ENGINE.paintCheck(g, context, Region.CHECK_BOX_MENU_ITEM, "check", + x + GTKIconFactory.CHECK_ICON_EXTRA_INSET, + y + GTKIconFactory.CHECK_ICON_EXTRA_INSET, + size, size); } public void paintRadioButtonMenuItemCheckIcon(SynthContext context, Graphics g, int state, int x, int y, int w, int h) { - int gtkState = GTKLookAndFeel.synthStateToGTKState( - context.getRegion(), state); - if ((state & SynthConstants.MOUSE_OVER) != 0) { - gtkState = SynthConstants.MOUSE_OVER; - } - ShadowType shadowType = ShadowType.OUT; - if ((state & SynthConstants.SELECTED) != 0) { - shadowType = ShadowType.IN; - } - ENGINE.paintOption(g, context, Region.RADIO_BUTTON_MENU_ITEM, - gtkState, shadowType, "option", x, y, w, h); + + GTKStyle style = (GTKStyle)context.getStyle(); + int size = style.getClassSpecificIntValue(context,"indicator-size", + GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE); + + ENGINE.paintOption(g, context, Region.RADIO_BUTTON_MENU_ITEM, "option", + x + GTKIconFactory.CHECK_ICON_EXTRA_INSET, + y + GTKIconFactory.CHECK_ICON_EXTRA_INSET, + size, size); } public void paintToolBarHandleIcon(SynthContext context, Graphics g, diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,17 +31,19 @@ import javax.swing.plaf.*; import javax.swing.plaf.basic.*; import java.awt.*; -import java.awt.event.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.beans.*; import java.io.File; import java.io.IOException; import java.util.*; import sun.awt.shell.ShellFolder; +import sun.swing.SwingUtilities2; /** * Motif FileChooserUI. * - * @version 1.57 05/05/07 + * @version 1.59 06/08/07 * @author Jeff Dinkins */ public class MotifFileChooserUI extends BasicFileChooserUI { @@ -73,11 +75,12 @@ private static final Insets buttonMargin = new Insets(3, 3, 3, 3); - private JPanel directoryPanel = new JPanel(); private JPanel bottomPanel; protected JButton approveButton; + private String enterFolderNameLabelText = null; + private int enterFolderNameLabelMnemonic = 0; private String enterFileNameLabelText = null; private int enterFileNameLabelMnemonic = 0; @@ -93,6 +96,25 @@ private String filterLabelText = null; private int filterLabelMnemonic = 0; + private JLabel fileNameLabel; + private final PropertyChangeListener modeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fileNameLabel != null) { + populateFileNameLabel(); + } + } + }; + + private void populateFileNameLabel() { + if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { + fileNameLabel.setText(enterFolderNameLabelText); + fileNameLabel.setDisplayedMnemonic(enterFolderNameLabelMnemonic); + } else { + fileNameLabel.setText(enterFileNameLabelText); + fileNameLabel.setDisplayedMnemonic(enterFileNameLabelMnemonic); + } + } + private String fileNameString(File file) { if (file == null) { return null; @@ -166,25 +188,27 @@ if(f != null) { setFileName(getFileChooser().getName(f)); } - } - else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) { - File[] files = (File[]) e.getNewValue(); - JFileChooser fc = getFileChooser(); - if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled() || !files[0].isDirectory())) { - setFileName(fileNameString(files)); - } + } else if (prop.equals(JFileChooser.SELECTED_FILES_CHANGED_PROPERTY)) { + File[] files = (File[]) e.getNewValue(); + JFileChooser fc = getFileChooser(); + if (files != null && files.length > 0 && (files.length > 1 || fc.isDirectorySelectionEnabled() + || !files[0].isDirectory())) { + setFileName(fileNameString(files)); + } + } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { + fileList.clearSelection(); } else if(prop.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) { directoryList.clearSelection(); ListSelectionModel sm = directoryList.getSelectionModel(); if (sm instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)sm).setAnchorSelectionIndex(0); + sm.setAnchorSelectionIndex(0); } fileList.clearSelection(); sm = fileList.getSelectionModel(); if (sm instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)sm).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)sm).setAnchorSelectionIndex(0); + sm.setAnchorSelectionIndex(0); } File currentDirectory = getFileChooser().getCurrentDirectory(); if(currentDirectory != null) { @@ -199,7 +223,7 @@ } } else if(prop.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) { directoryList.clearSelection(); - } else if(prop == JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY) { + } else if (prop.equals(JFileChooser.MULTI_SELECTION_ENABLED_CHANGED_PROPERTY)) { if(getFileChooser().isMultiSelectionEnabled()) { fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); } else { @@ -207,7 +231,7 @@ fileList.clearSelection(); getFileChooser().setSelectedFiles(null); } - } else if(prop == JFileChooser.ACCESSORY_CHANGED_PROPERTY) { + } else if (prop.equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) { if(getAccessoryPanel() != null) { if(e.getOldValue() != null) { getAccessoryPanel().remove((JComponent) e.getOldValue()); @@ -222,9 +246,9 @@ getAccessoryPanel().setMaximumSize(ZERO_ACC_SIZE); } } - } else if (prop == JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY || - prop == JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY || - prop == JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) { + } else if (prop.equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY) || + prop.equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY) || + prop.equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY)) { approveButton.setText(getApproveButtonText(getFileChooser())); approveButton.setToolTipText(getApproveButtonToolTipText(getFileChooser())); } else if (prop.equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) { @@ -387,10 +411,10 @@ interior.add(Box.createRigidArea(vstrut10)); // add the filename field PENDING(jeff) - I18N - l = new JLabel(enterFileNameLabelText); - l.setDisplayedMnemonic(enterFileNameLabelMnemonic); - align(l); - interior.add(l); + fileNameLabel = new JLabel(); + populateFileNameLabel(); + align(fileNameLabel); + interior.add(fileNameLabel); filenameTextField = new JTextField() { public Dimension getMaximumSize() { @@ -400,7 +424,7 @@ } }; filenameTextField.setInheritsPopupMenu(true); - l.setLabelFor(filenameTextField); + fileNameLabel.setLabelFor(filenameTextField); filenameTextField.addActionListener(getApproveSelectionAction()); align(filenameTextField); filenameTextField.setAlignmentX(JComponent.LEFT_ALIGNMENT); @@ -479,6 +503,16 @@ } } + protected void installListeners(JFileChooser fc) { + super.installListeners(fc); + fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + } + + protected void uninstallListeners(JFileChooser fc) { + fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + super.uninstallListeners(fc); + } + protected JPanel getBottomPanel() { if (bottomPanel == null) { bottomPanel = new JPanel(new BorderLayout(0, 4)); @@ -506,6 +540,8 @@ Locale l = fc.getLocale(); + enterFolderNameLabelText = UIManager.getString("FileChooser.enterFolderNameLabelText",l); + enterFolderNameLabelMnemonic = UIManager.getInt("FileChooser.enterFolderNameLabelMnemonic"); enterFileNameLabelText = UIManager.getString("FileChooser.enterFileNameLabelText",l); enterFileNameLabelMnemonic = UIManager.getInt("FileChooser.enterFileNameLabelMnemonic"); @@ -546,6 +582,18 @@ fileList.setCellRenderer(new FileCellRenderer()); fileList.addListSelectionListener(createListSelectionListener(getFileChooser())); fileList.addMouseListener(createDoubleClickListener(getFileChooser(), fileList)); + fileList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + JFileChooser chooser = getFileChooser(); + if (SwingUtilities.isLeftMouseButton(e) && !chooser.isMultiSelectionEnabled()) { + int index = SwingUtilities2.loc2IndexFileList(fileList, e.getPoint()); + if (index >= 0) { + File file = (File) fileList.getModel().getElementAt(index); + setFileName(chooser.getName(file)); + } + } + } + }); align(fileList); JScrollPane scrollpane = new JScrollPane(fileList); scrollpane.setPreferredSize(prefListSize); @@ -746,10 +794,10 @@ public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); - if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { + if(prop.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) { filters = (FileFilter[]) e.getNewValue(); fireContentsChanged(this, -1, -1); - } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { + } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { fireContentsChanged(this, -1, -1); } } @@ -770,12 +818,12 @@ FileFilter currentFilter = getFileChooser().getFileFilter(); boolean found = false; if(currentFilter != null) { - for(int i=0; i < filters.length; i++) { - if(filters[i] == currentFilter) { - found = true; - } - } - if(found == false) { + for (FileFilter filter : filters) { + if (filter == currentFilter) { + found = true; + } + } + if (!found) { getFileChooser().addChoosableFileFilter(currentFilter); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,6 +44,7 @@ import javax.swing.plaf.basic.BasicComboBoxEditor; import sun.swing.SwingUtilities2; +import sun.awt.OSInfo; /** * Implements the Motif Look and Feel. @@ -57,7 +58,7 @@ * version of Swing. A future release of Swing will provide support for * long term persistence. * - * @version 1.192 05/05/07 + * @version 1.193 06/07/07 * @author unattributed */ public class MotifLookAndFeel extends BasicLookAndFeel @@ -76,9 +77,7 @@ public boolean isNativeLookAndFeel() { - String osName = System.getProperty("os.name"); - return (osName != null) && - (osName.indexOf("SunOS") != -1 || osName.indexOf("Solaris") != -1); + return OSInfo.getOSType() == OSInfo.OSType.SOLARIS; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.6 01/30/03 +# 1.7 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Folders FileChooser.filesLabelText=Files FileChooser.enterFileNameLabelText=Enter file name: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Abort file chooser dialog. FileChooser.saveButtonToolTipText=Save selected file. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.8 08/12/05 +# 1.9 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Ordner FileChooser.filesLabelText=Dateien FileChooser.enterFileNameLabelText=Filternamen eingeben: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Dialogfeld f\u00fcr Dateiauswahl abbrechen FileChooser.saveButtonToolTipText=Ausgew\u00e4hlte Datei speichern diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_es.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_es.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_es.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.7 08/12/05 +# 1.8 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Carpetas FileChooser.filesLabelText=Archivos FileChooser.enterFileNameLabelText=Introducir nombre de archivo: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Cuadro de di\u00e1logo para cancelar elector de archivo. FileChooser.saveButtonToolTipText=Guardar archivo seleccionado. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_fr.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_fr.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_fr.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.7 08/12/05 +# 1.8 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Dossiers FileChooser.filesLabelText=Fichiers FileChooser.enterFileNameLabelText=Entrez le nom du fichier : +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Ferme la bo\u00eete de dialogue du s\u00e9lecteur de fichiers FileChooser.saveButtonToolTipText=Enregistre le fichier s\u00e9lectionn\u00e9 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_it.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_it.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_it.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.5 08/12/05 +# 1.6 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Cartelle FileChooser.filesLabelText=File FileChooser.enterFileNameLabelText=Nome file: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Finestra di dialogo Interrompi Selezione file. FileChooser.saveButtonToolTipText=Salva file selezionato. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ja.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ja.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ja.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.6 08/12/05 +# 1.7 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=\u30d5\u30a9\u30eb\u30c0 FileChooser.filesLabelText=\u30d5\u30a1\u30a4\u30eb FileChooser.enterFileNameLabelText=\u30d5\u30a1\u30a4\u30eb\u540d\u3092\u5165\u529b: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=\u30d5\u30a1\u30a4\u30eb\u30c1\u30e5\u30fc\u30b6\u30c0\u30a4\u30a2\u30ed\u30b0\u3092\u7d42\u4e86 FileChooser.saveButtonToolTipText=\u9078\u629e\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.7 08/12/05 +# 1.8 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=\ud3f4\ub354 FileChooser.filesLabelText=\ud30c\uc77c FileChooser.enterFileNameLabelText=\ud30c\uc77c \uc774\ub984\uc744 \uc785\ub825\ud558\uc2ed\uc2dc\uc624: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=\ud30c\uc77c \uc120\ud0dd \ub300\ud654\uc0c1\uc790\ub97c \uc911\uc9c0\ud569\ub2c8\ub2e4. FileChooser.saveButtonToolTipText=\uc120\ud0dd\ub41c \ud30c\uc77c\uc744 \uc800\uc7a5\ud569\ub2c8\ub2e4. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_sv.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_sv.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_sv.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.8 08/12/05 +# 1.9 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=Mappar FileChooser.filesLabelText=Filer FileChooser.enterFileNameLabelText=Ange filnamn: +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=Avbryt \u00d6ppna fil. FileChooser.saveButtonToolTipText=Spara markerad fil. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_CN.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.11 08/12/05 +# 1.12 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=\u6587\u4ef6\u5939 FileChooser.filesLabelText=\u6587\u4ef6 FileChooser.enterFileNameLabelText=\u952e\u5165\u6587\u4ef6\u540d\uff1a +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=\u7ec8\u6b62\u6587\u4ef6\u9009\u62e9\u5668\u5bf9\u8bdd\u6846 FileChooser.saveButtonToolTipText=\u4fdd\u5b58\u9009\u62e9\u7684\u6587\u4ef6 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_zh_TW.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.6 08/12/05 +# 1.7 04/16/07 # @author Steve Wilson @@ -32,6 +32,7 @@ FileChooser.foldersLabelText=\u6a94\u6848\u593e FileChooser.filesLabelText=\u6a94\u6848 FileChooser.enterFileNameLabelText=\u8f38\u5165\u6a94\u6848\u540d\u7a31\ufe55 +FileChooser.enterFolderNameLabelText=Enter folder name: FileChooser.cancelButtonToolTipText=\u4e2d\u65b7\u300c\u6a94\u6848\u9078\u64c7\u5668\u300d\u5c0d\u8a71\u65b9\u584a\u3002 FileChooser.saveButtonToolTipText=\u5132\u5b58\u9078\u53d6\u7684\u6a94\u6848\u3002 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsClassicLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -35,8 +35,11 @@ * version of Swing. A future release of Swing will provide support for * long term persistence. * - * @version 1.9 05/05/07 + * @version 1.10 05/24/07 * @since 1.5 */ public class WindowsClassicLookAndFeel extends WindowsLookAndFeel { + public String getName() { + return "Windows Classic"; + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -33,6 +33,7 @@ import javax.swing.plaf.basic.*; import java.awt.*; import java.awt.event.*; +import java.awt.image.BufferedImage; import java.beans.*; import java.io.File; import java.io.FileNotFoundException; @@ -40,6 +41,7 @@ import java.util.*; import sun.awt.shell.ShellFolder; +import sun.awt.OSInfo; import sun.swing.*; import javax.accessibility.*; @@ -47,7 +49,7 @@ /** * Windows L&F implementation of a FileChooser. * - * @version 1.107 05/05/07 + * @version 1.110 06/08/07 * @author Jeff Dinkins */ public class WindowsFileChooserUI extends BasicFileChooserUI { @@ -55,7 +57,7 @@ // The following are private because the implementation of the // Windows FileChooser L&F is not complete yet. - private static final String OS_VERSION = System.getProperty("os.version"); + private static final OSInfo.WindowsVersion OS_VERSION = OSInfo.getWindowsVersion(); private JPanel centerPanel; @@ -67,8 +69,6 @@ private FilterComboBoxModel filterComboBoxModel; private JTextField filenameTextField; - private JToggleButton listViewButton; - private JToggleButton detailsViewButton; private FilePane filePane; private WindowsPlacesBar placesBar; private boolean useShellFolder; @@ -109,6 +109,8 @@ private int fileNameLabelMnemonic = 0; private String fileNameLabelText = null; + private int folderNameLabelMnemonic = 0; + private String folderNameLabelText = null; private int filesOfTypeLabelMnemonic = 0; private String filesOfTypeLabelText = null; @@ -128,8 +130,30 @@ private String detailsViewButtonToolTipText = null; private String detailsViewButtonAccessibleName = null; + private String viewMenuButtonToolTipText = null; + private String viewMenuButtonAccessibleName = null; + private BasicFileView fileView = new WindowsFileView(); + private JLabel fileNameLabel; + private final PropertyChangeListener modeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fileNameLabel != null) { + populateFileNameLabel(); + } + } + }; + + private void populateFileNameLabel() { + if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { + fileNameLabel.setText(folderNameLabelText); + fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic); + } else { + fileNameLabel.setText(fileNameLabelText); + fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + } + } + // // ComponentUI Interface Implementation methods // @@ -194,6 +218,10 @@ public ListSelectionListener createListSelectionListener() { return WindowsFileChooserUI.this.createListSelectionListener(getFileChooser()); } + + public boolean usesShellFolder() { + return useShellFolder; + } } public void installComponents(JFileChooser fc) { @@ -214,7 +242,7 @@ // Directory manipulation buttons JToolBar topPanel = new JToolBar(); topPanel.setFloatable(false); - if (OS_VERSION.compareTo("4.9") >= 0) { // Windows Me/2000 and later (4.90/5.0) + if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) >= 0) { topPanel.putClientProperty("JToolBar.isRollover", Boolean.TRUE); } @@ -283,13 +311,13 @@ upFolderButton.setMargin(shrinkwrap); upFolderButton.setFocusPainted(false); topPanel.add(upFolderButton); - if (OS_VERSION.compareTo("4.9") < 0) { // Before Windows Me/2000 (4.90/5.0) + if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) < 0) { topPanel.add(Box.createRigidArea(hstrut10)); } JButton b; - if (OS_VERSION.startsWith("4.1")) { // Windows 98 (4.10) + if (OS_VERSION == OSInfo.WINDOWS_98) { // Desktop Button File homeDir = fsv.getHomeDirectory(); String toolTipText = homeFolderToolTipText; @@ -325,62 +353,163 @@ b.setFocusPainted(false); topPanel.add(b); } - if (OS_VERSION.compareTo("4.9") < 0) { // Before Windows Me/2000 (4.90/5.0) + if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) < 0) { topPanel.add(Box.createRigidArea(hstrut10)); - } + + // View button group + ButtonGroup viewButtonGroup = new ButtonGroup(); - // View button group - ButtonGroup viewButtonGroup = new ButtonGroup(); + // List Button + final JToggleButton listViewButton = new JToggleButton(listViewIcon); + listViewButton.setToolTipText(listViewButtonToolTipText); + listViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, + listViewButtonAccessibleName); + listViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, + Boolean.TRUE); + listViewButton.setFocusPainted(false); + listViewButton.setSelected(true); + listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + listViewButton.setMargin(shrinkwrap); + listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); + topPanel.add(listViewButton); + viewButtonGroup.add(listViewButton); + + // Details Button + final JToggleButton detailsViewButton = new JToggleButton(detailsViewIcon); + detailsViewButton.setToolTipText(detailsViewButtonToolTipText); + detailsViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, + detailsViewButtonAccessibleName); + detailsViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, + Boolean.TRUE); + detailsViewButton.setFocusPainted(false); + detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + detailsViewButton.setMargin(shrinkwrap); + detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); + topPanel.add(detailsViewButton); + viewButtonGroup.add(detailsViewButton); - // List Button - listViewButton = new JToggleButton(listViewIcon); - listViewButton.setToolTipText(listViewButtonToolTipText); - listViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, - listViewButtonAccessibleName); - listViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, - Boolean.TRUE); - listViewButton.setFocusPainted(false); - listViewButton.setSelected(true); - listViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); - listViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); - listViewButton.setMargin(shrinkwrap); - listViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); - topPanel.add(listViewButton); - viewButtonGroup.add(listViewButton); + topPanel.add(Box.createRigidArea(new Dimension(60, 0))); + + filePane.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if ("viewType".equals(e.getPropertyName())) { + int viewType = filePane.getViewType(); + + switch (viewType) { + case FilePane.VIEWTYPE_LIST: + listViewButton.setSelected(true); + break; + + case FilePane.VIEWTYPE_DETAILS: + detailsViewButton.setSelected(true); + break; + } + } + } + }); + } else { // After Windows Me + // View button group + ButtonGroup viewButtonGroup = new ButtonGroup(); + + // Popup Menu + final JPopupMenu viewTypePopupMenu = new JPopupMenu(); + + final JRadioButtonMenuItem listViewMenuItem = new JRadioButtonMenuItem( + filePane.getViewTypeAction(FilePane.VIEWTYPE_LIST)); + listViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_LIST); + viewTypePopupMenu.add(listViewMenuItem); + viewButtonGroup.add(listViewMenuItem); + + final JRadioButtonMenuItem detailsViewMenuItem = new JRadioButtonMenuItem( + filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); + detailsViewMenuItem.setSelected(filePane.getViewType() == FilePane.VIEWTYPE_DETAILS); + viewTypePopupMenu.add(detailsViewMenuItem); + viewButtonGroup.add(detailsViewMenuItem); - // Details Button - detailsViewButton = new JToggleButton(detailsViewIcon); - detailsViewButton.setToolTipText(detailsViewButtonToolTipText); - detailsViewButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, - detailsViewButtonAccessibleName); - detailsViewButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, - Boolean.TRUE); - detailsViewButton.setFocusPainted(false); - detailsViewButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); - detailsViewButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); - detailsViewButton.setMargin(shrinkwrap); - detailsViewButton.addActionListener(filePane.getViewTypeAction(FilePane.VIEWTYPE_DETAILS)); - topPanel.add(detailsViewButton); - viewButtonGroup.add(detailsViewButton); + // Create icon for viewMenuButton + BufferedImage image = new BufferedImage(viewMenuIcon.getIconWidth() + 7, viewMenuIcon.getIconHeight(), + BufferedImage.TYPE_INT_ARGB); + Graphics graphics = image.getGraphics(); + viewMenuIcon.paintIcon(filePane, graphics, 0, 0); + int x = image.getWidth() - 5; + int y = image.getHeight() / 2 - 1; + graphics.setColor(Color.BLACK); + graphics.fillPolygon(new int[]{x, x + 5, x + 2}, new int[]{y, y, y + 3}, 3); - topPanel.add(Box.createRigidArea(new Dimension(60, 0))); + // Details Button + final JButton viewMenuButton = new JButton(new ImageIcon(image)); + viewMenuButton.setToolTipText(viewMenuButtonToolTipText); + viewMenuButton.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, viewMenuButtonAccessibleName); + viewMenuButton.putClientProperty(WindowsLookAndFeel.HI_RES_DISABLED_ICON_CLIENT_KEY, Boolean.TRUE); + viewMenuButton.setFocusable(false); + viewMenuButton.setAlignmentX(JComponent.LEFT_ALIGNMENT); + viewMenuButton.setAlignmentY(JComponent.CENTER_ALIGNMENT); + viewMenuButton.setMargin(shrinkwrap); + viewMenuButton.setModel(new DefaultButtonModel() { + public void setPressed(boolean b) { + } + + public void setArmed(boolean b) { + } + + public void setSelected(boolean b) { + super.setSelected(b); + + if (b) { + stateMask |= PRESSED | ARMED; + } else { + stateMask &= ~(PRESSED | ARMED); + } + } + }); + viewMenuButton.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + viewMenuButton.setSelected(!viewMenuButton.isSelected()); - filePane.addPropertyChangeListener(new PropertyChangeListener() { - public void propertyChange(PropertyChangeEvent e) { - if ("viewType".equals(e.getPropertyName())) { - int viewType = filePane.getViewType(); - switch (viewType) { - case FilePane.VIEWTYPE_LIST: - listViewButton.setSelected(true); - break; + if (viewMenuButton.isSelected()) { + viewTypePopupMenu.show(viewMenuButton, 0, viewMenuButton.getHeight()); + } + } + } + }); + viewTypePopupMenu.addPopupMenuListener(new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + viewMenuButton.setSelected(false); + } + }); + } - case FilePane.VIEWTYPE_DETAILS: - detailsViewButton.setSelected(true); - break; - } - } - } - }); + public void popupMenuCanceled(PopupMenuEvent e) { + } + }); + topPanel.add(viewMenuButton); + + topPanel.add(Box.createRigidArea(new Dimension(80, 0))); + + filePane.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if ("viewType".equals(e.getPropertyName())) { + switch (filePane.getViewType()) { + case FilePane.VIEWTYPE_LIST: + listViewMenuItem.setSelected(true); + break; + + case FilePane.VIEWTYPE_DETAILS: + detailsViewMenuItem.setSelected(true); + break; + } + } + } + }); + } // ************************************** // // ******* Add the directory pane ******* // @@ -408,10 +537,10 @@ labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS)); labelPanel.add(Box.createRigidArea(vstrut4)); - JLabel fnl = new JLabel(fileNameLabelText); - fnl.setDisplayedMnemonic(fileNameLabelMnemonic); - fnl.setAlignmentY(0); - labelPanel.add(fnl); + fileNameLabel = new JLabel(); + populateFileNameLabel(); + fileNameLabel.setAlignmentY(0); + labelPanel.add(fileNameLabel); labelPanel.add(Box.createRigidArea(new Dimension(1,12))); @@ -434,7 +563,7 @@ } }; - fnl.setLabelFor(filenameTextField); + fileNameLabel.setLabelFor(filenameTextField); filenameTextField.addFocusListener( new FocusAdapter() { public void focusGained(FocusEvent e) { @@ -520,7 +649,7 @@ } } } - if (OS_VERSION.compareTo("4.9") >= 0) { // Windows Me/2000 and later (4.90/5.0) + if (OS_VERSION.compareTo(OSInfo.WINDOWS_ME) >= 0) { if (useShellFolder) { if (placesBar == null && !UIManager.getBoolean("FileChooser.noPlacesBar")) { placesBar = new WindowsPlacesBar(fc, XPStyle.getXP() != null); @@ -562,6 +691,8 @@ fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic"); fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l); + folderNameLabelMnemonic = UIManager.getInt("FileChooser.folderNameLabelMnemonic"); + folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l); filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic"); filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l); @@ -580,12 +711,21 @@ detailsViewButtonToolTipText = UIManager.getString("FileChooser.detailsViewButtonToolTipText",l); detailsViewButtonAccessibleName = UIManager.getString("FileChooser.detailsViewButtonAccessibleName",l); + + viewMenuButtonToolTipText = UIManager.getString("FileChooser.viewMenuButtonToolTipText",l); + viewMenuButtonAccessibleName = UIManager.getString("FileChooser.viewMenuButtonAccessibleName",l); } protected void installListeners(JFileChooser fc) { super.installListeners(fc); ActionMap actionMap = getActionMap(); SwingUtilities.replaceUIActionMap(fc, actionMap); + fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + } + + protected void uninstallListeners(JFileChooser fc) { + fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + super.uninstallListeners(fc); } protected ActionMap getActionMap() { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -51,25 +51,17 @@ import javax.swing.*; import javax.swing.plaf.basic.*; import javax.swing.border.*; -import javax.swing.text.JTextComponent; import javax.swing.text.DefaultEditorKit; import java.awt.Font; import java.awt.Color; -import java.awt.SystemColor; import java.awt.event.KeyEvent; -import java.awt.event.InputEvent; import java.awt.event.ActionEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; - -import java.net.URL; -import java.io.Serializable; import java.security.AccessController; -import java.util.*; import sun.awt.SunToolkit; +import sun.awt.OSInfo; import sun.awt.shell.ShellFolder; import sun.font.FontManager; import sun.security.action.GetPropertyAction; @@ -83,8 +75,7 @@ import static com.sun.java.swing.plaf.windows.TMSchema.*; import static com.sun.java.swing.plaf.windows.XPStyle.Skin; -import com.sun.java.swing.plaf.windows.WindowsIconFactory - .VistaMenuItemCheckIconFactory; +import com.sun.java.swing.plaf.windows.WindowsIconFactory.VistaMenuItemCheckIconFactory; /** * Implements the Windows95/98/NT/2000 Look and Feel. @@ -98,7 +89,7 @@ * version of Swing. A future release of Swing will provide support for * long term persistence. * - * @version 1.237 05/05/07 + * @version 1.239 06/08/07 * @author unattributed */ public class WindowsLookAndFeel extends BasicLookAndFeel @@ -150,8 +141,7 @@ } public boolean isNativeLookAndFeel() { - String osName = System.getProperty("os.name"); - return (osName != null) && (osName.indexOf("Windows") != -1); + return OSInfo.getOSType() == OSInfo.OSType.WINDOWS; } public boolean isSupportedLookAndFeel() { @@ -165,22 +155,18 @@ // Set the flag which determines which version of Windows should // be rendered. This flag only need to be set once. // if version <= 4.0 then the classic LAF should be loaded. - String osVersion = System.getProperty("os.version"); - if (osVersion != null) { - Float version = Float.valueOf(osVersion); - if (version.floatValue() <= 4.0) { - isClassicWindows = true; - } else { - isClassicWindows = false; - XPStyle.invalidateStyle(); - } - } + if (OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_95) <= 0) { + isClassicWindows = true; + } else { + isClassicWindows = false; + XPStyle.invalidateStyle(); + } // Using the fonts set by the user can potentially cause // performance and compatibility issues, so allow this feature // to be switched off either at runtime or programmatically // - String systemFonts = (String) java.security.AccessController.doPrivileged( + String systemFonts = java.security.AccessController.doPrivileged( new GetPropertyAction("swing.useSystemFontSettings")); useSystemFontSettings = (systemFonts == null || Boolean.valueOf(systemFonts).booleanValue()); @@ -315,8 +301,6 @@ // *** Shared Fonts Integer twelve = new Integer(12); - Integer eight = new Integer(8); - Integer ten = new Integer(10); Integer fontPlain = new Integer(Font.PLAIN); Integer fontBold = new Integer(Font.BOLD); @@ -343,32 +327,16 @@ ColorUIResource red = new ColorUIResource(Color.red); ColorUIResource black = new ColorUIResource(Color.black); ColorUIResource white = new ColorUIResource(Color.white); - ColorUIResource yellow = new ColorUIResource(Color.yellow); ColorUIResource gray = new ColorUIResource(Color.gray); - ColorUIResource lightGray = new ColorUIResource(Color.lightGray); ColorUIResource darkGray = new ColorUIResource(Color.darkGray); - ColorUIResource scrollBarTrack = lightGray; ColorUIResource scrollBarTrackHighlight = darkGray; // Set the flag which determines which version of Windows should // be rendered. This flag only need to be set once. // if version <= 4.0 then the classic LAF should be loaded. - String osVersion = System.getProperty("os.version"); - if (osVersion != null) { - try { - Float version = Float.valueOf(osVersion); - if (version.floatValue() <= 4.0) { - isClassicWindows = true; - } else { - isClassicWindows = false; - } - } catch (NumberFormatException ex) { - isClassicWindows = false; - } - } + isClassicWindows = OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_95) <= 0; // *** Tree - ColorUIResource treeSelection = new ColorUIResource(0, 0, 128); Object treeExpandedIcon = WindowsTreeUI.ExpandedIcon.createExpandedIcon(); Object treeCollapsedIcon = WindowsTreeUI.CollapsedIcon.createCollapsedIcon(); @@ -499,7 +467,7 @@ "control shift O", "toggle-componentOrientation"/*DefaultEditorKit.toggleComponentOrientation*/ }); - Object menuItemAcceleratorDelimiter = new String("+"); + Object menuItemAcceleratorDelimiter = "+"; Object ControlBackgroundColor = new DesktopProperty( "win.3d.backgroundColor", @@ -662,8 +630,8 @@ if (!(this instanceof WindowsClassicLookAndFeel) && - (System.getProperty("os.name").startsWith("Windows ") && - System.getProperty("os.version").compareTo("5.1") >= 0) && + (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && + OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0) && AccessController.doPrivileged(new GetPropertyAction("swing.noxp")) == null) { // These desktop properties are not used directly, but are needed to @@ -839,6 +807,8 @@ "FileChooser.listViewWindowsStyle", Boolean.TRUE, "FileChooser.detailsViewIcon", new LazyWindowsIcon("fileChooserIcon DetailsView", "icons/DetailsView.gif"), + "FileChooser.viewMenuIcon", new LazyWindowsIcon("fileChooserIcon ViewMenu", + "icons/ListView.gif"), "FileChooser.upFolderIcon", new LazyWindowsIcon("fileChooserIcon UpFolder", "icons/UpFolder.gif"), "FileChooser.newFolderIcon", new LazyWindowsIcon("fileChooserIcon NewFolder", @@ -1672,26 +1642,10 @@ } static boolean isOnVista() { - boolean rv = false; - String osName = System.getProperty("os.name"); - String osVers = System.getProperty("os.version"); - if (osName != null - && osName.startsWith("Windows") - && osVers != null - && osVers.length() > 0) { - - int p = osVers.indexOf('.'); - if (p >= 0) { - osVers = osVers.substring(0, p); - } - - try { - rv = (Integer.parseInt(osVers) >= 6); - } catch (NumberFormatException nfe) { - } - } - return rv; + return OSInfo.getOSType() == OSInfo.OSType.WINDOWS + && OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_VISTA) >= 0; } + private void initVistaComponentDefaults(UIDefaults table) { if (! isOnVista()) { return; @@ -2237,8 +2191,8 @@ this.nativeImageName = nativeImageName; this.fallback = fallback; - if (System.getProperty("os.name").startsWith("Windows ") && - System.getProperty("os.version").compareTo("5.1") < 0) { + if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && + OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) < 0) { // This desktop property is needed to trigger reloading the icon. // It is kept in member variable to avoid GC. this.desktopProperty = new TriggerDesktopProperty(desktopPropertyName) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.8 07/30/03 +# 1.10 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Look in: FileChooser.saveInLabelText=Save in: FileChooser.fileNameLabelText=File name: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Files of type: FileChooser.upFolderToolTipText=Up One Level FileChooser.upFolderAccessibleName=Up @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=List FileChooser.detailsViewButtonToolTipText=Details FileChooser.detailsViewButtonAccessibleName=Details +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=Details FileChooser.refreshActionLabelText=Refresh FileChooser.viewMenuLabelText=View diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_de.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.10 08/12/05 +# 1.12 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Suchen in: FileChooser.saveInLabelText=Speichern in: FileChooser.fileNameLabelText=Dateiname: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Dateityp: FileChooser.upFolderToolTipText=Eine Ebene h\u00f6her FileChooser.upFolderAccessibleName=H\u00f6her @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=Liste FileChooser.detailsViewButtonToolTipText=Einzelheiten FileChooser.detailsViewButtonAccessibleName=Einzelheiten +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=Einzelheiten FileChooser.refreshActionLabelText=Aktualisieren FileChooser.viewMenuLabelText=Ansicht diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_es.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_es.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_es.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Buscar en: FileChooser.saveInLabelText=Guardar en: FileChooser.fileNameLabelText=Nombre de archivo: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Archivos de tipo: FileChooser.upFolderToolTipText=Subir un nivel FileChooser.upFolderAccessibleName=Arriba @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=Lista FileChooser.detailsViewButtonToolTipText=Detalles FileChooser.detailsViewButtonAccessibleName=Detalles +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=Detalles FileChooser.refreshActionLabelText=Renovar FileChooser.viewMenuLabelText=Ver diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_fr.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_fr.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_fr.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Rechercher dans : FileChooser.saveInLabelText=Enregistrer dans : FileChooser.fileNameLabelText=Nom de fichier : +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Fichiers du type : FileChooser.upFolderToolTipText=Remonte d'un niveau. FileChooser.upFolderAccessibleName=Vers le haut @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=Liste FileChooser.detailsViewButtonToolTipText=D\u00e9tails FileChooser.detailsViewButtonAccessibleName=D\u00e9tails +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=D\u00e9tails FileChooser.refreshActionLabelText=Actualiser FileChooser.viewMenuLabelText=Affichage diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_it.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_it.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_it.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Cerca in: FileChooser.saveInLabelText=Salva in: FileChooser.fileNameLabelText=Nome file: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Tipo file: FileChooser.upFolderToolTipText=Cartella superiore FileChooser.upFolderAccessibleName=Superiore @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=Elenco FileChooser.detailsViewButtonToolTipText=Dettagli FileChooser.detailsViewButtonAccessibleName=Dettagli +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=Dettagli FileChooser.refreshActionLabelText=Aggiorna FileChooser.viewMenuLabelText=Visualizza diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ja.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ja.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ja.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.11 08/12/05 +# 1.13 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u53c2\u7167: FileChooser.saveInLabelText=\u4fdd\u5b58: FileChooser.fileNameLabelText=\u30d5\u30a1\u30a4\u30eb\u540d: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7: FileChooser.upFolderToolTipText=1 \u30ec\u30d9\u30eb\u4e0a\u3078 FileChooser.upFolderAccessibleName=\u4e0a\u3078 @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=\u30ea\u30b9\u30c8 FileChooser.detailsViewButtonToolTipText=\u8a73\u7d30 FileChooser.detailsViewButtonAccessibleName=\u8a73\u7d30 +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=\u8a73\u7d30 FileChooser.refreshActionLabelText=\u66f4\u65b0 FileChooser.viewMenuLabelText=\u8868\u793a diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ko.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ko.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_ko.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\uac80\uc0c9 \uc704\uce58: FileChooser.saveInLabelText=\uc800\uc7a5 \uc704\uce58: FileChooser.fileNameLabelText=\ud30c\uc77c \uc774\ub984: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\ud30c\uc77c \uc885\ub958: FileChooser.upFolderToolTipText=\ud55c \ub2e8\uacc4 \uc704\ub85c FileChooser.upFolderAccessibleName=\uc704 @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=\ubaa9\ub85d FileChooser.detailsViewButtonToolTipText=\uc790\uc138\ud788 FileChooser.detailsViewButtonAccessibleName=\uc790\uc138\ud788 +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=\uc790\uc138\ud788 FileChooser.refreshActionLabelText=\uac31\uc2e0 FileChooser.viewMenuLabelText=\ubcf4\uae30 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_sv.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_sv.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_sv.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Leta i: FileChooser.saveInLabelText=Spara i: FileChooser.fileNameLabelText=Filnamn: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Filformat: FileChooser.upFolderToolTipText=Upp en niv\u00e5 FileChooser.upFolderAccessibleName=Upp @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=Lista FileChooser.detailsViewButtonToolTipText=Detaljerad lista FileChooser.detailsViewButtonAccessibleName=Detaljerad lista +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=Detaljerad lista FileChooser.refreshActionLabelText=Uppdatera FileChooser.viewMenuLabelText=Vy diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_CN.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.13 08/12/05 +# 1.15 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\uff1a FileChooser.saveInLabelText=\u4fdd\u5b58\uff1a FileChooser.fileNameLabelText=\u6587\u4ef6\u540d\uff1a +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6587\u4ef6\u7c7b\u578b\uff1a FileChooser.upFolderToolTipText=\u5411\u4e0a\u4e00\u5c42 FileChooser.upFolderAccessibleName=\u5411\u4e0a @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=\u5217\u8868 FileChooser.detailsViewButtonToolTipText=\u8be6\u7ec6\u4fe1\u606f FileChooser.detailsViewButtonAccessibleName=\u8be6\u7ec6\u4fe1\u606f +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=\u8be6\u7ec6\u4fe1\u606f FileChooser.refreshActionLabelText=\u5237\u65b0 FileChooser.viewMenuLabelText=\u89c6\u56fe diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.properties --- a/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/java/swing/plaf/windows/resources/windows_zh_TW.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.9 08/12/05 +# 1.11 06/08/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\ufe55 FileChooser.saveInLabelText=\u5132\u5b58\u65bc\uff1a FileChooser.fileNameLabelText=\u6a94\u6848\u540d\u7a31\ufe55 +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6a94\u6848\u985e\u578b\ufe55 FileChooser.upFolderToolTipText=\u5f80\u4e0a\u4e00\u5c64 FileChooser.upFolderAccessibleName=\u5f80\u4e0a @@ -35,6 +36,8 @@ FileChooser.listViewActionLabelText=\u6e05\u55ae FileChooser.detailsViewButtonToolTipText=\u8a73\u7d30\u8cc7\u8a0a FileChooser.detailsViewButtonAccessibleName=\u8a73\u7d30\u8cc7\u8a0a +FileChooser.viewMenuButtonToolTipText = View Menu +FileChooser.viewMenuButtonAccessibleName = View Menu FileChooser.detailsViewActionLabelText=\u8a73\u7d30\u8cc7\u8a0a FileChooser.refreshActionLabelText=\u66f4\u65b0 FileChooser.viewMenuLabelText=\u6aa2\u8996 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/jndi/ldap/LdapSchemaCtx.java --- a/j2se/src/share/classes/com/sun/jndi/ldap/LdapSchemaCtx.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/jndi/ldap/LdapSchemaCtx.java Thu Jul 05 23:47:33 2007 +0000 @@ -163,7 +163,7 @@ if (!setupMode) { throw new SchemaViolationException("Cannot rename a schema object"); } else { - doRename(oldname, newname); + super.doRename(oldname, newname); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/regexp/internal/REDemo.java --- a/j2se/src/share/classes/com/sun/org/apache/regexp/internal/REDemo.java Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 1999-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the 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. - */ - -package com.sun.org.apache.regexp.internal; - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.TextEvent; -import java.awt.event.TextListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.CharArrayWriter; -import java.io.PrintWriter; - -/** - * Interactive demonstration and testing harness for regular expressions classes. - * @author Jonathan Locke - * @version $Id: REDemo.java,v 1.1.2.1 2005/08/01 00:02:54 jeffsuttor Exp $ - */ -public class REDemo extends Applet implements TextListener -{ - /** - * Matcher and compiler objects - */ - RE r = new RE(); - REDebugCompiler compiler = new REDebugCompiler(); - - /** - * Components - */ - TextField fieldRE; // Field for entering regexps - TextField fieldMatch; // Field for entering match strings - TextArea outRE; // Output of RE compiler - TextArea outMatch; // Results of matching operation - - /** - * Add controls and init applet - */ - public void init() - { - // Add components using the dreaded GridBagLayout - GridBagLayout gb = new GridBagLayout(); - setLayout(gb); - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(5, 5, 5, 5); - c.anchor = GridBagConstraints.EAST; - gb.setConstraints(add(new Label("Regular expression:", Label.RIGHT)), c); - c.gridy = 0; - c.anchor = GridBagConstraints.WEST; - gb.setConstraints(add(fieldRE = new TextField("\\[([:javastart:][:javapart:]*)\\]", 40)), c); - c.gridx = 0; - c.gridy = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.EAST; - gb.setConstraints(add(new Label("String:", Label.RIGHT)), c); - c.gridy = 1; - c.gridx = GridBagConstraints.RELATIVE; - c.anchor = GridBagConstraints.WEST; - gb.setConstraints(add(fieldMatch = new TextField("aaa([foo])aaa", 40)), c); - c.gridy = 2; - c.gridx = GridBagConstraints.RELATIVE; - c.fill = GridBagConstraints.BOTH; - c.weighty = 1.0; - c.weightx = 1.0; - gb.setConstraints(add(outRE = new TextArea()), c); - c.gridy = 2; - c.gridx = GridBagConstraints.RELATIVE; - gb.setConstraints(add(outMatch = new TextArea()), c); - - // Listen to text changes - fieldRE.addTextListener(this); - fieldMatch.addTextListener(this); - - // Initial UI update - textValueChanged(null); - } - - /** - * Say something into RE text area - * @param s What to say - */ - void sayRE(String s) - { - outRE.setText(s); - } - - /** - * Say something into match text area - * @param s What to say - */ - void sayMatch(String s) - { - outMatch.setText(s); - } - - /** - * Convert throwable to string - * @param t Throwable to convert to string - */ - String throwableToString(Throwable t) - { - String s = t.getClass().getName(); - String m; - if ((m = t.getMessage()) != null) - { - s += "\n" + m; - } - return s; - } - - /** - * Change regular expression - * @param expr Expression to compile - */ - void updateRE(String expr) - { - try - { - // Compile program - r.setProgram(compiler.compile(expr)); - - // Dump program into RE feedback area - CharArrayWriter w = new CharArrayWriter(); - compiler.dumpProgram(new PrintWriter(w)); - sayRE(w.toString()); - System.out.println(w); - } - catch (Exception e) - { - r.setProgram(null); - sayRE(throwableToString(e)); - } - catch (Throwable t) - { - r.setProgram(null); - sayRE(throwableToString(t)); - } - } - - /** - * Update matching info by matching the string against the current - * compiled regular expression. - * @param match String to match against - */ - void updateMatch(String match) - { - try - { - // If the string matches the regexp - if (r.match(match)) - { - // Say that it matches - String out = "Matches.\n\n"; - - // Show contents of parenthesized subexpressions - for (int i = 0; i < r.getParenCount(); i++) - { - out += "$" + i + " = " + r.getParen(i) + "\n"; - } - sayMatch(out); - } - else - { - // Didn't match! - sayMatch("Does not match"); - } - } - catch (Throwable t) - { - sayMatch(throwableToString(t)); - } - } - - /** - * Called when text values change - * @param e TextEvent - */ - public void textValueChanged(TextEvent e) - { - // If it's a generic update or the regexp changed... - if (e == null || e.getSource() == fieldRE) - { - // Update regexp - updateRE(fieldRE.getText()); - } - - // We always need to update the match results - updateMatch(fieldMatch.getText()); - } - - /** - * Main application entrypoint. - * @param arg Command line arguments - */ - static public void main(String[] arg) - { - Frame f = new Frame("RE Demo"); - // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - f.addWindowListener(new WindowAdapter() - { - public void windowClosing(WindowEvent e) - { - System.exit(0); - } - }); - REDemo demo = new REDemo(); - f.add(demo); - demo.init(); - f.pack(); - f.setVisible(true); - } -} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Copy.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Copy.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Copy.java Thu Jul 05 23:47:33 2007 +0000 @@ -109,8 +109,13 @@ il.append(new ALOAD(name.getIndex())); final int lengthMethod = cpg.addMethodref(STRING_CLASS,"length","()I"); il.append(new INVOKEVIRTUAL(lengthMethod)); + il.append(DUP); il.append(new ISTORE(length.getIndex())); + // Ignore attribute sets if current node is ROOT. DOM.shallowCopy() + // returns "" for ROOT, so skip attribute sets if length == 0 + final BranchHandle ifBlock4 = il.append(new IFEQ(null)); + // Copy in attribute sets if specified if (_useSets != null) { // If the parent of this element will result in an element being @@ -134,6 +139,7 @@ } // Instantiate body of xsl:copy + ifBlock4.setTarget(il.append(NOP)); translateContents(classGen, methodGen); // Call the output handler's endElement() if we copied an element diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Number.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Number.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Number.java Thu Jul 05 23:47:33 2007 +0000 @@ -27,6 +27,7 @@ import com.sun.org.apache.bcel.internal.classfile.Field; import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ILOAD; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.BranchHandle; import com.sun.org.apache.bcel.internal.generic.CHECKCAST; @@ -296,26 +297,29 @@ new com.sun.org.apache.bcel.internal.generic.Type[] { Util.getJCRefType(TRANSLET_INTF_SIG), Util.getJCRefType(DOM_INTF_SIG), - Util.getJCRefType(NODE_ITERATOR_SIG) + Util.getJCRefType(NODE_ITERATOR_SIG), + com.sun.org.apache.bcel.internal.generic.Type.BOOLEAN }, new String[] { "dom", "translet", - "iterator" + "iterator", + "hasFrom" }, "", _className, il, cpg); - il.append(ALOAD_0); // this - il.append(ALOAD_1); // translet - il.append(ALOAD_2); // DOM - il.append(new ALOAD(3));// iterator + il.append(ALOAD_0); // this + il.append(ALOAD_1); // translet + il.append(ALOAD_2); // DOM + il.append(new ALOAD(3)); // iterator + il.append(new ILOAD(4)); // hasFrom int index = cpg.addMethodref(ClassNames[_level], "", "(" + TRANSLET_INTF_SIG + DOM_INTF_SIG + NODE_ITERATOR_SIG - + ")V"); + + "Z)V"); il.append(new INVOKESPECIAL(index)); il.append(RETURN); @@ -480,12 +484,13 @@ "(" + TRANSLET_INTF_SIG + DOM_INTF_SIG + NODE_ITERATOR_SIG - + ")V"); + + "Z)V"); il.append(new NEW(cpg.addClass(_className))); il.append(DUP); il.append(classGen.loadTranslet()); il.append(methodGen.loadDOM()); il.append(methodGen.loadIterator()); + il.append(_from != null ? ICONST_1 : ICONST_0); il.append(new INVOKESPECIAL(index)); // Initialize closure variables diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,8 +44,8 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; -import com.sun.org.apache.xalan.internal.xsltc.runtime.AttributeList; import org.xml.sax.Attributes; +import org.xml.sax.helpers.AttributesImpl; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.Locator; @@ -360,7 +360,7 @@ stylesheet = new Stylesheet(); stylesheet.setSimplified(); stylesheet.addElement(element); - stylesheet.setAttributes((AttributeList) element.getAttributes()); + stylesheet.setAttributes((AttributesImpl) element.getAttributes()); // Map the default NS if not already defined if (element.lookupNamespace(EMPTYSTRING) == null) { @@ -1265,7 +1265,7 @@ parent.addElement(element); element.setParent(parent); } - element.setAttributes(new AttributeList(attributes)); + element.setAttributes(new AttributesImpl(attributes)); element.setPrefixMapping(_prefixMapping); if (element instanceof Stylesheet) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Thu Jul 05 23:47:33 2007 +0000 @@ -47,10 +47,10 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; import com.sun.org.apache.xalan.internal.xsltc.DOM; -import com.sun.org.apache.xalan.internal.xsltc.runtime.AttributeList; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import org.xml.sax.Attributes; - +import org.xml.sax.helpers.AttributesImpl; /** @@ -75,7 +75,7 @@ // Element description data protected QName _qname; // The element QName private int _line; // Source file line number - protected AttributeList _attributes = null; // Attributes of this element + protected AttributesImpl _attributes = null; // Attributes of this element private Hashtable _prefixMapping = null; // Namespace declarations // Sentinel - used to denote unrecognised syntaxt tree nodes. @@ -166,7 +166,7 @@ * @param attributes Attributes for the element. Must be passed in as an * implementation of org.xml.sax.Attributes. */ - protected void setAttributes(AttributeList attributes) { + protected void setAttributes(AttributesImpl attributes) { _attributes = attributes; } @@ -193,7 +193,15 @@ } protected void addAttribute(String qname, String value) { - _attributes.add(qname, value); + int index = _attributes.getIndex(qname); + if (index != -1) { + _attributes.setAttribute(index, "", Util.getLocalName(qname), + qname, "CDATA", value); + } + else { + _attributes.addAttribute("", Util.getLocalName(qname), qname, + "CDATA", value); + } } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AnyNodeCounter.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AnyNodeCounter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AnyNodeCounter.java Thu Jul 05 23:47:33 2007 +0000 @@ -37,6 +37,13 @@ super(translet, document, iterator); } + public AnyNodeCounter(Translet translet, + DOM document, + DTMAxisIterator iterator, + boolean hasFrom) { + super(translet, document, iterator, hasFrom); + } + public NodeCounter setStartNode(int node) { _node = node; _nodeType = _document.getExpandedTypeID(node); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/KeyIndex.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/KeyIndex.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/KeyIndex.java Thu Jul 05 23:47:33 2007 +0000 @@ -413,14 +413,14 @@ } public void setDom(DOM dom, int node) { - // If a multi DOM, then select the appropriate dom + _dom = dom; + + // If a MultiDOM, ensure _enhancedDOM is correctly set + // so that getElementById() works in lookupNodes below if (dom instanceof MultiDOM) { dom = ((MultiDOM) dom).getDTM(node); } - _dom = dom; - _enhancedDOM = null; // reset - if (dom instanceof DOMEnhancedForDTM) { _enhancedDOM = (DOMEnhancedForDTM)dom; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultipleNodeCounter.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultipleNodeCounter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultipleNodeCounter.java Thu Jul 05 23:47:33 2007 +0000 @@ -41,6 +41,13 @@ super(translet, document, iterator); } + public MultipleNodeCounter(Translet translet, + DOM document, + DTMAxisIterator iterator, + boolean hasFrom) { + super(translet, document, iterator, hasFrom); + } + public NodeCounter setStartNode(int node) { _node = node; _nodeType = _document.getExpandedTypeID(node); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeCounter.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeCounter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeCounter.java Thu Jul 05 23:47:33 2007 +0000 @@ -69,7 +69,12 @@ private final static String[] Ones = {"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix"}; - private StringBuffer _tempBuffer = new StringBuffer(); + private StringBuffer _tempBuffer = new StringBuffer(); + + /** + * Indicates if this instance of xsl:number has a from pattern. + */ + protected boolean _hasFrom; protected NodeCounter(Translet translet, DOM document, DTMAxisIterator iterator) { @@ -77,6 +82,14 @@ _document = document; _iterator = iterator; } + + protected NodeCounter(Translet translet, + DOM document, DTMAxisIterator iterator, boolean hasFrom) { + _translet = translet; + _document = document; + _iterator = iterator; + _hasFrom = hasFrom; + } /** * Set the start node for this counter. The same NodeCounter diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SingleNodeCounter.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SingleNodeCounter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SingleNodeCounter.java Thu Jul 05 23:47:33 2007 +0000 @@ -43,6 +43,13 @@ super(translet, document, iterator); } + public SingleNodeCounter(Translet translet, + DOM document, + DTMAxisIterator iterator, + boolean hasFrom) { + super(translet, document, iterator, hasFrom); + } + public NodeCounter setStartNode(int node) { _node = node; _nodeType = _document.getExpandedTypeID(node); @@ -63,7 +70,9 @@ else { int next = _node; result = 0; - if (!matchesCount(next)) { + boolean matchesCount = matchesCount(next); + + if (!matchesCount) { while ((next = _document.getParent(next)) > END) { if (matchesCount(next)) { break; // found target @@ -76,15 +85,30 @@ } if (next != END) { - _countSiblings.setStartNode(next); - do { - if (matchesCount(next)) result++; - } while ((next = _countSiblings.next()) != END); + int from = next; + + if (!matchesCount && _hasFrom) { + // Target found, but need to check if ancestor matches from + while ((from = _document.getParent(from)) > END) { + if (matchesFrom(from)) { + break; // found from + } + } + } + + // Have we found ancestor matching from? + if (from != END) { + _countSiblings.setStartNode(next); + do { + if (matchesCount(next)) result++; + } while ((next = _countSiblings.next()) != END); + + return formatNumbers(result); + } } - else { - // If no target found then pass the empty list - return formatNumbers(EmptyArray); - } + + // If no target found then pass the empty list + return formatNumbers(EmptyArray); } return formatNumbers(result); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AttributeList.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/AttributeList.java Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ -/* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the 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. - */ -/* - * $Id: AttributeList.java,v 1.2.4.1 2005/09/06 10:50:13 pvedula Exp $ - */ - -package com.sun.org.apache.xalan.internal.xsltc.runtime; - -import java.util.Vector; - -/** - * @author Morten Jorgensen - */ -public class AttributeList implements org.xml.sax.Attributes { - - private final static String EMPTYSTRING = ""; - private final static String CDATASTRING = "CDATA"; - - private Hashtable _attributes; - private Vector _names; - private Vector _qnames; - private Vector _values; - private Vector _uris; - private int _length; - - /** - * AttributeList constructor - */ - public AttributeList() { - /* - _attributes = new Hashtable(); - _names = new Vector(); - _values = new Vector(); - _qnames = new Vector(); - _uris = new Vector(); - */ - _length = 0; - } - - /** - * Attributes clone constructor - */ - public AttributeList(org.xml.sax.Attributes attributes) { - this(); - if (attributes != null) { - final int count = attributes.getLength(); - for (int i = 0; i < count; i++) { - add(attributes.getQName(i),attributes.getValue(i)); - } - } - } - - /** - * Allocate memory for the AttributeList - * %OPT% Use on-demand allocation for the internal vectors. The memory - * is only allocated when there is an attribute. This reduces the cost - * of creating many small RTFs. - */ - private void alloc() { - _attributes = new Hashtable(); - _names = new Vector(); - _values = new Vector(); - _qnames = new Vector(); - _uris = new Vector(); - } - - /** - * SAX2: Return the number of attributes in the list. - */ - public int getLength() { - return(_length); - } - - /** - * SAX2: Look up an attribute's Namespace URI by index. - */ - public String getURI(int index) { - if (index < _length) - return((String)_uris.elementAt(index)); - else - return(null); - } - - /** - * SAX2: Look up an attribute's local name by index. - */ - public String getLocalName(int index) { - if (index < _length) - return((String)_names.elementAt(index)); - else - return(null); - } - - /** - * Return the name of an attribute in this list (by position). - */ - public String getQName(int pos) { - if (pos < _length) - return((String)_qnames.elementAt(pos)); - else - return(null); - } - - /** - * SAX2: Look up an attribute's type by index. - */ - public String getType(int index) { - return(CDATASTRING); - } - - /** - * SAX2: Look up the index of an attribute by Namespace name. - */ - public int getIndex(String namespaceURI, String localPart) { - return(-1); - } - - /** - * SAX2: Look up the index of an attribute by XML 1.0 qualified name. - */ - public int getIndex(String qname) { - return(-1); - } - - /** - * SAX2: Look up an attribute's type by Namespace name. - */ - public String getType(String uri, String localName) { - return(CDATASTRING); - } - - /** - * SAX2: Look up an attribute's type by qname. - */ - public String getType(String qname) { - return(CDATASTRING); - } - - /** - * SAX2: Look up an attribute's value by index. - */ - public String getValue(int pos) { - if (pos < _length) - return((String)_values.elementAt(pos)); - else - return(null); - } - - /** - * SAX2: Look up an attribute's value by qname. - */ - public String getValue(String qname) { - if (_attributes != null) { - final Integer obj = (Integer)_attributes.get(qname); - if (obj == null) return null; - return(getValue(obj.intValue())); - } - else - return null; - } - - /** - * SAX2: Look up an attribute's value by Namespace name - SLOW! - */ - public String getValue(String uri, String localName) { - return(getValue(uri+':'+localName)); - } - - /** - * Adds an attribute to the list - */ - public void add(String qname, String value) { - // Initialize the internal vectors at the first usage. - if (_attributes == null) - alloc(); - - // Stuff the QName into the names vector & hashtable - Integer obj = (Integer)_attributes.get(qname); - if (obj == null) { - _attributes.put(qname, obj = new Integer(_length++)); - _qnames.addElement(qname); - _values.addElement(value); - int col = qname.lastIndexOf(':'); - if (col > -1) { - _uris.addElement(qname.substring(0,col)); - _names.addElement(qname.substring(col+1)); - } - else { - _uris.addElement(EMPTYSTRING); - _names.addElement(qname); - } - } - else { - final int index = obj.intValue(); - _values.set(index, value); - } - } - - /** - * Clears the attribute list - */ - public void clear() { - _length = 0; - if (_attributes != null) { - _attributes.clear(); - _names.removeAllElements(); - _values.removeAllElements(); - _qnames.removeAllElements(); - _uris.removeAllElements(); - } - } - -} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java --- a/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -463,9 +463,8 @@ } url = new URL(systemId); - - _tohFactory.setOutputStream( - new FileOutputStream(url.getFile())); + _ostream = new FileOutputStream(url.getFile()); + _tohFactory.setOutputStream(_ostream); return _tohFactory.getSerializationHandler(); } else if (systemId.startsWith("http:")) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java --- a/j2se/src/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xerces/internal/dom/ElementImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -54,7 +54,7 @@ * @author Joe Kesselman, IBM * @author Andy Clark, IBM * @author Ralf Pfeiffer, IBM - * @version $Id: ElementImpl.java,v 1.3 2005/09/02 05:52:22 neerajbj Exp $ + * @version $Id: ElementImpl.java,v 1.5 2007/02/05 16:15:44 ndw Exp $ * @since PR-DOM-Level-1-19980818. */ public class ElementImpl @@ -654,7 +654,7 @@ localName = qualifiedName.substring(index + 1); } Attr newAttr = getAttributeNodeNS(namespaceURI, localName); - if (newAttr == null) { + if (newAttr == null) { // REVISIT: this is not efficient, we are creating twice the same // strings for prefix and localName. newAttr = getOwnerDocument().createAttributeNS( @@ -668,8 +668,21 @@ } else { if (newAttr instanceof AttrNSImpl){ - // change prefix and value - ((AttrNSImpl)newAttr).name= (prefix!=null)?(prefix+":"+localName):localName; + String origNodeName = ((AttrNSImpl) newAttr).name; + String newName = (prefix!=null) ? (prefix+":"+localName) : localName; + + ((AttrNSImpl) newAttr).name = newName; + + if (!newName.equals(origNodeName)) { + // Note: we can't just change the name of the attribute. Names have to be in sorted + // order in the attributes vector because a binary search is used to locate them. + // If the new name has a different prefix, the list may become unsorted. + // Maybe it would be better to resort the list, but the simplest + // fix seems to be to remove the old attribute and re-insert it. + // -- Norman.Walsh@Sun.COM, 2 Feb 2007 + newAttr = (Attr) attributes.removeItem(newAttr, false); + attributes.addItem(newAttr); + } } else { // This case may happen if user calls: diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java --- a/j2se/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java Thu Jul 05 23:47:33 2007 +0000 @@ -21,8 +21,6 @@ */ package com.sun.org.apache.xml.internal.security.utils.resolver.implementations; - - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -119,26 +117,28 @@ useProxy = true; } - String oldProxySet = - (String) System.getProperties().get("http.proxySet"); - String oldProxyHost = - (String) System.getProperties().get("http.proxyHost"); - String oldProxyPort = - (String) System.getProperties().get("http.proxyPort"); + // switch on proxy usage + String oldProxySet = null; + String oldProxyHost = null; + String oldProxyPort = null; + if (useProxy) { + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "Use of HTTP proxy enabled: " + proxyHost + ":" + + proxyPort); + } + oldProxySet = System.getProperty("http.proxySet"); + oldProxyHost = System.getProperty("http.proxyHost"); + oldProxyPort = System.getProperty("http.proxyPort"); + System.setProperty("http.proxySet", "true"); + System.setProperty("http.proxyHost", proxyHost); + System.setProperty("http.proxyPort", proxyPort); + } + boolean switchBackProxy = ((oldProxySet != null) && (oldProxyHost != null) && (oldProxyPort != null)); - // switch on proxy usage - if (useProxy) { - if (true) - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Use of HTTP proxy enabled: " + proxyHost + ":" - + proxyPort); - System.getProperties().put("http.proxySet", "true"); - System.getProperties().put("http.proxyHost", proxyHost); - System.getProperties().put("http.proxyPort", proxyPort); - } - // calculate new URI URI uriNew = getNewURI(uri.getNodeValue(), BaseURI); @@ -215,8 +215,11 @@ summarized += read; } - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "Fetched " + summarized + " bytes from URI " - + uriNew.toString()); + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "Fetched " + summarized + " bytes from URI " + + uriNew.toString()); + } XMLSignatureInput result = new XMLSignatureInput(baos.toByteArray()); @@ -225,10 +228,10 @@ result.setMIMEType(mimeType); // switch off proxy usage - if (switchBackProxy) { - System.getProperties().put("http.proxySet", oldProxySet); - System.getProperties().put("http.proxyHost", oldProxyHost); - System.getProperties().put("http.proxyPort", oldProxyPort); + if (useProxy && switchBackProxy) { + System.setProperty("http.proxySet", oldProxySet); + System.setProperty("http.proxyHost", oldProxyHost); + System.setProperty("http.proxyPort", oldProxyPort); } return result; @@ -250,33 +253,39 @@ */ public boolean engineCanResolve(Attr uri, String BaseURI) { if (uri == null) { - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "quick fail, uri == null"); - + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "quick fail, uri == null"); + } return false; } String uriNodeValue = uri.getNodeValue(); if (uriNodeValue.equals("") || (uriNodeValue.charAt(0)=='#')) { - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "quick fail for empty URIs and local ones"); - + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "quick fail for empty URIs and local ones"); + } return false; } - if (true) - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I was asked whether I can resolve " + uriNodeValue); - + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "I was asked whether I can resolve " + uriNodeValue); + } if ( uriNodeValue.startsWith("http:") || BaseURI.startsWith("http:")) { - if (true) - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I state that I can resolve " + uriNodeValue); - + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "I state that I can resolve " + uriNodeValue); + } return true; } - if (true) - if (log.isLoggable(java.util.logging.Level.FINE)) log.log(java.util.logging.Level.FINE, "I state that I can't resolve " + uriNodeValue); - + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "I state that I can't resolve " + uriNodeValue); + } return false; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java --- a/j2se/src/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/org/apache/xml/internal/serializer/ToHTMLStream.java Thu Jul 05 23:47:33 2007 +0000 @@ -1293,6 +1293,19 @@ // We now we reset the next possible clean character. cleanStart = i + 1; } + else if (ch == '&') + { + // HTML 4.01 reads, "Authors should use "&" (ASCII decimal 38) + // instead of "&" to avoid confusion with the beginning of a character + // reference (entity reference open delimiter). + if (cleanLength > 0) + { + writer.write(chars, cleanStart, cleanLength); + cleanLength = 0; + } + writer.write("&"); + cleanStart = i + 1; + } else { // no processing for this character, just count how diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/CachedRowSetImpl.java --- a/j2se/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -215,7 +215,7 @@ * The ResultSet object that is used to maintain the data when * a ResultSet and start position are passed as parameters to the populate function */ - private ResultSet resultSet; + private transient ResultSet resultSet; /** * The integer value indicating the end position in the ResultSetwhere the picking @@ -311,9 +311,11 @@ */ private TransactionalWriter tWriter = null; - private transient JdbcRowSetResourceBundle resBundle; - - + protected transient JdbcRowSetResourceBundle resBundle; + + private boolean updateOnInsert; + + /** * Constructs a new default CachedRowSetImpl object with @@ -350,7 +352,7 @@ try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - + throw new RuntimeException(ioe); } // set the Reader, this maybe overridden latter @@ -453,9 +455,9 @@ try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - } - - + throw new RuntimeException(ioe); + } + if (env == null) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nullhash").toString()); } @@ -473,11 +475,6 @@ initParams(); // allocate the parameters collection initContainer(); initProperties(); // set up some default values - - // insert row setup - onInsertRow = false; - insertRow = null; - } /** @@ -502,9 +499,12 @@ private void initProperties() throws SQLException { - try { - resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { + if(resBundle == null) { + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } } setShowDeleted(false); setQueryTimeout(0); @@ -616,7 +616,8 @@ * violated while populating the RowSet * @see #execute */ - public void populate(ResultSet data) throws SQLException { + + public void populate(ResultSet data) throws SQLException { int rowsFetched; Row currentRow; int numCols; @@ -628,7 +629,7 @@ if (data == null) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.populate").toString()); } - + this.resultSet = data; // get the meta data for this ResultSet RSMD = data.getMetaData(); @@ -694,7 +695,7 @@ notifyRowSetChanged(); - } + } /** * Initializes the given RowSetMetaData object with the values @@ -713,35 +714,55 @@ md.setColumnCount(numCols); for (int col=1; col <= numCols; col++) { md.setAutoIncrement(col, rsmd.isAutoIncrement(col)); + if(rsmd.isAutoIncrement(col)) + updateOnInsert = true; md.setCaseSensitive(col, rsmd.isCaseSensitive(col)); md.setCurrency(col, rsmd.isCurrency(col)); md.setNullable(col, rsmd.isNullable(col)); md.setSigned(col, rsmd.isSigned(col)); md.setSearchable(col, rsmd.isSearchable(col)); - md.setColumnDisplaySize(col, rsmd.getColumnDisplaySize(col)); + /* + * The PostgreSQL drivers sometimes return negative columnDisplaySize, + * which causes an exception to be thrown. Check for it. + */ + int size = rsmd.getColumnDisplaySize(col); + if (size < 0) { + size = 0; + } + md.setColumnDisplaySize(col, size); md.setColumnLabel(col, rsmd.getColumnLabel(col)); md.setColumnName(col, rsmd.getColumnName(col)); md.setSchemaName(col, rsmd.getSchemaName(col)); - md.setPrecision(col, rsmd.getPrecision(col)); - md.setScale(col, rsmd.getScale(col)); + /* + * Drivers return some strange values for precision, for non-numeric data, including reports of + * non-integer values; maybe we should check type, & set to 0 for non-numeric types. + */ + int precision = rsmd.getPrecision(col); + if (precision < 0) { + precision = 0; + } + md.setPrecision(col, precision); + + /* + * It seems, from a bug report, that a driver can sometimes return a negative + * value for scale. javax.sql.rowset.RowSetMetaDataImpl will throw an exception + * if we attempt to set a negative value. As such, we'll check for this case. + */ + int scale = rsmd.getScale(col); + if (scale < 0) { + scale = 0; + } + md.setScale(col, scale); md.setTableName(col, rsmd.getTableName(col)); md.setCatalogName(col, rsmd.getCatalogName(col)); md.setColumnType(col, rsmd.getColumnType(col)); md.setColumnTypeName(col, rsmd.getColumnTypeName(col)); - - if( conn != null){ - - try { - dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); - } catch(SQLException sqle) { - /* - * Since the Lobs and this method is not mandated by J2EE spec, - * drivers are not implementing it. We need to catch this - * and do nothing in this block and help populate() - * method do it's task(bug id 5055528) - */ - } - } + } + + if( conn != null){ + // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods + // must be implemented, therefore, the previous fix for 5055528 is being backed out + dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); } } @@ -781,35 +802,11 @@ RowSetMD = (RowSetMetaDataImpl)this.getMetaData(); if(conn != null){ - - try { - dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); - } catch(SQLException sqle) { - /* - * Since the Lobs and this method is not mandated by J2EE spec, - * drivers are not implementing it. We need to catch this - * and do nothing in this block and help populate() - * method do it's task - */ - } //end catch - - } else { - - CachedRowSetReader crsTempReader = (CachedRowSetReader)rowSetReader; - Connection tempCon = crsTempReader.connect((RowSetInternal)this); - - try { - dbmslocatorsUpdateCopy = tempCon.getMetaData().locatorsUpdateCopy(); - } catch(SQLException sqle) { - /* - * Since the Lobs and this method is not mandated by J2EE spec, - * drivers are not implementing it. We need to catch this - * and do nothing in this block and help populate() - * method do it's task(bug id 5055528) - */ - } //end catch - tempCon = null; - } // end if ... else + // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods + // must be implemented, therefore, the previous fix for 5055528 is being backed out + dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy(); + } + } /** @@ -889,7 +886,7 @@ success = false; } else { tWriter = (TransactionalWriter)rowSetWriter; - tWriter.commit(); + ((CachedRowSetWriter)tWriter).commit(this, updateOnInsert); success = true; } } @@ -1160,7 +1157,7 @@ out = new ObjectOutputStream(bOut); out.writeObject(this); } catch (IOException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } ObjectInputStream in; @@ -1169,9 +1166,9 @@ ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); in = new ObjectInputStream(bIn); } catch (StreamCorruptedException ex) { - throw new SQLException("Clone failed: " + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } catch (IOException ex) { - throw new SQLException("Clone failed: " + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } try { @@ -1181,11 +1178,11 @@ return ((CachedRowSet)crsTemp); } catch (ClassNotFoundException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } catch (OptionalDataException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } catch (IOException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() + ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.clonefail").toString() , ex.getMessage())); } } @@ -1284,23 +1281,17 @@ */ public Collection toCollection() throws SQLException { - System.out.println("in crs toColl"); TreeMap tMap; int count = 0; Row origRow; Vector newRow; int colCount = ((RowSetMetaDataImpl)this.getMetaData()).getColumnCount(); - //int colCount = RowSetMD.getColumnCount(); - - System.out.println("in crs toColl 2"); - + tMap = new TreeMap(); for (int i = 0; iCachedRowSetImpl @@ -2986,11 +2971,11 @@ try { obj = (SQLData)c.newInstance(); } catch (java.lang.InstantiationException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString() + - ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(), + ex.getMessage())); } catch (java.lang.IllegalAccessException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString() + - ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(), + ex.getMessage())); } // get the attributes from the struct Object attribs[] = s.getAttributes(map); @@ -3177,8 +3162,8 @@ try { return (new BigDecimal(value.toString().trim())); } catch (NumberFormatException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString() + - value.toString().trim() + columnIndex); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.doublefail").toString(), + new Object[] {value.toString().trim(), columnIndex})); } } @@ -3310,7 +3295,7 @@ * is ResultSet.TYPE_FORWARD_ONLY */ public void beforeFirst() throws SQLException { - if (getType() == ResultSet.TYPE_FORWARD_ONLY) { + if (getType() == ResultSet.TYPE_FORWARD_ONLY) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.beforefirst").toString()); } cursorPos = 0; @@ -3345,7 +3330,7 @@ * is ResultSet.TYPE_FORWARD_ONLY */ public boolean first() throws SQLException { - if (getType() == ResultSet.TYPE_FORWARD_ONLY) { + if(getType() == ResultSet.TYPE_FORWARD_ONLY) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.first").toString()); } @@ -5476,13 +5461,13 @@ insertRow.isCompleteRow(RowSetMD) == false) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString()); } - // Added the setting of parameters that are passed - // to setXXX methods after an empty CRS Object is - // created through RowSetMetaData object + // Added the setting of parameters that are passed + // to setXXX methods after an empty CRS Object is + // created through RowSetMetaData object Object [] toInsert = getParams(); for(int i = 0;i < toInsert.length; i++) { - insertRow.setColumnObject(i+1,toInsert[i]); + insertRow.setColumnObject(i+1,toInsert[i]); } Row insRow = new Row(RowSetMD.getColumnCount(), @@ -5737,11 +5722,11 @@ try { obj = (SQLData)c.newInstance(); } catch (java.lang.InstantiationException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString()+ - ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(), + ex.getMessage())); } catch (java.lang.IllegalAccessException ex) { - throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString() + - ex.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(), + ex.getMessage())); } // get the attributes from the struct Object attribs[] = s.getAttributes(map); @@ -5818,7 +5803,7 @@ checkCursor(); if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.BLOB) { - System.out.println(resBundle.handleGetObject("cachedrowsetimpl.type").toString()+RowSetMD.getColumnType(columnIndex)); + System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex))); throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()); } @@ -5858,7 +5843,7 @@ checkCursor(); if (RowSetMD.getColumnType(columnIndex) != java.sql.Types.CLOB) { - System.out.println(resBundle.handleGetObject("cachedrowsetimpl.type").toString()+RowSetMD.getColumnType(columnIndex)); + System.out.println(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.type").toString(), RowSetMD.getColumnType(columnIndex))); throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.dtypemismt").toString()); } @@ -7137,8 +7122,7 @@ */ public void setMatchColumn(String columnName) throws SQLException { // validate, if col is ok to be set - columnName = columnName.trim(); - if( columnName == "" || columnName.equals(null)) { + if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) { throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.matchcols2").toString()); } else { // set strMatchColumn @@ -7416,22 +7400,17 @@ if (populatecallcount == 0){ throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.nextpage").toString()); } - if (populatecallcount == 1){ - populatecallcount++; - return pagenotend; + // Fix for 6554186 + onFirstPage = false; + if(callWithCon){ + crsReader.setStartPosition(endPos); + crsReader.readData((RowSetInternal)this); + resultSet = null; } - else{ - onFirstPage = false; - if(callWithCon){ - crsReader.setStartPosition(endPos); - crsReader.readData((RowSetInternal)this); - resultSet = null; - } - else { - populate(resultSet,endPos); - } - return pagenotend; + else { + populate(resultSet,endPos); } + return pagenotend; } /** @@ -7719,7 +7698,7 @@ checkCursor(); if(onInsertRow == true) - throw new SQLException("Invalid Operation on insert Row"); + throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.invalidop").toString()); if( insertFlag ) { ((Row)getCurrentRow()).setInserted(); @@ -7727,7 +7706,7 @@ ((Row)getCurrentRow()).clearInserted(); } } - + /** * Retrieves the value of the designated SQL XML parameter as a * SQLXML object in the Java programming language. @@ -7737,7 +7716,7 @@ * @since 6.0 */ public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7748,7 +7727,7 @@ * @throws SQLException if a database access error occurs */ public SQLXML getSQLXML(String colName) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7763,7 +7742,7 @@ * @since 6.0 */ public RowId getRowId(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7778,7 +7757,7 @@ * @since 6.0 */ public RowId getRowId(String columnName) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7794,7 +7773,7 @@ * @since 6.0 */ public void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7810,7 +7789,7 @@ * @since 6.0 */ public void updateRowId(String columnName, RowId x) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7820,7 +7799,7 @@ * @since 6.0 */ public int getHoldability() throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7831,7 +7810,7 @@ * @since 6.0 */ public boolean isClosed() throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7843,7 +7822,7 @@ * @since 6.0 */ public void updateNString(int columnIndex, String nString) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7855,7 +7834,7 @@ * @since 6.0 */ public void updateNString(String columnName, String nString) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -7868,7 +7847,7 @@ * @since 6.0 */ public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7880,7 +7859,7 @@ * @since 6.0 */ public void updateNClob(String columnName, NClob nClob) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7895,7 +7874,7 @@ * @since 6.0 */ public NClob getNClob(int i) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -7911,7 +7890,7 @@ * @since 6.0 */ public NClob getNClob(String colName) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } public T unwrap(java.lang.Class iface) throws java.sql.SQLException { @@ -7932,7 +7911,7 @@ * @since 1.6 */ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -7944,7 +7923,7 @@ * @since 1.6 */ public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -7960,7 +7939,7 @@ * @since 1.6 */ public void setRowId(int parameterIndex, RowId x) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -7975,7 +7954,7 @@ * @since 1.6 */ public void setRowId(String parameterName, RowId x) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -8002,7 +7981,7 @@ * @since 1.6 */ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -8018,7 +7997,7 @@ * @since 1.6 */ public void setNClob(String parameterName, NClob value) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -8038,7 +8017,7 @@ * @since 1.6 */ public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -8058,7 +8037,7 @@ * @since 1.6 */ public java.io.Reader getNCharacterStream(String columnName) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } @@ -8075,7 +8054,7 @@ * @since 1.6 */ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8092,7 +8071,7 @@ * @since 1.6 */ public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8110,7 +8089,7 @@ * @since 1.6 */ public String getNString(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8128,7 +8107,7 @@ * @since 1.6 */ public String getNString(String columnName) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8150,7 +8129,7 @@ java.io.Reader x, long length) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8172,7 +8151,7 @@ java.io.Reader x, long length) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.opnotysupp").toString()); } /** @@ -8202,7 +8181,7 @@ */ public void updateNCharacterStream(int columnIndex, java.io.Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8234,7 +8213,7 @@ */ public void updateNCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } ////////////////////////// @@ -8269,7 +8248,7 @@ * @since 1.6 */ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8302,7 +8281,7 @@ * @since 1.6 */ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8337,7 +8316,7 @@ * @since 1.6 */ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8372,7 +8351,7 @@ * @since 1.6 */ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8404,7 +8383,7 @@ * @since 1.6 */ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8436,7 +8415,7 @@ * @since 1.6 */ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8470,7 +8449,7 @@ * @since 1.6 */ public void updateClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8505,7 +8484,7 @@ * @since 1.6 */ public void updateClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8539,7 +8518,7 @@ * @since 1.6 */ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8573,7 +8552,7 @@ * @since 1.6 */ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8609,7 +8588,7 @@ * @since 1.6 */ public void updateNClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8646,7 +8625,7 @@ * @since 1.6 */ public void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8717,7 +8696,7 @@ public void updateCharacterStream(int columnIndex, java.io.Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8743,7 +8722,7 @@ public void updateCharacterStream(String columnLabel, java.io.Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** * Updates the designated column with an ascii stream value, which will have @@ -8813,7 +8792,7 @@ */ public void updateBinaryStream(int columnIndex, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -8840,7 +8819,7 @@ */ public void updateBinaryStream(String columnLabel, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8865,7 +8844,7 @@ */ public void updateCharacterStream(int columnIndex, java.io.Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8892,7 +8871,7 @@ */ public void updateCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8917,7 +8896,7 @@ */ public void updateAsciiStream(int columnIndex, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8959,7 +8938,7 @@ * @since 1.4 */ public void setURL(int parameterIndex, java.net.URL x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -8987,7 +8966,7 @@ */ public void setNClob(int parameterIndex, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9015,7 +8994,7 @@ */ public void setNClob(String parameterName, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9042,7 +9021,7 @@ */ public void setNClob(String parameterName, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9070,7 +9049,7 @@ */ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9086,7 +9065,7 @@ * @since 1.6 */ public void setNClob(int parameterIndex, NClob value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9106,7 +9085,7 @@ * @since 1.6 */ public void setNString(int parameterIndex, String value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9123,7 +9102,7 @@ */ public void setNString(String parameterName, String value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9141,7 +9120,7 @@ * @since 1.6 */ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9160,7 +9139,7 @@ */ public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9186,7 +9165,7 @@ * @since 1.6 */ public void setNCharacterStream(String parameterName, Reader value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9212,7 +9191,7 @@ */ public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9238,7 +9217,7 @@ */ public void setClob(String parameterName, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9256,7 +9235,7 @@ * @since 1.6 */ public void setClob (String parameterName, Clob x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9282,7 +9261,7 @@ */ public void setClob(String parameterName, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9304,7 +9283,7 @@ */ public void setDate(String parameterName, java.sql.Date x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9331,7 +9310,7 @@ */ public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9351,7 +9330,7 @@ */ public void setTime(String parameterName, java.sql.Time x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9378,7 +9357,7 @@ */ public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9404,7 +9383,7 @@ */ public void setClob(int parameterIndex, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9428,7 +9407,7 @@ */ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9458,7 +9437,7 @@ */ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9488,7 +9467,7 @@ */ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9520,7 +9499,7 @@ */ public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9538,7 +9517,7 @@ * @since 1.6 */ public void setBlob (String parameterName, Blob x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9565,7 +9544,7 @@ */ public void setBlob(String parameterName, InputStream inputStream) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9611,7 +9590,7 @@ */ public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9639,7 +9618,7 @@ */ public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9680,7 +9659,7 @@ * @since 1.4 */ public void setObject(String parameterName, Object x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9707,7 +9686,7 @@ */ public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9734,7 +9713,7 @@ */ public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9764,7 +9743,7 @@ public void setCharacterStream(String parameterName, java.io.Reader reader, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9792,7 +9771,7 @@ */ public void setAsciiStream(String parameterName, java.io.InputStream x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9819,7 +9798,7 @@ */ public void setBinaryStream(String parameterName, java.io.InputStream x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9850,7 +9829,7 @@ */ public void setCharacterStream(String parameterName, java.io.Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9869,7 +9848,7 @@ * @since 1.4 */ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9892,7 +9871,7 @@ * @since 1.4 */ public void setString(String parameterName, String x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9914,7 +9893,7 @@ * @since 1.4 */ public void setBytes(String parameterName, byte x[]) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9936,7 +9915,7 @@ */ public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } /** @@ -9953,7 +9932,7 @@ * @since 1.4 */ public void setNull(String parameterName, int sqlType) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -9991,7 +9970,7 @@ */ public void setNull (String parameterName, int sqlType, String typeName) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10011,7 +9990,7 @@ * @since 1.4 */ public void setBoolean(String parameterName, boolean x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10031,7 +10010,7 @@ * @since 1.4 */ public void setByte(String parameterName, byte x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10051,7 +10030,7 @@ * @since 1.4 */ public void setShort(String parameterName, short x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10070,7 +10049,7 @@ * @since 1.4 */ public void setInt(String parameterName, int x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10089,7 +10068,7 @@ * @since 1.4 */ public void setLong(String parameterName, long x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10108,7 +10087,7 @@ * @since 1.4 */ public void setFloat(String parameterName, float x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } @@ -10127,8 +10106,25 @@ * @since 1.4 */ public void setDouble(String parameterName, double x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("cachedrowsetimpl.featnotsupp").toString()); } + + /** + * This method re populates the resBundle + * during the deserialization process + * + */ + protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + // Default state initialization happens here + ois.defaultReadObject(); + // Initialization of transient Res Bundle happens here . + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + + } static final long serialVersionUID =1884577171200622428L; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java --- a/j2se/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -51,19 +51,12 @@ private boolean onInsertRow = false; - private transient JdbcRowSetResourceBundle frsResBundle; - + /** * Construct a FilteredRowSet */ public FilteredRowSetImpl() throws SQLException { super(); - - try { - frsResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - - } } /** @@ -75,12 +68,6 @@ */ public FilteredRowSetImpl(Hashtable env) throws SQLException { super(env); - - try { - frsResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - - } } /** @@ -310,7 +297,7 @@ boolean boolval = false; if(getType() == ResultSet.TYPE_FORWARD_ONLY) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.relative").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.relative").toString()); } if( rows > 0 ) { @@ -338,7 +325,8 @@ } retval = boolval; } - + if(rows != 0) + notifyCursorMoved(); return retval; } @@ -393,14 +381,13 @@ boolean retval; boolean bool = false; - boolean boolval = false; - + if(rows == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.absolute").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.absolute").toString()); } if (rows > 0) { - internalFirst(); + bool = internalFirst(); int i = 0; while(i < (rows-1)) { @@ -412,19 +399,19 @@ } retval = bool; } else { - internalLast(); + bool = internalLast(); int j = rows; while((j+1) < 0 ) { if( isBeforeFirst() ) { return false; } - boolval = internalPrevious(); + bool = internalPrevious(); j++; } - retval = boolval; + retval = bool; } - + notifyCursorMoved(); return retval; } @@ -515,7 +502,7 @@ bool = p.evaluate(new Integer(x),columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -582,7 +569,7 @@ bool = p.evaluate(new Boolean(x) , columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -650,7 +637,7 @@ bool = p.evaluate(new Byte(x),columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -719,7 +706,7 @@ bool = p.evaluate(new Short(x), columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -787,7 +774,7 @@ bool = p.evaluate(new Long(x), columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -854,7 +841,7 @@ bool = p.evaluate(new Float(x) , columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -921,7 +908,7 @@ bool = p.evaluate(new Double(x) , columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -988,7 +975,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1058,7 +1045,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1134,7 +1121,7 @@ bool = p.evaluate(val,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1202,7 +1189,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1272,7 +1259,7 @@ bool = p.evaluate(x, columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1343,7 +1330,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1413,7 +1400,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1482,7 +1469,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1556,7 +1543,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1627,7 +1614,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } @@ -1699,7 +1686,7 @@ bool = p.evaluate(x,columnIndex); if(!bool) { - throw new SQLException(frsResBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); + throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString()); } } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java --- a/j2se/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -93,14 +93,15 @@ /** * The Vector holding the Match Columns */ - private Vector iMatchColumns; + private Vector iMatchColumns; /** * The Vector that will hold the Match Column names. */ - private Vector strMatchColumns; + private Vector strMatchColumns; - private transient JdbcRowSetResourceBundle jdbcResBundle; + + protected transient JdbcRowSetResourceBundle jdbcResBundle; /** * Constructs a default JdbcRowSet object. @@ -134,15 +135,14 @@ * properties are set or [3] if no connection to a data source exists. */ public JdbcRowSetImpl() { - - conn = null; + conn = null; ps = null; rs = null; try { jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - + throw new RuntimeException(ioe); } propertyChangeSupport = new PropertyChangeSupport(this); @@ -154,43 +154,43 @@ try { setShowDeleted(false); } catch(SQLException sqle) { - System.err.println("JdbcRowSet (setShowDeleted) :" + - sqle.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setshowdeleted").toString() + + sqle.getLocalizedMessage()); } try { setQueryTimeout(0); } catch(SQLException sqle) { - System.err.println("JdbcRowSet (setQueryTimeout) :" + - sqle.getMessage()); - } + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() + + sqle.getLocalizedMessage()); + } try { setMaxRows(0); } catch(SQLException sqle) { - System.err.println("JdbcRowSet (setMaxRows) :" + - sqle.getMessage()); - } + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() + + sqle.getLocalizedMessage()); + } try { setMaxFieldSize(0); } catch(SQLException sqle) { - System.err.println("JdbcRowSet (setMaxFieldSize) :" + - sqle.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() + + sqle.getLocalizedMessage()); } try { setEscapeProcessing(true); } catch(SQLException sqle) { - System.err.println("JdbcRowSet (setEscapeProcessing) :" + - sqle.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() + + sqle.getLocalizedMessage()); } try { setConcurrency(ResultSet.CONCUR_UPDATABLE); } catch (SQLException sqle) { - System.err.println("JdbcRowSet (setConcurrency) :" + - sqle.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setconcurrency").toString() + + sqle.getLocalizedMessage()); } setTypeMap(null); @@ -198,7 +198,8 @@ try { setType(ResultSet.TYPE_SCROLL_INSENSITIVE); } catch(SQLException sqle){ - sqle.getMessage(); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settype").toString() + + sqle.getLocalizedMessage()); } setReadOnly(true); @@ -206,7 +207,8 @@ try { setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED); } catch(SQLException sqle){ - sqle.getMessage(); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settransactionisolation").toString() + + sqle.getLocalizedMessage()); } //Instantiating the vector for MatchColumns @@ -263,7 +265,7 @@ try { jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - + throw new RuntimeException(ioe); } propertyChangeSupport = new PropertyChangeSupport(this); @@ -338,7 +340,7 @@ try { jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - + throw new RuntimeException(ioe); } propertyChangeSupport = new PropertyChangeSupport(this); @@ -430,7 +432,7 @@ try { jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { - + throw new RuntimeException(ioe); } propertyChangeSupport = new PropertyChangeSupport(this); @@ -591,29 +593,29 @@ try { ps.setEscapeProcessing(getEscapeProcessing()); } catch (SQLException ex) { - System.err.println("JdbcRowSet (setEscapeProcessing): " + - ex.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() + + ex.getLocalizedMessage()); } try { ps.setMaxFieldSize(getMaxFieldSize()); } catch (SQLException ex) { - System.err.println("JdbcRowSet (setMaxFieldSize): " + - ex.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() + + ex.getLocalizedMessage()); } try { ps.setMaxRows(getMaxRows()); } catch (SQLException ex) { - System.err.println("JdbcRowSet (setMaxRows): " + - ex.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() + + ex.getLocalizedMessage()); } try { ps.setQueryTimeout(getQueryTimeout()); } catch (SQLException ex) { - System.err.println("JdbcRowSet (setQueryTimeout): " + - ex.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() + + ex.getLocalizedMessage()); } } @@ -642,7 +644,7 @@ (getDataSourceName()); //return ds.getConnection(getUsername(),getPassword()); - if(getUsername() != null) { + if(getUsername() != null && !getUsername().equals("")) { return ds.getConnection(getUsername(),getPassword()); } else { return ds.getConnection(); @@ -670,22 +672,17 @@ protected PreparedStatement prepare() throws SQLException { // get a connection conn = connect(); - + try { - conn.setTypeMap(getTypeMap()); - } catch (Throwable ex) { - System.err.println("JdbcRowSet (setTypeMap): " + - ex.getMessage()); - } - try { - // int type = getType(); - // int concur = getConcurrency(); - + Map aMap = getTypeMap(); + if( aMap != null) { + conn.setTypeMap(aMap); + } ps = conn.prepareStatement(getCommand(),ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); } catch (SQLException ex) { - System.err.println("JdbcRowSet (execute): " + - ex.getMessage()); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.prepare").toString() + + ex.getLocalizedMessage()); if (ps != null) ps.close(); @@ -724,9 +721,9 @@ if (param[0] instanceof java.sql.Date || param[0] instanceof java.sql.Time || param[0] instanceof java.sql.Timestamp) { - System.err.println("Detected a Date"); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detecteddate")); if (param[1] instanceof java.util.Calendar) { - System.err.println("Detected a Calendar"); + System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detectedcalendar")); ps.setDate(i + 1, (java.sql.Date)param[0], (java.util.Calendar)param[1]); continue; @@ -2112,12 +2109,16 @@ } catch(SQLException sqle) { return super.getType(); } - try { - int rstype = rs.getType(); + + // If the ResultSet has not been created, then return the default type + // otherwise return the type from the ResultSet. + if(rs == null) { + return super.getType(); + } else { + int rstype = rs.getType(); return rstype; - } catch(NullPointerException npe) { - throw new SQLException("Cannot return the type of a closed ResultSet : " + npe); } + } @@ -3939,8 +3940,7 @@ */ public void setMatchColumn(String columnName) throws SQLException { // validate, if col is ok to be set - columnName = columnName.trim(); - if( columnName == "" || columnName.equals(null)) { + if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) { throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString()); } else { // set strMatchColumn @@ -4642,7 +4642,7 @@ * @since 6.0 */ public SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4653,7 +4653,7 @@ * @throws SQLException if a database access error occurs */ public SQLXML getSQLXML(String colName) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4668,7 +4668,7 @@ * @since 6.0 */ public RowId getRowId(int columnIndex) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4683,7 +4683,7 @@ * @since 6.0 */ public RowId getRowId(String columnName) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4699,7 +4699,7 @@ * @since 6.0 */ public void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4715,7 +4715,7 @@ * @since 6.0 */ public void updateRowId(String columnName, RowId x) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4725,7 +4725,7 @@ * @since 6.0 */ public int getHoldability() throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4736,7 +4736,7 @@ * @since 6.0 */ public boolean isClosed() throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4748,7 +4748,7 @@ * @since 6.0 */ public void updateNString(int columnIndex, String nString) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4760,7 +4760,7 @@ * @since 6.0 */ public void updateNString(String columnName, String nString) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4773,7 +4773,7 @@ * @since 6.0 */ public void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4785,7 +4785,7 @@ * @since 6.0 */ public void updateNClob(String columnName, NClob nClob) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4800,7 +4800,7 @@ * @since 6.0 */ public NClob getNClob(int i) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4816,7 +4816,7 @@ * @since 6.0 */ public NClob getNClob(String colName) throws SQLException { - throw new UnsupportedOperationException(); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } public T unwrap(java.lang.Class iface) throws java.sql.SQLException{ @@ -4836,7 +4836,7 @@ * @since 1.6 */ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4848,7 +4848,7 @@ * @since 1.6 */ public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4863,7 +4863,7 @@ * @since 1.6 */ public void setRowId(int parameterIndex, RowId x) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4877,7 +4877,7 @@ * @since 1.6 */ public void setRowId(String parameterName, RowId x) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4897,7 +4897,7 @@ * @since 1.6 */ public void setNString(int parameterIndex, String value) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4925,7 +4925,7 @@ * @since 1.6 */ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4940,7 +4940,7 @@ * @since 1.6 */ public void setNClob(String parameterName, NClob value) throws SQLException { - throw new UnsupportedOperationException("operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4960,7 +4960,7 @@ * @since 1.6 */ public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -4980,7 +4980,7 @@ * @since 1.6 */ public java.io.Reader getNCharacterStream(String columnName) throws SQLException { - throw new UnsupportedOperationException("Operation ot yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -4996,7 +4996,7 @@ * @since 1.6 */ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5013,7 +5013,7 @@ * @since 1.6 */ public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5031,7 +5031,7 @@ * @since 1.6 */ public String getNString(int columnIndex) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5049,7 +5049,7 @@ * @since 1.6 */ public String getNString(String columnName) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5071,7 +5071,7 @@ java.io.Reader x, long length) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5093,7 +5093,7 @@ java.io.Reader x, long length) throws SQLException { - throw new UnsupportedOperationException("Operation not yet supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5123,7 +5123,7 @@ */ public void updateNCharacterStream(int columnIndex, java.io.Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5155,7 +5155,7 @@ */ public void updateNCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5188,7 +5188,7 @@ * @since 1.6 */ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5221,7 +5221,7 @@ * @since 1.6 */ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5256,7 +5256,7 @@ * @since 1.6 */ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5291,7 +5291,7 @@ * @since 1.6 */ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5323,7 +5323,7 @@ * @since 1.6 */ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5355,7 +5355,7 @@ * @since 1.6 */ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5389,7 +5389,7 @@ * @since 1.6 */ public void updateClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5424,7 +5424,7 @@ * @since 1.6 */ public void updateClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5458,7 +5458,7 @@ * @since 1.6 */ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5492,7 +5492,7 @@ * @since 1.6 */ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5528,7 +5528,7 @@ * @since 1.6 */ public void updateNClob(int columnIndex, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5565,7 +5565,7 @@ * @since 1.6 */ public void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5590,7 +5590,7 @@ public void updateAsciiStream(int columnIndex, java.io.InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5614,7 +5614,7 @@ public void updateBinaryStream(int columnIndex, java.io.InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5638,7 +5638,7 @@ public void updateCharacterStream(int columnIndex, java.io.Reader x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5662,7 +5662,7 @@ public void updateAsciiStream(String columnLabel, java.io.InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5687,7 +5687,7 @@ */ public void updateAsciiStream(int columnIndex, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5713,7 +5713,7 @@ */ public void updateAsciiStream(String columnLabel, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5738,7 +5738,7 @@ public void updateBinaryStream(String columnLabel, java.io.InputStream x, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5763,7 +5763,7 @@ */ public void updateBinaryStream(int columnIndex, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5790,7 +5790,7 @@ */ public void updateBinaryStream(String columnLabel, java.io.InputStream x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5816,7 +5816,7 @@ public void updateCharacterStream(String columnLabel, java.io.Reader reader, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5841,7 +5841,7 @@ */ public void updateCharacterStream(int columnIndex, java.io.Reader x) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5868,7 +5868,7 @@ */ public void updateCharacterStream(String columnLabel, java.io.Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5885,7 +5885,7 @@ * @since 1.4 */ public void setURL(int parameterIndex, java.net.URL x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5914,7 +5914,7 @@ */ public void setNClob(int parameterIndex, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -5942,7 +5942,7 @@ */ public void setNClob(String parameterName, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5969,7 +5969,7 @@ */ public void setNClob(String parameterName, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -5996,7 +5996,7 @@ */ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6012,7 +6012,7 @@ * @since 1.6 */ public void setNClob(int parameterIndex, NClob value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6029,7 +6029,7 @@ */ public void setNString(String parameterName, String value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6046,7 +6046,7 @@ * @since 1.6 */ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6066,7 +6066,7 @@ */ public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6092,7 +6092,7 @@ * @since 1.6 */ public void setNCharacterStream(String parameterName, Reader value) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6118,7 +6118,7 @@ */ public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6144,7 +6144,7 @@ */ public void setClob(String parameterName, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6163,7 +6163,7 @@ * @since 1.6 */ public void setClob (String parameterName, Clob x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6188,7 +6188,7 @@ */ public void setClob(String parameterName, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6210,7 +6210,7 @@ */ public void setDate(String parameterName, java.sql.Date x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6236,7 +6236,7 @@ */ public void setDate(String parameterName, java.sql.Date x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6256,7 +6256,7 @@ */ public void setTime(String parameterName, java.sql.Time x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6282,7 +6282,7 @@ */ public void setTime(String parameterName, java.sql.Time x, Calendar cal) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6308,7 +6308,7 @@ */ public void setClob(int parameterIndex, Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6333,7 +6333,7 @@ */ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6363,7 +6363,7 @@ */ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6395,7 +6395,7 @@ */ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6426,7 +6426,7 @@ */ public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6444,7 +6444,7 @@ * @since 1.6 */ public void setBlob (String parameterName, Blob x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6470,7 +6470,7 @@ */ public void setBlob(String parameterName, InputStream inputStream) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6516,7 +6516,7 @@ */ public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6542,7 +6542,7 @@ */ public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6582,7 +6582,7 @@ * @since 1.4 */ public void setObject(String parameterName, Object x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6609,7 +6609,7 @@ */ public void setAsciiStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6636,7 +6636,7 @@ */ public void setBinaryStream(String parameterName, java.io.InputStream x, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6665,7 +6665,7 @@ public void setCharacterStream(String parameterName, java.io.Reader reader, int length) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6692,7 +6692,7 @@ */ public void setAsciiStream(String parameterName, java.io.InputStream x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6719,7 +6719,7 @@ */ public void setBinaryStream(String parameterName, java.io.InputStream x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6748,7 +6748,7 @@ */ public void setCharacterStream(String parameterName, java.io.Reader reader) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6767,7 +6767,7 @@ * @since 1.4 */ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6788,7 +6788,7 @@ * @since 1.4 */ public void setString(String parameterName, String x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6810,7 +6810,7 @@ * @since 1.4 */ public void setBytes(String parameterName, byte x[]) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6830,7 +6830,7 @@ */ public void setTimestamp(String parameterName, java.sql.Timestamp x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6847,7 +6847,7 @@ * @since 1.4 */ public void setNull(String parameterName, int sqlType) throws SQLException { - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6884,7 +6884,7 @@ */ public void setNull (String parameterName, int sqlType, String typeName) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6902,7 +6902,7 @@ * @since 1.4 */ public void setBoolean(String parameterName, boolean x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6922,7 +6922,7 @@ * @since 1.4 */ public void setByte(String parameterName, byte x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6941,7 +6941,7 @@ * @since 1.4 */ public void setShort(String parameterName, short x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6960,7 +6960,7 @@ * @since 1.4 */ public void setInt(String parameterName, int x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -6978,7 +6978,7 @@ * @since 1.4 */ public void setLong(String parameterName, long x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } @@ -6997,7 +6997,7 @@ * @since 1.4 */ public void setFloat(String parameterName, float x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } /** @@ -7015,9 +7015,24 @@ * @since 1.4 */ public void setDouble(String parameterName, double x) throws SQLException{ - throw new SQLFeatureNotSupportedException("Feature not supported"); + throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString()); } - - static final long serialVersionUID = -3591946023893483003L; + + /** + * This method re populates the resBundle + * during the deserialization process + * + */ + protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + // Default state initialization happens here + ois.defaultReadObject(); + // Initialization of transient Res Bundle happens here . + try { + jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) {} + + } + + static final long serialVersionUID = -3591946023893483003L; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/JoinRowSetImpl.java --- a/j2se/src/share/classes/com/sun/rowset/JoinRowSetImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/JoinRowSetImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -108,8 +108,7 @@ */ private WebRowSet wrs; - private transient JdbcRowSetResourceBundle joinResBundle; - + /** * Constructor for JoinRowSetImpl class. Configures various internal data * structures to provide mechanisms required for JoinRowSet interface @@ -120,11 +119,6 @@ */ public JoinRowSetImpl() throws SQLException { - try { - joinResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - - } vecRowSetsInJOIN = new Vector(); crsInternal = new CachedRowSetImpl(); vecJoinType = new Vector(); @@ -162,33 +156,37 @@ CachedRowSetImpl cRowset; if(!(rowset instanceof RowSet)) { - throw new SQLException(joinResBundle.handleGetObject("joinrowsetimpl.notinstance").toString()); + throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notinstance").toString()); } if(rowset instanceof JdbcRowSetImpl ) { cRowset = new CachedRowSetImpl(); cRowset.populate((RowSet)rowset); if(cRowset.size() == 0){ - throw new SQLException(joinResBundle.handleGetObject("joinrowsetimpl.emptyrowset").toString()); + throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.emptyrowset").toString()); } try { - cRowset.setMatchColumn(rowset.getMatchColumnIndexes()[0]); + int matchColumnCount = 0; + for(int i=0; i< rowset.getMatchColumnIndexes().length; i++) { + if(rowset.getMatchColumnIndexes()[i] != -1) + ++ matchColumnCount; + else + break; + } + int[] pCol = new int[matchColumnCount]; + for(int i=0; i= JoinRowSet.CROSS_JOIN && type <= JoinRowSet.FULL_JOIN) { if (type != JoinRowSet.INNER_JOIN) { // This 'if' will be removed after all joins are implemented. - throw new SQLException(joinResBundle.handleGetObject("joinrowsetimpl.notsupported").toString()); + throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notsupported").toString()); } else { Integer Intgr = new Integer(JoinRowSet.INNER_JOIN); vecJoinType.add(Intgr); } } else { - throw new SQLException(joinResBundle.handleGetObject("joinrowsetimpl.notdefined").toString()); + throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notdefined").toString()); } //end if } @@ -573,7 +584,7 @@ commenting this out for present if (!supportedJOINs[1]) { - throw new SQLException(joinResBundle.handleGetObject("joinrowsetimpl.notsupported").toString()); + throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notsupported").toString()); } */ @@ -631,40 +642,59 @@ // total columns in the new CachedRowSet will be sum of both -1 // (common column) - rsmd.setColumnCount + int matchColumnCount = 0; + for(int i=0; i< crsInternal.getMatchColumnIndexes().length; i++) { + if(crsInternal.getMatchColumnIndexes()[i] != -1) + ++ matchColumnCount; + else + break; + } + + rsmd.setColumnCount (crsInternal.getMetaData().getColumnCount() + - cRowset.getMetaData().getColumnCount() - 1); + cRowset.getMetaData().getColumnCount() - matchColumnCount); crsTemp.setMetaData(rsmd); crsInternal.beforeFirst(); cRowset.beforeFirst(); for (int i = 1 ; i <= rowCount1 ; i++) { if(crsInternal.isAfterLast() ) { - break; - } + break; + } if(crsInternal.next()) { cRowset.beforeFirst(); - - for(int j = 1 ; j <= rowCount2 ; j++) { + for(int j = 1 ; j <= rowCount2 ; j++) { if( cRowset.isAfterLast()) { - break; - } - if(cRowset.next()) { - - if (crsInternal.getObject( - crsInternal.getMatchColumnIndexes()[0]).equals - (cRowset.getObject(cRowset.getMatchColumnIndexes()[0]))) { + break; + } + if(cRowset.next()) { + boolean match = true; + for(int k=0; k ((crsInternal.getMetaData().getColumnCount()) + - (cRowset.getMetaData().getColumnCount()) - 1)) { - --p; - } + //if((p+q-1) > ((crsInternal.getMetaData().getColumnCount()) + + // (cRowset.getMetaData().getColumnCount()) - 1)) { + // --p; + //} rsmd.setColumnType(p+q-1, cRowset.getMetaData().getColumnType(q)); rsmd.setAutoIncrement(p+q-1, cRowset.getMetaData().isAutoIncrement(q)); rsmd.setCaseSensitive(p+q-1, cRowset.getMetaData().isCaseSensitive(q)); @@ -763,6 +800,9 @@ rsmd.setSearchable(p+q-1, cRowset.getMetaData().isSearchable(q)); rsmd.setSigned(p+q-1, cRowset.getMetaData().isSigned(q)); } + else { + --p; + } } crsTemp.insertRow(); crsTemp.moveToCurrentRow(); @@ -785,9 +825,10 @@ // Now the join is done. // Make crsInternal = crsTemp, to be ready for next merge, if at all. - int pCol = crsInternal.getMatchColumnIndexes()[0]; - - crsInternal = new CachedRowSetImpl(); + int[] pCol = new int[matchColumnCount]; + for(int i=0; iJoinRowSet + * object. + *

+ * A listener might, for example, be a table or graph that needs to + * be updated in order to accurately reflect the current state of + * the RowSet object. + *

+ * Note: if the RowSetListener object is + * null, this method silently discards the null + * value and does not add a null reference to the set of listeners. + *

+ * Note: if the listener is already set, and the new RowSetListerner + * instance is added to the set of listeners already registered to receive + * event notifications from this RowSet. + * + * @param listener an object that has implemented the + * javax.sql.RowSetListener interface and wants to be notified + * of any events that occur on this JoinRowSet object; May be + * null. + * @see #removeRowSetListener + */ + public void addRowSetListener(RowSetListener listener) { + crsInternal.addRowSetListener(listener); + } + + /** + * Removes the designated object from this JoinRowSet object's list of listeners. + * If the given argument is not a registered listener, this method + * does nothing. + * + * Note: if the RowSetListener object is + * null, this method silently discards the null + * value. + * + * @param listener a RowSetListener object that is on the list + * of listeners for this JoinRowSet object + * @see #addRowSetListener + */ + public void removeRowSetListener(RowSetListener listener) { + crsInternal.removeRowSetListener(listener); + } + + /** + * Converts this JoinRowSetImpl object to a collection + * of tables. The sample implementation utilitizes the TreeMap + * collection type. + * This class guarantees that the map will be in ascending key order, + * sorted according to the natural order for the key's class. + * + * @return a Collection object consisting of tables, + * each of which is a copy of a row in this + * JoinRowSetImpl object + * @throws SQLException if an error occurs in generating the collection + * @see #toCollection(int) + * @see #toCollection(String) + * @see java.util.TreeMap + */ + public Collection toCollection() throws SQLException { + return crsInternal.toCollection(); + } + + /** + * Returns the specified column of this JoinRowSetImpl object + * as a Collection object. This method makes a copy of the + * column's data and utilitizes the Vector to establish the + * collection. The Vector class implements a growable array + * objects allowing the individual components to be accessed using an + * an integer index similar to that of an array. + * + * @return a Collection object that contains the value(s) + * stored in the specified column of this + * JoinRowSetImpl + * object + * @throws SQLException if an error occurs generated the collection; or + * an invalid column is provided. + * @see #toCollection() + * @see #toCollection(String) + * @see java.util.Vector + */ + public Collection toCollection(int column) throws SQLException { + return crsInternal.toCollection(column); + } + + /** + * Returns the specified column of this JoinRowSetImpl object + * as a Collection object. This method makes a copy of the + * column's data and utilitizes the Vector to establish the + * collection. The Vector class implements a growable array + * objects allowing the individual components to be accessed using an + * an integer index similar to that of an array. + * + * @return a Collection object that contains the value(s) + * stored in the specified column of this + * JoinRowSetImpl + * object + * @throws SQLException if an error occurs generated the collection; or + * an invalid column is provided. + * @see #toCollection() + * @see #toCollection(int) + * @see java.util.Vector + */ + public Collection toCollection(String column) throws SQLException { + return crsInternal.toCollection(column); + } + + /** + * Creates a RowSet object that is a copy of + * this JoinRowSetImpl object's table structure + * and the constraints only. + * There will be no data in the object being returned. + * Updates made on a copy are not visible to the original rowset. + *

+ * This helps in getting the underlying XML schema which can + * be used as the basis for populating a WebRowSet. + * + * @return a new CachedRowSet object that is a copy + * of this JoinRowSetImpl object's schema and + * retains all the constraints on the original rowset but contains + * no data + * @throws SQLException if an error occurs in generating the copy + * of the CachedRowSet object + * @see #createShared + * @see #createCopy + * @see #createCopyNoConstraints + * @see javax.sql.RowSetEvent + * @see javax.sql.RowSetListener + */ + public CachedRowSet createCopySchema() throws SQLException { + return crsInternal.createCopySchema(); + } + static final long serialVersionUID = -5590501621560008453L; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties --- a/j2se/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties Thu Jul 05 23:47:33 2007 +0000 @@ -41,7 +41,7 @@ cachedrowsetimpl.longfail = getLong Failed on value ( {0} ) in column {1} cachedrowsetimpl.floatfail = getFloat failed on value ( {0} ) in column {1} cachedrowsetimpl.doublefail = getDouble failed on value ( {0} ) in column {1} -cachedrowsetimpl.dtypemismt = Data Type Mismatch +cachedrowsetimpl.dtypemismt = Data Type Mismatch cachedrowsetimpl.datefail = getDate Failed on value ( {0} ) in column {1} no conversion available cachedrowsetimpl.timefail = getTime failed on value ( {0} ) in column {1} no conversion available cachedrowsetimpl.posupdate = Positioned updates not supported @@ -76,6 +76,8 @@ cachedrowsetimpl.pagesize1 = Page size cannot be greater than maxRows cachedrowsetimpl.fwdonly = ResultSet is forward only cachedrowsetimpl.type = Type is : {0} +cachedrowsetimpl.opnotysupp = Operation not yet supported +cachedrowsetimpl.featnotsupp = Feature not supported # WebRowSetImpl exceptions webrowsetimpl.nullhash = Cannot instantiate WebRowSetImpl instance. Null Hashtable supplied to constructor @@ -109,22 +111,28 @@ jdbcrowsetimpl.usecolname = Use column name as argument to unsetMatchColumn jdbcrowsetimpl.usecolid = Use column ID as argument to unsetMatchColumn jdbcrowsetimpl.resnotupd = ResultSet is not updatable +jdbcrowsetimpl.opnotysupp = Operation not yet supported +jdbcrowsetimpl.featnotsupp = Feature not supported #CachedRowSetReader exceptions crsreader.connect = (JNDI) Unable to connect crsreader.paramtype = Unable to deduce param type +crsreader.connecterr = Internal Error in RowSetReader: no connection or command +crsreader.datedetected = Detected a Date +crsreader.caldetected = Detected a Calendar #CachedRowSetWriter exceptions crswriter.connect = Unable to get connection crswriter.tname = writeData cannot determine table name crswriter.params1 = Value of params1 : {0} crswriter.params2 = Value of params2 : {0} +crswriter.conflictsno = conflicts while synchronizing #InsertRow exceptions insertrow.novalue = No value has been inserted #SyncResolverImpl exceptions -syncrsimpl.indexval = Index value out of range +syncrsimpl.indexval = Index value out of range syncrsimpl.noconflict = This column not in conflict syncrsimpl.syncnotpos = Synchronization is not possible syncrsimpl.valtores = Value to be resolved can either be in the database or in cachedrowset @@ -132,32 +140,28 @@ #WebRowSetXmlReader exception wrsxmlreader.invalidcp = End of RowSet reached. Invalid cursor position wrsxmlreader.readxml = readXML : {0} -wrsxmlreader.parseerr = ** Parsing Error -wrsxmlreader.line = , line -wrsxmlreader.uri = , uri +wrsxmlreader.parseerr = ** Parsing Error : {0} , line : {0} , uri : {0} #WebRowSetXmlWriter exceptions wrsxmlwriter.ioex = IOException : {0} -wrsxmlwriter.sqlex = SQLException : {0} +wrsxmlwriter.sqlex = SQLException : {0} wrsxmlwriter.failedwrite = Failed to write value wsrxmlwriter.notproper = Not a proper type -#XmlReaderContentHandle exceptions -xmlrch.errmap = Error setting Map : {0} -xmlrch.errmetadata = Error setting metadata : {0} +#XmlReaderContentHandler exceptions +xmlrch.errmap = Error setting Map : {0} +xmlrch.errmetadata = Error setting metadata : {0} xmlrch.errinsert = Error inserting values : {0} xmlrch.errconstr = Error constructing row : {0} xmlrch.errdel = Error deleting row : {0} xmlrch.errinsert = Error constructing insert row : {0} xmlrch.errinsdel = Error constructing insdel row : {0} xmlrch.errupdate = Error constructing update row : {0} -xmlrch errupdrow = Error updating row : {0} +xmlrch.errupdrow = Error updating row : {0} xmlrch.chars = characters : xmlrch.badvalue = Bad value ; non-nullable property xmlrch.badvalue1 = Bad value ; non-nullable metadata -xmlrch.warning = ** Warning -xmlrch.line = , line -xmlrch.uri = , uri +xmlrch.warning = ** Warning : {0} , line : {0} , uri : {0} #RIOptimisticProvider Exceptions riop.locking = Locking classification is not supported diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/WebRowSetImpl.java --- a/j2se/src/share/classes/com/sun/rowset/WebRowSetImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/WebRowSetImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -70,8 +70,6 @@ private SyncProvider provider; - private transient JdbcRowSetResourceBundle wrsResBundle; - /** * Constructs a new WebRowSet object initialized with the * default values for a CachedRowSet object instance. This @@ -87,13 +85,7 @@ public WebRowSetImpl() throws SQLException { super(); - try { - wrsResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - - } - - // %%% + // %%% // Needs to use to SPI XmlReader,XmlWriters // xmlReader = new WebRowSetXmlReader(); @@ -111,14 +103,8 @@ */ public WebRowSetImpl(Hashtable env) throws SQLException { - try { - wrsResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - - } - if ( env == null) { - throw new SQLException(wrsResBundle.handleGetObject("webrowsetimpl.nullhash").toString()); + throw new SQLException(resBundle.handleGetObject("webrowsetimpl.nullhash").toString()); } String providerName = @@ -171,7 +157,7 @@ xmlWriter.writeXML(this, writer); } else { - throw new SQLException(wrsResBundle.handleGetObject("webrowsetimpl.invalidwr").toString()); + throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidwr").toString()); } } @@ -186,7 +172,7 @@ // Xml that is used when a WRS is instantiated. //WebRowSetXmlReader xmlReader = getXmlReader(); try { - if (reader != null) { + if (reader != null) { xmlReader.readXML(this, reader); // Position is before the first row @@ -202,7 +188,7 @@ } } else { - throw new SQLException(wrsResBundle.handleGetObject("webrowsetimpl.invalidrd").toString()); + throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidrd").toString()); } } catch (Exception e) { throw new SQLException(e.getMessage()); @@ -234,7 +220,7 @@ } } else { - throw new SQLException(wrsResBundle.handleGetObject("webrowsetimpl.invalidrd").toString()); + throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidrd").toString()); } } @@ -255,7 +241,7 @@ xmlWriter.writeXML(this, oStream); } else { - throw new SQLException(wrsResBundle.handleGetObject("webrowsetimpl.invalidwr").toString()); + throw new SQLException(resBundle.handleGetObject("webrowsetimpl.invalidwr").toString()); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java --- a/j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java Thu Jul 05 23:47:33 2007 +0000 @@ -82,6 +82,16 @@ private boolean userCon = false; private int startPosition; + + private JdbcRowSetResourceBundle resBundle; + + public CachedRowSetReader() { + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } /** @@ -115,12 +125,12 @@ * this CachedRowSetReader object set as * its reader * @throws SQLException if there is a database access error, there is a - * problem making the connection, or the command property has not + * problem making the connection, or the command property has not * been set */ public void readData(RowSetInternal caller) throws SQLException { - + Connection con = null; try { CachedRowSet crs = (CachedRowSet)caller; @@ -145,11 +155,11 @@ // connection. userCon = false; - Connection con = this.connect(caller); + con = this.connect(caller); // Check our assumptions. if (con == null || crs.getCommand() == null) - throw new SQLException(); + throw new SQLException(resBundle.handleGetObject("crsreader.connecterr").toString()); try { con.setTransactionIsolation(crs.getTransactionIsolation()); @@ -171,7 +181,7 @@ * drivers may not support the above - esp. older * drivers being used by the bridge.. */ - ; + throw new SQLException(ex.getMessage()); } if(crs.getCommand().toLowerCase().indexOf("select") != -1) { @@ -205,7 +215,7 @@ * drivers may not support the above - esp. older * drivers being used by the bridge.. */ - ; + throw new SQLException(ex.getMessage()); } rs = pstmt.executeQuery(); crs.populate(rs,startPosition); @@ -229,6 +239,29 @@ catch (SQLException ex) { // Throw an exception if reading fails for any reason. throw ex; + } finally { + try { + // only close connections we created... + if (con != null && getCloseConnection() == true) { + try { + if (!con.getAutoCommit()) { + con.rollback(); + } + } catch (Exception dummy) { + /* + * not an error condition, we're closing anyway, but + * we'd like to clean up any locks if we can since + * it is not clear the connection pool will clean + * these connections in a timely manner + */ + } + con.close(); + con = null; + } + } catch (SQLException e) { + // will get exception if something already went wrong, but don't + // override that exception with this one + } } } @@ -299,7 +332,9 @@ } } catch (javax.naming.NamingException ex) { - throw new SQLException("(JNDI) Unable to connect"); + SQLException sqlEx = new SQLException(resBundle.handleGetObject("crsreader.connect").toString()); + sqlEx.initCause(ex); + throw sqlEx; } } else if (((RowSet)caller).getUrl() != null) { // Connect using the driver manager. @@ -354,15 +389,15 @@ if (param[0] instanceof java.sql.Date || param[0] instanceof java.sql.Time || param[0] instanceof java.sql.Timestamp) { - System.err.println("Detected a Date"); + System.err.println(resBundle.handleGetObject("crsreader.datedetected").toString()); if (param[1] instanceof java.util.Calendar) { - System.err.println("Detected a Calendar"); + System.err.println(resBundle.handleGetObject("crsreader.caldetected").toString()); pstmt.setDate(i + 1, (java.sql.Date)param[0], (java.util.Calendar)param[1]); continue; } else { - throw new SQLException("Unable to deduce param type"); + throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString()); } } @@ -403,7 +438,7 @@ (java.io.InputStream)param[0], ((Integer)param[1]).intValue()); default: - throw new SQLException("Unable to deduce parameter type"); + throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString()); } } @@ -417,7 +452,7 @@ continue; } - throw new SQLException("Unable to deduce param type"); + throw new SQLException(resBundle.handleGetObject("crsreader.paramtype").toString()); } else { // common case - this catches all SQL92 types diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java --- a/j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java Thu Jul 05 23:47:33 2007 +0000 @@ -190,6 +190,16 @@ * changed only in database. */ private int iChangedValsinDbOnly ; + + private JdbcRowSetResourceBundle resBundle; + + public CachedRowSetWriter() { + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } /** * Propagates changes in the given RowSet object @@ -264,16 +274,17 @@ // to get a JDBC connection, so call it. con = reader.connect(caller); + if (con == null) { - throw new SQLException("Unable to get Connection"); + throw new SQLException(resBundle.handleGetObject("crswriter.connect").toString()); } /* // Fix 6200646. // Don't change the connection or transaction properties. This will fail in a // J2EE container. - if (con.getAutoCommit() == true) { + if (con.getAutoCommit() == true) { con.setAutoCommit(false); } @@ -301,7 +312,7 @@ this.crsResolve.setMetaData(rsmdResolv); // moved outside the insert inner loop - pstmtIns = con.prepareStatement(insertCmd); + //pstmtIns = con.prepareStatement(insertCmd); if (callerColumnCount < 1) { // No data, so return success. @@ -330,7 +341,9 @@ } else if (crs.rowInserted()) { // The row has been inserted. - if ( (conflict = insertNewRow(crs, pstmtIns, this.crsResolve)) == true) { + + pstmtIns = con.prepareStatement(insertCmd); + if ( (conflict = insertNewRow(crs, pstmtIns, this.crsResolve)) == true) { status.add(rows, new Integer(SyncResolver.INSERT_ROW_CONFLICT)); } else { // insert happened without any occurrence of conflicts @@ -371,6 +384,7 @@ } //end while // close the insert statement + if(pstmtIns!=null) pstmtIns.close(); // reset crs.setShowDeleted(showDel); @@ -389,8 +403,7 @@ this.crsResolve.beforeFirst(); if(boolConf) { - - SyncProviderException spe = new SyncProviderException(status.size() - 1+" conflicts while synchronizing "); + SyncProviderException spe = new SyncProviderException(status.size() - 1+resBundle.handleGetObject("crswriter.conflictsno").toString()); //SyncResolver syncRes = spe.getSyncResolver(); SyncResolverImpl syncResImpl = (SyncResolverImpl) spe.getSyncResolver(); @@ -780,9 +793,13 @@ primaryKeys[k] = pkcolname; k++; } + if(rs.next()) { for(int j=0;jInsertRow object. */ private int cols; + + private JdbcRowSetResourceBundle resBundle; /** * Creates an InsertRow object initialized with the @@ -65,6 +68,11 @@ origVals = new Object[numCols]; colsInserted = new BitSet(numCols); cols = numCols; + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } } /** @@ -126,7 +134,7 @@ */ public Object getColumnObject(int idx) throws SQLException { if (colsInserted.get(idx - 1) == false) { - throw new SQLException("No value has been inserted"); + throw new SQLException(resBundle.handleGetObject("insertrow.novalue").toString()); } return (origVals[idx - 1]); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java --- a/j2se/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -27,7 +27,6 @@ import java.sql.*; import javax.sql.*; -import java.lang.*; import java.util.*; import java.math.BigDecimal; @@ -35,8 +34,7 @@ import javax.sql.rowset.spi.*; import com.sun.rowset.*; -import com.sun.rowset.internal.*; -import java.lang.Comparable; +import java.io.IOException; /** * There will be two sets of data which will be maintained by the rowset at the @@ -98,6 +96,8 @@ * row basis encapsulated as a CahedRowSet. */ private CachedRowSet row; + + private JdbcRowSetResourceBundle resBundle; /** * Public constructor @@ -109,6 +109,12 @@ crw = new CachedRowSetWriter(); row = new CachedRowSetImpl(); rowStatus = 1; + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } catch(SQLException sqle) { } } @@ -184,11 +190,11 @@ try { // check whether the index is in range if(index<=0 || index > crsSync.getMetaData().getColumnCount() ) { - throw new SQLException("Index value out of range :"+ index); + throw new SQLException(resBundle.handleGetObject("syncrsimpl.indexval").toString()+ index); } // check whether index col is in conflict if(crsRes.getObject(index) == null) { - throw new SQLException("This column not in conflict"); + throw new SQLException(resBundle.handleGetObject("syncrsimpl.noconflict").toString()); } } catch (SQLException sqle) { // modify method to throw for SQLException @@ -266,13 +272,12 @@ * due to some reasons. * Also will prevent from going into a loop of SPE's **/ - throw new SQLException("Synchronization not possible"); + throw new SQLException(resBundle.handleGetObject("syncrsimpl.syncnotpos").toString()); } } //end if(bool) } else { - throw new SQLException("Value to be resolved can be either of "+ - "database or inside CachedRowSet "); + throw new SQLException(resBundle.handleGetObject("syncrsimpl.valtores").toString()); } //end if (crs.getObject ...) block diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java --- a/j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java Thu Jul 05 23:47:33 2007 +0000 @@ -34,9 +34,9 @@ import javax.xml.parsers.*; import com.sun.rowset.*; +import java.text.MessageFormat; import javax.sql.rowset.*; import javax.sql.rowset.spi.*; -import com.sun.rowset.providers.*; /** * An implementation of the XmlReader interface, which @@ -69,6 +69,17 @@ * reader for the given rowset * @see XmlReaderContentHandler */ + + private JdbcRowSetResourceBundle resBundle; + + public WebRowSetXmlReader(){ + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } + public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException { try { // Crimson Parser(as in J2SE 1.4.1 is NOT able to handle @@ -81,16 +92,14 @@ InputSource is = new InputSource(reader); DefaultHandler dh = new XmlErrorHandler(); XmlReaderContentHandler hndr = new XmlReaderContentHandler((RowSet)caller); - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); + factory.setNamespaceAware(true); factory.setValidating(true); - SAXParser parser = factory.newSAXParser() ; parser.setProperty( "http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema"); - + XMLReader reader1 = parser.getXMLReader() ; reader1.setEntityResolver(new XmlResolver()); reader1.setContentHandler(hndr); @@ -100,10 +109,7 @@ reader1.parse(is); } catch (SAXParseException err) { - System.out.println ("** Parsing error" - + ", line " + err.getLineNumber () - + ", uri " + err.getSystemId ()); - System.out.println(" " + err.getMessage ()); + System.out.println (MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.parseerr").toString(), new Object[]{ err.getMessage (), err.getLineNumber(), err.getSystemId()})); err.printStackTrace(); throw new SQLException(err.getMessage()); @@ -119,10 +125,10 @@ // Will be here if trying to write beyond the RowSet limits catch (ArrayIndexOutOfBoundsException aie) { - throw new SQLException("End of Rowset reached. Invalid cursor position"); + throw new SQLException(resBundle.handleGetObject("wrsxmlreader.invalidcp").toString()); } catch (Throwable e) { - throw new SQLException("readXML: " + e.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.readxml").toString() , e.getMessage())); } } @@ -177,9 +183,7 @@ reader1.parse(is); } catch (SAXParseException err) { - System.out.println ("** Parsing error" - + ", line " + err.getLineNumber () - + ", uri " + err.getSystemId ()); + System.out.println (MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.parseerr").toString(), new Object[]{err.getLineNumber(), err.getSystemId() })); System.out.println(" " + err.getMessage ()); err.printStackTrace(); throw new SQLException(err.getMessage()); @@ -196,11 +200,11 @@ // Will be here if trying to write beyond the RowSet limits catch (ArrayIndexOutOfBoundsException aie) { - throw new SQLException("End of Rowset reached. Invalid cursor position"); + throw new SQLException(resBundle.handleGetObject("wrsxmlreader.invalidcp").toString()); } catch (Throwable e) { - throw new SQLException("readXML: " + e.getMessage()); + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlreader.readxml").toString() , e.getMessage())); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java --- a/j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,20 +25,15 @@ package com.sun.rowset.internal; +import com.sun.rowset.JdbcRowSetResourceBundle; import java.sql.*; import javax.sql.*; import java.io.*; -import java.math.*; +import java.text.MessageFormat; import java.util.*; -import java.text.*; - -import javax.xml.parsers.*; -import org.xml.sax.*; -import org.xml.sax.helpers.*; import javax.sql.rowset.*; import javax.sql.rowset.spi.*; -import com.sun.rowset.providers.*; /** * An implementation of the XmlWriter interface, which writes a @@ -46,7 +41,7 @@ */ public class WebRowSetXmlWriter implements XmlWriter, Serializable { - + /** * The java.io.Writer object to which this WebRowSetXmlWriter * object will write when its writeXML method is called. The value @@ -54,14 +49,25 @@ * as the second argument to the writeXML method. */ private java.io.Writer writer; - + /** * The java.util.Stack object that this WebRowSetXmlWriter * object will use for storing the tags to be used for writing the calling * WebRowSet object as an XML document. */ private java.util.Stack stack; - + + private JdbcRowSetResourceBundle resBundle; + + public WebRowSetXmlWriter() { + + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } + /** * Writes the given WebRowSet object as an XML document * using the given java.io.Writer object. The XML document @@ -71,28 +77,28 @@ *

* This method is called by the XmlWriter object that is * referenced in the calling WebRowSet object's - * xmlWriter field. The XmlWriter.writeXML + * xmlWriter field. The XmlWriter.writeXML * method passes to this method the arguments that were supplied to it. - * + * * @param caller the WebRowSet object to be written; must * be a rowset for which this WebRowSetXmlWriter object * is the writer - * @param wrt the java.io.Writer object to which + * @param wrt the java.io.Writer object to which * caller will be written * @exception SQLException if a database access error occurs or * this WebRowSetXmlWriter object is not the writer * for the given rowset * @see XmlWriter#writeXML */ - public void writeXML(WebRowSet caller, java.io.Writer wrt) - throws SQLException { - - // create a new stack for tag checking. - stack = new java.util.Stack(); - writer = wrt; - writeRowSet(caller); + public void writeXML(WebRowSet caller, java.io.Writer wrt) + throws SQLException { + + // create a new stack for tag checking. + stack = new java.util.Stack(); + writer = wrt; + writeRowSet(caller); } - + /** * Writes the given WebRowSet object as an XML document * using the given java.io.OutputStream object. The XML document @@ -100,64 +106,64 @@ * properties. If a data value has been updated, that information is also * included. *

- * Using stream is a faster way than using java.io.Writer - * + * Using stream is a faster way than using java.io.Writer + * * This method is called by the XmlWriter object that is * referenced in the calling WebRowSet object's - * xmlWriter field. The XmlWriter.writeXML + * xmlWriter field. The XmlWriter.writeXML * method passes to this method the arguments that were supplied to it. - * + * * @param caller the WebRowSet object to be written; must * be a rowset for which this WebRowSetXmlWriter object * is the writer - * @param oStream the java.io.OutputStream object to which + * @param oStream the java.io.OutputStream object to which * caller will be written * @throws SQLException if a database access error occurs or * this WebRowSetXmlWriter object is not the writer * for the given rowset * @see XmlWriter#writeXML */ - public void writeXML(WebRowSet caller, java.io.OutputStream oStream) - throws SQLException { - - // create a new stack for tag checking. - stack = new java.util.Stack(); - writer = new OutputStreamWriter(oStream); - writeRowSet(caller); + public void writeXML(WebRowSet caller, java.io.OutputStream oStream) + throws SQLException { + + // create a new stack for tag checking. + stack = new java.util.Stack(); + writer = new OutputStreamWriter(oStream); + writeRowSet(caller); } - + /** * * * @exception SQLException if a database access error occurs */ private void writeRowSet(WebRowSet caller) throws SQLException { - - try { - - startHeader(); - - writeProperties(caller); - writeMetaData(caller); - writeData(caller); - - endHeader(); - - } catch (java.io.IOException ex) { - throw new SQLException("IOException: " + ex.getMessage()); - } + + try { + + startHeader(); + + writeProperties(caller); + writeMetaData(caller); + writeData(caller); + + endHeader(); + + } catch (java.io.IOException ex) { + throw new SQLException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.ioex").toString(), ex.getMessage())); + } } - + private void startHeader() throws java.io.IOException { - - setTag("webRowSet"); - writer.write("\n"); + + setTag("webRowSet"); + writer.write("\n"); writer.write("\n"); } - + private void endHeader() throws java.io.IOException { - endTag("webRowSet"); + endTag("webRowSet"); } /** @@ -166,96 +172,96 @@ * @exception SQLException if a database access error occurs */ private void writeProperties(WebRowSet caller) throws java.io.IOException { - - beginSection("properties"); - - try { - propString("command", processSpecialCharacters(caller.getCommand())); - propInteger("concurrency", caller.getConcurrency()); - propString("datasource", caller.getDataSourceName()); - propBoolean("escape-processing", - caller.getEscapeProcessing()); - - try { - propInteger("fetch-direction", caller.getFetchDirection()); - } catch(SQLException sqle) { - // it may be the case that fetch direction has not been set - // fetchDir == 0 - // in that case it will throw a SQLException. - // To avoid that catch it here - } - - propInteger("fetch-size", caller.getFetchSize()); - propInteger("isolation-level", - caller.getTransactionIsolation()); - - beginSection("key-columns"); - - int[] kc = caller.getKeyColumns(); - for (int i = 0; kc != null && i < kc.length; i++) - propInteger("column", kc[i]); - - endSection("key-columns"); - - //Changed to beginSection and endSection for maps for proper indentation - beginSection("map"); - java.util.Map typeMap = caller.getTypeMap(); - if (typeMap != null) { - Iterator i = typeMap.keySet().iterator(); - Class c; - String type; - while (i.hasNext()) { - type = (String)i.next(); - c = (Class)typeMap.get(type); - propString("type", type); - propString("class", c.getName()); - } - } - endSection("map"); - - propInteger("max-field-size", caller.getMaxFieldSize()); - propInteger("max-rows", caller.getMaxRows()); - propInteger("query-timeout", caller.getQueryTimeout()); - propBoolean("read-only", caller.isReadOnly()); - - int itype = caller.getType(); - String strType = ""; - - if(itype == 1003) { - strType = "ResultSet.TYPE_FORWARD_ONLY"; - } else if(itype == 1004) { - strType = "ResultSet.TYPE_SCROLL_INSENSITIVE"; - } else if(itype == 1005) { - strType = "ResultSet.TYPE_SCROLL_SENSITIVE"; - } - - propString("rowset-type", strType); - - propBoolean("show-deleted", caller.getShowDeleted()); - propString("table-name", caller.getTableName()); - propString("url", caller.getUrl()); - - beginSection("sync-provider"); - // 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("@")); - - propString("sync-provider-name", strProvider); - propString("sync-provider-vendor", "Sun Microsystems Inc."); - propString("sync-provider-version", "1.0"); - propInteger("sync-provider-grade", caller.getSyncProvider().getProviderGrade()); - propInteger("data-source-lock", caller.getSyncProvider().getDataSourceLock()); - - endSection("sync-provider"); - - } catch (SQLException ex) { - throw new java.io.IOException("SQLException: " + ex.getMessage()); - } - - endSection("properties"); + + beginSection("properties"); + + try { + propString("command", processSpecialCharacters(caller.getCommand())); + propInteger("concurrency", caller.getConcurrency()); + propString("datasource", caller.getDataSourceName()); + propBoolean("escape-processing", + caller.getEscapeProcessing()); + + try { + propInteger("fetch-direction", caller.getFetchDirection()); + } catch(SQLException sqle) { + // it may be the case that fetch direction has not been set + // fetchDir == 0 + // in that case it will throw a SQLException. + // To avoid that catch it here + } + + propInteger("fetch-size", caller.getFetchSize()); + propInteger("isolation-level", + caller.getTransactionIsolation()); + + beginSection("key-columns"); + + int[] kc = caller.getKeyColumns(); + for (int i = 0; kc != null && i < kc.length; i++) + propInteger("column", kc[i]); + + endSection("key-columns"); + + //Changed to beginSection and endSection for maps for proper indentation + beginSection("map"); + java.util.Map typeMap = caller.getTypeMap(); + if (typeMap != null) { + Iterator i = typeMap.keySet().iterator(); + Class c; + String type; + while (i.hasNext()) { + type = (String)i.next(); + c = (Class)typeMap.get(type); + propString("type", type); + propString("class", c.getName()); + } + } + endSection("map"); + + propInteger("max-field-size", caller.getMaxFieldSize()); + propInteger("max-rows", caller.getMaxRows()); + propInteger("query-timeout", caller.getQueryTimeout()); + propBoolean("read-only", caller.isReadOnly()); + + int itype = caller.getType(); + String strType = ""; + + if(itype == 1003) { + strType = "ResultSet.TYPE_FORWARD_ONLY"; + } else if(itype == 1004) { + strType = "ResultSet.TYPE_SCROLL_INSENSITIVE"; + } else if(itype == 1005) { + strType = "ResultSet.TYPE_SCROLL_SENSITIVE"; + } + + propString("rowset-type", strType); + + propBoolean("show-deleted", caller.getShowDeleted()); + propString("table-name", caller.getTableName()); + propString("url", caller.getUrl()); + + beginSection("sync-provider"); + // 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("@")); + + propString("sync-provider-name", strProvider); + propString("sync-provider-vendor", "Sun Microsystems Inc."); + propString("sync-provider-version", "1.0"); + propInteger("sync-provider-grade", caller.getSyncProvider().getProviderGrade()); + propInteger("data-source-lock", caller.getSyncProvider().getDataSourceLock()); + + endSection("sync-provider"); + + } catch (SQLException ex) { + throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage())); + } + + endSection("properties"); } - + /** * * @@ -263,45 +269,45 @@ */ private void writeMetaData(WebRowSet caller) throws java.io.IOException { int columnCount; - - beginSection("metadata"); - - try { - - ResultSetMetaData rsmd = caller.getMetaData(); - columnCount = rsmd.getColumnCount(); - propInteger("column-count", columnCount); - - for (int colIndex = 1; colIndex <= columnCount; colIndex++) { - beginSection("column-definition"); - - propInteger("column-index", colIndex); - propBoolean("auto-increment", rsmd.isAutoIncrement(colIndex)); - propBoolean("case-sensitive", rsmd.isCaseSensitive(colIndex)); - propBoolean("currency", rsmd.isCurrency(colIndex)); - propInteger("nullable", rsmd.isNullable(colIndex)); - propBoolean("signed", rsmd.isSigned(colIndex)); - propBoolean("searchable", rsmd.isSearchable(colIndex)); - propInteger("column-display-size",rsmd.getColumnDisplaySize(colIndex)); - propString("column-label", rsmd.getColumnLabel(colIndex)); - propString("column-name", rsmd.getColumnName(colIndex)); - propString("schema-name", rsmd.getSchemaName(colIndex)); - propInteger("column-precision", rsmd.getPrecision(colIndex)); - propInteger("column-scale", rsmd.getScale(colIndex)); - propString("table-name", rsmd.getTableName(colIndex)); - propString("catalog-name", rsmd.getCatalogName(colIndex)); - propInteger("column-type", rsmd.getColumnType(colIndex)); - propString("column-type-name", rsmd.getColumnTypeName(colIndex)); - - endSection("column-definition"); - } - } catch (SQLException ex) { - throw new java.io.IOException("SQLException: " + ex.getMessage()); - } - - endSection("metadata"); + + beginSection("metadata"); + + try { + + ResultSetMetaData rsmd = caller.getMetaData(); + columnCount = rsmd.getColumnCount(); + propInteger("column-count", columnCount); + + for (int colIndex = 1; colIndex <= columnCount; colIndex++) { + beginSection("column-definition"); + + propInteger("column-index", colIndex); + propBoolean("auto-increment", rsmd.isAutoIncrement(colIndex)); + propBoolean("case-sensitive", rsmd.isCaseSensitive(colIndex)); + propBoolean("currency", rsmd.isCurrency(colIndex)); + propInteger("nullable", rsmd.isNullable(colIndex)); + propBoolean("signed", rsmd.isSigned(colIndex)); + propBoolean("searchable", rsmd.isSearchable(colIndex)); + propInteger("column-display-size",rsmd.getColumnDisplaySize(colIndex)); + propString("column-label", rsmd.getColumnLabel(colIndex)); + propString("column-name", rsmd.getColumnName(colIndex)); + propString("schema-name", rsmd.getSchemaName(colIndex)); + propInteger("column-precision", rsmd.getPrecision(colIndex)); + propInteger("column-scale", rsmd.getScale(colIndex)); + propString("table-name", rsmd.getTableName(colIndex)); + propString("catalog-name", rsmd.getCatalogName(colIndex)); + propInteger("column-type", rsmd.getColumnType(colIndex)); + propString("column-type-name", rsmd.getColumnTypeName(colIndex)); + + endSection("column-definition"); + } + } catch (SQLException ex) { + throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage())); + } + + endSection("metadata"); } - + /** * * @@ -309,205 +315,173 @@ */ private void writeData(WebRowSet caller) throws java.io.IOException { ResultSet rs; - - try { - ResultSetMetaData rsmd = caller.getMetaData(); - int columnCount = rsmd.getColumnCount(); - int i; - + + try { + ResultSetMetaData rsmd = caller.getMetaData(); + int columnCount = rsmd.getColumnCount(); + int i; + beginSection("data"); - + caller.beforeFirst(); - caller.setShowDeleted(true); + caller.setShowDeleted(true); while (caller.next()) { - if (caller.rowDeleted() && caller.rowInserted()) { - beginSection("modifyRow"); - } else if (caller.rowDeleted()) { - beginSection("deleteRow"); - } else if (caller.rowInserted()) { - beginSection("insertRow"); - } else { - beginSection("currentRow"); - } - - for (i = 1; i <= columnCount; i++) { - if (caller.columnUpdated(i)) { - rs = caller.getOriginalRow(); - rs.next(); - beginTag("columnValue"); - writeValue(i, (RowSet)rs); - endTag("columnValue"); - beginTag("updateRow"); - writeValue(i, caller); - endTag("updateRow"); - } else { - beginTag("columnValue"); - writeValue(i, caller); - endTag("columnValue"); - } - } - - endSection(); // this is unchecked - } - endSection("data"); + if (caller.rowDeleted() && caller.rowInserted()) { + beginSection("modifyRow"); + } else if (caller.rowDeleted()) { + beginSection("deleteRow"); + } else if (caller.rowInserted()) { + beginSection("insertRow"); + } else { + beginSection("currentRow"); + } + + for (i = 1; i <= columnCount; i++) { + if (caller.columnUpdated(i)) { + rs = caller.getOriginalRow(); + rs.next(); + beginTag("columnValue"); + writeValue(i, (RowSet)rs); + endTag("columnValue"); + beginTag("updateRow"); + writeValue(i, caller); + endTag("updateRow"); + } else { + beginTag("columnValue"); + writeValue(i, caller); + endTag("columnValue"); + } + } + + endSection(); // this is unchecked + } + endSection("data"); } catch (SQLException ex) { - throw new java.io.IOException("SQLException: " + ex.getMessage()); + throw new java.io.IOException(MessageFormat.format(resBundle.handleGetObject("wrsxmlwriter.sqlex").toString(), ex.getMessage())); } } - + private void writeValue(int idx, RowSet caller) throws java.io.IOException { - try { - int type = caller.getMetaData().getColumnType(idx); - - switch (type) { - case java.sql.Types.BIT: - case java.sql.Types.BOOLEAN: - boolean b = caller.getBoolean(idx); - if (caller.wasNull()) - writeNull(); - else - writeBoolean(b); - break; - case java.sql.Types.TINYINT: - case java.sql.Types.SMALLINT: - short s = caller.getShort(idx); - if (caller.wasNull()) - writeNull(); - else - writeShort(s); - break; - case java.sql.Types.INTEGER: - int i = caller.getInt(idx); - if (caller.wasNull()) - writeNull(); - else - writeInteger(caller.getInt(idx)); - break; - case java.sql.Types.BIGINT: - long l = caller.getLong(idx); - if (caller.wasNull()) - writeNull(); - else - writeLong(l); - break; - case java.sql.Types.REAL: - case java.sql.Types.FLOAT: - float f = caller.getFloat(idx); - if (caller.wasNull()) - writeNull(); - else - writeFloat(f); - break; - case java.sql.Types.DOUBLE: - double d = caller.getDouble(idx); - if (caller.wasNull()) - writeNull(); - else - writeDouble(d); - break; - case java.sql.Types.NUMERIC: - case java.sql.Types.DECIMAL: - writeBigDecimal(caller.getBigDecimal(idx)); - break; - case java.sql.Types.BINARY: - case java.sql.Types.VARBINARY: - case java.sql.Types.LONGVARBINARY: - break; - case java.sql.Types.DATE: - java.sql.Date date = caller.getDate(idx); - if (caller.wasNull()) - writeNull(); - else - writeLong(date.getTime()); - break; - case java.sql.Types.TIME: - java.sql.Time time = caller.getTime(idx); - if (caller.wasNull()) - writeNull(); - else - writeLong(time.getTime()); - break; - case java.sql.Types.TIMESTAMP: - java.sql.Timestamp ts = caller.getTimestamp(idx); - if (caller.wasNull()) - writeNull(); - else - writeLong(ts.getTime()); - break; - case java.sql.Types.CHAR: - case java.sql.Types.VARCHAR: - case java.sql.Types.LONGVARCHAR: - writeStringData(caller.getString(idx)); - break; - default: - System.out.println("Not a proper type"); - //Need to take care of BLOB, CLOB, Array, Ref here - } - } catch (SQLException ex) { - throw new java.io.IOException("Failed to writeValue: " + - ex.getMessage()); - } + try { + int type = caller.getMetaData().getColumnType(idx); + + switch (type) { + case java.sql.Types.BIT: + case java.sql.Types.BOOLEAN: + boolean b = caller.getBoolean(idx); + if (caller.wasNull()) + writeNull(); + else + writeBoolean(b); + break; + case java.sql.Types.TINYINT: + case java.sql.Types.SMALLINT: + short s = caller.getShort(idx); + if (caller.wasNull()) + writeNull(); + else + writeShort(s); + break; + case java.sql.Types.INTEGER: + int i = caller.getInt(idx); + if (caller.wasNull()) + writeNull(); + else + writeInteger(caller.getInt(idx)); + break; + case java.sql.Types.BIGINT: + long l = caller.getLong(idx); + if (caller.wasNull()) + writeNull(); + else + writeLong(l); + break; + case java.sql.Types.REAL: + case java.sql.Types.FLOAT: + float f = caller.getFloat(idx); + if (caller.wasNull()) + writeNull(); + else + writeFloat(f); + break; + case java.sql.Types.DOUBLE: + double d = caller.getDouble(idx); + if (caller.wasNull()) + writeNull(); + else + writeDouble(d); + break; + case java.sql.Types.NUMERIC: + case java.sql.Types.DECIMAL: + writeBigDecimal(caller.getBigDecimal(idx)); + break; + case java.sql.Types.BINARY: + case java.sql.Types.VARBINARY: + case java.sql.Types.LONGVARBINARY: + break; + case java.sql.Types.DATE: + java.sql.Date date = caller.getDate(idx); + if (caller.wasNull()) + writeNull(); + else + writeLong(date.getTime()); + break; + case java.sql.Types.TIME: + java.sql.Time time = caller.getTime(idx); + if (caller.wasNull()) + writeNull(); + else + writeLong(time.getTime()); + break; + case java.sql.Types.TIMESTAMP: + java.sql.Timestamp ts = caller.getTimestamp(idx); + if (caller.wasNull()) + writeNull(); + else + writeLong(ts.getTime()); + break; + case java.sql.Types.CHAR: + case java.sql.Types.VARCHAR: + case java.sql.Types.LONGVARCHAR: + writeStringData(caller.getString(idx)); + break; + default: + System.out.println(resBundle.handleGetObject("wsrxmlwriter.notproper").toString()); + //Need to take care of BLOB, CLOB, Array, Ref here + } + } catch (SQLException ex) { + throw new java.io.IOException(resBundle.handleGetObject("wrsxmlwriter.failedwrite").toString()+ ex.getMessage()); + } } /* * This begins a new tag with a indent * - */ + */ private void beginSection(String tag) throws java.io.IOException { // store the current tag setTag(tag); - + writeIndent(stack.size()); - + // write it out writer.write("<" + tag + ">\n"); } - + /* * This closes a tag started by beginTag with a indent * - */ + */ private void endSection(String tag) throws java.io.IOException { writeIndent(stack.size()); - + String beginTag = getTag(); if(beginTag.indexOf("webRowSet") != -1) { - beginTag ="webRowSet"; - } - - if (tag.equals(beginTag) ) { - // get the current tag and write it out - writer.write("\n"); - } else { - ; + beginTag ="webRowSet"; } - writer.flush(); - } - - private void endSection() throws java.io.IOException { - writeIndent(stack.size()); - - // get the current tag and write it out - String beginTag = getTag(); - writer.write("\n"); - - writer.flush(); - } - - private void beginTag(String tag) throws java.io.IOException { - // store the current tag - setTag(tag); - - writeIndent(stack.size()); - - // write tag out - writer.write("<" + tag + ">"); - } - - private void endTag(String tag) throws java.io.IOException { - String beginTag = getTag(); - if (tag.equals(beginTag)) { + + if (tag.equals(beginTag) ) { // get the current tag and write it out writer.write("\n"); } else { @@ -515,55 +489,86 @@ } writer.flush(); } - + + private void endSection() throws java.io.IOException { + writeIndent(stack.size()); + + // get the current tag and write it out + String beginTag = getTag(); + writer.write("\n"); + + writer.flush(); + } + + private void beginTag(String tag) throws java.io.IOException { + // store the current tag + setTag(tag); + + writeIndent(stack.size()); + + // write tag out + writer.write("<" + tag + ">"); + } + + private void endTag(String tag) throws java.io.IOException { + String beginTag = getTag(); + if (tag.equals(beginTag)) { + // get the current tag and write it out + writer.write("\n"); + } else { + ; + } + writer.flush(); + } + private void emptyTag(String tag) throws java.io.IOException { // write an emptyTag writer.write("<" + tag + "/>"); } - + private void setTag(String tag) { // add the tag to stack stack.push(tag); } - + private String getTag() { return (String)stack.pop(); } - + private void writeNull() throws java.io.IOException { - emptyTag("null"); + emptyTag("null"); } - - private void writeStringData(String s) throws java.io.IOException { + + private void writeStringData(String s) throws java.io.IOException { if (s == null) { - writeNull(); + writeNull(); } else if (s.equals("")) { - writeEmptyString(); + writeEmptyString(); } else { - - s = processSpecialCharacters(s); - - writer.write(s); + + s = processSpecialCharacters(s); + + writer.write(s); } } - private void writeString(String s) throws java.io.IOException { + private void writeString(String s) throws java.io.IOException { if (s != null) { - writer.write(s); + writer.write(s); } else { - writeNull(); - } + writeNull(); + } } private void writeShort(short s) throws java.io.IOException { - writer.write(Short.toString(s)); + writer.write(Short.toString(s)); } - + private void writeLong(long l) throws java.io.IOException { - writer.write(Long.toString(l)); + writer.write(Long.toString(l)); } - + private void writeInteger(int i) throws java.io.IOException { writer.write(Integer.toString(i)); } @@ -571,22 +576,22 @@ private void writeBoolean(boolean b) throws java.io.IOException { writer.write(new Boolean(b).toString()); } - + private void writeFloat(float f) throws java.io.IOException { - writer.write(Float.toString(f)); + writer.write(Float.toString(f)); } - + private void writeDouble(double d) throws java.io.IOException { - writer.write(Double.toString(d)); + writer.write(Double.toString(d)); } - + private void writeBigDecimal(java.math.BigDecimal bd) throws java.io.IOException { - if (bd != null) - writer.write(bd.toString()); - else - emptyTag("null"); + if (bd != null) + writer.write(bd.toString()); + else + emptyTag("null"); } - + private void writeIndent(int tabs) throws java.io.IOException { // indent... for (int i = 1; i < tabs; i++) { @@ -595,70 +600,67 @@ } private void propString(String tag, String s) throws java.io.IOException { - beginTag(tag); - writeString(s); - endTag(tag); + beginTag(tag); + writeString(s); + endTag(tag); } - + private void propInteger(String tag, int i) throws java.io.IOException { - beginTag(tag); - writeInteger(i); - endTag(tag); + beginTag(tag); + writeInteger(i); + endTag(tag); } - + private void propBoolean(String tag, boolean b) throws java.io.IOException { - beginTag(tag); - writeBoolean(b); - endTag(tag); + beginTag(tag); + writeBoolean(b); + endTag(tag); } - + private void writeEmptyString() throws java.io.IOException { - emptyTag("emptyString"); + emptyTag("emptyString"); } - /** + /** * Purely for code coverage purposes.. */ public boolean writeData(RowSetInternal caller) { - return false; + return false; } /** - * This function has been added for the processing of special characters - * lik <,>,'," and & in the data to be serialized. These have to be taken - * of specifically or else there will be parsing error while trying to read - * the contents of the XML file. - **/ + * This function has been added for the processing of special characters + * lik <,>,'," and & in the data to be serialized. These have to be taken + * of specifically or else there will be parsing error while trying to read + * the contents of the XML file. + **/ private String processSpecialCharacters(String s) { + + if(s == null) { + return null; + } + char []charStr = s.toCharArray(); + String specialStr = new String(); + + for(int i = 0; i < charStr.length; i++) { + if(charStr[i] == '&') { + specialStr = specialStr.concat("&"); + } else if(charStr[i] == '<') { + specialStr = specialStr.concat("<"); + } else if(charStr[i] == '>') { + specialStr = specialStr.concat(">"); + } else if(charStr[i] == '\'') { + specialStr = specialStr.concat("'"); + } else if(charStr[i] == '\"') { + specialStr = specialStr.concat("""); + } else { + specialStr = specialStr.concat(String.valueOf(charStr[i])); + } + } + + s = specialStr; + return s; + } - if(s == null) - { - return null; - } - char []charStr = s.toCharArray(); - String specialStr = new String(); - - for(int i = 0; i < charStr.length; i++) - { - if(charStr[i] == '&') - { - specialStr = specialStr.concat("&"); - } else if(charStr[i] == '<') { - specialStr = specialStr.concat("<"); - } else if(charStr[i] == '>') { - specialStr = specialStr.concat(">"); - } else if(charStr[i] == '\'') { - specialStr = specialStr.concat("'"); - } else if(charStr[i] == '\"') { - specialStr = specialStr.concat("""); - } else { - specialStr = specialStr.concat(String.valueOf(charStr[i])); - } - } - - s = specialStr; - return s; - } - } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java --- a/j2se/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Thu Jul 05 23:47:33 2007 +0000 @@ -35,6 +35,8 @@ import javax.sql.rowset.*; import com.sun.rowset.*; +import java.io.IOException; +import java.text.MessageFormat; /** * The document handler that receives parse events that an XML parser sends while it @@ -414,7 +416,9 @@ * data. */ private final static int DATA = 3; - + + private JdbcRowSetResourceBundle resBundle; + /** * Constructs a new XmlReaderContentHandler object that will * assist the SAX parser in reading a WebRowSet object in the @@ -446,6 +450,12 @@ tempStr = ""; tempUpdate = ""; tempCommand = ""; + + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } } /** @@ -652,8 +662,7 @@ typeMap.put(Key_map,Class.forName(Value_map)); }catch(ClassNotFoundException ex) { - throw new SAXException("Error setting Map: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmap").toString(), ex.getMessage())); } break; @@ -686,8 +695,7 @@ rs.setMetaData(md); state = INITIAL; } catch (SQLException ex) { - throw new SAXException("Error setting Metadata: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmetadata").toString(), ex.getMessage())); } } else { try { @@ -698,8 +706,8 @@ setMetaDataValue(metaDataValue); } } catch (SQLException ex) { - throw new SAXException("Error setting Metadata: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmetadata").toString(), ex.getMessage())); + } // metaDataValue needs to be reset to an empty string metaDataValue = new String(""); @@ -730,8 +738,7 @@ // columnValue now need to be reset to the empty string columnValue = new String(""); } catch (SQLException ex) { - throw new SAXException("Error inserting values: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsert").toString(), ex.getMessage())); } break; case RowTag: @@ -746,8 +753,7 @@ applyUpdates(); } catch (SQLException ex) { - throw new SAXException("Error constructing row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errconstr").toString(), ex.getMessage())); } break; case DelTag: @@ -758,8 +764,7 @@ rs.setOriginalRow(); applyUpdates(); } catch (SQLException ex) { - throw new SAXException("Error constructing deleted row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errdel").toString() , ex.getMessage())); } break; case InsTag: @@ -769,8 +774,7 @@ rs.next(); applyUpdates(); } catch (SQLException ex) { - throw new SAXException("Error constructing inserted row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsert").toString() , ex.getMessage())); } break; @@ -782,8 +786,7 @@ rs.setOriginalRow(); applyUpdates(); } catch (SQLException ex) { - throw new SAXException("Error constructing insdel row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsdel").toString() , ex.getMessage())); } break; @@ -800,8 +803,7 @@ updates.add(upd); } } catch(SQLException ex) { - throw new SAXException("Error constructing update row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errupdate").toString() , ex.getMessage())); } break; @@ -830,8 +832,7 @@ rs.updateRow(); } catch (SQLException ex) { - throw new SAXException("Error updating row: " + - ex.getMessage()); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errupdrow").toString() , ex.getMessage())); } updates.removeAllElements(); } @@ -905,7 +906,7 @@ ; } } catch (SQLException ex) { - throw new SAXException("characters: " + ex.getMessage()); + throw new SAXException(resBundle.handleGetObject("xmlrch.chars").toString() + ex.getMessage()); } } @@ -1036,7 +1037,7 @@ break; case ConcurrencyTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setConcurrency(getIntegerValue(s)); break; @@ -1048,25 +1049,25 @@ break; case EscapeProcessingTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setEscapeProcessing(getBooleanValue(s)); break; case FetchDirectionTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setFetchDirection(getIntegerValue(s)); break; case FetchSizeTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setFetchSize(getIntegerValue(s)); break; case IsolationLevelTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setTransactionIsolation(getIntegerValue(s)); break; @@ -1081,31 +1082,31 @@ break; case MaxFieldSizeTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setMaxFieldSize(getIntegerValue(s)); break; case MaxRowsTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setMaxRows(getIntegerValue(s)); break; case QueryTimeoutTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setQueryTimeout(getIntegerValue(s)); break; case ReadOnlyTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setReadOnly(getBooleanValue(s)); break; case RowsetTypeTag: if (nullValue) { - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); } else { //rs.setType(getIntegerValue(s)); String strType = getStringValue(s); @@ -1123,7 +1124,7 @@ break; case ShowDeletedTag: if (nullValue) - throw new SQLException("Bad value; non-nullable property"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString()); else rs.setShowDeleted(getBooleanValue(s)); break; @@ -1176,7 +1177,7 @@ idx = 0; if (nullValue) { - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); } else { md.setColumnCount(getIntegerValue(s)); } @@ -1188,43 +1189,43 @@ break; case AutoIncrementTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setAutoIncrement(idx, getBooleanValue(s)); break; case CaseSensitiveTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setCaseSensitive(idx, getBooleanValue(s)); break; case CurrencyTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setCurrency(idx, getBooleanValue(s)); break; case NullableTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setNullable(idx, getIntegerValue(s)); break; case SignedTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setSigned(idx, getBooleanValue(s)); break; case SearchableTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setSearchable(idx, getBooleanValue(s)); break; case ColumnDisplaySizeTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setColumnDisplaySize(idx, getIntegerValue(s)); break; @@ -1249,13 +1250,13 @@ break; case ColumnPrecisionTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setPrecision(idx, getIntegerValue(s)); break; case ColumnScaleTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setScale(idx, getIntegerValue(s)); break; @@ -1273,7 +1274,7 @@ break; case ColumnTypeTag: if (nullValue) - throw new SQLException("Bad value; non-nullable metadata"); + throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString()); else md.setColumnType(idx, getIntegerValue(s)); break; @@ -1409,10 +1410,7 @@ * @param err a warning generated by the SAX parser */ public void warning (SAXParseException err) throws SAXParseException { - System.out.println ("** Warning" - + ", line " + err.getLineNumber () - + ", uri " + err.getSystemId ()); - System.out.println(" " + err.getMessage ()); + System.out.println (MessageFormat.format(resBundle.handleGetObject("xmlrch.warning").toString(), new Object[] { err.getMessage(), err.getLineNumber(), err.getSystemId() })); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java --- a/j2se/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,6 +25,7 @@ package com.sun.rowset.providers; +import com.sun.rowset.JdbcRowSetResourceBundle; import javax.sql.*; import java.io.*; @@ -105,6 +106,11 @@ * The version number of this SyncProvider implementation */ private String versionNumber = "1.0"; + + /** + * ResourceBundle + */ + private JdbcRowSetResourceBundle resBundle; /** * Creates an RIOptimisticProvider object initialized with the @@ -118,6 +124,11 @@ providerID = this.getClass().getName(); reader = new CachedRowSetReader(); writer = new CachedRowSetWriter(); + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } } /** @@ -185,7 +196,7 @@ */ public void setDataSourceLock(int datasource_lock) throws SyncProviderException { if(datasource_lock != SyncProvider.DATASOURCE_NO_LOCK ) { - throw new SyncProviderException("Locking classsification is not supported"); + throw new SyncProviderException(resBundle.handleGetObject("riop.locking").toString()); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java --- a/j2se/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/rowset/providers/RIXMLProvider.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,11 +25,12 @@ package com.sun.rowset.providers; +import com.sun.rowset.JdbcRowSetResourceBundle; +import java.io.IOException; import java.sql.*; import javax.sql.*; import javax.sql.rowset.spi.*; -import javax.sql.rowset.*; /** * A reference implementation of a JDBC RowSet synchronization provider @@ -89,7 +90,9 @@ /** * The version number of this SyncProvider implementation. */ - private String versionNumber = "1.0"; + private String versionNumber = "1.0"; + + private JdbcRowSetResourceBundle resBundle; private XmlReader xmlReader; private XmlWriter xmlWriter; @@ -100,6 +103,11 @@ */ public RIXMLProvider() { providerID = this.getClass().getName(); + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } } /** @@ -199,7 +207,7 @@ * function with non-locking XML data sources. */ public void setDataSourceLock(int lock) throws SyncProviderException { - throw new UnsupportedOperationException("Unsupported with RIXMLProvider"); + throw new UnsupportedOperationException(resBundle.handleGetObject("rixml.unsupp").toString()); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 07/30/03 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Look In: FileChooser.saveInLabelText=Save In: FileChooser.fileNameLabelText=File Name: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Files of Type: FileChooser.upFolderToolTipText=Up One Level FileChooser.upFolderAccessibleName=Up diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_de.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.13 08/12/05 +# 1.14 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Suchen in: FileChooser.saveInLabelText=Speichern in: FileChooser.fileNameLabelText=Dateiname: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Dateityp: FileChooser.upFolderToolTipText=Eine Ebene h\u00f6her FileChooser.upFolderAccessibleName=H\u00f6her diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_es.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Buscar en: FileChooser.saveInLabelText=Guardar en: FileChooser.fileNameLabelText=Nombre de archivo: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Archivos de tipo: FileChooser.upFolderToolTipText=Subir un nivel FileChooser.upFolderAccessibleName=Arriba diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_fr.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Rechercher dans : FileChooser.saveInLabelText=Enregistrer dans : FileChooser.fileNameLabelText=Nom de fichier : +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Fichiers du type : FileChooser.upFolderToolTipText=Remonte d'un niveau. FileChooser.upFolderAccessibleName=Vers le haut diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_it.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Cerca in: FileChooser.saveInLabelText=Salva in: FileChooser.fileNameLabelText=Nome file: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Tipo file: FileChooser.upFolderToolTipText=Cartella superiore FileChooser.upFolderAccessibleName=Superiore diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ja.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u53c2\u7167: FileChooser.saveInLabelText=\u4fdd\u5b58: FileChooser.fileNameLabelText=\u30d5\u30a1\u30a4\u30eb\u540d: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7: FileChooser.upFolderToolTipText=1 \u30ec\u30d9\u30eb\u4e0a\u3078 FileChooser.upFolderAccessibleName=\u4e0a\u3078 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_ko.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\uac80\uc0c9 \uc704\uce58: FileChooser.saveInLabelText=\uc800\uc7a5 \uc704\uce58 FileChooser.fileNameLabelText=\ud30c\uc77c \uc774\ub984: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\ud30c\uc77c \uc885\ub958: FileChooser.upFolderToolTipText=\ud55c \ub2e8\uacc4 \uc704\ub85c FileChooser.upFolderAccessibleName=\uc704 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.12 08/12/05 +# 1.13 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=S\u00f6k i: FileChooser.saveInLabelText=Spara i: FileChooser.fileNameLabelText=Filnamn: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Filformat: FileChooser.upFolderToolTipText=Upp en niv\u00e5 FileChooser.upFolderAccessibleName=Upp diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_CN.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.18 08/12/05 +# 1.19 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\uff1a FileChooser.saveInLabelText=\u4fdd\u5b58\uff1a FileChooser.fileNameLabelText=\u6587\u4ef6\u540d\uff1a +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6587\u4ef6\u7c7b\u578b\uff1a FileChooser.upFolderToolTipText=\u5411\u4e0a\u4e00\u5c42 FileChooser.upFolderAccessibleName=\u5411\u4e0a diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_zh_TW.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.11 08/12/05 +# 1.12 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\ufe55 FileChooser.saveInLabelText=\u5132\u5b58\u65bc\uff1a FileChooser.fileNameLabelText=\u6a94\u6848\u540d\u7a31\ufe55 +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6a94\u6848\u985e\u578b\ufe55 FileChooser.upFolderToolTipText=\u5f80\u4e0a\u4e00\u5c64 FileChooser.upFolderAccessibleName=\u5f80\u4e0a diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.1 12/05/03 +# 1.2 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=Look In: FileChooser.saveInLabelText=Save In: FileChooser.fileNameLabelText=File Name: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Files of Type: FileChooser.upFolderToolTipText=Up One Level FileChooser.upFolderAccessibleName=Up diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_de.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_de.properties 1.1 03/12/05 +# @(#)synth_de.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=Suchen in: FileChooser.saveInLabelText=Speichern in: FileChooser.fileNameLabelText=Dateiname: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Dateityp: FileChooser.upFolderToolTipText=Eine Ebene h\u00f6her FileChooser.upFolderAccessibleName=H\u00f6her diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_es.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_es.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_es.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_es.properties 1.1 03/12/05 +# @(#)synth_es.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=Buscar en: FileChooser.saveInLabelText=Guardar en: FileChooser.fileNameLabelText=Nombre de archivo: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Archivos de tipo: FileChooser.upFolderToolTipText=Subir un nivel FileChooser.upFolderAccessibleName=Arriba diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_fr.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_fr.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_fr.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_fr.properties 1.1 03/12/05 +# @(#)synth_fr.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=Rechercher dans : FileChooser.saveInLabelText=Enregistrer dans : FileChooser.fileNameLabelText=Nom de fichier : +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Fichiers du type : FileChooser.upFolderToolTipText=Remonte d'un niveau. FileChooser.upFolderAccessibleName=Vers le haut diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_it.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_it.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_it.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_it.properties 1.1 03/12/05 +# @(#)synth_it.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=Cerca in: FileChooser.saveInLabelText=Salva in: FileChooser.fileNameLabelText=Nome file: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Tipo file: FileChooser.upFolderToolTipText=Cartella superiore FileChooser.upFolderAccessibleName=Superiore diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ja.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ja.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ja.properties Thu Jul 05 23:47:33 2007 +0000 @@ -13,7 +13,7 @@ # Refer to the note in basic.properties for a description as to what # the mnemonics correspond to and how to calculate them. # -# 1.1 12/05/03 +# 1.2 04/16/07 # @author Steve Wilson @@ -22,6 +22,7 @@ FileChooser.lookInLabelText=\u53c2\u7167: FileChooser.saveInLabelText=\u4fdd\u5b58: FileChooser.fileNameLabelText=\u30d5\u30a1\u30a4\u30eb\u540d: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u30d5\u30a1\u30a4\u30eb\u30bf\u30a4\u30d7: FileChooser.upFolderToolTipText=1 \u30ec\u30d9\u30eb\u4e0a\u3078 FileChooser.upFolderAccessibleName=\u4e0a\u3078 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ko.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ko.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_ko.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_ko.properties 1.1 03/12/05 +# @(#)synth_ko.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=\uac80\uc0c9 \uc704\uce58: FileChooser.saveInLabelText=\uc800\uc7a5 \uc704\uce58 FileChooser.fileNameLabelText=\ud30c\uc77c \uc774\ub984: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\ud30c\uc77c \uc885\ub958: FileChooser.upFolderToolTipText=\ud55c \ub2e8\uacc4 \uc704\ub85c FileChooser.upFolderAccessibleName=\uc704 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_sv.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_sv.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_sv.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_sv.properties 1.1 03/12/05 +# @(#)synth_sv.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=S\u00f6k i: FileChooser.saveInLabelText=Spara i: FileChooser.fileNameLabelText=Filnamn: +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=Filformat: FileChooser.upFolderToolTipText=Upp en niv\u00e5 FileChooser.upFolderAccessibleName=Upp diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_CN.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_CN.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_CN.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_zh_CN.properties 1.1 03/12/05 +# @(#)synth_zh_CN.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\uff1a FileChooser.saveInLabelText=\u4fdd\u5b58\uff1a FileChooser.fileNameLabelText=\u6587\u4ef6\u540d\uff1a +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6587\u4ef6\u7c7b\u578b\uff1a FileChooser.upFolderToolTipText=\u5411\u4e0a\u4e00\u5c42 FileChooser.upFolderAccessibleName=\u5411\u4e0a diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_TW.properties --- a/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_TW.properties Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/swing/internal/plaf/synth/resources/synth_zh_TW.properties Thu Jul 05 23:47:33 2007 +0000 @@ -10,7 +10,7 @@ # This may change in future versions of Swing as we improve localization # support. # -# @(#)synth_zh_TW.properties 1.1 03/12/05 +# @(#)synth_zh_TW.properties 1.2 07/04/16 # @author Steve Wilson @@ -19,6 +19,7 @@ FileChooser.lookInLabelText=\u67e5\u770b\ufe55 FileChooser.saveInLabelText=\u5132\u5b58\u65bc\uff1a FileChooser.fileNameLabelText=\u6a94\u6848\u540d\u7a31\ufe55 +FileChooser.folderNameLabelText=Folder name: FileChooser.filesOfTypeLabelText=\u6a94\u6848\u985e\u578b\ufe55 FileChooser.upFolderToolTipText=\u5f80\u4e0a\u4e00\u5c64 FileChooser.upFolderAccessibleName=\u5f80\u4e0a diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/corba/se/idl/first.set --- a/j2se/src/share/classes/com/sun/tools/corba/se/idl/first.set Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/corba/se/idl/first.set Thu Jul 05 23:47:33 2007 +0000 @@ -6,7 +6,7 @@ * THIS PRODUCT CONTAINS RESTRICTED MATERIALS OF IBM * 5639-D57, (C) COPYRIGHT International Business Machines Corp., 1997, 1998 * - * @(#) 1.3 @(#)first.set 1.3 04/30/07 19:05:31 [06/21/07 00:46:12] + * @(#) 1.3 @(#)first.set 1.3 04/30/07 19:05:31 [07/05/07 00:46:51] */ CORBA IDL diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/corba/se/idl/follow.set --- a/j2se/src/share/classes/com/sun/tools/corba/se/idl/follow.set Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/corba/se/idl/follow.set Thu Jul 05 23:47:33 2007 +0000 @@ -6,7 +6,7 @@ * THIS PRODUCT CONTAINS RESTRICTED MATERIALS OF IBM * 5639-D57, (C) COPYRIGHT International Business Machines Corp., 1997, 1998 * - * @(#) 1.3 @(#)follow.set 1.3 04/30/07 19:05:31 [06/21/07 00:46:12] + * @(#) 1.3 @(#)follow.set 1.3 04/30/07 19:05:31 [07/05/07 00:46:51] */ CORBA IDL diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java --- a/j2se/src/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/debug/tty/MessageOutput.java Thu Jul 05 23:47:33 2007 +0000 @@ -33,7 +33,7 @@ * the only class that should be printing directly or otherwise * accessing System.[out,err]. * - * @version @(#) MessageOutput.java 1.14 07/05/05 00:46:15 + * @version @(#) MessageOutput.java 1.14 07/05/05 00:46:58 * @bug 4348376 * @author Tim Bell */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/doc/index.html --- a/j2se/src/share/classes/com/sun/tools/example/doc/index.html Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/doc/index.html Thu Jul 05 23:47:33 2007 +0000 @@ -79,7 +79,7 @@

java-debugger@java.sun.com

-@(#) index.html 1.2 01/06/04 00:46:15 +@(#) index.html 1.2 01/06/04 00:46:58

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/doc/javadt.html --- a/j2se/src/share/classes/com/sun/tools/example/doc/javadt.html Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/doc/javadt.html Thu Jul 05 23:47:33 2007 +0000 @@ -169,7 +169,7 @@
java-debugger@java.sun.com

-@(#) javadt.html 1.3 07/04/04 00:46:15 +@(#) javadt.html 1.3 07/04/04 00:46:58

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/doc/jdb.html --- a/j2se/src/share/classes/com/sun/tools/example/doc/jdb.html Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/doc/jdb.html Thu Jul 05 23:47:33 2007 +0000 @@ -99,7 +99,7 @@
java-debugger@java.sun.com

-@(#) jdb.html 1.3 07/04/04 00:46:15 +@(#) jdb.html 1.3 07/04/04 00:46:58

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/doc/trace.html --- a/j2se/src/share/classes/com/sun/tools/example/doc/trace.html Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/doc/trace.html Thu Jul 05 23:47:33 2007 +0000 @@ -66,7 +66,7 @@
java-debugger@java.sun.com

-@(#) trace.html 1.4 07/04/04 00:46:15 +@(#) trace.html 1.4 07/04/04 00:46:58

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/trace/EventThread.java --- a/j2se/src/share/classes/com/sun/tools/example/trace/EventThread.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/trace/EventThread.java Thu Jul 05 23:47:33 2007 +0000 @@ -35,7 +35,7 @@ /** * This class processes incoming JDI events and displays them * - * @version @(#) EventThread.java 1.12 07/05/05 00:46:15 + * @version @(#) EventThread.java 1.12 07/05/05 00:46:58 * @author Robert Field */ public class EventThread extends Thread { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/trace/StreamRedirectThread.java --- a/j2se/src/share/classes/com/sun/tools/example/trace/StreamRedirectThread.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/trace/StreamRedirectThread.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,7 +31,7 @@ * StreamRedirectThread is a thread which copies it's input to * it's output and terminates when it completes. * - * @version @(#) StreamRedirectThread.java 1.12 07/05/05 00:46:15 + * @version @(#) StreamRedirectThread.java 1.12 07/05/05 00:46:58 * @author Robert Field */ class StreamRedirectThread extends Thread { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/com/sun/tools/example/trace/Trace.java --- a/j2se/src/share/classes/com/sun/tools/example/trace/Trace.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/com/sun/tools/example/trace/Trace.java Thu Jul 05 23:47:33 2007 +0000 @@ -42,7 +42,7 @@ * See "java Trace -help". * It is a simple example of the use of the Java Debug Interface. * - * @version @(#) Trace.java 1.12 07/05/05 00:46:15 + * @version @(#) Trace.java 1.12 07/05/05 00:46:58 * @author Robert Field */ public class Trace { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/AWTEvent.java --- a/j2se/src/share/classes/java/awt/AWTEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/AWTEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.awt.peer.ComponentPeer; import java.awt.peer.LightweightPeer; import java.lang.reflect.Field; +import java.util.logging.Logger; +import java.util.logging.Level; /** * The root event class for all AWT events. @@ -70,10 +72,11 @@ * * @author Carl Quinn * @author Amy Fowler - * @version 1.66 05/05/07 + * @version 1.68 06/05/07 * @since 1.1 */ public abstract class AWTEvent extends EventObject { + private static final Logger log = Logger.getLogger("java.awt.AWTEvent"); private byte bdata[]; /** @@ -243,7 +246,13 @@ field.setAccessible(true); return field; } catch (SecurityException e) { + if (log.isLoggable(Level.FINE)) { + log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got SecurityException ", e); + } } catch (NoSuchFieldException e) { + if (log.isLoggable(Level.FINE)) { + log.log(Level.FINE, "AWTEvent.get_InputEvent_CanAccessSystemClipboard() got NoSuchFieldException ", e); + } } return null; } @@ -534,6 +543,9 @@ boolean b = field.getBoolean(this); field.setBoolean(that, b); } catch(IllegalAccessException e) { + if (log.isLoggable(Level.FINE)) { + log.log(Level.FINE, "AWTEvent.copyPrivateDataInto() got IllegalAccessException ", e); + } } } } @@ -546,6 +558,9 @@ try { field.setBoolean(this, false); } catch(IllegalAccessException e) { + if (log.isLoggable(Level.FINE)) { + log.log(Level.FINE, "AWTEvent.dispatched() got IllegalAccessException ", e); + } } } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Canvas.java --- a/j2se/src/share/classes/java/awt/Canvas.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Canvas.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt; import java.awt.image.BufferStrategy; -import java.awt.peer.CanvasPeer; import javax.accessibility.*; /** @@ -38,7 +37,7 @@ * component. The paint method must be overridden * in order to perform custom graphics on the canvas. * - * @version 1.46 05/05/07 + * @version 1.48 06/05/07 * @author Sami Shaio * @since JDK1.0 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Component.java --- a/j2se/src/share/classes/java/awt/Component.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Component.java Thu Jul 05 23:47:33 2007 +0000 @@ -161,7 +161,7 @@ * Focus Specification * for more information. * - * @version 1.438, 05/05/07 + * @version 1.441, 06/19/07 * @author Arthur van Hoff * @author Sami Shaio */ @@ -908,26 +908,24 @@ */ public GraphicsConfiguration getGraphicsConfiguration() { synchronized(getTreeLock()) { - if (graphicsConfig != null) { - return graphicsConfig; - } else if (getParent() != null) { - return getParent().getGraphicsConfiguration(); - } else { - return null; - } + GraphicsConfiguration gc = graphicsConfig; + Component parent = getParent(); + while ((gc == null) && (parent != null)) { + gc = parent.getGraphicsConfiguration(); + parent = parent.getParent(); + } + return gc; } } final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { - GraphicsConfiguration graphicsConfig = this.graphicsConfig; - Container parent = this.parent; - if (graphicsConfig != null) { - return graphicsConfig; - } else if (parent != null) { - return parent.getGraphicsConfiguration_NoClientCode(); - } else { - return null; - } + GraphicsConfiguration gc = this.graphicsConfig; + Component par = this.parent; + while ((gc == null) && (par != null)) { + gc = par.getGraphicsConfiguration_NoClientCode(); + par = par.parent; + } + return gc; } /** @@ -1063,6 +1061,9 @@ * @since JDK1.0 */ public boolean isVisible() { + return isVisible_NoClientCode(); + } + final boolean isVisible_NoClientCode() { return visible; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Dialog.java --- a/j2se/src/share/classes/java/awt/Dialog.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Dialog.java Thu Jul 05 23:47:33 2007 +0000 @@ -89,7 +89,7 @@ * @see WindowEvent * @see Window#addWindowListener * - * @version 1.136, 05/08/07 + * @version 1.137, 06/05/07 * @author Sami Shaio * @author Arthur van Hoff * @since JDK1.0 @@ -781,6 +781,9 @@ * @see java.awt.Dialog#setModalityType */ public boolean isModal() { + return isModal_NoClientCode(); + } + final boolean isModal_NoClientCode() { return modalityType != ModalityType.MODELESS; } @@ -1404,7 +1407,7 @@ if (d.shouldBlock(this)) { Window w = d; while ((w != null) && (w != this)) { - w = w.getOwner(); + w = (Window)(w.getOwner_NoClientCode()); } if ((w == this) || !shouldBlock(d) || (modalityType.compareTo(d.getModalityType()) < 0)) { blockers.add(d); @@ -1432,7 +1435,7 @@ int k = 0; while (k < blockersHierarchies.size()) { Window w = blockersHierarchies.get(k); - Window[] ownedWindows = w.getOwnedWindows(); + Window[] ownedWindows = w.getOwnedWindows_NoClientCode(); for (Window win : ownedWindows) { blockersHierarchies.add(win); } @@ -1444,7 +1447,7 @@ IdentityArrayList unblockedWindows = Window.getAllUnblockedWindows(); for (Window w : unblockedWindows) { if (shouldBlock(w) && !blockersHierarchies.contains(w)) { - if ((w instanceof Dialog) && ((Dialog)w).isModal()) { + if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { Dialog wd = (Dialog)w; if (wd.shouldBlock(this) && (modalDialogs.indexOf(wd) > modalDialogs.indexOf(this))) { continue; @@ -1480,7 +1483,7 @@ // by another dialogs for (int i = 0; i < blockedWindowsCount; i++) { Window w = save.get(i); - if ((w instanceof Dialog) && ((Dialog)w).isModal()) { + if ((w instanceof Dialog) && ((Dialog)w).isModal_NoClientCode()) { Dialog d = (Dialog)w; d.modalShow(); } else { @@ -1499,11 +1502,11 @@ * This method should be called on the getTreeLock() lock. */ boolean shouldBlock(Window w) { - if (!isVisible() || - (!w.isVisible() && !w.isInShow) || + if (!isVisible_NoClientCode() || + (!w.isVisible_NoClientCode() && !w.isInShow) || isInHide || (w == this) || - !isModal()) + !isModal_NoClientCode()) { return false; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/EventQueue.java --- a/j2se/src/share/classes/java/awt/EventQueue.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/EventQueue.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ import java.awt.event.WindowEvent; import java.awt.ActiveEvent; import java.awt.peer.ComponentPeer; -import java.awt.peer.LightweightPeer; import java.awt.TrayIcon; import java.util.EmptyStackException; import java.lang.ref.WeakReference; @@ -45,7 +44,6 @@ import java.security.PrivilegedAction; import sun.awt.PeerEvent; import sun.awt.SunToolkit; -import sun.awt.DebugHelper; import sun.awt.AWTAutoShutdown; import sun.awt.AppContext; @@ -91,11 +89,10 @@ * @author Fred Ecks * @author David Mendenhall * - * @version 1.112, 05/05/07 + * @version 1.114, 06/05/07 * @since 1.1 */ public class EventQueue { - private static final DebugHelper dbg = DebugHelper.create(EventQueue.class); // From Thread.java private static int threadInitNumber; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/GradientPaintContext.java --- a/j2se/src/share/classes/java/awt/GradientPaintContext.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/GradientPaintContext.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,7 +26,6 @@ package java.awt; import java.awt.image.Raster; -import java.awt.image.WritableRaster; import sun.awt.image.IntegerComponentRaster; import java.awt.image.ColorModel; import java.awt.image.DirectColorModel; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/GraphicsConfigTemplate.java --- a/j2se/src/share/classes/java/awt/GraphicsConfigTemplate.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/GraphicsConfigTemplate.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt; -import java.awt.Component; import java.io.*; /** @@ -40,7 +39,7 @@ * @see GraphicsDevice * @see GraphicsConfiguration * - * @version 1.24, 05/05/07 + * @version 1.26, 06/05/07 * @since 1.2 */ public abstract class GraphicsConfigTemplate implements Serializable { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/GraphicsEnvironment.java --- a/j2se/src/share/classes/java/awt/GraphicsEnvironment.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/GraphicsEnvironment.java Thu Jul 05 23:47:33 2007 +0000 @@ -27,10 +27,7 @@ package java.awt; import java.awt.image.BufferedImage; -import java.util.Hashtable; import java.util.Locale; -import java.util.Map; -import java.io.InputStream; import sun.java2d.HeadlessGraphicsEnvironment; import sun.java2d.SunGraphicsEnvironment; @@ -48,7 +45,7 @@ * GraphicsDevice can be used. * @see GraphicsDevice * @see GraphicsConfiguration - * @version 1.73, 05/05/07 + * @version 1.74, 06/04/07 */ public abstract class GraphicsEnvironment { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/MediaTracker.java --- a/j2se/src/share/classes/java/awt/MediaTracker.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/MediaTracker.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.Component; import java.awt.Image; -import java.awt.Graphics; import java.awt.image.ImageObserver; /** @@ -163,7 +162,7 @@ * } *
* - * @version 1.50, 05/05/07 + * @version 1.52, 06/05/07 * @author Jim Graham * @since JDK1.0 */ @@ -905,7 +904,7 @@ return image; } - int getStatus(boolean doLoad, boolean doVerify) { + synchronized int getStatus(boolean doLoad, boolean doVerify) { if (doVerify) { int flags = tracker.target.checkImage(image, width, height, null); int s = parseflags(flags); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Paint.java --- a/j2se/src/share/classes/java/awt/Paint.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Paint.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.image.ColorModel; import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** @@ -47,7 +46,7 @@ * @see GradientPaint * @see TexturePaint * @see Graphics2D#setPaint - * @version 1.34, 05/05/07 + * @version 1.36, 06/05/07 */ public interface Paint extends Transparency { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/PaintContext.java --- a/j2se/src/share/classes/java/awt/PaintContext.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/PaintContext.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt; -import java.awt.color.ColorSpace; import java.awt.image.Raster; import java.awt.image.ColorModel; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Panel.java --- a/j2se/src/share/classes/java/awt/Panel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Panel.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package java.awt; -import java.awt.peer.PanelPeer; import javax.accessibility.*; /** @@ -35,7 +34,7 @@ * The default layout manager for a panel is the * FlowLayout layout manager. * - * @version 1.44, 05/05/07 + * @version 1.46, 06/05/07 * @author Sami Shaio * @see java.awt.FlowLayout * @since JDK1.0 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/SentEvent.java --- a/j2se/src/share/classes/java/awt/SentEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/SentEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package java.awt; -import java.awt.AWTEvent; -import java.awt.ActiveEvent; import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -36,7 +34,7 @@ * event even if it is currently blocked waiting for a SequencedEvent or * another SentEvent to be handled. * - * @version 1.14, 05/05/07 + * @version 1.16, 06/05/07 * @author David Mendenhall */ class SentEvent extends AWTEvent implements ActiveEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/SequencedEvent.java --- a/j2se/src/share/classes/java/awt/SequencedEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/SequencedEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package java.awt; -import java.awt.AWTEvent; -import java.awt.ActiveEvent; import java.util.LinkedList; import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -40,7 +38,7 @@ * before the wrapping SequencedEvent was able to be dispatched. In this case, * the nested event is never dispatched. * - * @version 1.18, 05/05/07 + * @version 1.20, 06/05/07 * @author David Mendenhall */ class SequencedEvent extends AWTEvent implements ActiveEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/SystemColor.java --- a/j2se/src/share/classes/java/awt/SystemColor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/SystemColor.java Thu Jul 05 23:47:33 2007 +0000 @@ -24,9 +24,6 @@ */ package java.awt; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.image.ColorModel; import java.io.ObjectStreamException; /** @@ -47,7 +44,7 @@ * * @see Toolkit#getDesktopProperty * - * @version 1.35, 05/28/07 + * @version 1.36, 06/06/07 * @author Carl Quinn * @author Amy Fowler */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/TexturePaint.java --- a/j2se/src/share/classes/java/awt/TexturePaint.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/TexturePaint.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.geom.Rectangle2D; import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; @@ -46,7 +45,7 @@ * replicated Rectangle2D. * @see Paint * @see Graphics2D#setPaint - * @version 1.46, 05/05/07 + * @version 1.48, 06/05/07 */ public class TexturePaint implements Paint { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/Window.java --- a/j2se/src/share/classes/java/awt/Window.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/Window.java Thu Jul 05 23:47:33 2007 +0000 @@ -134,7 +134,7 @@ * Windows are capable of generating the following WindowEvents: * WindowOpened, WindowClosed, WindowGainedFocus, WindowLostFocus. * - * @version @(#)Window.java 1.265 07/05/08 + * @version @(#)Window.java 1.266 07/06/05 * @author Sami Shaio * @author Arthur van Hoff * @see WindowEvent @@ -1299,6 +1299,9 @@ * @since 1.2 */ public Window getOwner() { + return getOwner_NoClientCode(); + } + final Window getOwner_NoClientCode() { return (Window)parent; } @@ -1308,6 +1311,9 @@ * @since 1.2 */ public Window[] getOwnedWindows() { + return getOwnedWindows_NoClientCode(); + } + final Window[] getOwnedWindows_NoClientCode() { Window realCopy[]; synchronized(ownedWindowList) { @@ -1554,7 +1560,7 @@ { return true; } - Window owner = getOwner(); + Window owner = getOwner_NoClientCode(); return (owner != null) && owner.isModalExcluded(exclusionType); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/DnDEventMulticaster.java --- a/j2se/src/share/classes/java/awt/dnd/DnDEventMulticaster.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/DnDEventMulticaster.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package java.awt.dnd; import java.awt.AWTEventMulticaster; -import java.lang.reflect.Array; -import java.util.EventListener; -import java.io.Serializable; import java.io.ObjectOutputStream; import java.io.IOException; import java.util.EventListener; @@ -38,7 +35,7 @@ * thread-safe multi-cast event dispatching for the drag-and-drop events defined * in the java.awt.dnd package. * - * @version 1.12, 05/05/07 + * @version 1.14, 06/05/07 * @since 1.4 * @see AWTEventMulticaster */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/DragSourceContext.java --- a/j2se/src/share/classes/java/awt/dnd/DragSourceContext.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/DragSourceContext.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,7 +84,7 @@ * @see DragSourceListener * @see DragSourceMotionListener * @see DnDConstants - * @version 1.60, 05/05/07 + * @version 1.62, 06/05/07 * @since 1.2 */ @@ -486,9 +486,8 @@ Cursor c = null; + targetAct = DnDConstants.ACTION_NONE; switch (status) { - default: - targetAct = DnDConstants.ACTION_NONE; case ENTER: case OVER: case CHANGED: diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/DropTarget.java --- a/j2se/src/share/classes/java/awt/dnd/DropTarget.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/DropTarget.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,6 @@ import java.io.ObjectOutputStream; import java.io.Serializable; -import java.awt.AWTEvent; import java.awt.Component; import java.awt.Dimension; import java.awt.GraphicsEnvironment; @@ -62,7 +61,7 @@ * The default FlavorMap hereafter designates the * FlavorMap returned by SystemFlavorMap.getDefaultFlavorMap(). * - * @version 1.57, 05/05/07 + * @version 1.59, 06/05/07 * @since 1.2 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/DropTargetEvent.java --- a/j2se/src/share/classes/java/awt/dnd/DropTargetEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/DropTargetEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,6 @@ package java.awt.dnd; import java.util.EventObject; - -import java.awt.Component; -import java.awt.Point; - -import java.awt.datatransfer.DataFlavor; - -import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetContext; /** @@ -43,7 +36,7 @@ * Drop operations, in particular the current * DropTargetContext. * - * @version 1.25, 05/05/07 + * @version 1.27, 06/05/07 * @since 1.2 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/DropTargetListener.java --- a/j2se/src/share/classes/java/awt/dnd/DropTargetListener.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/DropTargetListener.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.util.EventListener; -import java.awt.dnd.DropTargetContext; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; @@ -64,7 +63,7 @@ * respective listener's method and all the necessary data should be retrieved * from the returned Transferable before that method returns. * - * @version 1.29, 05/05/07 + * @version 1.31, 06/05/07 * @since 1.2 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/peer/DragSourceContextPeer.java --- a/j2se/src/share/classes/java/awt/dnd/peer/DragSourceContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/peer/DragSourceContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,10 @@ package java.awt.dnd.peer; -import java.awt.event.InputEvent; -import java.awt.Component; import java.awt.Cursor; import java.awt.Image; import java.awt.Point; -import java.awt.Rectangle; - -import java.awt.datatransfer.Transferable; - -import java.awt.dnd.DragSource; -import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragSourceContext; -import java.awt.dnd.DragSourceListener; import java.awt.dnd.InvalidDnDOperationException; @@ -48,7 +39,7 @@ * the same *

* - * @version 1.22, 05/05/07 + * @version 1.24, 06/05/07 * @since 1.2 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/dnd/peer/DropTargetContextPeer.java --- a/j2se/src/share/classes/java/awt/dnd/peer/DropTargetContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/dnd/peer/DropTargetContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,26 +25,18 @@ package java.awt.dnd.peer; -import java.awt.Insets; - import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; - import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetContext; import java.awt.dnd.InvalidDnDOperationException; -import java.io.InputStream; -import java.io.IOException; - /** *

* This interface is exposed by the underlying window system platform to * enable control of platform DnD operations *

* - * @version 1.20, 05/05/07 + * @version 1.22, 06/05/07 * @since 1.2 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/AWTEventListenerProxy.java --- a/j2se/src/share/classes/java/awt/event/AWTEventListenerProxy.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/AWTEventListenerProxy.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.util.EventListenerProxy; import java.awt.AWTEvent; -import java.awt.event.AWTEventListener; /** * A class which extends the EventListenerProxy, specifically diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/AdjustmentEvent.java --- a/j2se/src/share/classes/java/awt/event/AdjustmentEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/AdjustmentEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.Adjustable; import java.awt.AWTEvent; -import java.awt.Event; /** * The adjustment event emitted by Adjustable objects. @@ -35,7 +34,7 @@ * @see AdjustmentListener * * @author Amy Fowler - * @version 1.35 05/05/07 + * @version 1.37 06/05/07 * @since 1.1 */ public class AdjustmentEvent extends AWTEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/ComponentEvent.java --- a/j2se/src/share/classes/java/awt/event/ComponentEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/ComponentEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.awt.event; import java.awt.AWTEvent; -import java.awt.Event; import java.awt.Component; import java.awt.Rectangle; @@ -59,7 +58,7 @@ * @see Tutorial: Writing a Component Listener * * @author Carl Quinn - * @version 1.35 05/05/07 + * @version 1.37 06/05/07 * @since 1.1 */ public class ComponentEvent extends AWTEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/ContainerEvent.java --- a/j2se/src/share/classes/java/awt/event/ContainerEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/ContainerEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt.event; -import java.awt.AWTEvent; import java.awt.Container; import java.awt.Component; @@ -53,7 +52,7 @@ * * @author Tim Prinzing * @author Amy Fowler - * @version 1.26 05/05/07 + * @version 1.28 06/05/07 * @since 1.1 */ public class ContainerEvent extends ComponentEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/FocusEvent.java --- a/j2se/src/share/classes/java/awt/event/FocusEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/FocusEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ package java.awt.event; import java.awt.Component; -import java.awt.Event; - import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -59,7 +57,7 @@ * * @author Carl Quinn * @author Amy Fowler - * @version 1.39 05/05/07 + * @version 1.41 06/05/07 * @since 1.1 */ public class FocusEvent extends ComponentEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/InputEvent.java --- a/j2se/src/share/classes/java/awt/event/InputEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/InputEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.awt.Component; import java.awt.GraphicsEnvironment; import java.awt.Toolkit; +import java.util.logging.Logger; +import java.util.logging.Level; /** * The root event class for all component-level input events. @@ -42,7 +44,7 @@ * activated. * * @author Carl Quinn - * @version 1.44 05/05/07 + * @version 1.46 06/05/07 * * @see KeyEvent * @see KeyAdapter @@ -53,6 +55,7 @@ * @since 1.1 */ public abstract class InputEvent extends ComponentEvent { + private static final Logger log = Logger.getLogger("java.awt.event.InputEvent"); /** * The Shift key modifier constant. @@ -235,6 +238,9 @@ sm.checkSystemClipboardAccess(); b = true; } catch (SecurityException se) { + if (log.isLoggable(Level.FINE)) { + log.log(Level.FINE, "InputEvent.canAccessSystemClipboard() got SecurityException ", se); + } } } else { b = true; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/InputMethodEvent.java --- a/j2se/src/share/classes/java/awt/event/InputMethodEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/InputMethodEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.awt.font.TextHitInfo; import java.io.IOException; import java.io.ObjectInputStream; -import java.lang.Integer; import java.text.AttributedCharacterIterator; import java.text.CharacterIterator; @@ -54,7 +53,7 @@ * always precedes composed text. * * @author JavaSoft Asia/Pacific - * @version 1.30 05/05/07 + * @version 1.32 06/05/07 * @since 1.2 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/ItemEvent.java --- a/j2se/src/share/classes/java/awt/event/ItemEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/ItemEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ package java.awt.event; -import java.awt.Component; import java.awt.AWTEvent; -import java.awt.Event; import java.awt.ItemSelectable; /** @@ -44,7 +42,7 @@ * clicks, and can instead process a "meaningful" (semantic) event like * "item selected" or "item deselected". * - * @version 1.36 05/05/07 + * @version 1.38 06/05/07 * @author Carl Quinn * * @see java.awt.ItemSelectable diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/MouseEvent.java --- a/j2se/src/share/classes/java/awt/event/MouseEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/MouseEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.awt.event; import java.awt.Component; -import java.awt.Event; import java.awt.GraphicsEnvironment; import java.awt.Point; import java.awt.Toolkit; @@ -162,7 +161,7 @@ * * * @author Carl Quinn - * 1.63, 05/05/07 + * 1.65, 06/05/07 * * @see MouseAdapter * @see MouseListener diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/PaintEvent.java --- a/j2se/src/share/classes/java/awt/event/PaintEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/PaintEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.awt.event; import java.awt.Component; -import java.awt.Event; import java.awt.Rectangle; /** @@ -39,7 +38,7 @@ * render themselves properly. * * @author Amy Fowler - * @version 1.27, 05/05/07 + * @version 1.29, 06/05/07 * @since 1.1 */ public class PaintEvent extends ComponentEvent { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/TextEvent.java --- a/j2se/src/share/classes/java/awt/event/TextEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/TextEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.awt.event; import java.awt.AWTEvent; -import java.awt.Event; /** * A semantic event which indicates that an object's text changed. @@ -41,7 +40,7 @@ * Instead, it can process a "meaningful" (semantic) event like "text changed". * * @author Georges Saab - * @version 1.24 05/05/07 + * @version 1.26 06/05/07 * * @see java.awt.TextComponent * @see TextListener diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/event/WindowEvent.java --- a/j2se/src/share/classes/java/awt/event/WindowEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/event/WindowEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,7 @@ package java.awt.event; -import java.awt.Component; -import java.awt.Event; import java.awt.Window; - import sun.awt.AppContext; import sun.awt.SunToolkit; @@ -47,7 +44,7 @@ * * @author Carl Quinn * @author Amy Fowler - * @version 1.43, 05/05/07 + * @version 1.45, 06/05/07 * * @see WindowAdapter * @see WindowListener diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/ButtonPeer.java --- a/j2se/src/share/classes/java/awt/peer/ButtonPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/ButtonPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package java.awt.peer; -import java.awt.*; - /** * The peer interfaces are intended only for use in porting * the AWT. They are not intended for use by application diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/CanvasPeer.java --- a/j2se/src/share/classes/java/awt/peer/CanvasPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/CanvasPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package java.awt.peer; -import java.awt.*; - /** * The peer interfaces are intended only for use in porting * the AWT. They are not intended for use by application diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/ChoicePeer.java --- a/j2se/src/share/classes/java/awt/peer/ChoicePeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/ChoicePeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package java.awt.peer; -import java.awt.*; - /** * The peer interfaces are intended only for use in porting * the AWT. They are not intended for use by application diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/ComponentPeer.java --- a/j2se/src/share/classes/java/awt/peer/ComponentPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/ComponentPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,6 @@ import java.awt.image.ColorModel; import java.awt.image.VolatileImage; import java.awt.GraphicsConfiguration; -import java.awt.event.FocusEvent; - -import java.awt.dnd.peer.DropTargetPeer; import sun.awt.CausedFocusEvent; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/FileDialogPeer.java --- a/j2se/src/share/classes/java/awt/peer/FileDialogPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/FileDialogPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt.peer; -import java.awt.*; import java.io.FilenameFilter; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/LabelPeer.java --- a/j2se/src/share/classes/java/awt/peer/LabelPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/LabelPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,6 @@ */ package java.awt.peer; -import java.awt.Color; -import java.awt.Font; - /** * The peer interfaces are intended only for use in porting * the AWT. They are not intended for use by application diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/PanelPeer.java --- a/j2se/src/share/classes/java/awt/peer/PanelPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/PanelPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package java.awt.peer; -import java.awt.*; - /** * The peer interfaces are intended only for use in porting * the AWT. They are not intended for use by application diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/ScrollPanePeer.java --- a/j2se/src/share/classes/java/awt/peer/ScrollPanePeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/ScrollPanePeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-1998 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package java.awt.peer; -import java.awt.Point; import java.awt.Adjustable; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/SystemTrayPeer.java --- a/j2se/src/share/classes/java/awt/peer/SystemTrayPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/SystemTrayPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.awt.peer; -import java.awt.TrayIcon; import java.awt.Dimension; public interface SystemTrayPeer { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/TextComponentPeer.java --- a/j2se/src/share/classes/java/awt/peer/TextComponentPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/TextComponentPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package java.awt.peer; -import java.awt.Point; import java.awt.Rectangle; import java.awt.im.InputMethodRequests; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/TrayIconPeer.java --- a/j2se/src/share/classes/java/awt/peer/TrayIconPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/TrayIconPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,6 @@ package java.awt.peer; -import java.awt.TrayIcon; -import java.awt.Dimension; -import java.awt.Point; - public interface TrayIconPeer { void dispose(); void setToolTip(String tooltip); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/awt/peer/WindowPeer.java --- a/j2se/src/share/classes/java/awt/peer/WindowPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/awt/peer/WindowPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.awt.peer; import java.awt.*; -import java.awt.event.KeyEvent; /** * The peer interfaces are intended only for use in porting diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/BeanDescriptor.java --- a/j2se/src/share/classes/java/beans/BeanDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/BeanDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -37,8 +37,8 @@ public class BeanDescriptor extends FeatureDescriptor { - private Reference beanClassRef; - private Reference customizerClassRef; + private Reference beanClassRef; + private Reference customizerClassRef; /** * Create a BeanDescriptor for a bean that doesn't have a customizer. @@ -59,8 +59,8 @@ * the bean's Customizer. For example sun.beans.OurButtonCustomizer.class. */ public BeanDescriptor(Class beanClass, Class customizerClass) { - beanClassRef = createReference(beanClass); - customizerClassRef = createReference(customizerClass); + this.beanClassRef = getWeakReference((Class)beanClass); + this.customizerClassRef = getWeakReference((Class)customizerClass); String name = beanClass.getName(); while (name.indexOf('.') >= 0) { @@ -75,7 +75,9 @@ * @return The Class object for the bean. */ public Class getBeanClass() { - return (Class)getObject(beanClassRef); + return (this.beanClassRef != null) + ? this.beanClassRef.get() + : null; } /** @@ -85,7 +87,9 @@ * be null if the bean doesn't have a customizer. */ public Class getCustomizerClass() { - return (Class)getObject(customizerClassRef); + return (this.customizerClassRef != null) + ? this.customizerClassRef.get() + : null; } /* diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/EventSetDescriptor.java --- a/j2se/src/share/classes/java/beans/EventSetDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/EventSetDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,8 +44,8 @@ private MethodDescriptor removeMethodDescriptor; private MethodDescriptor getMethodDescriptor; - private Reference listenerMethodsRef; - private Reference listenerTypeRef; + private Reference listenerMethodsRef; + private Reference listenerTypeRef; private boolean unicast; private boolean inDefaultEventSet = true; @@ -74,14 +74,14 @@ throws IntrospectionException { this(sourceClass, eventSetName, listenerType, new String[] { listenerMethodName }, - "add" + getListenerClassName(listenerType), - "remove" + getListenerClassName(listenerType), - "get" + getListenerClassName(listenerType) + "s"); + Introspector.ADD_PREFIX + getListenerClassName(listenerType), + Introspector.REMOVE_PREFIX + getListenerClassName(listenerType), + Introspector.GET_PREFIX + getListenerClassName(listenerType) + "s"); - String eventName = capitalize(eventSetName) + "Event"; + String eventName = NameGenerator.capitalize(eventSetName) + "Event"; Method[] listenerMethods = getListenerMethods(); if (listenerMethods.length > 0) { - Class[] args = listenerMethods[0].getParameterTypes(); + Class[] args = getParameterTypes(getClass0(), listenerMethods[0]); // Check for EventSet compliance. Special case for vetoableChange. See 4529996 if (!"vetoableChange".equals(eventSetName) && !args[0].getName().endsWith(eventName)) { throw new IntrospectionException("Method \"" + listenerMethodName + @@ -291,11 +291,13 @@ * get invoked when the event is fired. */ public Class getListenerType() { - return (Class)getObject(listenerTypeRef); + return (this.listenerTypeRef != null) + ? this.listenerTypeRef.get() + : null; } private void setListenerType(Class cls) { - listenerTypeRef = createReference(cls); + this.listenerTypeRef = getWeakReference(cls); } /** @@ -329,11 +331,13 @@ listenerMethodDescriptors[i] = new MethodDescriptor(methods[i]); } } - listenerMethodsRef = createReference(methods, true); + this.listenerMethodsRef = getSoftReference(methods); } private Method[] getListenerMethods0() { - return (Method[])getObject(listenerMethodsRef); + return (this.listenerMethodsRef != null) + ? this.listenerMethodsRef.get() + : null; } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/FeatureDescriptor.java --- a/j2se/src/share/classes/java/beans/FeatureDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/FeatureDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,10 +25,15 @@ package java.beans; +import com.sun.beans.TypeResolver; + import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.ref.SoftReference; +import java.lang.reflect.Method; +import java.lang.reflect.Type; + /** * The FeatureDescriptor class is the common baseclass for PropertyDescriptor, * EventSetDescriptor, and MethodDescriptor, etc. @@ -42,7 +47,7 @@ public class FeatureDescriptor { - private Reference classRef; + private Reference classRef; /** * Constructs a FeatureDescriptor. @@ -278,11 +283,13 @@ // Package private methods for recreating the weak/soft referent void setClass0(Class cls) { - classRef = createReference(cls); + this.classRef = getWeakReference(cls); } Class getClass0() { - return (Class)getObject(classRef); + return (this.classRef != null) + ? this.classRef.get() + : null; } /** @@ -318,8 +325,64 @@ return (ref == null) ? null : (Object)ref.get(); } - static String capitalize(String s) { - return NameGenerator.capitalize(s); + /** + * Creates a new soft reference that refers to the given object. + * + * @return a new soft reference or null if object is null + * + * @see SoftReference + */ + static Reference getSoftReference(T object) { + return (object != null) + ? new SoftReference(object) + : null; + } + + /** + * Creates a new weak reference that refers to the given object. + * + * @return a new weak reference or null if object is null + * + * @see WeakReference + */ + static Reference getWeakReference(T object) { + return (object != null) + ? new WeakReference(object) + : null; + } + + /** + * Resolves the return type of the method. + * + * @param base the class that contains the method in the hierarchy + * @param method the object that represents the method + * @return a class identifying the return type of the method + * + * @see Method#getGenericReturnType + * @see Method#getReturnType + */ + static Class getReturnType(Class base, Method method) { + if (base == null) { + base = method.getDeclaringClass(); + } + return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericReturnType())); + } + + /** + * Resolves the parameter types of the method. + * + * @param base the class that contains the method in the hierarchy + * @param method the object that represents the method + * @return an array of classes identifying the parameter types of the method + * + * @see Method#getGenericParameterTypes + * @see Method#getParameterTypes + */ + static Class[] getParameterTypes(Class base, Method method) { + if (base == null) { + base = method.getDeclaringClass(); + } + return TypeResolver.erase(TypeResolver.resolveInClass(base, method.getGenericParameterTypes())); } private boolean expert; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/IndexedPropertyDescriptor.java --- a/j2se/src/share/classes/java/beans/IndexedPropertyDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/IndexedPropertyDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -41,9 +41,9 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { - private Reference indexedPropertyTypeRef; - private Reference indexedReadMethodRef; - private Reference indexedWriteMethodRef; + private Reference indexedPropertyTypeRef; + private Reference indexedReadMethodRef; + private Reference indexedWriteMethodRef; private String indexedReadMethodName; private String indexedWriteMethodName; @@ -66,10 +66,10 @@ public IndexedPropertyDescriptor(String propertyName, Class beanClass) throws IntrospectionException { this(propertyName, beanClass, - "get" + capitalize(propertyName), - "set" + capitalize(propertyName), - "get" + capitalize(propertyName), - "set" + capitalize(propertyName)); + Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName), + Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName), + Introspector.GET_PREFIX + NameGenerator.capitalize(propertyName), + Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName)); } /** @@ -141,7 +141,31 @@ // Type checking setIndexedPropertyType(findIndexedPropertyType(indexedReadMethod, indexedWriteMethod)); } - + + /** + * Creates PropertyDescriptor for the specified bean + * with the specified name and methods to read/write the property value. + * + * @param bean the type of the target bean + * @param base the base name of the property (the rest of the method name) + * @param read the method used for reading the property value + * @param write the method used for writing the property value + * @param readIndexed the method used for reading an indexed property value + * @param writeIndexed the method used for writing an indexed property value + * @exception IntrospectionException if an exception occurs during introspection + * + * @since 1.7 + */ + IndexedPropertyDescriptor(Class bean, String base, Method read, Method write, Method readIndexed, Method writeIndexed) throws IntrospectionException { + super(bean, base, read, write); + + setIndexedReadMethod0(readIndexed); + setIndexedWriteMethod0(writeIndexed); + + // Type checking + setIndexedPropertyType(findIndexedPropertyType(readIndexed, writeIndexed)); + } + /** * Gets the method that should be used to read an indexed * property value. @@ -162,9 +186,9 @@ if (indexedReadMethodName == null) { Class type = getIndexedPropertyType0(); if (type == boolean.class || type == null) { - indexedReadMethodName = "is" + getBaseName(); + indexedReadMethodName = Introspector.IS_PREFIX + getBaseName(); } else { - indexedReadMethodName = "get" + getBaseName(); + indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); } } @@ -174,7 +198,7 @@ 1, args); if (indexedReadMethod == null) { // no "is" method, so look for a "get" method. - indexedReadMethodName = "get" + getBaseName(); + indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, 1, args); } @@ -206,7 +230,7 @@ setClass0(readMethod.getDeclaringClass()); indexedReadMethodName = readMethod.getName(); - indexedReadMethodRef = createReference(readMethod); + this.indexedReadMethodRef = getSoftReference(readMethod); } @@ -245,7 +269,7 @@ } if (indexedWriteMethodName == null) { - indexedWriteMethodName = "set" + getBaseName(); + indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName(); } indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, 2, (type == null) ? null : new Class[] { int.class, type }); @@ -278,7 +302,7 @@ setClass0(writeMethod.getDeclaringClass()); indexedWriteMethodName = writeMethod.getName(); - indexedWriteMethodRef = createReference(writeMethod); + this.indexedWriteMethodRef = getSoftReference(writeMethod); } /** @@ -305,19 +329,25 @@ // Private methods which set get/set the Reference objects private void setIndexedPropertyType(Class type) { - indexedPropertyTypeRef = createReference(type); + this.indexedPropertyTypeRef = getWeakReference(type); } private Class getIndexedPropertyType0() { - return (Class)getObject(indexedPropertyTypeRef); + return (this.indexedPropertyTypeRef != null) + ? this.indexedPropertyTypeRef.get() + : null; } private Method getIndexedReadMethod0() { - return (Method)getObject(indexedReadMethodRef); + return (this.indexedReadMethodRef != null) + ? this.indexedReadMethodRef.get() + : null; } private Method getIndexedWriteMethod0() { - return (Method)getObject(indexedWriteMethodRef); + return (this.indexedWriteMethodRef != null) + ? this.indexedWriteMethodRef.get() + : null; } private Class findIndexedPropertyType(Method indexedReadMethod, @@ -326,20 +356,20 @@ Class indexedPropertyType = null; if (indexedReadMethod != null) { - Class params[] = indexedReadMethod.getParameterTypes(); + Class params[] = getParameterTypes(getClass0(), indexedReadMethod); if (params.length != 1) { throw new IntrospectionException("bad indexed read method arg count"); } if (params[0] != Integer.TYPE) { throw new IntrospectionException("non int index to indexed read method"); } - indexedPropertyType = indexedReadMethod.getReturnType(); + indexedPropertyType = getReturnType(getClass0(), indexedReadMethod); if (indexedPropertyType == Void.TYPE) { throw new IntrospectionException("indexed read method returns void"); } } if (indexedWriteMethod != null) { - Class params[] = indexedWriteMethod.getParameterTypes(); + Class params[] = getParameterTypes(getClass0(), indexedWriteMethod); if (params.length != 2) { throw new IntrospectionException("bad indexed write method arg count"); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/Introspector.java --- a/j2se/src/share/classes/java/beans/Introspector.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/Introspector.java Thu Jul 05 23:47:33 2007 +0000 @@ -143,11 +143,12 @@ private final static EventSetDescriptor[] EMPTY_EVENTSETDESCRIPTORS = new EventSetDescriptor[0]; - private static final String ADD_PREFIX = "add"; - private static final String REMOVE_PREFIX = "remove"; - private static final String GET_PREFIX = "get"; - private static final String SET_PREFIX = "set"; - private static final String IS_PREFIX = "is"; + static final String ADD_PREFIX = "add"; + static final String REMOVE_PREFIX = "remove"; + static final String GET_PREFIX = "get"; + static final String SET_PREFIX = "set"; + static final String IS_PREFIX = "is"; + private static final String BEANINFO_SUFFIX = "BeanInfo"; //====================================================================== @@ -496,39 +497,21 @@ // explicit information. PropertyDescriptor[] explicitProperties = null; if (explicitBeanInfo != null) { - explicitProperties = explicitBeanInfo.getPropertyDescriptors(); - int ix = explicitBeanInfo.getDefaultPropertyIndex(); - if (ix >= 0 && ix < explicitProperties.length) { - defaultPropertyName = explicitProperties[ix].getName(); - } + explicitProperties = getPropertyDescriptors(this.explicitBeanInfo); } if (explicitProperties == null && superBeanInfo != null) { // We have no explicit BeanInfo properties. Check with our parent. - PropertyDescriptor supers[] = superBeanInfo.getPropertyDescriptors(); - for (int i = 0 ; i < supers.length; i++) { - addPropertyDescriptor(supers[i]); - } - int ix = superBeanInfo.getDefaultPropertyIndex(); - if (ix >= 0 && ix < supers.length) { - defaultPropertyName = supers[ix].getName(); - } + addPropertyDescriptors(getPropertyDescriptors(this.superBeanInfo)); } for (int i = 0; i < additionalBeanInfo.length; i++) { - PropertyDescriptor additional[] = additionalBeanInfo[i].getPropertyDescriptors(); - if (additional != null) { - for (int j = 0 ; j < additional.length; j++) { - addPropertyDescriptor(additional[j]); - } - } + addPropertyDescriptors(additionalBeanInfo[i].getPropertyDescriptors()); } if (explicitProperties != null) { // Add the explicit BeanInfo data to our results. - for (int i = 0 ; i < explicitProperties.length; i++) { - addPropertyDescriptor(explicitProperties[i]); - } + addPropertyDescriptors(explicitProperties); } else { @@ -540,7 +523,7 @@ // Now analyze each method. for (int i = 0; i < methodList.length; i++) { Method method = methodList[i]; - if (method == null) { + if (method == null || method.isSynthetic()) { continue; } // skip static methods. @@ -564,33 +547,24 @@ if (argCount == 0) { if (name.startsWith(GET_PREFIX)) { // Simple getter - pd = new PropertyDescriptor(decapitalize(name.substring(3)), - method, null); + pd = new PropertyDescriptor(this.beanClass, name.substring(3), method, null); } else if (resultType == boolean.class && name.startsWith(IS_PREFIX)) { // Boolean getter - pd = new PropertyDescriptor(decapitalize(name.substring(2)), - method, null); + pd = new PropertyDescriptor(this.beanClass, name.substring(2), method, null); } } else if (argCount == 1) { if (argTypes[0] == int.class && name.startsWith(GET_PREFIX)) { - pd = new IndexedPropertyDescriptor( - decapitalize(name.substring(3)), - null, null, - method, null); + pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, method, null); } else if (resultType == void.class && name.startsWith(SET_PREFIX)) { // Simple setter - pd = new PropertyDescriptor(decapitalize(name.substring(3)), - null, method); + pd = new PropertyDescriptor(this.beanClass, name.substring(3), null, method); if (throwsException(method, PropertyVetoException.class)) { pd.setConstrained(true); } } } else if (argCount == 2) { if (argTypes[0] == int.class && name.startsWith(SET_PREFIX)) { - pd = new IndexedPropertyDescriptor( - decapitalize(name.substring(3)), - null, null, - null, method); + pd = new IndexedPropertyDescriptor(this.beanClass, name.substring(3), null, null, null, method); if (throwsException(method, PropertyVetoException.class)) { pd.setConstrained(true); } @@ -644,9 +618,52 @@ list = new ArrayList(); pdStore.put(propName, list); } + if (this.beanClass != pd.getClass0()) { + // replace existing property descriptor + // only if we have types to resolve + // in the context of this.beanClass + try { + String name = pd.getName(); + Method read = pd.getReadMethod(); + Method write = pd.getWriteMethod(); + boolean cls = true; + if (read != null) cls = cls && read.getGenericReturnType() instanceof Class; + if (write != null) cls = cls && write.getGenericParameterTypes()[0] instanceof Class; + if (pd instanceof IndexedPropertyDescriptor) { + IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor)pd; + Method readI = ipd.getIndexedReadMethod(); + Method writeI = ipd.getIndexedWriteMethod(); + if (readI != null) cls = cls && readI.getGenericReturnType() instanceof Class; + if (writeI != null) cls = cls && writeI.getGenericParameterTypes()[1] instanceof Class; + if (!cls) { + pd = new IndexedPropertyDescriptor(this.beanClass, name, read, write, readI, writeI); + } + } else if (!cls) { + pd = new PropertyDescriptor(this.beanClass, name, read, write); + } + } catch ( IntrospectionException e ) { + } + } list.add(pd); } + private void addPropertyDescriptors(PropertyDescriptor[] descriptors) { + if (descriptors != null) { + for (PropertyDescriptor descriptor : descriptors) { + addPropertyDescriptor(descriptor); + } + } + } + + private PropertyDescriptor[] getPropertyDescriptors(BeanInfo info) { + PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); + int index = info.getDefaultPropertyIndex(); + if ((0 <= index) && (index < descriptors.length)) { + this.defaultPropertyName = descriptors[index].getName(); + } + return descriptors; + } + /** * Populates the property descriptor table by merging the * lists of Property descriptors. @@ -860,7 +877,7 @@ if (read == null && write != null) { read = findMethod(result.getClass0(), - "get" + result.capitalize(result.getName()), 0); + GET_PREFIX + NameGenerator.capitalize(result.getName()), 0); if (read != null) { try { result.setReadMethod(read); @@ -871,8 +888,8 @@ } if (write == null && read != null) { write = findMethod(result.getClass0(), - "set" + result.capitalize(result.getName()), 1, - new Class[] { read.getReturnType() }); + SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, + new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); if (write != null) { try { result.setWriteMethod(write); @@ -984,8 +1001,8 @@ continue; } - Class argTypes[] = method.getParameterTypes(); - Class resultType = method.getReturnType(); + Class argTypes[] = FeatureDescriptor.getParameterTypes(beanClass, method); + Class resultType = FeatureDescriptor.getReturnType(beanClass, method); if (name.startsWith(ADD_PREFIX) && argTypes.length == 1 && resultType == Void.TYPE && @@ -1044,7 +1061,7 @@ if (gets != null) { getMethod = (Method)gets.get(listenerName); } - Class argType = addMethod.getParameterTypes()[0]; + Class argType = FeatureDescriptor.getParameterTypes(beanClass, addMethod)[0]; // generate a list of Method objects for each of the target methods: Method allMethods[] = getPublicDeclaredMethods(argType); @@ -1257,7 +1274,7 @@ private boolean isEventHandler(Method m) { // We assume that a method is an event handler if it has a single // argument, whose type inherit from java.util.Event. - Class argTypes[] = m.getParameterTypes(); + Class argTypes[] = FeatureDescriptor.getParameterTypes(beanClass, m); if (argTypes.length != 1) { return false; } @@ -1331,7 +1348,7 @@ } // make sure method signature matches. - Class params[] = method.getParameterTypes(); + Class params[] = FeatureDescriptor.getParameterTypes(start, method); if (method.getName().equals(methodName) && params.length == argCount) { if (args != null) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/MetaData.java --- a/j2se/src/share/classes/java/beans/MetaData.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/MetaData.java Thu Jul 05 23:47:33 2007 +0000 @@ -47,6 +47,7 @@ import java.util.*; +import javax.swing.JLayeredPane; import javax.swing.border.MatteBorder; /* @@ -57,7 +58,7 @@ * * @see java.beans.Intropector * - * @version 1.58 05/05/07 + * @version 1.59 05/09/07 * @author Philip Milne * @author Steve Langley */ @@ -940,7 +941,7 @@ // Bounds java.awt.Container p = c.getParent(); - if (p == null || p.getLayout() == null && !(p instanceof javax.swing.JLayeredPane)) { + if (p == null || p.getLayout() == null) { // Use the most concise construct. boolean locationCorrect = c.getLocation().equals(c2.getLocation()); boolean sizeCorrect = c.getSize().equals(c2.getSize()); @@ -975,11 +976,17 @@ ? ( BorderLayout )oldC.getLayout() : null; + JLayeredPane oldLayeredPane = (oldInstance instanceof JLayeredPane) + ? (JLayeredPane) oldInstance + : null; + // Pending. Assume all the new children are unaltered. for(int i = newChildren.length; i < oldChildren.length; i++) { Object[] args = ( layout != null ) ? new Object[] {oldChildren[i], layout.getConstraints( oldChildren[i] )} - : new Object[] {oldChildren[i]}; + : (oldLayeredPane != null) + ? new Object[] {oldChildren[i], oldLayeredPane.getLayer(oldChildren[i]), Integer.valueOf(-1)} + : new Object[] {oldChildren[i]}; invokeStatement(oldInstance, "add", args, out); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/MethodDescriptor.java --- a/j2se/src/share/classes/java/beans/MethodDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/MethodDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -33,8 +33,6 @@ import java.util.List; import java.util.ArrayList; -import com.sun.beans.ObjectHandler; - /** * A MethodDescriptor describes a particular method that a Java Bean * supports for external access from other components. @@ -42,7 +40,7 @@ public class MethodDescriptor extends FeatureDescriptor { - private Reference methodRef; + private Reference methodRef; private String[] paramNames; @@ -115,12 +113,14 @@ if (getClass0() == null) { setClass0(method.getDeclaringClass()); } - setParams(method.getParameterTypes()); - methodRef = createReference(method, true); + setParams(getParameterTypes(getClass0(), method)); + this.methodRef = getSoftReference(method); } private Method getMethod0() { - return (Method)getObject(methodRef); + return (this.methodRef != null) + ? this.methodRef.get() + : null; } private synchronized void setParams(Class[] param) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/PropertyDescriptor.java --- a/j2se/src/share/classes/java/beans/PropertyDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/PropertyDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -36,10 +36,10 @@ */ public class PropertyDescriptor extends FeatureDescriptor { - private Reference propertyTypeRef; - private Reference readMethodRef; - private Reference writeMethodRef; - private Reference propertyEditorClassRef; + private Reference propertyTypeRef; + private Reference readMethodRef; + private Reference writeMethodRef; + private Reference propertyEditorClassRef; private boolean bound; private boolean constrained; @@ -69,8 +69,8 @@ public PropertyDescriptor(String propertyName, Class beanClass) throws IntrospectionException { this(propertyName, beanClass, - "is" + capitalize(propertyName), - "set" + capitalize(propertyName)); + Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName), + Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName)); } /** @@ -136,6 +136,29 @@ } /** + * Creates PropertyDescriptor for the specified bean + * with the specified name and methods to read/write the property value. + * + * @param bean the type of the target bean + * @param base the base name of the property (the rest of the method name) + * @param read the method used for reading the property value + * @param write the method used for writing the property value + * @exception IntrospectionException if an exception occurs during introspection + * + * @since 1.7 + */ + PropertyDescriptor(Class bean, String base, Method read, Method write) throws IntrospectionException { + if (bean == null) { + throw new IntrospectionException("Target Bean class is null"); + } + setClass0(bean); + setName(Introspector.decapitalize(base)); + setReadMethod(read); + setWriteMethod(write); + this.baseName = base; + } + + /** * Gets the Class object for the property. * * @return The Java type info for the property. Note that @@ -159,11 +182,13 @@ } private void setPropertyType(Class type) { - propertyTypeRef = createReference(type); + this.propertyTypeRef = getWeakReference(type); } private Class getPropertyType0() { - return (Class)getObject(propertyTypeRef); + return (this.propertyTypeRef != null) + ? this.propertyTypeRef.get() + : null; } /** @@ -183,9 +208,9 @@ if (readMethodName == null) { Class type = getPropertyType0(); if (type == boolean.class || type == null) { - readMethodName = "is" + getBaseName(); + readMethodName = Introspector.IS_PREFIX + getBaseName(); } else { - readMethodName = "get" + getBaseName(); + readMethodName = Introspector.GET_PREFIX + getBaseName(); } } @@ -196,7 +221,7 @@ // reader method so look for this one first. readMethod = Introspector.findMethod(cls, readMethodName, 0); if (readMethod == null) { - readMethodName = "get" + getBaseName(); + readMethodName = Introspector.GET_PREFIX + getBaseName(); readMethod = Introspector.findMethod(cls, readMethodName, 0); } try { @@ -225,7 +250,7 @@ setClass0(readMethod.getDeclaringClass()); readMethodName = readMethod.getName(); - readMethodRef = createReference(readMethod, true); + this.readMethodRef = getSoftReference(readMethod); } /** @@ -258,7 +283,7 @@ } if (writeMethodName == null) { - writeMethodName = "set" + getBaseName(); + writeMethodName = Introspector.SET_PREFIX + getBaseName(); } writeMethod = Introspector.findMethod(cls, writeMethodName, 1, @@ -289,16 +314,20 @@ setClass0(writeMethod.getDeclaringClass()); writeMethodName = writeMethod.getName(); - writeMethodRef = createReference(writeMethod, true); + this.writeMethodRef = getSoftReference(writeMethod); } private Method getReadMethod0() { - return (Method)getObject(readMethodRef); + return (this.readMethodRef != null) + ? this.readMethodRef.get() + : null; } private Method getWriteMethod0() { - return (Method)getObject(writeMethodRef); + return (this.writeMethodRef != null) + ? this.writeMethodRef.get() + : null; } /** @@ -362,7 +391,7 @@ * @param propertyEditorClass The Class for the desired PropertyEditor. */ public void setPropertyEditorClass(Class propertyEditorClass) { - propertyEditorClassRef = createReference(propertyEditorClass); + this.propertyEditorClassRef = getWeakReference((Class)propertyEditorClass); } /** @@ -376,7 +405,9 @@ * a suitable PropertyEditor. */ public Class getPropertyEditorClass() { - return (Class)getObject(propertyEditorClassRef); + return (this.propertyEditorClassRef != null) + ? this.propertyEditorClassRef.get() + : null; } /** @@ -533,10 +564,10 @@ // give priority to a boolean "is" method over a boolean "get" method. if (xr != null && yr != null && xr.getDeclaringClass() == yr.getDeclaringClass() && - xr.getReturnType() == boolean.class && - yr.getReturnType() == boolean.class && - xr.getName().indexOf("is") == 0 && - yr.getName().indexOf("get") == 0) { + getReturnType(getClass0(), xr) == boolean.class && + getReturnType(getClass0(), yr) == boolean.class && + xr.getName().indexOf(Introspector.IS_PREFIX) == 0 && + yr.getName().indexOf(Introspector.GET_PREFIX) == 0) { try { setReadMethod(xr); } catch (IntrospectionException ex) { @@ -600,19 +631,19 @@ Class propertyType = null; try { if (readMethod != null) { - Class[] params = readMethod.getParameterTypes(); + Class[] params = getParameterTypes(getClass0(), readMethod); if (params.length != 0) { throw new IntrospectionException("bad read method arg count: " + readMethod); } - propertyType = readMethod.getReturnType(); + propertyType = getReturnType(getClass0(), readMethod); if (propertyType == Void.TYPE) { throw new IntrospectionException("read method " + readMethod.getName() + " returns void"); } } if (writeMethod != null) { - Class params[] = writeMethod.getParameterTypes(); + Class params[] = getParameterTypes(getClass0(), writeMethod); if (params.length != 1) { throw new IntrospectionException("bad write method arg count: " + writeMethod); @@ -661,7 +692,7 @@ // Calculate once since capitalize() is expensive. String getBaseName() { if (baseName == null) { - baseName = capitalize(getName()); + baseName = NameGenerator.capitalize(getName()); } return baseName; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/beans/XMLEncoder.java --- a/j2se/src/share/classes/java/beans/XMLEncoder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/beans/XMLEncoder.java Thu Jul 05 23:47:33 2007 +0000 @@ -202,7 +202,7 @@ * * @since 1.4 * - * @version 1.43 05/05/07 + * @version 1.44 05/09/07 * @author Philip Milne */ public class XMLEncoder extends Encoder { @@ -708,7 +708,9 @@ d.refs = 2; getValueData(target).refs++; outputValue(target, outer, false); - outputValue(value, outer, false); + if (isArgument) { + outputValue(value, outer, false); + } return; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/io/FileInputStream.java --- a/j2se/src/share/classes/java/io/FileInputStream.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/io/FileInputStream.java Thu Jul 05 23:47:33 2007 +0000 @@ -39,7 +39,7 @@ * FileReader. * * @author Arthur van Hoff - * @version 1.77, 05/05/07 + * @version 1.78, 06/13/07 * @see java.io.File * @see java.io.FileDescriptor * @see java.io.FileOutputStream @@ -134,6 +134,7 @@ throw new NullPointerException(); } fd = new FileDescriptor(); + fd.incrementAndGetUseCount(); open(name); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/io/FileOutputStream.java --- a/j2se/src/share/classes/java/io/FileOutputStream.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/io/FileOutputStream.java Thu Jul 05 23:47:33 2007 +0000 @@ -43,7 +43,7 @@ * FileWriter. * * @author Arthur van Hoff - * @version 1.67, 05/05/07 + * @version 1.68, 06/13/07 * @see java.io.File * @see java.io.FileDescriptor * @see java.io.FileInputStream @@ -202,6 +202,7 @@ throw new NullPointerException(); } fd = new FileDescriptor(); + fd.incrementAndGetUseCount(); this.append = append; if (append) { openAppend(name); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/io/RandomAccessFile.java --- a/j2se/src/share/classes/java/io/RandomAccessFile.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/io/RandomAccessFile.java Thu Jul 05 23:47:33 2007 +0000 @@ -53,7 +53,7 @@ * IOException may be thrown if the stream has been closed. * * @author unascribed - * @version 1.89, 05/05/07 + * @version 1.90, 06/13/07 * @since JDK1.0 */ @@ -230,6 +230,7 @@ throw new NullPointerException(); } fd = new FileDescriptor(); + fd.incrementAndGetUseCount(); open(name, imode); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/Comparable.java --- a/j2se/src/share/classes/java/lang/Comparable.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/Comparable.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,7 @@ * @param the type of objects that this object may be compared to * * @author Josh Bloch - * @version 1.32, 05/05/07 + * @version 1.33, 06/12/07 * @see java.util.Comparator * @since 1.2 */ @@ -131,6 +131,7 @@ * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. * + * @throws NullPointerException if the specified object is null * @throws ClassCastException if the specified object's type prevents it * from being compared to this object. */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/Double.java --- a/j2se/src/share/classes/java/lang/Double.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/Double.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,7 +44,7 @@ * @author Lee Boynton * @author Arthur van Hoff * @author Joseph D. Darcy - * @version 1.107, 05/05/07 + * @version 1.108, 06/12/07 * @since JDK1.0 */ public final class Double extends Number implements Comparable { @@ -393,7 +393,7 @@ * where Sign, FloatingPointLiteral, * HexNumeral, HexDigits, SignedInteger and * FloatTypeSuffix are as defined in the lexical structure - * sections of the of the Java Language * Specification. If {@code s} does not have the form of * a FloatValue, then a {@code NumberFormatException} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/Float.java --- a/j2se/src/share/classes/java/lang/Float.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/Float.java Thu Jul 05 23:47:33 2007 +0000 @@ -45,7 +45,7 @@ * @author Lee Boynton * @author Arthur van Hoff * @author Joseph D. Darcy - * @version 1.108, 05/05/07 + * @version 1.109, 06/12/07 * @since JDK1.0 */ public final class Float extends Number implements Comparable { @@ -354,7 +354,7 @@ * where Sign, FloatingPointLiteral, * HexNumeral, HexDigits, SignedInteger and * FloatTypeSuffix are as defined in the lexical structure - * sections of the of the Java Language * Specification. If {@code s} does not have the form of * a FloatValue, then a {@code NumberFormatException} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/System.java --- a/j2se/src/share/classes/java/lang/System.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/System.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * method for quickly copying a portion of an array. * * @author unascribed - * @version 1.164, 05/05/07 + * @version 1.165, 06/11/07 * @since JDK1.0 */ public final class System { @@ -209,7 +209,7 @@ return cons; } - /** + /** * Returns the channel inherited from the entity that created this * Java virtual machine. * @@ -301,7 +301,7 @@ // calls the installed security manager's checkPermission method // which will loop infinitely if there is a non-system class // (in this case: the new security manager class) on the stack). - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction() { public Object run() { s.getClass().getProtectionDomain().implies (SecurityConstants.ALL_PERMISSION); @@ -345,28 +345,47 @@ public static native long currentTimeMillis(); /** - * Returns the current value of the most precise available system - * timer, in nanoseconds. + * Returns the current value of the running Java Virtual Machine's + * high-resolution time source, in nanoseconds. * *

This method can only be used to measure elapsed time and is * not related to any other notion of system or wall-clock time. * The value returned represents nanoseconds since some fixed but - * arbitrary time (perhaps in the future, so values may be - * negative). This method provides nanosecond precision, but not - * necessarily nanosecond accuracy. No guarantees are made about - * how frequently values change. Differences in successive calls - * that span greater than approximately 292 years (263 - * nanoseconds) will not accurately compute elapsed time due to - * numerical overflow. + * arbitrary origin time (perhaps in the future, so values + * may be negative). The same origin is used by all invocations of + * this method in an instance of a Java virtual machine; other + * virtual machine instances are likely to use a different origin. + * + *

This method provides nanosecond precision, but not necessarily + * nanosecond resolution (that is, how frequently the value changes) + * - no guarantees are made except that the resolution is at least as + * good as that of {@link #currentTimeMillis()}. + * + *

Differences in successive calls that span greater than + * approximately 292 years (263 nanoseconds) will not + * correctly compute elapsed time due to numerical overflow. + * + *

The values returned by this method become meaningful only when + * the difference between two such values, obtained within the same + * instance of a Java virtual machine, is computed. * *

For example, to measure how long some code takes to execute: - *

-     *   long startTime = System.nanoTime();
-     *   // ... the code being measured ...
-     *   long estimatedTime = System.nanoTime() - startTime;
-     * 
- * - * @return The current value of the system timer, in nanoseconds. + *
 {@code
+     * long startTime = System.nanoTime();
+     * // ... the code being measured ...
+     * long estimatedTime = System.nanoTime() - startTime;}
+ * + *

To compare two nanoTime values + *

 {@code
+     * long t0 = System.nanoTime();
+     * ...
+     * long t1 = System.nanoTime();}
+ * + * one should use {@code t1 - t0 < 0}, not {@code t1 < t0}, + * because of the possibility of numerical overflow. + * + * @return the current value of the running Java Virtual Machine's + * high-resolution time source, in nanoseconds * @since 1.5 */ public static native long nanoTime(); @@ -511,12 +530,12 @@ * checkPropertiesAccess method is called with no * arguments. This may result in a security exception. *

- * The current set of system properties for use by the - * {@link #getProperty(String)} method is returned as a - * Properties object. If there is no current set of - * system properties, a set of system properties is first created and - * initialized. This set of system properties always includes values - * for the following keys: + * The current set of system properties for use by the + * {@link #getProperty(String)} method is returned as a + * Properties object. If there is no current set of + * system properties, a set of system properties is first created and + * initialized. This set of system properties always includes values + * for the following keys: * * * @@ -728,7 +747,7 @@ * @exception SecurityException if a security manager exists and its * checkPermission method doesn't allow * setting of the specified property. - * @exception NullPointerException if key or + * @exception NullPointerException if key or * value is null. * @exception IllegalArgumentException if key is empty. * @see #getProperty @@ -750,20 +769,20 @@ } /** - * Removes the system property indicated by the specified key. + * Removes the system property indicated by the specified key. *

- * First, if a security manager exists, its + * First, if a security manager exists, its * SecurityManager.checkPermission method * is called with a PropertyPermission(key, "write") * permission. This may result in a SecurityException being thrown. * If no exception is thrown, the specified property is removed. *

* - * @param key the name of the system property to be removed. + * @param key the name of the system property to be removed. * @return the previous string value of the system property, * or null if there was no property with that key. * - * @exception SecurityException if a security manager exists and its + * @exception SecurityException if a security manager exists and its * checkPropertyAccess method doesn't allow * access to the specified system property. * @exception NullPointerException if key is @@ -850,7 +869,7 @@ return ProcessEnvironment.getenv(name); } - + /** * Returns an unmodifiable string map view of the current system environment. * The environment is a system-dependent mapping from names to @@ -1104,7 +1123,7 @@ Terminator.setup(); // The order in with the hooks are added here is important as it - // determines the order in which they are run. + // determines the order in which they are run. // (1)Console restore hook needs to be called first. // (2)Application hooks must be run before calling deleteOnExitHook. Shutdown.add(sun.misc.SharedSecrets.getJavaIOAccess().consoleRestoreHook()); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/ThreadDeath.java --- a/j2se/src/share/classes/java/lang/ThreadDeath.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/ThreadDeath.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1997 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,27 +26,24 @@ package java.lang; /** - * An instance of ThreadDeath is thrown in the victim - * thread when the stop method with zero arguments in - * class Thread is called. - *

- * An application should catch instances of this class only if it - * must clean up after being terminated asynchronously. If - * ThreadDeath is caught by a method, it is important - * that it be rethrown so that the thread actually dies. - *

- * The top-level error handler does not print out a message if - * ThreadDeath is never caught. - *

- * The class ThreadDeath is specifically a subclass of - * Error rather than Exception, even though - * it is a "normal occurrence", because many applications - * catch all occurrences of Exception and then discard - * the exception. + * An instance of {@code ThreadDeath} is thrown in the victim thread + * when the (deprecated) {@link Thread#stop()} method is invoked. + * + *

An application should catch instances of this class only if it + * must clean up after being terminated asynchronously. If + * {@code ThreadDeath} is caught by a method, it is important that it + * be rethrown so that the thread actually dies. * - * @author unascribed - * @version 1.22, 05/05/07 - * @see java.lang.Thread#stop() + *

The {@linkplain ThreadGroup#uncaughtException top-level error + * handler} does not print out a message if {@code ThreadDeath} is + * never caught. + * + *

The class {@code ThreadDeath} is specifically a subclass of + * {@code Error} rather than {@code Exception}, even though it is a + * "normal occurrence", because many applications catch all + * occurrences of {@code Exception} and then discard the exception. + * + * @version 1.23, 06/07/07 * @since JDK1.0 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/lang/ThreadGroup.java --- a/j2se/src/share/classes/java/lang/ThreadGroup.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/lang/ThreadGroup.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * parent thread group or any other thread groups. * * @author unascribed - * @version 1.71, 05/05/07 + * @version 1.73, 06/27/07 * @since JDK1.0 */ /* The locking strategy for this code is to try to lock only one level of the @@ -251,11 +251,10 @@ ThreadGroup[] groupsSnapshot; synchronized (this) { checkAccess(); - if (pri < Thread.MIN_PRIORITY) { - maxPriority = Thread.MIN_PRIORITY; - } else if (pri < maxPriority) { - maxPriority = pri; + if (pri < Thread.MIN_PRIORITY || pri > Thread.MAX_PRIORITY) { + return; } + maxPriority = (parent != null) ? Math.min(pri, parent.maxPriority) : pri; ngroupsSnapshot = ngroups; if (groups != null) { groupsSnapshot = Arrays.copyOf(groups, ngroupsSnapshot); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/math/BigDecimal.java --- a/j2se/src/share/classes/java/math/BigDecimal.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/math/BigDecimal.java Thu Jul 05 23:47:33 2007 +0000 @@ -2869,22 +2869,24 @@ throw new ArithmeticException("Rounding necessary"); // round to an integer, with Exception if decimal part non-0 BigDecimal num = this.setScale(0, ROUND_UNNECESSARY).inflate(); - if (num.precision() >= 19) { // need to check carefully - if (LONGMIN == null) { // initialize constants - LONGMIN = BigInteger.valueOf(Long.MIN_VALUE); - LONGMAX = BigInteger.valueOf(Long.MAX_VALUE); - } - if ((num.intVal.compareTo(LONGMIN) < 0) || + if (num.precision() >= 19) // need to check carefully + LongOverflow.check(num); + return num.intVal.longValue(); + } + + private static class LongOverflow { + /** BigInteger equal to Long.MIN_VALUE. */ + private static final BigInteger LONGMIN = BigInteger.valueOf(Long.MIN_VALUE); + + /** BigInteger equal to Long.MAX_VALUE. */ + private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE); + + public static void check(BigDecimal num) { + if ((num.intVal.compareTo(LONGMIN) < 0) || (num.intVal.compareTo(LONGMAX) > 0)) throw new java.lang.ArithmeticException("Overflow"); - } - return num.intVal.longValue(); + } } - // These constants are only initialized if needed - /** BigInteger equal to Long.MIN_VALUE. */ - private static BigInteger LONGMIN = null; - /** BigInteger equal to Long.MAX_VALUE. */ - private static BigInteger LONGMAX = null; /** * Converts this {@code BigDecimal} to an {@code int}. This diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,343 @@ +/* + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.util.Enumeration; + +/** + * Abstract datagram and multicast socket implementation base class. + * Note: This is not a public class, so that applets cannot call + * into the implementation directly and hence cannot bypass the + * security checks present in the DatagramSocket and MulticastSocket + * classes. + * + * @author Pavani Diwanji + */ + +abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl +{ + /* timeout value for receive() */ + int timeout = 0; + boolean connected = false; + private int trafficClass = 0; + private InetAddress connectedAddress = null; + private int connectedPort = -1; + + /* cached socket options */ + private int multicastInterface = 0; + private boolean loopbackMode = true; + private int ttl = -1; + + /** + * Load net library into runtime. + */ + static { + java.security.AccessController.doPrivileged( + new sun.security.action.LoadLibraryAction("net")); + } + + /** + * Creates a datagram socket + */ + protected synchronized void create() throws SocketException { + fd = new FileDescriptor(); + datagramSocketCreate(); + } + + /** + * Binds a datagram socket to a local port. + */ + protected synchronized void bind(int lport, InetAddress laddr) + throws SocketException { + bind0(lport, laddr); + } + + protected abstract void bind0(int lport, InetAddress laddr) + throws SocketException; + + /** + * Sends a datagram packet. The packet contains the data and the + * destination address to send the packet to. + * @param packet to be sent. + */ + protected abstract void send(DatagramPacket p) throws IOException; + + /** + * Connects a datagram socket to a remote destination. This associates the remote + * address with the local socket so that datagrams may only be sent to this destination + * and received from this destination. + * @param address the remote InetAddress to connect to + * @param port the remote port number + */ + protected void connect(InetAddress address, int port) throws SocketException { + connect0(address, port); + connectedAddress = address; + connectedPort = port; + connected = true; + } + + /** + * Disconnects a previously connected socket. Does nothing if the socket was + * not connected already. + */ + protected void disconnect() { + disconnect0(connectedAddress.family); + connected = false; + connectedAddress = null; + connectedPort = -1; + } + + /** + * Peek at the packet to see who it is from. + * @param return the address which the packet came from. + */ + protected abstract int peek(InetAddress i) throws IOException; + protected abstract int peekData(DatagramPacket p) throws IOException; + /** + * Receive the datagram packet. + * @param Packet Received. + */ + protected synchronized void receive(DatagramPacket p) + throws IOException { + receive0(p); + } + + protected abstract void receive0(DatagramPacket p) + throws IOException; + + /** + * Set the TTL (time-to-live) option. + * @param TTL to be set. + */ + protected abstract void setTimeToLive(int ttl) throws IOException; + + /** + * Get the TTL (time-to-live) option. + */ + protected abstract int getTimeToLive() throws IOException; + + /** + * Set the TTL (time-to-live) option. + * @param TTL to be set. + */ + protected abstract void setTTL(byte ttl) throws IOException; + + /** + * Get the TTL (time-to-live) option. + */ + protected abstract byte getTTL() throws IOException; + + /** + * Join the multicast group. + * @param multicast address to join. + */ + protected void join(InetAddress inetaddr) throws IOException { + join(inetaddr, null); + } + + /** + * Leave the multicast group. + * @param multicast address to leave. + */ + protected void leave(InetAddress inetaddr) throws IOException { + leave(inetaddr, null); + } + /** + * Join the multicast group. + * @param multicast address to join. + * @param netIf specifies the local interface to receive multicast + * datagram packets + * @throws IllegalArgumentException if mcastaddr is null or is a + * SocketAddress subclass not supported by this socket + * @since 1.4 + */ + + protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) + throws IOException { + if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) + throw new IllegalArgumentException("Unsupported address type"); + join(((InetSocketAddress)mcastaddr).getAddress(), netIf); + } + + protected abstract void join(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + /** + * Leave the multicast group. + * @param multicast address to leave. + * @param netIf specified the local interface to leave the group at + * @throws IllegalArgumentException if mcastaddr is null or is a + * SocketAddress subclass not supported by this socket + * @since 1.4 + */ + protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) + throws IOException { + if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) + throw new IllegalArgumentException("Unsupported address type"); + leave(((InetSocketAddress)mcastaddr).getAddress(), netIf); + } + + protected abstract void leave(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + /** + * Close the socket. + */ + protected void close() { + if (fd != null) { + datagramSocketClose(); + fd = null; + } + } + + protected boolean isClosed() { + return (fd == null) ? true : false; + } + + protected void finalize() { + close(); + } + + /** + * set a value - since we only support (setting) binary options + * here, o must be a Boolean + */ + + public void setOption(int optID, Object o) throws SocketException { + if (isClosed()) { + throw new SocketException("Socket Closed"); + } + switch (optID) { + /* check type safety b4 going native. These should never + * fail, since only java.Socket* has access to + * PlainSocketImpl.setOption(). + */ + case SO_TIMEOUT: + if (o == null || !(o instanceof Integer)) { + throw new SocketException("bad argument for SO_TIMEOUT"); + } + int tmp = ((Integer) o).intValue(); + if (tmp < 0) + throw new IllegalArgumentException("timeout < 0"); + timeout = tmp; + return; + case IP_TOS: + if (o == null || !(o instanceof Integer)) { + throw new SocketException("bad argument for IP_TOS"); + } + trafficClass = ((Integer)o).intValue(); + break; + case SO_REUSEADDR: + if (o == null || !(o instanceof Boolean)) { + throw new SocketException("bad argument for SO_REUSEADDR"); + } + break; + case SO_BROADCAST: + if (o == null || !(o instanceof Boolean)) { + throw new SocketException("bad argument for SO_BROADCAST"); + } + break; + case SO_BINDADDR: + throw new SocketException("Cannot re-bind Socket"); + case SO_RCVBUF: + case SO_SNDBUF: + if (o == null || !(o instanceof Integer) || + ((Integer)o).intValue() < 0) { + throw new SocketException("bad argument for SO_SNDBUF or " + + "SO_RCVBUF"); + } + break; + case IP_MULTICAST_IF: + if (o == null || !(o instanceof InetAddress)) + throw new SocketException("bad argument for IP_MULTICAST_IF"); + break; + case IP_MULTICAST_IF2: + if (o == null || !(o instanceof NetworkInterface)) + throw new SocketException("bad argument for IP_MULTICAST_IF2"); + break; + case IP_MULTICAST_LOOP: + if (o == null || !(o instanceof Boolean)) + throw new SocketException("bad argument for IP_MULTICAST_LOOP"); + break; + default: + throw new SocketException("invalid option: " + optID); + } + socketSetOption(optID, o); + } + + /* + * get option's state - set or not + */ + + public Object getOption(int optID) throws SocketException { + if (isClosed()) { + throw new SocketException("Socket Closed"); + } + + Object result; + + switch (optID) { + case SO_TIMEOUT: + result = new Integer(timeout); + break; + + case IP_TOS: + result = socketGetOption(optID); + if ( ((Integer)result).intValue() == -1) { + result = new Integer(trafficClass); + } + break; + + case SO_BINDADDR: + case IP_MULTICAST_IF: + case IP_MULTICAST_IF2: + case SO_RCVBUF: + case SO_SNDBUF: + case IP_MULTICAST_LOOP: + case SO_REUSEADDR: + case SO_BROADCAST: + result = socketGetOption(optID); + break; + + default: + throw new SocketException("invalid option: " + optID); + } + + return result; + } + + protected abstract void datagramSocketCreate() throws SocketException; + protected abstract void datagramSocketClose(); + protected abstract void socketSetOption(int opt, Object val) + throws SocketException; + protected abstract Object socketGetOption(int opt) throws SocketException; + + protected abstract void connect0(InetAddress address, int port) throws SocketException; + protected abstract void disconnect0(int family); + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/AbstractPlainSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/java/net/AbstractPlainSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,678 @@ +/* + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.InterruptedIOException; +import java.io.FileDescriptor; +import java.io.ByteArrayOutputStream; + +import sun.net.ConnectionResetException; + +/** + * Default Socket Implementation. This implementation does + * not implement any security checks. + * Note this class should NOT be public. + * + * @author Steven B. Byrne + * @version 1.74, 06/11/07 + */ +abstract class AbstractPlainSocketImpl extends SocketImpl +{ + /* instance variable for SO_TIMEOUT */ + int timeout; // timeout in millisec + // traffic class + private int trafficClass; + + private boolean shut_rd = false; + private boolean shut_wr = false; + + private SocketInputStream socketInputStream = null; + + /* number of threads using the FileDescriptor */ + protected int fdUseCount = 0; + + /* lock when increment/decrementing fdUseCount */ + protected Object fdLock = new Object(); + + /* indicates a close is pending on the file descriptor */ + protected boolean closePending = false; + + /* indicates connection reset state */ + private int CONNECTION_NOT_RESET = 0; + private int CONNECTION_RESET_PENDING = 1; + private int CONNECTION_RESET = 2; + private int resetState; + private Object resetLock = new Object(); + + /** + * Load net library into runtime. + */ + static { + java.security.AccessController.doPrivileged( + new sun.security.action.LoadLibraryAction("net")); + } + + /** + * Creates a socket with a boolean that specifies whether this + * is a stream socket (true) or an unconnected UDP socket (false). + */ + protected synchronized void create(boolean stream) throws IOException { + fd = new FileDescriptor(); + socketCreate(stream); + if (socket != null) + socket.setCreated(); + if (serverSocket != null) + serverSocket.setCreated(); + } + + /** + * Creates a socket and connects it to the specified port on + * the specified host. + * @param host the specified host + * @param port the specified port + */ + protected void connect(String host, int port) + throws UnknownHostException, IOException + { + IOException pending = null; + try { + InetAddress address = InetAddress.getByName(host); + this.port = port; + this.address = address; + + try { + connectToAddress(address, port, timeout); + return; + } catch (IOException e) { + pending = e; + } + } catch (UnknownHostException e) { + pending = e; + } + + // everything failed + close(); + throw pending; + } + + /** + * Creates a socket and connects it to the specified address on + * the specified port. + * @param address the address + * @param port the specified port + */ + protected void connect(InetAddress address, int port) throws IOException { + this.port = port; + this.address = address; + + try { + connectToAddress(address, port, timeout); + return; + } catch (IOException e) { + // everything failed + close(); + throw e; + } + } + + /** + * Creates a socket and connects it to the specified address on + * the specified port. + * @param address the address + * @param timeout the timeout value in milliseconds, or zero for no timeout. + * @throws IOException if connection fails + * @throws IllegalArgumentException if address is null or is a + * SocketAddress subclass not supported by this socket + * @since 1.4 + */ + protected void connect(SocketAddress address, int timeout) throws IOException { + if (address == null || !(address instanceof InetSocketAddress)) + throw new IllegalArgumentException("unsupported address type"); + InetSocketAddress addr = (InetSocketAddress) address; + if (addr.isUnresolved()) + throw new UnknownHostException(addr.getHostName()); + this.port = addr.getPort(); + this.address = addr.getAddress(); + + try { + connectToAddress(this.address, port, timeout); + return; + } catch (IOException e) { + // everything failed + close(); + throw e; + } + } + + private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { + if (address.isAnyLocalAddress()) { + doConnect(InetAddress.getLocalHost(), port, timeout); + } else { + doConnect(address, port, timeout); + } + } + + public void setOption(int opt, Object val) throws SocketException { + if (isClosedOrPending()) { + throw new SocketException("Socket Closed"); + } + boolean on = true; + switch (opt) { + /* check type safety b4 going native. These should never + * fail, since only java.Socket* has access to + * PlainSocketImpl.setOption(). + */ + case SO_LINGER: + if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) + throw new SocketException("Bad parameter for option"); + if (val instanceof Boolean) { + /* true only if disabling - enabling should be Integer */ + on = false; + } + break; + case SO_TIMEOUT: + if (val == null || (!(val instanceof Integer))) + throw new SocketException("Bad parameter for SO_TIMEOUT"); + int tmp = ((Integer) val).intValue(); + if (tmp < 0) + throw new IllegalArgumentException("timeout < 0"); + timeout = tmp; + break; + case IP_TOS: + if (val == null || !(val instanceof Integer)) { + throw new SocketException("bad argument for IP_TOS"); + } + trafficClass = ((Integer)val).intValue(); + break; + case SO_BINDADDR: + throw new SocketException("Cannot re-bind socket"); + case TCP_NODELAY: + if (val == null || !(val instanceof Boolean)) + throw new SocketException("bad parameter for TCP_NODELAY"); + on = ((Boolean)val).booleanValue(); + break; + case SO_SNDBUF: + case SO_RCVBUF: + if (val == null || !(val instanceof Integer) || + !(((Integer)val).intValue() > 0)) { + throw new SocketException("bad parameter for SO_SNDBUF " + + "or SO_RCVBUF"); + } + break; + case SO_KEEPALIVE: + if (val == null || !(val instanceof Boolean)) + throw new SocketException("bad parameter for SO_KEEPALIVE"); + on = ((Boolean)val).booleanValue(); + break; + case SO_OOBINLINE: + if (val == null || !(val instanceof Boolean)) + throw new SocketException("bad parameter for SO_OOBINLINE"); + on = ((Boolean)val).booleanValue(); + break; + case SO_REUSEADDR: + if (val == null || !(val instanceof Boolean)) + throw new SocketException("bad parameter for SO_REUSEADDR"); + on = ((Boolean)val).booleanValue(); + break; + default: + throw new SocketException("unrecognized TCP option: " + opt); + } + socketSetOption(opt, on, val); + } + public Object getOption(int opt) throws SocketException { + if (isClosedOrPending()) { + throw new SocketException("Socket Closed"); + } + if (opt == SO_TIMEOUT) { + return new Integer(timeout); + } + int ret = 0; + /* + * The native socketGetOption() knows about 3 options. + * The 32 bit value it returns will be interpreted according + * to what we're asking. A return of -1 means it understands + * the option but its turned off. It will raise a SocketException + * if "opt" isn't one it understands. + */ + + switch (opt) { + case TCP_NODELAY: + ret = socketGetOption(opt, null); + return Boolean.valueOf(ret != -1); + case SO_OOBINLINE: + ret = socketGetOption(opt, null); + return Boolean.valueOf(ret != -1); + case SO_LINGER: + ret = socketGetOption(opt, null); + return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret)); + case SO_REUSEADDR: + ret = socketGetOption(opt, null); + return Boolean.valueOf(ret != -1); + case SO_BINDADDR: + InetAddressContainer in = new InetAddressContainer(); + ret = socketGetOption(opt, in); + return in.addr; + case SO_SNDBUF: + case SO_RCVBUF: + ret = socketGetOption(opt, null); + return new Integer(ret); + case IP_TOS: + ret = socketGetOption(opt, null); + if (ret == -1) { // ipv6 tos + return new Integer(trafficClass); + } else { + return new Integer(ret); + } + case SO_KEEPALIVE: + ret = socketGetOption(opt, null); + return Boolean.valueOf(ret != -1); + // should never get here + default: + return null; + } + } + + /** + * The workhorse of the connection operation. Tries several times to + * establish a connection to the given . If unsuccessful, + * throws an IOException indicating what went wrong. + */ + + synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { + try { + FileDescriptor fd = acquireFD(); + try { + socketConnect(address, port, timeout); + // If we have a ref. to the Socket, then sets the flags + // created, bound & connected to true. + // This is normally done in Socket.connect() but some + // subclasses of Socket may call impl.connect() directly! + if (socket != null) { + socket.setBound(); + socket.setConnected(); + } + } finally { + releaseFD(); + } + } catch (IOException e) { + close(); + throw e; + } + } + + /** + * Binds the socket to the specified address of the specified local port. + * @param address the address + * @param port the port + */ + protected synchronized void bind(InetAddress address, int lport) + throws IOException + { + socketBind(address, lport); + if (socket != null) + socket.setBound(); + if (serverSocket != null) + serverSocket.setBound(); + } + + /** + * Listens, for a specified amount of time, for connections. + * @param count the amount of time to listen for connections + */ + protected synchronized void listen(int count) throws IOException { + socketListen(count); + } + + /** + * Accepts connections. + * @param s the connection + */ + protected synchronized void accept(SocketImpl s) throws IOException { + FileDescriptor fd = acquireFD(); + try { + socketAccept(s); + } finally { + releaseFD(); + } + } + + /** + * Gets an InputStream for this socket. + */ + protected synchronized InputStream getInputStream() throws IOException { + if (isClosedOrPending()) { + throw new IOException("Socket Closed"); + } + if (shut_rd) { + throw new IOException("Socket input is shutdown"); + } + if (socketInputStream == null) { + socketInputStream = new SocketInputStream(this); + } + return socketInputStream; + } + + void setInputStream(SocketInputStream in) { + socketInputStream = in; + } + + /** + * Gets an OutputStream for this socket. + */ + protected synchronized OutputStream getOutputStream() throws IOException { + if (isClosedOrPending()) { + throw new IOException("Socket Closed"); + } + if (shut_wr) { + throw new IOException("Socket output is shutdown"); + } + return new SocketOutputStream(this); + } + + void setFileDescriptor(FileDescriptor fd) { + this.fd = fd; + } + + void setAddress(InetAddress address) { + this.address = address; + } + + void setPort(int port) { + this.port = port; + } + + void setLocalPort(int localport) { + this.localport = localport; + } + + /** + * Returns the number of bytes that can be read without blocking. + */ + protected synchronized int available() throws IOException { + if (isClosedOrPending()) { + throw new IOException("Stream closed."); + } + + /* + * If connection has been reset then return 0 to indicate + * there are no buffered bytes. + */ + if (isConnectionReset()) { + return 0; + } + + /* + * If no bytes available and we were previously notified + * of a connection reset then we move to the reset state. + * + * If are notified of a connection reset then check + * again if there are bytes buffered on the socket. + */ + int n = 0; + try { + n = socketAvailable(); + if (n == 0 && isConnectionResetPending()) { + setConnectionReset(); + } + } catch (ConnectionResetException exc1) { + setConnectionResetPending(); + try { + n = socketAvailable(); + if (n == 0) { + setConnectionReset(); + } + } catch (ConnectionResetException exc2) { + } + } + return n; + } + + /** + * Closes the socket. + */ + protected void close() throws IOException { + synchronized(fdLock) { + if (fd != null) { + if (fdUseCount == 0) { + if (closePending) { + return; + } + closePending = true; + /* + * We close the FileDescriptor in two-steps - first the + * "pre-close" which closes the socket but doesn't + * release the underlying file descriptor. This operation + * may be lengthy due to untransmitted data and a long + * linger interval. Once the pre-close is done we do the + * actual socket to release the fd. + */ + try { + socketPreClose(); + } finally { + socketClose(); + } + fd = null; + return; + } else { + /* + * If a thread has acquired the fd and a close + * isn't pending then use a deferred close. + * Also decrement fdUseCount to signal the last + * thread that releases the fd to close it. + */ + if (!closePending) { + closePending = true; + fdUseCount--; + socketPreClose(); + } + } + } + } + } + + void reset() throws IOException { + if (fd != null) { + socketClose(); + } + fd = null; + super.reset(); + } + + + /** + * Shutdown read-half of the socket connection; + */ + protected void shutdownInput() throws IOException { + if (fd != null) { + socketShutdown(SHUT_RD); + if (socketInputStream != null) { + socketInputStream.setEOF(true); + } + shut_rd = true; + } + } + + /** + * Shutdown write-half of the socket connection; + */ + protected void shutdownOutput() throws IOException { + if (fd != null) { + socketShutdown(SHUT_WR); + shut_wr = true; + } + } + + protected boolean supportsUrgentData () { + return true; + } + + protected void sendUrgentData (int data) throws IOException { + if (fd == null) { + throw new IOException("Socket Closed"); + } + socketSendUrgentData (data); + } + + /** + * Cleans up if the user forgets to close it. + */ + protected void finalize() throws IOException { + close(); + } + + + /* + * "Acquires" and returns the FileDescriptor for this impl + * + * A corresponding releaseFD is required to "release" the + * FileDescriptor. + */ + FileDescriptor acquireFD() { + synchronized (fdLock) { + fdUseCount++; + return fd; + } + } + + /* + * "Release" the FileDescriptor for this impl. + * + * If the use count goes to -1 then the socket is closed. + */ + void releaseFD() { + synchronized (fdLock) { + fdUseCount--; + if (fdUseCount == -1) { + if (fd != null) { + try { + socketClose(); + } catch (IOException e) { + } finally { + fd = null; + } + } + } + } + } + + public boolean isConnectionReset() { + synchronized (resetLock) { + return (resetState == CONNECTION_RESET); + } + } + + public boolean isConnectionResetPending() { + synchronized (resetLock) { + return (resetState == CONNECTION_RESET_PENDING); + } + } + + public void setConnectionReset() { + synchronized (resetLock) { + resetState = CONNECTION_RESET; + } + } + + public void setConnectionResetPending() { + synchronized (resetLock) { + if (resetState == CONNECTION_NOT_RESET) { + resetState = CONNECTION_RESET_PENDING; + } + } + + } + + /* + * Return true if already closed or close is pending + */ + public boolean isClosedOrPending() { + /* + * Lock on fdLock to ensure that we wait if a + * close is in progress. + */ + synchronized (fdLock) { + if (closePending || (fd == null)) { + return true; + } else { + return false; + } + } + } + + /* + * Return the current value of SO_TIMEOUT + */ + public int getTimeout() { + return timeout; + } + + /* + * "Pre-close" a socket by dup'ing the file descriptor - this enables + * the socket to be closed without releasing the file descriptor. + */ + private void socketPreClose() throws IOException { + socketClose0(true); + } + + /* + * Close the socket (and release the file descriptor). + */ + protected void socketClose() throws IOException { + socketClose0(false); + } + + abstract void socketCreate(boolean isServer) throws IOException; + abstract void socketConnect(InetAddress address, int port, int timeout) + throws IOException; + abstract void socketBind(InetAddress address, int port) + throws IOException; + abstract void socketListen(int count) + throws IOException; + abstract void socketAccept(SocketImpl s) + throws IOException; + abstract int socketAvailable() + throws IOException; + abstract void socketClose0(boolean useDeferredClose) + throws IOException; + abstract void socketShutdown(int howto) + throws IOException; + abstract void socketSetOption(int cmd, boolean on, Object value) + throws SocketException; + abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException; + abstract int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException; + abstract void socketSendUrgentData(int data) + throws IOException; + + public final static int SHUT_RD = 0; + public final static int SHUT_WR = 1; +} + +class InetAddressContainer { + InetAddress addr; +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/DatagramSocket.java --- a/j2se/src/share/classes/java/net/DatagramSocket.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/net/DatagramSocket.java Thu Jul 05 23:47:33 2007 +0000 @@ -60,7 +60,7 @@ * UDP port 8888. * * @author Pavani Diwanji - * @version 1.110, 05/05/07 + * @version 1.111, 06/11/07 * @see java.net.DatagramPacket * @see java.nio.channels.DatagramChannel * @since JDK1.0 @@ -309,29 +309,10 @@ impl = factory.createDatagramSocketImpl(); checkOldImpl(); } else { - if (implClass == null) { - String prefix = null; - try { - prefix = (String) AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("impl.prefix", "Plain")); - implClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); - } catch (Exception e) { - System.err.println("Can't find class: java.net." + - prefix + - "DatagramSocketImpl: check impl.prefix property"); - } - if (implClass == null) - implClass = java.net.PlainDatagramSocketImpl.class; - } - try { - impl = (DatagramSocketImpl) implClass.newInstance(); - } catch (Exception e) { - throw new SocketException("can't instantiate DatagramSocketImpl"); - } - // No need to do a checkOldImpl() here, we know it's an up to date - // SocketImpl! - if (!(impl instanceof java.net.PlainDatagramSocketImpl)) - checkOldImpl(); + boolean isMulticast = (this instanceof MulticastSocket) ? true : false; + impl = DefaultDatagramSocketImplFactory.createDatagramSocketImpl(isMulticast); + + checkOldImpl(); } } // creates a udp socket @@ -1182,7 +1163,7 @@ } /** - * The factory for all datagram sockets. + * User defined factory for all datagram sockets. */ static DatagramSocketImplFactory factory; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/InetAddress.java --- a/j2se/src/share/classes/java/net/InetAddress.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/net/InetAddress.java Thu Jul 05 23:47:33 2007 +0000 @@ -171,7 +171,7 @@ * * * @author Chris Warth - * @version 1.124, 05/05/07 + * @version 1.125, 06/12/07 * @see java.net.InetAddress#getByAddress(byte[]) * @see java.net.InetAddress#getByAddress(java.lang.String, byte[]) * @see java.net.InetAddress#getAllByName(java.lang.String) @@ -1342,8 +1342,18 @@ return getByAddress(null, addr); } + private static InetAddress cachedLocalHost = null; + private static long cacheTime = 0; + private static final long maxCacheTime = 5000L; + private static final Object cacheLock = new Object(); + /** - * Returns the local host. + * Returns the address of the local host. This is achieved by retrieving + * the name of the host from the system, then resolving that name into + * an InetAddress. + * + *

Note: The resolved address may be cached for a short period of time. + *

* *

If there is a security manager, its * checkConnect method is called @@ -1352,12 +1362,13 @@ * If the operation is not allowed, an InetAddress representing * the loopback address is returned. * - * @return the IP address of the local host. + * @return the address of the local host. * - * @exception UnknownHostException if no IP address for the - * host could be found. + * @exception UnknownHostException if the local host name could not + * be resolved into an address. * * @see SecurityManager#checkConnect + * @see java.net.InetAddress#getByName(java.lang.String) */ public static InetAddress getLocalHost() throws UnknownHostException { @@ -1373,17 +1384,32 @@ return impl.loopbackAddress(); } - // we are calling getAddressFromNameService directly - // to avoid getting localHost from cache + InetAddress ret = null; + synchronized (cacheLock) { + long now = System.currentTimeMillis(); + if (cachedLocalHost != null) { + if ((now - cacheTime) < maxCacheTime) // Less than 5s old? + ret = cachedLocalHost; + else + cachedLocalHost = null; + } - InetAddress[] localAddrs; - try { - localAddrs = - (InetAddress[]) InetAddress.getAddressFromNameService(local); - } catch (UnknownHostException uhe) { - throw new UnknownHostException(local + ": " + uhe.getMessage()); + // we are calling getAddressFromNameService directly + // to avoid getting localHost from cache + if (ret == null) { + InetAddress[] localAddrs; + try { + localAddrs = + (InetAddress[]) InetAddress.getAddressFromNameService(local); + } catch (UnknownHostException uhe) { + throw new UnknownHostException(local + ": " + uhe.getMessage()); + } + cachedLocalHost = localAddrs[0]; + cacheTime = now; + ret = localAddrs[0]; + } } - return localAddrs[0]; + return ret; } catch (java.lang.SecurityException e) { return impl.loopbackAddress(); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/PlainDatagramSocketImpl.java --- a/j2se/src/share/classes/java/net/PlainDatagramSocketImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,380 +0,0 @@ -/* - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.net; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.io.InterruptedIOException; -import java.util.Enumeration; - -/** - * Concrete datagram and multicast socket implementation base class. - * Note: This is not a public class, so that applets cannot call - * into the implementation directly and hence cannot bypass the - * security checks present in the DatagramSocket and MulticastSocket - * classes. - * - * @author Pavani Diwanji - */ - -class PlainDatagramSocketImpl extends DatagramSocketImpl -{ - /* timeout value for receive() */ - private int timeout = 0; - private int trafficClass = 0; - private boolean connected = false; - private InetAddress connectedAddress = null; - private int connectedPort = -1; - - /* cached socket options */ - private int multicastInterface = 0; - private boolean loopbackMode = true; - private int ttl = -1; - - /* Used for IPv6 on Windows only */ - private FileDescriptor fd1; - private int fduse=-1; /* saved between peek() and receive() calls */ - - /* saved between successive calls to receive, if data is detected - * on both sockets at same time. To ensure that one socket is not - * starved, they rotate using this field - */ - private int lastfd=-1; - - /* - * Needed for ipv6 on windows because we need to know - * if the socket was bound to ::0 or 0.0.0.0, when a caller - * asks for it. In this case, both sockets are used, but we - * don't know whether the caller requested ::0 or 0.0.0.0 - * and need to remember it here. - */ - private InetAddress anyLocalBoundAddr=null; - - /** - * Load net library into runtime. - */ - static { - java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); - init(); - } - - /** - * Creates a datagram socket - */ - protected synchronized void create() throws SocketException { - fd = new FileDescriptor(); - fd1 = new FileDescriptor(); - datagramSocketCreate(); - } - - /** - * Binds a datagram socket to a local port. - */ - protected synchronized void bind(int lport, InetAddress laddr) - throws SocketException { - - bind0(lport, laddr); - if (laddr.isAnyLocalAddress()) { - anyLocalBoundAddr = laddr; - } - } - - protected synchronized native void bind0(int lport, InetAddress laddr) - throws SocketException; - - /** - * Sends a datagram packet. The packet contains the data and the - * destination address to send the packet to. - * @param packet to be sent. - */ - protected native void send(DatagramPacket p) throws IOException; - - /** - * Connects a datagram socket to a remote destination. This associates the remote - * address with the local socket so that datagrams may only be sent to this destination - * and received from this destination. - * @param address the remote InetAddress to connect to - * @param port the remote port number - */ - protected void connect(InetAddress address, int port) throws SocketException { - connect0(address, port); - connectedAddress = address; - connectedPort = port; - connected = true; - } - - /** - * Disconnects a previously connected socket. Does nothing if the socket was - * not connected already. - */ - protected void disconnect() { - disconnect0(connectedAddress.family); - connected = false; - connectedAddress = null; - connectedPort = -1; - } - - /** - * Peek at the packet to see who it is from. - * @param return the address which the packet came from. - */ - protected synchronized native int peek(InetAddress i) throws IOException; - protected synchronized native int peekData(DatagramPacket p) throws IOException; - /** - * Receive the datagram packet. - * @param Packet Received. - */ - protected synchronized void receive(DatagramPacket p) - throws IOException { - try { - receive0(p); - } finally { - fduse = -1; - } - } - - protected synchronized native void receive0(DatagramPacket p) - throws IOException; - - /** - * Set the TTL (time-to-live) option. - * @param TTL to be set. - */ - protected native void setTimeToLive(int ttl) throws IOException; - - /** - * Get the TTL (time-to-live) option. - */ - protected native int getTimeToLive() throws IOException; - - /** - * Set the TTL (time-to-live) option. - * @param TTL to be set. - */ - protected native void setTTL(byte ttl) throws IOException; - - /** - * Get the TTL (time-to-live) option. - */ - protected native byte getTTL() throws IOException; - - /** - * Join the multicast group. - * @param multicast address to join. - */ - protected void join(InetAddress inetaddr) throws IOException { - join(inetaddr, null); - } - - /** - * Leave the multicast group. - * @param multicast address to leave. - */ - protected void leave(InetAddress inetaddr) throws IOException { - leave(inetaddr, null); - } - /** - * Join the multicast group. - * @param multicast address to join. - * @param netIf specifies the local interface to receive multicast - * datagram packets - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - - protected void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) - throw new IllegalArgumentException("Unsupported address type"); - join(((InetSocketAddress)mcastaddr).getAddress(), netIf); - } - - private native void join(InetAddress inetaddr, NetworkInterface netIf) - throws IOException; - - /** - * Leave the multicast group. - * @param multicast address to leave. - * @param netIf specified the local interface to leave the group at - * @throws IllegalArgumentException if mcastaddr is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - protected void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - if (mcastaddr == null || !(mcastaddr instanceof InetSocketAddress)) - throw new IllegalArgumentException("Unsupported address type"); - leave(((InetSocketAddress)mcastaddr).getAddress(), netIf); - } - - private native void leave(InetAddress inetaddr, NetworkInterface netIf) - throws IOException; - - /** - * Close the socket. - */ - protected void close() { - if (fd != null || fd1 != null) { - datagramSocketClose(); - fd = null; - fd1 = null; - } - } - - protected void finalize() { - close(); - } - - /** - * set a value - since we only support (setting) binary options - * here, o must be a Boolean - */ - - public void setOption(int optID, Object o) throws SocketException { - if (fd == null && fd1 == null) { - throw new SocketException("Socket Closed"); - } - switch (optID) { - /* check type safety b4 going native. These should never - * fail, since only java.Socket* has access to - * PlainSocketImpl.setOption(). - */ - case SO_TIMEOUT: - if (o == null || !(o instanceof Integer)) { - throw new SocketException("bad argument for SO_TIMEOUT"); - } - int tmp = ((Integer) o).intValue(); - if (tmp < 0) - throw new IllegalArgumentException("timeout < 0"); - timeout = tmp; - return; - case IP_TOS: - if (o == null || !(o instanceof Integer)) { - throw new SocketException("bad argument for IP_TOS"); - } - trafficClass = ((Integer)o).intValue(); - break; - case SO_REUSEADDR: - if (o == null || !(o instanceof Boolean)) { - throw new SocketException("bad argument for SO_REUSEADDR"); - } - break; - case SO_BROADCAST: - if (o == null || !(o instanceof Boolean)) { - throw new SocketException("bad argument for SO_BROADCAST"); - } - break; - case SO_BINDADDR: - throw new SocketException("Cannot re-bind Socket"); - case SO_RCVBUF: - case SO_SNDBUF: - if (o == null || !(o instanceof Integer) || - ((Integer)o).intValue() < 0) { - throw new SocketException("bad argument for SO_SNDBUF or " + - "SO_RCVBUF"); - } - break; - case IP_MULTICAST_IF: - if (o == null || !(o instanceof InetAddress)) - throw new SocketException("bad argument for IP_MULTICAST_IF"); - break; - case IP_MULTICAST_IF2: - if (o == null || !(o instanceof NetworkInterface)) - throw new SocketException("bad argument for IP_MULTICAST_IF2"); - break; - case IP_MULTICAST_LOOP: - if (o == null || !(o instanceof Boolean)) - throw new SocketException("bad argument for IP_MULTICAST_LOOP"); - break; - default: - throw new SocketException("invalid option: " + optID); - } - socketSetOption(optID, o); - } - - /* - * get option's state - set or not - */ - - public Object getOption(int optID) throws SocketException { - if (fd == null && fd1 == null) { - throw new SocketException("Socket Closed"); - } - - Object result; - - switch (optID) { - case SO_TIMEOUT: - result = new Integer(timeout); - break; - - case IP_TOS: - result = socketGetOption(optID); - if ( ((Integer)result).intValue() == -1) { - result = new Integer(trafficClass); - } - break; - - case SO_BINDADDR: - if (fd != null && fd1 != null) { - return anyLocalBoundAddr; - } - /* fall through */ - case IP_MULTICAST_IF: - case IP_MULTICAST_IF2: - case SO_RCVBUF: - case SO_SNDBUF: - case IP_MULTICAST_LOOP: - case SO_REUSEADDR: - case SO_BROADCAST: - result = socketGetOption(optID); - break; - - default: - throw new SocketException("invalid option: " + optID); - } - - return result; - } - - private native void datagramSocketCreate() throws SocketException; - private native void datagramSocketClose(); - private native void socketSetOption(int opt, Object val) - throws SocketException; - private native Object socketGetOption(int opt) throws SocketException; - - private native void connect0(InetAddress address, int port) throws SocketException; - private native void disconnect0(int family); - - /** - * Perform class load-time initializations. - */ - private native static void init(); - -} - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/PlainSocketImpl.java --- a/j2se/src/share/classes/java/net/PlainSocketImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,708 +0,0 @@ -/* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package java.net; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.InterruptedIOException; -import java.io.FileDescriptor; -import java.io.ByteArrayOutputStream; - -import sun.net.ConnectionResetException; - -/** - * Default Socket Implementation. This implementation does - * not implement any security checks. - * Note this class should NOT be public. - * - * @author Steven B. Byrne - * @version 1.73, 05/05/07 - */ -class PlainSocketImpl extends SocketImpl -{ - /* instance variable for SO_TIMEOUT */ - int timeout; // timeout in millisec - // traffic class - private int trafficClass; - - private boolean shut_rd = false; - private boolean shut_wr = false; - - private SocketInputStream socketInputStream = null; - - /* number of threads using the FileDescriptor */ - private int fdUseCount = 0; - - /* lock when increment/decrementing fdUseCount */ - private Object fdLock = new Object(); - - /* indicates a close is pending on the file descriptor */ - private boolean closePending = false; - - /* indicates connection reset state */ - private int CONNECTION_NOT_RESET = 0; - private int CONNECTION_RESET_PENDING = 1; - private int CONNECTION_RESET = 2; - private int resetState; - private Object resetLock = new Object(); - - /* second fd, used for ipv6 on windows only. - * fd1 is used for listeners and for client sockets at initialization - * until the socket is connected. Up to this point fd always refers - * to the ipv4 socket and fd1 to the ipv6 socket. After the socket - * becomes connected, fd always refers to the connected socket - * (either v4 or v6) and fd1 is closed. - * - * For ServerSockets, fd always refers to the v4 listener and - * fd1 the v6 listener. - */ - private FileDescriptor fd1; - /* - * Needed for ipv6 on windows because we need to know - * if the socket is bound to ::0 or 0.0.0.0, when a caller - * asks for it. Otherwise we don't know which socket to ask. - */ - private InetAddress anyLocalBoundAddr=null; - - /* to prevent starvation when listening on two sockets, this is - * is used to hold the id of the last socket we accepted on. - */ - private int lastfd = -1; - - /** - * Load net library into runtime. - */ - static { - java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("net")); - initProto(); - } - - /** - * Constructs an empty instance. - */ - PlainSocketImpl() { } - - /** - * Constructs an instance with the given file descriptor. - * Note, this will not work with IPv6, since two fds are used. - */ - PlainSocketImpl(FileDescriptor fd) { - this.fd = fd; - } - - /** - * Creates a socket with a boolean that specifies whether this - * is a stream socket (true) or an unconnected UDP socket (false). - */ - protected synchronized void create(boolean stream) throws IOException { - fd = new FileDescriptor(); - fd1 = new FileDescriptor(); - socketCreate(stream); - if (socket != null) - socket.setCreated(); - if (serverSocket != null) - serverSocket.setCreated(); - } - - /** - * Creates a socket and connects it to the specified port on - * the specified host. - * @param host the specified host - * @param port the specified port - */ - protected void connect(String host, int port) - throws UnknownHostException, IOException - { - IOException pending = null; - try { - InetAddress address = InetAddress.getByName(host); - - try { - connectToAddress(address, port, timeout); - return; - } catch (IOException e) { - pending = e; - } - } catch (UnknownHostException e) { - pending = e; - } - - // everything failed - close(); - throw pending; - } - - /** - * Creates a socket and connects it to the specified address on - * the specified port. - * @param address the address - * @param port the specified port - */ - protected void connect(InetAddress address, int port) throws IOException { - this.port = port; - this.address = address; - - try { - connectToAddress(address, port, timeout); - return; - } catch (IOException e) { - // everything failed - close(); - throw e; - } - } - - /** - * Creates a socket and connects it to the specified address on - * the specified port. - * @param address the address - * @param timeout the timeout value in milliseconds, or zero for no timeout. - * @throws IOException if connection fails - * @throws IllegalArgumentException if address is null or is a - * SocketAddress subclass not supported by this socket - * @since 1.4 - */ - protected void connect(SocketAddress address, int timeout) throws IOException { - if (address == null || !(address instanceof InetSocketAddress)) - throw new IllegalArgumentException("unsupported address type"); - InetSocketAddress addr = (InetSocketAddress) address; - if (addr.isUnresolved()) - throw new UnknownHostException(addr.getHostName()); - this.port = addr.getPort(); - this.address = addr.getAddress(); - - try { - connectToAddress(this.address, port, timeout); - return; - } catch (IOException e) { - // everything failed - close(); - throw e; - } - } - - private void connectToAddress(InetAddress address, int port, int timeout) throws IOException { - if (address.isAnyLocalAddress()) { - doConnect(InetAddress.getLocalHost(), port, timeout); - } else { - doConnect(address, port, timeout); - } - } - - public void setOption(int opt, Object val) throws SocketException { - if (isClosedOrPending()) { - throw new SocketException("Socket Closed"); - } - boolean on = true; - switch (opt) { - /* check type safety b4 going native. These should never - * fail, since only java.Socket* has access to - * PlainSocketImpl.setOption(). - */ - case SO_LINGER: - if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean))) - throw new SocketException("Bad parameter for option"); - if (val instanceof Boolean) { - /* true only if disabling - enabling should be Integer */ - on = false; - } - break; - case SO_TIMEOUT: - if (val == null || (!(val instanceof Integer))) - throw new SocketException("Bad parameter for SO_TIMEOUT"); - int tmp = ((Integer) val).intValue(); - if (tmp < 0) - throw new IllegalArgumentException("timeout < 0"); - timeout = tmp; - break; - case IP_TOS: - if (val == null || !(val instanceof Integer)) { - throw new SocketException("bad argument for IP_TOS"); - } - trafficClass = ((Integer)val).intValue(); - break; - case SO_BINDADDR: - throw new SocketException("Cannot re-bind socket"); - case TCP_NODELAY: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for TCP_NODELAY"); - on = ((Boolean)val).booleanValue(); - break; - case SO_SNDBUF: - case SO_RCVBUF: - if (val == null || !(val instanceof Integer) || - !(((Integer)val).intValue() > 0)) { - throw new SocketException("bad parameter for SO_SNDBUF " + - "or SO_RCVBUF"); - } - break; - case SO_KEEPALIVE: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_KEEPALIVE"); - on = ((Boolean)val).booleanValue(); - break; - case SO_OOBINLINE: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_OOBINLINE"); - on = ((Boolean)val).booleanValue(); - break; - case SO_REUSEADDR: - if (val == null || !(val instanceof Boolean)) - throw new SocketException("bad parameter for SO_REUSEADDR"); - on = ((Boolean)val).booleanValue(); - break; - default: - throw new SocketException("unrecognized TCP option: " + opt); - } - socketSetOption(opt, on, val); - } - public Object getOption(int opt) throws SocketException { - if (isClosedOrPending()) { - throw new SocketException("Socket Closed"); - } - if (opt == SO_TIMEOUT) { - return new Integer(timeout); - } - int ret = 0; - /* - * The native socketGetOption() knows about 3 options. - * The 32 bit value it returns will be interpreted according - * to what we're asking. A return of -1 means it understands - * the option but its turned off. It will raise a SocketException - * if "opt" isn't one it understands. - */ - - switch (opt) { - case TCP_NODELAY: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_OOBINLINE: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_LINGER: - ret = socketGetOption(opt, null); - return (ret == -1) ? Boolean.FALSE: (Object)(new Integer(ret)); - case SO_REUSEADDR: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - case SO_BINDADDR: - if (fd != null && fd1 != null ) { - /* must be unbound or else bound to anyLocal */ - return anyLocalBoundAddr; - } - InetAddressContainer in = new InetAddressContainer(); - ret = socketGetOption(opt, in); - return in.addr; - case SO_SNDBUF: - case SO_RCVBUF: - ret = socketGetOption(opt, null); - return new Integer(ret); - case IP_TOS: - ret = socketGetOption(opt, null); - if (ret == -1) { // ipv6 tos - return new Integer(trafficClass); - } else { - return new Integer(ret); - } - case SO_KEEPALIVE: - ret = socketGetOption(opt, null); - return Boolean.valueOf(ret != -1); - // should never get here - default: - return null; - } - } - - /** - * The workhorse of the connection operation. Tries several times to - * establish a connection to the given . If unsuccessful, - * throws an IOException indicating what went wrong. - */ - - private synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { - try { - FileDescriptor fd = acquireFD(); - try { - socketConnect(address, port, timeout); - // If we have a ref. to the Socket, then sets the flags - // created, bound & connected to true. - // This is normally done in Socket.connect() but some - // subclasses of Socket may call impl.connect() directly! - if (socket != null) { - socket.setBound(); - socket.setConnected(); - } - } finally { - releaseFD(); - } - } catch (IOException e) { - close(); - throw e; - } - } - - /** - * Binds the socket to the specified address of the specified local port. - * @param address the address - * @param port the port - */ - protected synchronized void bind(InetAddress address, int lport) - throws IOException - { - socketBind(address, lport); - if (socket != null) - socket.setBound(); - if (serverSocket != null) - serverSocket.setBound(); - if (address.isAnyLocalAddress()) { - anyLocalBoundAddr = address; - } - } - - /** - * Listens, for a specified amount of time, for connections. - * @param count the amount of time to listen for connections - */ - protected synchronized void listen(int count) throws IOException { - socketListen(count); - } - - /** - * Accepts connections. - * @param s the connection - */ - protected synchronized void accept(SocketImpl s) throws IOException { - FileDescriptor fd = acquireFD(); - try { - socketAccept(s); - } finally { - releaseFD(); - } - } - - /** - * Gets an InputStream for this socket. - */ - protected synchronized InputStream getInputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_rd) { - throw new IOException("Socket input is shutdown"); - } - if (socketInputStream == null) { - socketInputStream = new SocketInputStream(this); - } - return socketInputStream; - } - - void setInputStream(SocketInputStream in) { - socketInputStream = in; - } - - /** - * Gets an OutputStream for this socket. - */ - protected synchronized OutputStream getOutputStream() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Socket Closed"); - } - if (shut_wr) { - throw new IOException("Socket output is shutdown"); - } - return new SocketOutputStream(this); - } - - /** - * Returns the number of bytes that can be read without blocking. - */ - protected synchronized int available() throws IOException { - if (isClosedOrPending()) { - throw new IOException("Stream closed."); - } - - /* - * If connection has been reset then return 0 to indicate - * there are no buffered bytes. - */ - if (isConnectionReset()) { - return 0; - } - - /* - * If no bytes available and we were previously notified - * of a connection reset then we move to the reset state. - * - * If are notified of a connection reset then check - * again if there are bytes buffered on the socket. - */ - int n = 0; - try { - n = socketAvailable(); - if (n == 0 && isConnectionResetPending()) { - setConnectionReset(); - } - } catch (ConnectionResetException exc1) { - setConnectionResetPending(); - try { - n = socketAvailable(); - if (n == 0) { - setConnectionReset(); - } - } catch (ConnectionResetException exc2) { - } - } - return n; - } - - /** - * Closes the socket. - */ - protected void close() throws IOException { - synchronized(fdLock) { - if (fd != null || fd1 != null) { - if (fdUseCount == 0) { - if (closePending) { - return; - } - closePending = true; - /* - * We close the FileDescriptor in two-steps - first the - * "pre-close" which closes the socket but doesn't - * release the underlying file descriptor. This operation - * may be lengthy due to untransmitted data and a long - * linger interval. Once the pre-close is done we do the - * actual socket to release the fd. - */ - try { - socketPreClose(); - } finally { - socketClose(); - } - fd = null; - fd1 = null; - return; - } else { - /* - * If a thread has acquired the fd and a close - * isn't pending then use a deferred close. - * Also decrement fdUseCount to signal the last - * thread that releases the fd to close it. - */ - if (!closePending) { - closePending = true; - fdUseCount--; - socketPreClose(); - } - } - } - } - } - - void reset() throws IOException { - if (fd != null || fd1 != null) { - socketClose(); - } - fd = null; - fd1 = null; - super.reset(); - } - - - /** - * Shutdown read-half of the socket connection; - */ - protected void shutdownInput() throws IOException { - if (fd != null) { - socketShutdown(SHUT_RD); - if (socketInputStream != null) { - socketInputStream.setEOF(true); - } - shut_rd = true; - } - } - - /** - * Shutdown write-half of the socket connection; - */ - protected void shutdownOutput() throws IOException { - if (fd != null) { - socketShutdown(SHUT_WR); - shut_wr = true; - } - } - - protected boolean supportsUrgentData () { - return true; - } - - protected void sendUrgentData (int data) throws IOException { - if (fd == null) { - throw new IOException("Socket Closed"); - } - socketSendUrgentData (data); - } - - /** - * Cleans up if the user forgets to close it. - */ - protected void finalize() throws IOException { - close(); - } - - - /* - * "Acquires" and returns the FileDescriptor for this impl - * - * A corresponding releaseFD is required to "release" the - * FileDescriptor. - */ - public final FileDescriptor acquireFD() { - synchronized (fdLock) { - fdUseCount++; - return fd; - } - } - - /* - * "Release" the FileDescriptor for this impl. - * - * If the use count goes to -1 then the socket is closed. - */ - public final void releaseFD() { - synchronized (fdLock) { - fdUseCount--; - if (fdUseCount == -1) { - if (fd != null) { - try { - socketClose(); - } catch (IOException e) { - } finally { - fd = null; - } - } - } - } - } - - public boolean isConnectionReset() { - synchronized (resetLock) { - return (resetState == CONNECTION_RESET); - } - } - - public boolean isConnectionResetPending() { - synchronized (resetLock) { - return (resetState == CONNECTION_RESET_PENDING); - } - } - - public void setConnectionReset() { - synchronized (resetLock) { - resetState = CONNECTION_RESET; - } - } - - public void setConnectionResetPending() { - synchronized (resetLock) { - if (resetState == CONNECTION_NOT_RESET) { - resetState = CONNECTION_RESET_PENDING; - } - } - - } - - /* - * Return true if already closed or close is pending - */ - public boolean isClosedOrPending() { - /* - * Lock on fdLock to ensure that we wait if a - * close is in progress. - */ - synchronized (fdLock) { - if (closePending || (fd == null && fd1 == null)) { - return true; - } else { - return false; - } - } - } - - /* - * Return the current value of SO_TIMEOUT - */ - public int getTimeout() { - return timeout; - } - - /* - * "Pre-close" a socket by dup'ing the file descriptor - this enables - * the socket to be closed without releasing the file descriptor. - */ - private void socketPreClose() throws IOException { - socketClose0(true); - } - - /* - * Close the socket (and release the file descriptor). - */ - private void socketClose() throws IOException { - socketClose0(false); - } - - private native void socketCreate(boolean isServer) throws IOException; - private native void socketConnect(InetAddress address, int port, int timeout) - throws IOException; - private native void socketBind(InetAddress address, int port) - throws IOException; - private native void socketListen(int count) - throws IOException; - private native void socketAccept(SocketImpl s) - throws IOException; - private native int socketAvailable() - throws IOException; - private native void socketClose0(boolean useDeferredClose) - throws IOException; - private native void socketShutdown(int howto) - throws IOException; - private static native void initProto(); - private native void socketSetOption(int cmd, boolean on, Object value) - throws SocketException; - private native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; - private native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException; - private native void socketSendUrgentData(int data) - throws IOException; - - public final static int SHUT_RD = 0; - public final static int SHUT_WR = 1; -} - -class InetAddressContainer { - InetAddress addr; -} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/SocketInputStream.java --- a/j2se/src/share/classes/java/net/SocketInputStream.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/net/SocketInputStream.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * SocketInputStream. Note that this class should NOT be * public. * - * @version 1.41, 05/05/07 + * @version 1.42, 06/11/07 * @author Jonathan Payne * @author Arthur van Hoff */ @@ -48,7 +48,7 @@ } private boolean eof; - private PlainSocketImpl impl = null; + private AbstractPlainSocketImpl impl = null; private byte temp[]; private Socket socket = null; @@ -58,7 +58,7 @@ * that the fd will not be closed. * @param impl the implemented socket input stream */ - SocketInputStream(PlainSocketImpl impl) throws IOException { + SocketInputStream(AbstractPlainSocketImpl impl) throws IOException { super(impl.getFileDescriptor()); this.impl = impl; socket = impl.getSocket(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/SocketOutputStream.java --- a/j2se/src/share/classes/java/net/SocketOutputStream.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/net/SocketOutputStream.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ * SocketOutputStream. Note that this class should NOT be * public. * - * @version 1.37, 05/05/07 + * @version 1.38, 06/11/07 * @author Jonathan Payne * @author Arthur van Hoff */ @@ -45,7 +45,7 @@ init(); } - private PlainSocketImpl impl = null; + private AbstractPlainSocketImpl impl = null; private byte temp[] = new byte[1]; private Socket socket = null; @@ -55,7 +55,7 @@ * that the fd will not be closed. * @param impl the socket output stream inplemented */ - SocketOutputStream(PlainSocketImpl impl) throws IOException { + SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException { super(impl.getFileDescriptor()); this.impl = impl; socket = impl.getSocket(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/net/SocksSocketImpl.java --- a/j2se/src/share/classes/java/net/SocksSocketImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/net/SocksSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -992,12 +992,19 @@ ((SocksSocketImpl)s).external_address = real_end; } if (s instanceof PlainSocketImpl) { - ((PlainSocketImpl)s).setInputStream((SocketInputStream) in); + PlainSocketImpl psi = (PlainSocketImpl) s; + psi.setInputStream((SocketInputStream) in); + psi.setFileDescriptor(cmdsock.getImpl().getFileDescriptor()); + psi.setAddress(cmdsock.getImpl().getInetAddress()); + psi.setPort(cmdsock.getImpl().getPort()); + psi.setLocalPort(cmdsock.getImpl().getLocalPort()); + } else { + s.fd = cmdsock.getImpl().fd; + s.address = cmdsock.getImpl().address; + s.port = cmdsock.getImpl().port; + s.localport = cmdsock.getImpl().localport; } - s.fd = cmdsock.getImpl().fd; - s.address = cmdsock.getImpl().address; - s.port = cmdsock.getImpl().port; - s.localport = cmdsock.getImpl().localport; + // Need to do that so that the socket won't be closed // when the ServerSocket is closed by the user. // It kinds of detaches the Socket because it is now diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/nio/Bits.java --- a/j2se/src/share/classes/java/nio/Bits.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/nio/Bits.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -567,11 +567,15 @@ // -- Processor and memory-system properties -- - private static ByteOrder byteOrder = null; + private static final ByteOrder byteOrder; static ByteOrder byteOrder() { - if (byteOrder != null) - return byteOrder; + if (byteOrder == null) + throw new Error("Unknown byte order"); + return byteOrder; + } + + static { long a = unsafe.allocateMemory(8); try { unsafe.putLong(a, 0x0102030405060708L); @@ -580,12 +584,12 @@ case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break; case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break; default: - throw new Error("Unknown byte order"); + assert false; + byteOrder = null; } } finally { unsafe.freeMemory(a); } - return byteOrder; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/nio/Buffer.java --- a/j2se/src/share/classes/java/nio/Buffer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/nio/Buffer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ * *

There is one subclass of this class for each non-boolean primitive type. * - * + * *

Transferring data

* *

Each subclass of this class defines two categories of get and @@ -104,8 +104,8 @@ *

A newly-created buffer always has a position of zero and a mark that is * undefined. The initial limit may be zero, or it may be some other value * that depends upon the type of the buffer and the manner in which it is - * constructed. The initial content of a buffer is, in general, - * undefined. + * constructed. Each element of a newly-allocated buffer is initialized + * to zero. * * *

Clearing, flipping, and rewinding

@@ -168,7 +168,6 @@ * * @author Mark Reinhold * @author JSR-51 Expert Group - * @version 1.45, 07/05/05 * @since 1.4 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/nio/X-Buffer.java --- a/j2se/src/share/classes/java/nio/X-Buffer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/nio/X-Buffer.java Thu Jul 05 23:47:33 2007 +0000 @@ -229,7 +229,7 @@ * *
  * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
- * + * #end[byte] #if[char] * @@ -251,7 +251,6 @@ * * @author Mark Reinhold * @author JSR-51 Expert Group - * @version 1.69, 07/05/05 * @since 1.4 */ @@ -291,8 +290,9 @@ * Allocates a new direct $fulltype$ buffer. * *

The new buffer's position will be zero, its limit will be its - * capacity, and its mark will be undefined. Whether or not it has a - * {@link #hasArray backing array} is unspecified.

+ * capacity, its mark will be undefined, and each of its elements will be + * initialized to zero. Whether or not it has a + * {@link #hasArray backing array} is unspecified. * * @param capacity * The new buffer's capacity, in $fulltype$s @@ -312,7 +312,8 @@ * Allocates a new $fulltype$ buffer. * *

The new buffer's position will be zero, its limit will be its - * capacity, and its mark will be undefined. It will have a {@link #array + * capacity, its mark will be undefined, and each of its elements will be + * initialized to zero. It will have a {@link #array * backing array}, and its {@link #arrayOffset array * offset} will be zero. * @@ -380,7 +381,7 @@ * array.length, its position will be zero, and its mark will be * undefined. Its {@link #array backing array} will be the * given array, and its {@link #arrayOffset array offset} will - * be zero.

+ * be zero.

* * @param array * The array that will back this buffer @@ -400,7 +401,7 @@ * rewinding of the buffer is performed. * * @param target the buffer to read characters into - * @return The number of characters added to the buffer, or + * @return The number of characters added to the buffer, or * -1 if this source of characters is at its end * @throws IOException if an I/O error occurs * @throws NullPointerException if target is null @@ -466,7 +467,7 @@ /** * Wraps a character sequence into a buffer. - * + * *

The content of the new, read-only buffer will be the content of the * given character sequence. The new buffer's capacity and limit will be * csq.length(), its position will be zero, and its mark will be @@ -556,7 +557,7 @@ /** * Relative put method  (optional operation). - * + * *

Writes the given $fulltype$ into this buffer at the current * position, and then increments the position.

* @@ -590,7 +591,7 @@ /** * Absolute put method  (optional operation). - * + * *

Writes the given $fulltype$ into this buffer at the given * index.

* @@ -1020,7 +1021,7 @@ * out.write(buf); * buf.compact(); // In case of partial write * } - * + * #end[byte] * * @return This buffer @@ -1201,7 +1202,7 @@ * position.

* * @param index - * The index of the character to be read, relative to the position; + * The index of the character to be read, relative to the position; * must be non-negative and smaller than remaining() * * @return The character at index @@ -1229,7 +1230,7 @@ * * @param start * The index, relative to the current position, of the first - * character in the subsequence; must be non-negative and no larger + * character in the subsequence; must be non-negative and no larger * than remaining() * * @param end @@ -1252,7 +1253,7 @@ /** * Appends the specified character sequence to this * buffer  (optional operation). - * + * *

An invocation of this method of the form dst.append(csq) * behaves in exactly the same way as the invocation * @@ -1290,7 +1291,7 @@ /** * Appends a subsequence of the specified character sequence to this * buffer  (optional operation). - * + * *

An invocation of this method of the form dst.append(csq, start, * end) when csq is not null, behaves in exactly the * same way as the invocation @@ -1327,7 +1328,7 @@ /** * Appends the specified $fulltype$ to this * buffer  (optional operation). - * + * *

An invocation of this method of the form dst.append($x$) * behaves in exactly the same way as the invocation * diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/security/DomainCombiner.java --- a/j2se/src/share/classes/java/security/DomainCombiner.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/security/DomainCombiner.java Thu Jul 05 23:47:33 2007 +0000 @@ -76,7 +76,7 @@ * * @see AccessController * @see AccessControlContext - * @version 1.15, 05/05/07 + * @version 1.16, 06/12/07 * @since 1.3 */ public interface DomainCombiner { @@ -85,7 +85,7 @@ * Modify or update the provided ProtectionDomains. * ProtectionDomains may be added to or removed from the given * ProtectionDomains. The ProtectionDomains may be re-ordered. - * Individual ProtectionDomains may be may be modified (with a new + * Individual ProtectionDomains may be modified (with a new * set of Permissions, for example). * *

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/sql/DriverManager.java --- a/j2se/src/share/classes/java/sql/DriverManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/sql/DriverManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,14 +25,11 @@ package java.sql; -// Comment below before mustang integration -import sun.misc.Service; - - -//Uncomment below before mustang integration -//import java.util.Service; - import java.util.Iterator; +import java.sql.Driver; +import java.util.ServiceLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; /** @@ -503,27 +500,50 @@ private static void loadInitialDrivers() { String drivers; - - try { - drivers = (String) java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("jdbc.drivers")); + try { + drivers = (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty("jdbc.drivers"); + } + }); } catch (Exception ex) { drivers = null; } - - // If the driver is packaged as a Service Provider, - // load it. - + // If the driver is packaged as a Service Provider, load it. // Get all the drivers through the classloader // exposed as a java.sql.Driver.class service. - - DriverService ds = new DriverService(); + // ServiceLoader.load() replaces the sun.misc.Providers() + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + + ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class); + Iterator driversIterator = loadedDrivers.iterator(); - // Have all the privileges to get all the - // implementation of java.sql.Driver - java.security.AccessController.doPrivileged(ds); - - println("DriverManager.initialize: jdbc.drivers = " + drivers); + /* Load these drivers, so that they can be instantiated. + * It may be the case that the driver class may not be there + * i.e. there may be a packaged driver with the service class + * as implementation of java.sql.Driver but the actual class + * may be missing. In that case a java.util.ServiceConfigurationError + * will be thrown at runtime by the VM trying to locate + * and load the service. + * + * Adding a try catch block to catch those runtime errors + * if driver not available in classpath but it's + * packaged as service and that service is there in classpath. + */ + try{ + while(driversIterator.hasNext()) { + println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next()); + } + } catch(Throwable t) { + // Do nothing + } + return null; + } + }); + + println("DriverManager.initialize: jdbc.drivers = " + drivers); if (drivers == null) { return; } @@ -652,43 +672,6 @@ } -// DriverService is a package-private support class. -class DriverService implements java.security.PrivilegedAction { - Iterator ps = null; - public DriverService() {}; - public Object run() { - - // uncomment the followin line before mustang integration - // Service s = Service.lookup(java.sql.Driver.class); - // ps = s.iterator(); - - ps = Service.providers(java.sql.Driver.class); - - /* Load these drivers, so that they can be instantiated. - * It may be the case that the driver class may not be there - * i.e. there may be a packaged driver with the service class - * as implementation of java.sql.Driver but the actual class - * may be missing. In that case a sun.misc.ServiceConfigurationError - * will be thrown at runtime by the VM trying to locate - * and load the service. - * - * Adding a try catch block to catch those runtime errors - * if driver not available in classpath but it's - * packaged as service and that service is there in classpath. - */ - - try { - while (ps.hasNext()) { - ps.next(); - } // end while - } catch(Throwable t) { - // Do nothing - } - return null; - } //end run - -} //end DriverService - // DriverInfo is a package-private support class. class DriverInfo { Driver driver; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/AbstractList.java --- a/j2se/src/share/classes/java/util/AbstractList.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/AbstractList.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ * * @author Josh Bloch * @author Neal Gafter - * @version 1.58, 05/05/07 + * @version 1.60, 06/11/07 * @since 1.2 */ @@ -275,17 +275,15 @@ * {@code get(int)}, and {@code remove(int)} methods. * *

Note that the iterator returned by this method will throw an - * {@code UnsupportedOperationException} in response to its + * {@link UnsupportedOperationException} in response to its * {@code remove} method unless the list's {@code remove(int)} method is * overridden. * *

This implementation can be made to throw runtime exceptions in the * face of concurrent modification, as described in the specification - * for the (protected) {@code modCount} field. + * for the (protected) {@link #modCount} field. * * @return an iterator over the elements in this list in proper sequence - * - * @see #modCount */ public Iterator iterator() { return new Itr(); @@ -313,18 +311,16 @@ * and {@code remove(int)} methods. * *

Note that the list iterator returned by this implementation will - * throw an {@code UnsupportedOperationException} in response to its + * throw an {@link UnsupportedOperationException} in response to its * {@code remove}, {@code set} and {@code add} methods unless the * list's {@code remove(int)}, {@code set(int, E)}, and * {@code add(int, E)} methods are overridden. * *

This implementation can be made to throw runtime exceptions in the * face of concurrent modification, as described in the specification for - * the (protected) {@code modCount} field. + * the (protected) {@link #modCount} field. * * @throws IndexOutOfBoundsException {@inheritDoc} - * - * @see #modCount */ public ListIterator listIterator(final int index) { if (index<0 || index>size()) @@ -360,8 +356,10 @@ public E next() { checkForComodification(); try { - E next = get(cursor); - lastRet = cursor++; + int i = cursor; + E next = get(i); + lastRet = i; + cursor = i + 1; return next; } catch (IndexOutOfBoundsException e) { checkForComodification(); @@ -370,7 +368,7 @@ } public void remove() { - if (lastRet == -1) + if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); @@ -422,7 +420,7 @@ } public void set(E e) { - if (lastRet == -1) + if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); @@ -438,8 +436,10 @@ checkForComodification(); try { - AbstractList.this.add(cursor++, e); + int i = cursor; + AbstractList.this.add(i, e); lastRet = -1; + cursor = i + 1; expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); @@ -477,7 +477,7 @@ * the backing list is equal to its expected value, and throw a * {@code ConcurrentModificationException} if it is not. * - * @throws IndexOutOfBoundsException endpoint index value out of range + * @throws IndexOutOfBoundsException if an endpoint index value is out of range * {@code (fromIndex < 0 || toIndex > size)} * @throws IllegalArgumentException if the endpoint indices are out of order * {@code (fromIndex > toIndex)} @@ -551,9 +551,8 @@ * Removes from this list all of the elements whose index is between * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). - * This call shortens the ArrayList by {@code (toIndex - fromIndex)} - * elements. (If {@code toIndex==fromIndex}, this operation has no - * effect.) + * This call shortens the list by {@code (toIndex - fromIndex)} elements. + * (If {@code toIndex==fromIndex}, this operation has no effect.) * *

This method is called by the {@code clear} operation on this list * and its subLists. Overriding this method to take advantage of @@ -608,10 +607,9 @@ } class SubList extends AbstractList { - private AbstractList l; - private int offset; + private final AbstractList l; + private final int offset; private int size; - private int expectedModCount; SubList(AbstractList list, int fromIndex, int toIndex) { if (fromIndex < 0) @@ -624,7 +622,7 @@ l = list; offset = fromIndex; size = toIndex - fromIndex; - expectedModCount = l.modCount; + this.modCount = l.modCount; } public E set(int index, E element) { @@ -645,31 +643,27 @@ } public void add(int index, E element) { - if (index<0 || index>size) - throw new IndexOutOfBoundsException(); + rangeCheckForAdd(index); checkForComodification(); l.add(index+offset, element); - expectedModCount = l.modCount; + this.modCount = l.modCount; size++; - modCount++; } public E remove(int index) { rangeCheck(index); checkForComodification(); E result = l.remove(index+offset); - expectedModCount = l.modCount; + this.modCount = l.modCount; size--; - modCount++; return result; } protected void removeRange(int fromIndex, int toIndex) { checkForComodification(); l.removeRange(fromIndex+offset, toIndex+offset); - expectedModCount = l.modCount; + this.modCount = l.modCount; size -= (toIndex-fromIndex); - modCount++; } public boolean addAll(Collection c) { @@ -677,18 +671,15 @@ } public boolean addAll(int index, Collection c) { - if (index<0 || index>size) - throw new IndexOutOfBoundsException( - "Index: "+index+", Size: "+size); + rangeCheckForAdd(index); int cSize = c.size(); if (cSize==0) return false; checkForComodification(); l.addAll(offset+index, c); - expectedModCount = l.modCount; + this.modCount = l.modCount; size += cSize; - modCount++; return true; } @@ -698,12 +689,10 @@ public ListIterator listIterator(final int index) { checkForComodification(); - if (index<0 || index>size) - throw new IndexOutOfBoundsException( - "Index: "+index+", Size: "+size); + rangeCheckForAdd(index); return new ListIterator() { - private ListIterator i = l.listIterator(index+offset); + private final ListIterator i = l.listIterator(index+offset); public boolean hasNext() { return nextIndex() < size; @@ -737,9 +726,8 @@ public void remove() { i.remove(); - expectedModCount = l.modCount; + SubList.this.modCount = l.modCount; size--; - modCount++; } public void set(E e) { @@ -748,9 +736,8 @@ public void add(E e) { i.add(e); - expectedModCount = l.modCount; + SubList.this.modCount = l.modCount; size++; - modCount++; } }; } @@ -760,13 +747,21 @@ } private void rangeCheck(int index) { - if (index<0 || index>=size) - throw new IndexOutOfBoundsException("Index: "+index+ - ",Size: "+size); + if (index < 0 || index >= size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+size; } private void checkForComodification() { - if (l.modCount != expectedModCount) + if (this.modCount != l.modCount) throw new ConcurrentModificationException(); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/AbstractMap.java --- a/j2se/src/share/classes/java/util/AbstractMap.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/AbstractMap.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ * * @author Josh Bloch * @author Neal Gafter - * @version 1.56, 05/05/07 + * @version 1.57, 06/12/07 * @see Map * @see Collection * @since 1.2 @@ -340,6 +340,14 @@ return AbstractMap.this.size(); } + public boolean isEmpty() { + return AbstractMap.this.isEmpty(); + } + + public void clear() { + AbstractMap.this.clear(); + } + public boolean contains(Object k) { return AbstractMap.this.containsKey(k); } @@ -388,6 +396,14 @@ return AbstractMap.this.size(); } + public boolean isEmpty() { + return AbstractMap.this.isEmpty(); + } + + public void clear() { + AbstractMap.this.clear(); + } + public boolean contains(Object v) { return AbstractMap.this.containsValue(v); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/AbstractQueue.java --- a/j2se/src/share/classes/java/util/AbstractQueue.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/AbstractQueue.java Thu Jul 05 23:47:33 2007 +0000 @@ -41,18 +41,17 @@ * the base implementation does not allow null * elements. Methods {@link #add add}, {@link #remove remove}, and * {@link #element element} are based on {@link #offer offer}, {@link - * #poll poll}, and {@link #peek peek}, respectively but throw + * #poll poll}, and {@link #peek peek}, respectively, but throw * exceptions instead of indicating failure via false or * null returns. * - *

A Queue implementation that extends this class must + *

A Queue implementation that extends this class must * minimally define a method {@link Queue#offer} which does not permit * insertion of null elements, along with methods {@link - * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and a - * {@link Collection#iterator} supporting {@link - * Iterator#remove}. Typically, additional methods will be overridden - * as well. If these requirements cannot be met, consider instead - * subclassing {@link AbstractCollection}. + * Queue#peek}, {@link Queue#poll}, {@link Collection#size}, and + * {@link Collection#iterator}. Typically, additional methods will be + * overridden as well. If these requirements cannot be met, consider + * instead subclassing {@link AbstractCollection}. * *

This class is a member of the * diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/ArrayList.java --- a/j2se/src/share/classes/java/util/ArrayList.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/ArrayList.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,23 +31,23 @@ * null. In addition to implementing the List interface, * this class provides methods to manipulate the size of the array that is * used internally to store the list. (This class is roughly equivalent to - * Vector, except that it is unsynchronized.)

+ * Vector, except that it is unsynchronized.) * - * The size, isEmpty, get, set, + *

The size, isEmpty, get, set, * iterator, and listIterator operations run in constant * time. The add operation runs in amortized constant time, * that is, adding n elements requires O(n) time. All of the other operations * run in linear time (roughly speaking). The constant factor is low compared - * to that for the LinkedList implementation.

+ * to that for the LinkedList implementation. * - * Each ArrayList instance has a capacity. The capacity is + *

Each ArrayList instance has a capacity. The capacity is * the size of the array used to store the elements in the list. It is always * at least as large as the list size. As elements are added to an ArrayList, * its capacity grows automatically. The details of the growth policy are not * specified beyond the fact that adding an element has constant amortized - * time cost.

+ * time cost. * - * An application can increase the capacity of an ArrayList instance + *

An application can increase the capacity of an ArrayList instance * before adding a large number of elements using the ensureCapacity * operation. This may reduce the amount of incremental reallocation. * @@ -66,30 +66,33 @@ * unsynchronized access to the list:

  *   List list = Collections.synchronizedList(new ArrayList(...));
* - *

The iterators returned by this class's iterator and - * listIterator methods are fail-fast: if the list is - * structurally modified at any time after the iterator is created, in any way - * except through the iterator's own remove or add methods, - * the iterator will throw a {@link ConcurrentModificationException}. Thus, in - * the face of concurrent modification, the iterator fails quickly and cleanly, - * rather than risking arbitrary, non-deterministic behavior at an undetermined - * time in the future.

+ *

+ * The iterators returned by this class's {@link #iterator() iterator} and + * {@link #listIterator(int) listIterator} methods are fail-fast: + * if the list is structurally modified at any time after the iterator is + * created, in any way except through the iterator's own + * {@link ListIterator#remove() remove} or + * {@link ListIterator#add(Object) add} methods, the iterator will throw a + * {@link ConcurrentModificationException}. Thus, in the face of + * concurrent modification, the iterator fails quickly and cleanly, rather + * than risking arbitrary, non-deterministic behavior at an undetermined + * time in the future. * - * Note that the fail-fast behavior of an iterator cannot be guaranteed + *

Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the * presence of unsynchronized concurrent modification. Fail-fast iterators - * throw ConcurrentModificationException on a best-effort basis. + * throw {@code ConcurrentModificationException} on a best-effort basis. * Therefore, it would be wrong to write a program that depended on this - * exception for its correctness: the fail-fast behavior of iterators - * should be used only to detect bugs.

+ * exception for its correctness: the fail-fast behavior of iterators + * should be used only to detect bugs. * - * This class is a member of the + *

This class is a member of the * * Java Collections Framework. * * @author Josh Bloch * @author Neal Gafter - * @version 1.63, 05/05/07 + * @version 1.65, 06/16/07 * @see Collection * @see List * @see LinkedList @@ -265,7 +268,8 @@ */ public Object clone() { try { - ArrayList v = (ArrayList) super.clone(); + @SuppressWarnings("unchecked") + ArrayList v = (ArrayList) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; @@ -317,6 +321,7 @@ * this list * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { if (a.length < size) // Make a new array of a's runtime type, but my contents: @@ -329,6 +334,11 @@ // Positional Access Operations + @SuppressWarnings("unchecked") + E elementData(int index) { + return (E) elementData[index]; + } + /** * Returns the element at the specified position in this list. * @@ -339,7 +349,7 @@ public E get(int index) { rangeCheck(index); - return (E) elementData[index]; + return elementData(index); } /** @@ -354,7 +364,7 @@ public E set(int index, E element) { rangeCheck(index); - E oldValue = (E) elementData[index]; + E oldValue = elementData(index); elementData[index] = element; return oldValue; } @@ -403,7 +413,7 @@ rangeCheck(index); modCount++; - E oldValue = (E) elementData[index]; + E oldValue = elementData(index); int numMoved = size - index - 1; if (numMoved > 0) @@ -527,16 +537,17 @@ /** * Removes from this list all of the elements whose index is between - * fromIndex, inclusive, and toIndex, exclusive. + * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. * Shifts any succeeding elements to the left (reduces their index). - * This call shortens the list by (toIndex - fromIndex) elements. - * (If toIndex==fromIndex, this operation has no effect.) + * This call shortens the list by {@code (toIndex - fromIndex)} elements. + * (If {@code toIndex==fromIndex}, this operation has no effect.) * - * @param fromIndex index of first element to be removed - * @param toIndex index after last element to be removed - * @throws IndexOutOfBoundsException if fromIndex or toIndex out of - * range (fromIndex < 0 || fromIndex >= size() || toIndex - * > size() || toIndex < fromIndex) + * @throws IndexOutOfBoundsException if {@code fromIndex} or + * {@code toIndex} is out of range + * ({@code fromIndex < 0 || + * fromIndex >= size() || + * toIndex > size() || + * toIndex < fromIndex}) */ protected void removeRange(int fromIndex, int toIndex) { modCount++; @@ -579,6 +590,69 @@ } /** + * Removes from this list all of its elements that are contained in the + * specified collection. + * + * @param c collection containing elements to be removed from this list + * @return {@code true} if this list changed as a result of the call + * @throws ClassCastException if the class of an element of this list + * is incompatible with the specified collection (optional) + * @throws NullPointerException if this list contains a null element and the + * specified collection does not permit null elements (optional), + * or if the specified collection is null + * @see Collection#contains(Object) + */ + public boolean removeAll(Collection c) { + return batchRemove(c, false); + } + + /** + * Retains only the elements in this list that are contained in the + * specified collection. In other words, removes from this list all + * of its elements that are not contained in the specified collection. + * + * @param c collection containing elements to be retained in this list + * @return {@code true} if this list changed as a result of the call + * @throws ClassCastException if the class of an element of this list + * is incompatible with the specified collection (optional) + * @throws NullPointerException if this list contains a null element and the + * specified collection does not permit null elements (optional), + * or if the specified collection is null + * @see Collection#contains(Object) + */ + public boolean retainAll(Collection c) { + return batchRemove(c, true); + } + + private boolean batchRemove(Collection c, boolean complement) { + final Object[] elementData = this.elementData; + int r = 0, w = 0; + boolean modified = false; + try { + for (; r < size; r++) + if (c.contains(elementData[r]) == complement) + elementData[w++] = elementData[r]; + } finally { + // Preserve behavioral compatibility with AbstractCollection, + // even if c.contains() throws. + if (r != size) { + System.arraycopy(elementData, r, + elementData, w, + size - r); + w += size - r; + } + if (w != size) { + for (int i = w; i < size; i++) + elementData[i] = null; + modCount += size - w; + size = w; + modified = true; + } + } + return modified; + } + + /** * Save the state of the ArrayList instance to a stream (that * is, serialize it). * @@ -622,4 +696,400 @@ for (int i=0; iThe returned list iterator is fail-fast. + * + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public ListIterator listIterator(int index) { + if (index < 0 || index > size) + throw new IndexOutOfBoundsException("Index: "+index); + return new ListItr(index); + } + + /** + * Returns a list iterator over the elements in this list (in proper + * sequence). + * + *

The returned list iterator is fail-fast. + * + * @see #listIterator(int) + */ + public ListIterator listIterator() { + return new ListItr(0); + } + + /** + * Returns an iterator over the elements in this list in proper sequence. + * + *

The returned iterator is fail-fast. + * + * @return an iterator over the elements in this list in proper sequence + */ + public Iterator iterator() { + return new Itr(); + } + + /** + * An optimized version of AbstractList.Itr + */ + private class Itr implements Iterator { + int cursor; // index of next element to return + int lastRet = -1; // index of last element returned; -1 if no such + int expectedModCount = modCount; + + public boolean hasNext() { + return cursor != size; + } + + @SuppressWarnings("unchecked") + public E next() { + checkForComodification(); + int i = cursor; + if (i >= size) + throw new NoSuchElementException(); + Object[] elementData = ArrayList.this.elementData; + if (i >= elementData.length) + throw new ConcurrentModificationException(); + cursor = i + 1; + return (E) elementData[lastRet = i]; + } + + public void remove() { + if (lastRet < 0) + throw new IllegalStateException(); + checkForComodification(); + + try { + ArrayList.this.remove(lastRet); + cursor = lastRet; + lastRet = -1; + expectedModCount = modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + final void checkForComodification() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + } + + /** + * An optimized version of AbstractList.ListItr + */ + private class ListItr extends Itr implements ListIterator { + ListItr(int index) { + super(); + cursor = index; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + @SuppressWarnings("unchecked") + public E previous() { + checkForComodification(); + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + Object[] elementData = ArrayList.this.elementData; + if (i >= elementData.length) + throw new ConcurrentModificationException(); + cursor = i; + return (E) elementData[lastRet = i]; + } + + public void set(E e) { + if (lastRet < 0) + throw new IllegalStateException(); + checkForComodification(); + + try { + ArrayList.this.set(lastRet, e); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void add(E e) { + checkForComodification(); + + try { + int i = cursor; + ArrayList.this.add(i, e); + cursor = i + 1; + lastRet = -1; + expectedModCount = modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + } + + /** + * Returns a view of the portion of this list between the specified + * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. (If + * {@code fromIndex} and {@code toIndex} are equal, the returned list is + * empty.) The returned list is backed by this list, so non-structural + * changes in the returned list are reflected in this list, and vice-versa. + * The returned list supports all of the optional list operations. + * + *

This method eliminates the need for explicit range operations (of + * the sort that commonly exist for arrays). Any operation that expects + * a list can be used as a range operation by passing a subList view + * instead of a whole list. For example, the following idiom + * removes a range of elements from a list: + *

+     *      list.subList(from, to).clear();
+     * 
+ * Similar idioms may be constructed for {@link #indexOf(Object)} and + * {@link #lastIndexOf(Object)}, and all of the algorithms in the + * {@link Collections} class can be applied to a subList. + * + *

The semantics of the list returned by this method become undefined if + * the backing list (i.e., this list) is structurally modified in + * any way other than via the returned list. (Structural modifications are + * those that change the size of this list, or otherwise perturb it in such + * a fashion that iterations in progress may yield incorrect results.) + * + * @throws IndexOutOfBoundsException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} + */ + public List subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size); + return new SubList(this, 0, fromIndex, toIndex); + } + + static void subListRangeCheck(int fromIndex, int toIndex, int size) { + if (fromIndex < 0) + throw new IndexOutOfBoundsException("fromIndex = " + fromIndex); + if (toIndex > size) + throw new IndexOutOfBoundsException("toIndex = " + toIndex); + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex + ")"); + } + + private class SubList extends AbstractList implements RandomAccess { + private final AbstractList parent; + private final int parentOffset; + private final int offset; + private int size; + + SubList(AbstractList parent, + int offset, int fromIndex, int toIndex) { + this.parent = parent; + this.parentOffset = fromIndex; + this.offset = offset + fromIndex; + this.size = toIndex - fromIndex; + this.modCount = ArrayList.this.modCount; + } + + public E set(int index, E e) { + rangeCheck(index); + checkForComodification(); + E oldValue = ArrayList.this.elementData(offset + index); + ArrayList.this.elementData[offset + index] = e; + return oldValue; + } + + public E get(int index) { + rangeCheck(index); + checkForComodification(); + return ArrayList.this.elementData(offset + index); + } + + public int size() { + checkForComodification(); + return this.size; + } + + public void add(int index, E e) { + rangeCheckForAdd(index); + checkForComodification(); + parent.add(parentOffset + index, e); + this.modCount = parent.modCount; + this.size++; + } + + public E remove(int index) { + rangeCheck(index); + checkForComodification(); + E result = parent.remove(parentOffset + index); + this.modCount = parent.modCount; + this.size--; + return result; + } + + protected void removeRange(int fromIndex, int toIndex) { + checkForComodification(); + parent.removeRange(parentOffset + fromIndex, + parentOffset + toIndex); + this.modCount = parent.modCount; + this.size -= toIndex - fromIndex; + } + + public boolean addAll(Collection c) { + return addAll(this.size, c); + } + + public boolean addAll(int index, Collection c) { + rangeCheckForAdd(index); + int cSize = c.size(); + if (cSize==0) + return false; + + checkForComodification(); + parent.addAll(parentOffset + index, c); + this.modCount = parent.modCount; + this.size += cSize; + return true; + } + + public Iterator iterator() { + return listIterator(); + } + + public ListIterator listIterator(final int index) { + checkForComodification(); + rangeCheckForAdd(index); + + return new ListIterator() { + int cursor = index; + int lastRet = -1; + int expectedModCount = ArrayList.this.modCount; + + public boolean hasNext() { + return cursor != SubList.this.size; + } + + @SuppressWarnings("unchecked") + public E next() { + checkForComodification(); + int i = cursor; + if (i >= SubList.this.size) + throw new NoSuchElementException(); + Object[] elementData = ArrayList.this.elementData; + if (offset + i >= elementData.length) + throw new ConcurrentModificationException(); + cursor = i + 1; + return (E) elementData[offset + (lastRet = i)]; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + @SuppressWarnings("unchecked") + public E previous() { + checkForComodification(); + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + Object[] elementData = ArrayList.this.elementData; + if (offset + i >= elementData.length) + throw new ConcurrentModificationException(); + cursor = i; + return (E) elementData[offset + (lastRet = i)]; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + public void remove() { + if (lastRet < 0) + throw new IllegalStateException(); + checkForComodification(); + + try { + SubList.this.remove(lastRet); + cursor = lastRet; + lastRet = -1; + expectedModCount = ArrayList.this.modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void set(E e) { + if (lastRet < 0) + throw new IllegalStateException(); + checkForComodification(); + + try { + ArrayList.this.set(offset + lastRet, e); + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + public void add(E e) { + checkForComodification(); + + try { + int i = cursor; + SubList.this.add(i, e); + cursor = i + 1; + lastRet = -1; + expectedModCount = ArrayList.this.modCount; + } catch (IndexOutOfBoundsException ex) { + throw new ConcurrentModificationException(); + } + } + + final void checkForComodification() { + if (expectedModCount != ArrayList.this.modCount) + throw new ConcurrentModificationException(); + } + }; + } + + public List subList(int fromIndex, int toIndex) { + subListRangeCheck(fromIndex, toIndex, size); + return new SubList(this, offset, fromIndex, toIndex); + } + + private void rangeCheck(int index) { + if (index < 0 || index >= this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private void rangeCheckForAdd(int index) { + if (index < 0 || index > this.size) + throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); + } + + private String outOfBoundsMsg(int index) { + return "Index: "+index+", Size: "+this.size; + } + + private void checkForComodification() { + if (ArrayList.this.modCount != this.modCount) + throw new ConcurrentModificationException(); + } + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/Collections.java --- a/j2se/src/share/classes/java/util/Collections.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/Collections.java Thu Jul 05 23:47:33 2007 +0000 @@ -61,7 +61,7 @@ * * @author Josh Bloch * @author Neal Gafter - * @version 1.113, 05/05/07 + * @version 1.114, 06/12/07 * @see Collection * @see Set * @see List @@ -2277,10 +2277,7 @@ throw new ClassCastException(); } - boolean result = false; - for (E e : a) - result |= c.add(e); - return result; + return c.addAll(Arrays.asList(a)); } private E[] zeroLengthElementArray = null; // Lazily initialized diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/Comparator.java --- a/j2se/src/share/classes/java/util/Comparator.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/Comparator.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,9 +80,13 @@ * equals, we mean that the quotient for the ordering is the equivalence * relation defined by the objects' {@link Object#equals(Object) * equals(Object)} method(s):

- *     {(x, y) such that x.equals(y)}. 

+ * {(x, y) such that x.equals(y)}. * - * This interface is a member of the + *

Unlike {@code Comparable}, a comparator may optionally permit + * comparison of null arguments, while maintaining the requirements for + * an equivalence relation. + * + *

This interface is a member of the * * Java Collections Framework. * @@ -90,7 +94,7 @@ * * @author Josh Bloch * @author Neal Gafter - * @version 1.32, 05/05/07 + * @version 1.33, 06/12/07 * @see Comparable * @see java.io.Serializable * @since 1.2 @@ -132,13 +136,14 @@ * @return a negative integer, zero, or a positive integer as the * first argument is less than, equal to, or greater than the * second. + * @throws NullPointerException if an argument is null and this + * comparator does not permit null arguments * @throws ClassCastException if the arguments' types prevent them from * being compared by this comparator. */ int compare(T o1, T o2); /** - * * Indicates whether some other object is "equal to" this * comparator. This method must obey the general contract of * {@link Object#equals(Object)}. Additionally, this method can return diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/Formatter.java --- a/j2se/src/share/classes/java/util/Formatter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/Formatter.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1816,7 +1816,6 @@ * NullPointerException} to be thrown. * * @author Iris Clark - * @version 1.33, 05/05/07 * @since 1.5 */ public final class Formatter implements Closeable, Flushable { @@ -3205,7 +3204,7 @@ int newW = width; if (width != -1) newW = adjustWidth(width - exp.length - 1, f, neg); - localizedMagnitude(sb, mant, f, newW, null); + localizedMagnitude(sb, mant, f, newW, l); sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); @@ -3216,7 +3215,7 @@ char[] tmp = new char[exp.length - 1]; System.arraycopy(exp, 1, tmp, 0, exp.length - 1); - sb.append(localizedMagnitude(null, tmp, flags, -1, null)); + sb.append(localizedMagnitude(null, tmp, flags, -1, l)); } else if (c == Conversion.DECIMAL_FLOAT) { // Create a new FormattedFloatingDecimal with the desired // precision. @@ -3278,7 +3277,7 @@ else newW = adjustWidth(width, f, neg); } - localizedMagnitude(sb, mant, f, newW, null); + localizedMagnitude(sb, mant, f, newW, l); if (exp != null) { sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); @@ -3290,7 +3289,7 @@ char[] tmp = new char[exp.length - 1]; System.arraycopy(exp, 1, tmp, 0, exp.length - 1); - sb.append(localizedMagnitude(null, tmp, flags, -1, null)); + sb.append(localizedMagnitude(null, tmp, flags, -1, l)); } } else if (c == Conversion.HEXADECIMAL_FLOAT) { int prec = precision; @@ -3536,7 +3535,7 @@ int newW = width; if (width != -1) newW = adjustWidth(width - exp.length - 1, f, neg); - localizedMagnitude(sb, mant, f, newW, null); + localizedMagnitude(sb, mant, f, newW, l); sb.append(f.contains(Flags.UPPERCASE) ? 'E' : 'e'); @@ -3547,13 +3546,13 @@ char[] tmp = new char[exp.length - 1]; System.arraycopy(exp, 1, tmp, 0, exp.length - 1); - sb.append(localizedMagnitude(null, tmp, flags, -1, null)); + sb.append(localizedMagnitude(null, tmp, flags, -1, l)); } else if (c == Conversion.DECIMAL_FLOAT) { // Create a new BigDecimal with the desired precision. int prec = (precision == -1 ? 6 : precision); int scale = value.scale(); int compPrec = value.precision(); - if (scale > prec) + if (scale > prec) compPrec -= (scale - prec); MathContext mc = new MathContext(compPrec); BigDecimal v @@ -3719,7 +3718,7 @@ } else { // xx form mant.append(coeff, 0, coeff.length); - for (int i = 0; i < -scale; i++) + for (int i = 0; i < -scale; i++) mant.append('0'); this.scale = 0; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/List.java --- a/j2se/src/share/classes/java/util/List.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/List.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ * * @author Josh Bloch * @author Neal Gafter - * @version 1.55, 05/05/07 + * @version 1.57, 06/16/07 * @see Collection * @see Set * @see ArrayList @@ -345,8 +345,8 @@ /** * Retains only the elements in this list that are contained in the * specified collection (optional operation). In other words, removes - * from this list all the elements that are not contained in the specified - * collection. + * from this list all of its elements that are not contained in the + * specified collection. * * @param c collection containing elements to be retained in this list * @return true if this list changed as a result of the call @@ -531,19 +531,19 @@ ListIterator listIterator(); /** - * Returns a list iterator of the elements in this list (in proper - * sequence), starting at the specified position in this list. + * Returns a list iterator over the elements in this list (in proper + * sequence), starting at the specified position in the list. * The specified index indicates the first element that would be * returned by an initial call to {@link ListIterator#next next}. * An initial call to {@link ListIterator#previous previous} would * return the element with the specified index minus one. * - * @param index index of first element to be returned from the - * list iterator (by a call to the next method) - * @return a list iterator of the elements in this list (in proper - * sequence), starting at the specified position in this list + * @param index index of the first element to be returned from the + * list iterator (by a call to {@link ListIterator#next next}) + * @return a list iterator over the elements in this list (in proper + * sequence), starting at the specified position in the list * @throws IndexOutOfBoundsException if the index is out of range - * (index < 0 || index > size()) + * ({@code index < 0 || index > size()}) */ ListIterator listIterator(int index); @@ -559,7 +559,7 @@ * by this list.

* * This method eliminates the need for explicit range operations (of - * the sort that commonly exist for arrays). Any operation that expects + * the sort that commonly exist for arrays). Any operation that expects * a list can be used as a range operation by passing a subList view * instead of a whole list. For example, the following idiom * removes a range of elements from a list: diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/Scanner.java --- a/j2se/src/share/classes/java/util/Scanner.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/Scanner.java Thu Jul 05 23:47:33 2007 +0000 @@ -340,7 +340,7 @@ * *

Whitespace is not significant in the above regular expressions. * - * @version 1.33, 05/05/07 + * @version 1.34, 06/11/07 * @since 1.5 */ public final class Scanner implements Iterator { @@ -766,7 +766,7 @@ typeCache = null; } - // Also clears the both the regular cache and the type cache + // Also clears both the regular cache and the type cache private String getCachedResult() { position = hasNextPosition; hasNextPattern = null; @@ -774,7 +774,7 @@ return hasNextResult; } - // Also clears the both the regular cache and the type cache + // Also clears both the regular cache and the type cache private void useTypeCache() { if (closed) throw new IllegalStateException("Scanner closed"); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/UUID.java --- a/j2se/src/share/classes/java/util/UUID.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/UUID.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,15 +30,14 @@ import java.io.UnsupportedEncodingException; /** - * - * A class that represents an immutable universally unique identifier (UUID). + * A class that represents an immutable universally unique identifier (UUID). * A UUID represents a 128-bit value. * - *

There exist different variants of these global identifiers. The methods + *

There exist different variants of these global identifiers. The methods * of this class are for manipulating the Leach-Salz variant, although the * constructors allow the creation of any variant of UUID (described below). - * - *

The layout of a variant 2 (Leach-Salz) UUID is as follows: + * + *

The layout of a variant 2 (Leach-Salz) UUID is as follows: * * The most significant long consists of the following unsigned fields: *

@@ -54,32 +53,28 @@
  * 0x0000FFFFFFFFFFFF node
  * 
* - *

The variant field contains a value which identifies the layout of - * the UUID. The bit layout described above is valid only for - * a UUID with a variant value of 2, which indicates the - * Leach-Salz variant. + *

The variant field contains a value which identifies the layout of the + * {@code UUID}. The bit layout described above is valid only for a {@code + * UUID} with a variant value of 2, which indicates the Leach-Salz variant. * - *

The version field holds a value that describes the type of this - * UUID. There are four different basic types of UUIDs: time-based, - * DCE security, name-based, and randomly generated UUIDs. These types - * have a version value of 1, 2, 3 and 4, respectively. - * - *

For more information including algorithms used to create UUIDs, - * see - * RFC 4122: A Universally Unique IDentifier (UUID) URN - * Namespace, section 4.2 "Algorithms for Creating a Time-Based - * UUID". + *

The version field holds a value that describes the type of this {@code + * UUID}. There are four different basic types of UUIDs: time-based, DCE + * security, name-based, and randomly generated UUIDs. These types have a + * version value of 1, 2, 3 and 4, respectively. * - * @version 1.24, 05/05/07 + *

For more information including algorithms used to create {@code UUID}s, + * see RFC 4122: A + * Universally Unique IDentifier (UUID) URN Namespace, section 4.2 + * "Algorithms for Creating a Time-Based UUID". + * * @since 1.5 */ -public final class UUID -implements java.io.Serializable, Comparable { +public final class UUID implements java.io.Serializable, Comparable { /** * Explicit serialVersionUID for interoperability. */ - private static final long serialVersionUID = -4856846361193249489L; + private static final long serialVersionUID = -4856846361193249489L; /* * The most significant 64 bits of this UUID. @@ -149,13 +144,16 @@ } /** - * Constructs a new UUID using the specified data. - * mostSigBits is used for the most significant 64 bits - * of the UUID and leastSigBits becomes the - * least significant 64 bits of the UUID. + * Constructs a new {@code UUID} using the specified data. {@code + * mostSigBits} is used for the most significant 64 bits of the {@code + * UUID} and {@code leastSigBits} becomes the least significant 64 bits of + * the {@code UUID}. * * @param mostSigBits + * The most significant bits of the {@code UUID} + * * @param leastSigBits + * The least significant bits of the {@code UUID} */ public UUID(long mostSigBits, long leastSigBits) { this.mostSigBits = mostSigBits; @@ -165,10 +163,10 @@ /** * Static factory to retrieve a type 4 (pseudo randomly generated) UUID. * - * The UUID is generated using a cryptographically strong - * pseudo random number generator. + * The {@code UUID} is generated using a cryptographically strong pseudo + * random number generator. * - * @return a randomly generated UUID. + * @return A randomly generated {@code UUID} */ public static UUID randomUUID() { SecureRandom ng = numberGenerator; @@ -186,11 +184,13 @@ } /** - * Static factory to retrieve a type 3 (name based) UUID based on + * Static factory to retrieve a type 3 (name based) {@code UUID} based on * the specified byte array. * - * @param name a byte array to be used to construct a UUID. - * @return a UUID generated from the specified array. + * @param name + * A byte array to be used to construct a {@code UUID} + * + * @return A {@code UUID} generated from the specified array */ public static UUID nameUUIDFromBytes(byte[] name) { MessageDigest md; @@ -208,13 +208,18 @@ } /** - * Creates a UUID from the string standard representation as + * Creates a {@code UUID} from the string standard representation as * described in the {@link #toString} method. * - * @param name a string that specifies a UUID. - * @return a UUID with the specified value. - * @throws IllegalArgumentException if name does not conform to the - * string representation as described in {@link #toString}. + * @param name + * A string that specifies a {@code UUID} + * + * @return A {@code UUID} with the specified value + * + * @throws IllegalArgumentException + * If name does not conform to the string representation as + * described in {@link #toString} + * */ public static UUID fromString(String name) { String[] components = name.split("-"); @@ -241,7 +246,7 @@ /** * Returns the least significant 64 bits of this UUID's 128 bit value. * - * @return the least significant 64 bits of this UUID's 128 bit value. + * @return The least significant 64 bits of this UUID's 128 bit value */ public long getLeastSignificantBits() { return leastSigBits; @@ -250,25 +255,25 @@ /** * Returns the most significant 64 bits of this UUID's 128 bit value. * - * @return the most significant 64 bits of this UUID's 128 bit value. + * @return The most significant 64 bits of this UUID's 128 bit value */ public long getMostSignificantBits() { return mostSigBits; } /** - * The version number associated with this UUID. The version - * number describes how this UUID was generated. + * The version number associated with this {@code UUID}. The version + * number describes how this {@code UUID} was generated. * - * The version number has the following meaning:

- *

    + * The version number has the following meaning: + *

      *
    • 1 Time-based UUID *
    • 2 DCE security UUID *
    • 3 Name-based UUID *
    • 4 Randomly generated UUID *
    * - * @return the version number of this UUID. + * @return The version number of this {@code UUID} */ public int version() { if (version < 0) { @@ -279,18 +284,18 @@ } /** - * The variant number associated with this UUID. The variant - * number describes the layout of the UUID. + * The variant number associated with this {@code UUID}. The variant + * number describes the layout of the {@code UUID}. * - * The variant number has the following meaning:

    - *

      + * The variant number has the following meaning: + *

        *
      • 0 Reserved for NCS backward compatibility *
      • 2 The Leach-Salz variant (used by this class) *
      • 6 Reserved, Microsoft Corporation backward compatibility *
      • 7 Reserved for future definition *
      * - * @return the variant number of this UUID. + * @return The variant number of this {@code UUID} */ public int variant() { if (variant < 0) { @@ -309,17 +314,17 @@ /** * The timestamp value associated with this UUID. * - *

      The 60 bit timestamp value is constructed from the time_low, - * time_mid, and time_hi fields of this UUID. The resulting - * timestamp is measured in 100-nanosecond units since midnight, - * October 15, 1582 UTC.

      + *

      The 60 bit timestamp value is constructed from the time_low, + * time_mid, and time_hi fields of this {@code UUID}. The resulting + * timestamp is measured in 100-nanosecond units since midnight, + * October 15, 1582 UTC. * - * The timestamp value is only meaningful in a time-based UUID, which - * has version type 1. If this UUID is not a time-based UUID then + *

      The timestamp value is only meaningful in a time-based UUID, which + * has version type 1. If this {@code UUID} is not a time-based UUID then * this method throws UnsupportedOperationException. - * - * @throws UnsupportedOperationException if this UUID is not a - * version 1 UUID. + * + * @throws UnsupportedOperationException + * If this UUID is not a version 1 UUID */ public long timestamp() { if (version() != 1) { @@ -338,17 +343,18 @@ /** * The clock sequence value associated with this UUID. * - *

      The 14 bit clock sequence value is constructed from the clock - * sequence field of this UUID. The clock sequence field is used to - * guarantee temporal uniqueness in a time-based UUID.

      + *

      The 14 bit clock sequence value is constructed from the clock + * sequence field of this UUID. The clock sequence field is used to + * guarantee temporal uniqueness in a time-based UUID. * - * The clockSequence value is only meaningful in a time-based UUID, which - * has version type 1. If this UUID is not a time-based UUID then - * this method throws UnsupportedOperationException. - * - * @return the clock sequence of this UUID. - * @throws UnsupportedOperationException if this UUID is not a - * version 1 UUID. + *

      The {@code clockSequence} value is only meaningful in a time-based + * UUID, which has version type 1. If this UUID is not a time-based UUID + * then this method throws UnsupportedOperationException. + * + * @return The clock sequence of this {@code UUID} + * + * @throws UnsupportedOperationException + * If this UUID is not a version 1 UUID */ public int clockSequence() { if (version() != 1) { @@ -363,18 +369,18 @@ /** * The node value associated with this UUID. * - *

      The 48 bit node value is constructed from the node field of - * this UUID. This field is intended to hold the IEEE 802 address - * of the machine that generated this UUID to guarantee spatial - * uniqueness.

      + *

      The 48 bit node value is constructed from the node field of this + * UUID. This field is intended to hold the IEEE 802 address of the machine + * that generated this UUID to guarantee spatial uniqueness. * - * The node value is only meaningful in a time-based UUID, which - * has version type 1. If this UUID is not a time-based UUID then - * this method throws UnsupportedOperationException. - * - * @return the node value of this UUID. - * @throws UnsupportedOperationException if this UUID is not a - * version 1 UUID. + *

      The node value is only meaningful in a time-based UUID, which has + * version type 1. If this UUID is not a time-based UUID then this method + * throws UnsupportedOperationException. + * + * @return The node value of this {@code UUID} + * + * @throws UnsupportedOperationException + * If this UUID is not a version 1 UUID */ public long node() { if (version() != 1) { @@ -389,10 +395,9 @@ // Object Inherited Methods /** - * Returns a String object representing this - * UUID. - * - *

      The UUID string representation is as described by this BNF : + * Returns a {@code String} object representing this {@code UUID}. + * + *

      The UUID string representation is as described by this BNF: *

            * {@code
            * UUID                   =  "-"  "-"
      @@ -411,7 +416,7 @@
            *       | "A" | "B" | "C" | "D" | "E" | "F"
            * }
      * - * @return a string representation of this UUID. + * @return A string representation of this {@code UUID} */ public String toString() { return (digits(mostSigBits >> 32, 8) + "-" + @@ -428,9 +433,9 @@ } /** - * Returns a hash code for this UUID. + * Returns a hash code for this {@code UUID}. * - * @return a hash code value for this UUID. + * @return A hash code value for this {@code UUID} */ public int hashCode() { if (hashCode == -1) { @@ -443,14 +448,16 @@ } /** - * Compares this object to the specified object. The result is - * true if and only if the argument is not - * null, is a UUID object, has the same variant, - * and contains the same value, bit for bit, as this UUID. + * Compares this object to the specified object. The result is {@code + * true} if and only if the argument is not {@code null}, is a {@code UUID} + * object, has the same variant, and contains the same value, bit for bit, + * as this {@code UUID}. * - * @param obj the object to compare with. - * @return true if the objects are the same; - * false otherwise. + * @param obj + * The object to be compared + * + * @return {@code true} if the objects are the same; {@code false} + * otherwise */ public boolean equals(Object obj) { if (!(obj instanceof UUID)) @@ -466,18 +473,22 @@ /** * Compares this UUID with the specified UUID. - * - *

      The first of two UUIDs follows the second if the most significant - * field in which the UUIDs differ is greater for the first UUID. + * + *

      The first of two UUIDs is greater than the second if the most + * significant field in which the UUIDs differ is greater for the first + * UUID. * - * @param val UUID to which this UUID is to be compared. - * @return -1, 0 or 1 as this UUID is less than, equal - * to, or greater than val. + * @param val + * {@code UUID} to which this {@code UUID} is to be compared + * + * @return -1, 0 or 1 as this {@code UUID} is less than, equal to, or + * greater than {@code val} + * */ public int compareTo(UUID val) { // The ordering is intentionally set up so that the UUIDs // can simply be numerically compared as two numbers - return (this.mostSigBits < val.mostSigBits ? -1 : + return (this.mostSigBits < val.mostSigBits ? -1 : (this.mostSigBits > val.mostSigBits ? 1 : (this.leastSigBits < val.leastSigBits ? -1 : (this.leastSigBits > val.leastSigBits ? 1 : @@ -485,10 +496,9 @@ } /** - * Reconstitute the UUID instance from a stream (that is, - * deserialize it). This is necessary to set the transient fields - * to their correct uninitialized value so they will be recomputed - * on demand. + * Reconstitute the {@code UUID} instance from a stream (that is, + * deserialize it). This is necessary to set the transient fields to their + * correct uninitialized value so they will be recomputed on demand. */ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/Vector.java --- a/j2se/src/share/classes/java/util/Vector.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/Vector.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1994-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,15 +41,18 @@ * capacity of a vector before inserting a large number of * components; this reduces the amount of incremental reallocation. * - *

      The Iterators returned by Vector's iterator and listIterator - * methods are fail-fast: if the Vector is structurally modified - * at any time after the Iterator is created, in any way except through the - * Iterator's own remove or add methods, the Iterator will throw a - * ConcurrentModificationException. Thus, in the face of concurrent - * modification, the Iterator fails quickly and cleanly, rather than risking - * arbitrary, non-deterministic behavior at an undetermined time in the future. - * The Enumerations returned by Vector's elements method are not - * fail-fast. + *

      + * The iterators returned by this class's {@link #iterator() iterator} and + * {@link #listIterator(int) listIterator} methods are fail-fast: + * if the vector is structurally modified at any time after the iterator is + * created, in any way except through the iterator's own + * {@link ListIterator#remove() remove} or + * {@link ListIterator#add(Object) add} methods, the iterator will throw a + * {@link ConcurrentModificationException}. Thus, in the face of + * concurrent modification, the iterator fails quickly and cleanly, rather + * than risking arbitrary, non-deterministic behavior at an undetermined + * time in the future. The {@link Enumeration Enumerations} returned by + * the {@link #elements() elements} method are not fail-fast. * *

      Note that the fail-fast behavior of an iterator cannot be guaranteed * as it is, generally speaking, impossible to make any hard guarantees in the @@ -67,7 +70,7 @@ * * @author Lee Boynton * @author Jonathan Payne - * @version 1.112, 05/05/07 + * @version 1.113, 06/11/07 * @see Collection * @see List * @see ArrayList @@ -317,7 +320,7 @@ public E nextElement() { synchronized (Vector.this) { if (count < elementCount) { - return (E)elementData[count++]; + return elementData(count++); } } throw new NoSuchElementException("Vector Enumeration"); @@ -445,7 +448,7 @@ throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } - return (E)elementData[index]; + return elementData(index); } /** @@ -459,7 +462,7 @@ if (elementCount == 0) { throw new NoSuchElementException(); } - return (E)elementData[0]; + return elementData(0); } /** @@ -473,7 +476,7 @@ if (elementCount == 0) { throw new NoSuchElementException(); } - return (E)elementData[elementCount - 1]; + return elementData(elementCount - 1); } /** @@ -512,7 +515,7 @@ * is decreased by {@code 1}. * *

      The index must be a value greater than or equal to {@code 0} - * and less than the current size of the vector. + * and less than the current size of the vector. * *

      This method is identical in functionality to the {@link #remove(int)} * method (which is part of the {@link List} interface). Note that the @@ -641,7 +644,8 @@ */ public synchronized Object clone() { try { - Vector v = (Vector) super.clone(); + @SuppressWarnings("unchecked") + Vector v = (Vector) super.clone(); v.elementData = Arrays.copyOf(elementData, elementCount); v.modCount = 0; return v; @@ -684,6 +688,7 @@ * @throws NullPointerException if the given array is null * @since 1.2 */ + @SuppressWarnings("unchecked") public synchronized T[] toArray(T[] a) { if (a.length < elementCount) return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass()); @@ -698,6 +703,11 @@ // Positional Access Operations + @SuppressWarnings("unchecked") + E elementData(int index) { + return (E) elementData[index]; + } + /** * Returns the element at the specified position in this Vector. * @@ -711,7 +721,7 @@ if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); - return (E)elementData[index]; + return elementData(index); } /** @@ -729,9 +739,9 @@ if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); - Object oldValue = elementData[index]; + E oldValue = elementData(index); elementData[index] = element; - return (E)oldValue; + return oldValue; } /** @@ -793,7 +803,7 @@ modCount++; if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); - Object oldValue = elementData[index]; + E oldValue = elementData(index); int numMoved = elementCount - index - 1; if (numMoved > 0) @@ -801,7 +811,7 @@ numMoved); elementData[--elementCount] = null; // Let gc do its work - return (E)oldValue; + return oldValue; } /** @@ -967,7 +977,7 @@ * operations supported by this List. * *

      This method eliminates the need for explicit range operations (of - * the sort that commonly exist for arrays). Any operation that expects + * the sort that commonly exist for arrays). Any operation that expects * a List can be used as a range operation by operating on a subList view * instead of a whole List. For example, the following idiom * removes a range of elements from a List: @@ -998,14 +1008,11 @@ } /** - * Removes from this List all of the elements whose index is between - * fromIndex, inclusive and toIndex, exclusive. Shifts any succeeding - * elements to the left (reduces their index). - * This call shortens the ArrayList by (toIndex - fromIndex) elements. (If - * toIndex==fromIndex, this operation has no effect.) - * - * @param fromIndex index of first element to be removed - * @param toIndex index after last element to be removed + * Removes from this list all of the elements whose index is between + * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive. + * Shifts any succeeding elements to the left (reduces their index). + * This call shortens the list by {@code (toIndex - fromIndex)} elements. + * (If {@code toIndex==fromIndex}, this operation has no effect.) */ protected synchronized void removeRange(int fromIndex, int toIndex) { modCount++; @@ -1029,4 +1036,141 @@ { s.defaultWriteObject(); } + + /** + * Returns a list iterator over the elements in this list (in proper + * sequence), starting at the specified position in the list. + * The specified index indicates the first element that would be + * returned by an initial call to {@link ListIterator#next next}. + * An initial call to {@link ListIterator#previous previous} would + * return the element with the specified index minus one. + * + *

      The returned list iterator is fail-fast. + * + * @throws IndexOutOfBoundsException {@inheritDoc} + */ + public synchronized ListIterator listIterator(int index) { + if (index < 0 || index > elementCount) + throw new IndexOutOfBoundsException("Index: "+index); + return new ListItr(index); + } + + /** + * Returns a list iterator over the elements in this list (in proper + * sequence). + * + *

      The returned list iterator is fail-fast. + * + * @see #listIterator(int) + */ + public synchronized ListIterator listIterator() { + return new ListItr(0); + } + + /** + * Returns an iterator over the elements in this list in proper sequence. + * + *

      The returned iterator is fail-fast. + * + * @return an iterator over the elements in this list in proper sequence + */ + public synchronized Iterator iterator() { + return new Itr(); + } + + /** + * An optimized version of AbstractList.Itr + */ + private class Itr implements Iterator { + int cursor; // index of next element to return + int lastRet = -1; // index of last element returned; -1 if no such + int expectedModCount = modCount; + + public boolean hasNext() { + // Racy but within spec, since modifications are checked + // within or after synchronization in next/previous + return cursor != elementCount; + } + + public E next() { + synchronized (Vector.this) { + checkForComodification(); + int i = cursor; + if (i >= elementCount) + throw new NoSuchElementException(); + cursor = i + 1; + return elementData(lastRet = i); + } + } + + public void remove() { + if (lastRet == -1) + throw new IllegalStateException(); + synchronized (Vector.this) { + checkForComodification(); + Vector.this.remove(lastRet); + expectedModCount = modCount; + } + cursor = lastRet; + lastRet = -1; + } + + final void checkForComodification() { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + } + } + + /** + * An optimized version of AbstractList.ListItr + */ + final class ListItr extends Itr implements ListIterator { + ListItr(int index) { + super(); + cursor = index; + } + + public boolean hasPrevious() { + return cursor != 0; + } + + public int nextIndex() { + return cursor; + } + + public int previousIndex() { + return cursor - 1; + } + + public E previous() { + synchronized (Vector.this) { + checkForComodification(); + int i = cursor - 1; + if (i < 0) + throw new NoSuchElementException(); + cursor = i; + return elementData(lastRet = i); + } + } + + public void set(E e) { + if (lastRet == -1) + throw new IllegalStateException(); + synchronized (Vector.this) { + checkForComodification(); + Vector.this.set(lastRet, e); + } + } + + public void add(E e) { + int i = cursor; + synchronized (Vector.this) { + checkForComodification(); + Vector.this.add(i, e); + expectedModCount = modCount; + } + cursor = i + 1; + lastRet = -1; + } + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/concurrent/ConcurrentHashMap.java --- a/j2se/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Thu Jul 05 23:47:33 2007 +0000 @@ -1199,6 +1199,9 @@ public int size() { return ConcurrentHashMap.this.size(); } + public boolean isEmpty() { + return ConcurrentHashMap.this.isEmpty(); + } public boolean contains(Object o) { return ConcurrentHashMap.this.containsKey(o); } @@ -1217,6 +1220,9 @@ public int size() { return ConcurrentHashMap.this.size(); } + public boolean isEmpty() { + return ConcurrentHashMap.this.isEmpty(); + } public boolean contains(Object o) { return ConcurrentHashMap.this.containsValue(o); } @@ -1245,6 +1251,9 @@ public int size() { return ConcurrentHashMap.this.size(); } + public boolean isEmpty() { + return ConcurrentHashMap.this.isEmpty(); + } public void clear() { ConcurrentHashMap.this.clear(); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java --- a/j2se/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Thu Jul 05 23:47:33 2007 +0000 @@ -29,8 +29,8 @@ * file: * * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain. Use, modify, and - * redistribute this code in any way without acknowledgement. + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain */ package java.util.concurrent; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/concurrent/Executors.java --- a/j2se/src/share/classes/java/util/concurrent/Executors.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/concurrent/Executors.java Thu Jul 05 23:47:33 2007 +0000 @@ -40,7 +40,9 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; import java.security.AccessControlException; +import sun.security.util.SecurityConstants; /** * Factory and utility methods for {@link Executor}, {@link @@ -461,7 +463,7 @@ static final class RunnableAdapter implements Callable { final Runnable task; final T result; - RunnableAdapter(Runnable task, T result) { + RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } @@ -475,30 +477,25 @@ * A callable that runs under established access control settings */ static final class PrivilegedCallable implements Callable { + private final Callable task; private final AccessControlContext acc; - private final Callable task; - private T result; - private Exception exception; - PrivilegedCallable(Callable task) { + + PrivilegedCallable(Callable task) { this.task = task; this.acc = AccessController.getContext(); } public T call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public T run() { - try { - result = task.call(); - } catch (Exception ex) { - exception = ex; - } - return null; - } - }, acc); - if (exception != null) - throw exception; - else - return result; + try { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public T run() throws Exception { + return task.call(); + } + }, acc); + } catch (PrivilegedActionException e) { + throw e.getException(); + } } } @@ -507,44 +504,50 @@ * current ClassLoader */ static final class PrivilegedCallableUsingCurrentClassLoader implements Callable { - private final ClassLoader ccl; + private final Callable task; private final AccessControlContext acc; - private final Callable task; - private T result; - private Exception exception; - PrivilegedCallableUsingCurrentClassLoader(Callable task) { + private final ClassLoader ccl; + + PrivilegedCallableUsingCurrentClassLoader(Callable task) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Calls to getContextClassLoader from this class + // never trigger a security check, but we check + // whether our callers have this permission anyways. + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + + // Whether setContextClassLoader turns out to be necessary + // or not, we fail fast if permission is not available. + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + } this.task = task; + this.acc = AccessController.getContext(); this.ccl = Thread.currentThread().getContextClassLoader(); - this.acc = AccessController.getContext(); - acc.checkPermission(new RuntimePermission("getContextClassLoader")); - acc.checkPermission(new RuntimePermission("setContextClassLoader")); } public T call() throws Exception { - AccessController.doPrivileged(new PrivilegedAction() { - public T run() { - ClassLoader savedcl = null; - Thread t = Thread.currentThread(); - try { - ClassLoader cl = t.getContextClassLoader(); - if (ccl != cl) { - t.setContextClassLoader(ccl); - savedcl = cl; - } - result = task.call(); - } catch (Exception ex) { - exception = ex; - } finally { - if (savedcl != null) - t.setContextClassLoader(savedcl); - } - return null; - } - }, acc); - if (exception != null) - throw exception; - else - return result; + try { + return AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public T run() throws Exception { + ClassLoader savedcl = null; + Thread t = Thread.currentThread(); + try { + ClassLoader cl = t.getContextClassLoader(); + if (ccl != cl) { + t.setContextClassLoader(ccl); + savedcl = cl; + } + return task.call(); + } finally { + if (savedcl != null) + t.setContextClassLoader(savedcl); + } + } + }, acc); + } catch (PrivilegedActionException e) { + throw e.getException(); + } } } @@ -552,10 +555,10 @@ * The default thread factory */ static class DefaultThreadFactory implements ThreadFactory { - static final AtomicInteger poolNumber = new AtomicInteger(1); - final ThreadGroup group; - final AtomicInteger threadNumber = new AtomicInteger(1); - final String namePrefix; + private static final AtomicInteger poolNumber = new AtomicInteger(1); + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); @@ -579,24 +582,33 @@ } /** - * Thread factory capturing access control and class loader + * Thread factory capturing access control context and class loader */ static class PrivilegedThreadFactory extends DefaultThreadFactory { + private final AccessControlContext acc; private final ClassLoader ccl; - private final AccessControlContext acc; PrivilegedThreadFactory() { super(); - this.ccl = Thread.currentThread().getContextClassLoader(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Calls to getContextClassLoader from this class + // never trigger a security check, but we check + // whether our callers have this permission anyways. + sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); + + // Fail fast + sm.checkPermission(new RuntimePermission("setContextClassLoader")); + } this.acc = AccessController.getContext(); - acc.checkPermission(new RuntimePermission("setContextClassLoader")); + this.ccl = Thread.currentThread().getContextClassLoader(); } public Thread newThread(final Runnable r) { return super.newThread(new Runnable() { public void run() { - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { Thread.currentThread().setContextClassLoader(ccl); r.run(); return null; @@ -605,7 +617,6 @@ } }); } - } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/concurrent/FutureTask.java --- a/j2se/src/share/classes/java/util/concurrent/FutureTask.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/concurrent/FutureTask.java Thu Jul 05 23:47:33 2007 +0000 @@ -326,15 +326,20 @@ void innerRun() { if (!compareAndSetState(READY, RUNNING)) return; - try { - runner = Thread.currentThread(); - if (getState() == RUNNING) // recheck after setting thread - set(callable.call()); - else - releaseShared(0); // cancel - } catch (Throwable ex) { - setException(ex); - } + + runner = Thread.currentThread(); + if (getState() == RUNNING) { // recheck after setting thread + V result; + try { + result = callable.call(); + } catch (Throwable ex) { + setException(ex); + return; + } + set(result); + } else { + releaseShared(0); // cancel + } } boolean innerRunAndReset() { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java --- a/j2se/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Thu Jul 05 23:47:33 2007 +0000 @@ -177,6 +177,9 @@ */ private final long period; + /** The actual task to be re-enqueued by reExecutePeriodic */ + RunnableScheduledFuture outerTask = this; + /** * Creates a one-shot action with given nanoTime-based trigger time. */ @@ -263,7 +266,7 @@ ScheduledFutureTask.super.run(); else if (ScheduledFutureTask.super.runAndReset()) { setNextRunTime(); - reExecutePeriodic(this); + reExecutePeriodic(outerTask); } } } @@ -462,7 +465,7 @@ if (delay < 0) delay = 0; long triggerTime = now() + unit.toNanos(delay); RunnableScheduledFuture t = decorateTask(command, - new ScheduledFutureTask(command, null, triggerTime)); + new ScheduledFutureTask(command, null, triggerTime)); delayedExecute(t); return t; } @@ -499,11 +502,13 @@ throw new IllegalArgumentException(); if (initialDelay < 0) initialDelay = 0; long triggerTime = now() + unit.toNanos(initialDelay); - RunnableScheduledFuture t = decorateTask(command, - new ScheduledFutureTask(command, - null, - triggerTime, - unit.toNanos(period))); + ScheduledFutureTask sft = + new ScheduledFutureTask(command, + null, + triggerTime, + unit.toNanos(period)); + RunnableScheduledFuture t = decorateTask(command, sft); + sft.outerTask = t; delayedExecute(t); return t; } @@ -523,11 +528,13 @@ throw new IllegalArgumentException(); if (initialDelay < 0) initialDelay = 0; long triggerTime = now() + unit.toNanos(initialDelay); - RunnableScheduledFuture t = decorateTask(command, - new ScheduledFutureTask(command, - null, - triggerTime, - unit.toNanos(-delay))); + ScheduledFutureTask sft = + new ScheduledFutureTask(command, + null, + triggerTime, + unit.toNanos(-delay)); + RunnableScheduledFuture t = decorateTask(command, sft); + sft.outerTask = t; delayedExecute(t); return t; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/naming/ldap/StartTlsRequest.java --- a/j2se/src/share/classes/javax/naming/ldap/StartTlsRequest.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/naming/ldap/StartTlsRequest.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,7 +31,8 @@ import javax.naming.ConfigurationException; import javax.naming.NamingException; import com.sun.naming.internal.VersionHelper; -import sun.misc.Service; +import java.util.ServiceLoader; +import java.util.ServiceConfigurationError; /** * This class implements the LDAPv3 Extended Request for StartTLS as @@ -179,17 +180,16 @@ StartTlsResponse resp = null; - Iterator ps = Service.providers(StartTlsResponse.class, - getContextClassLoader()); + ServiceLoader sl = ServiceLoader.load( + StartTlsResponse.class, getContextClassLoader()); + Iterator iter = sl.iterator(); - while (resp == null && privilegedHasNext(ps)) { - resp = (StartTlsResponse)ps.next(); + while (resp == null && privilegedHasNext(iter)) { + resp = iter.next(); } - if (resp != null) { return resp; } - try { VersionHelper helper = VersionHelper.getVersionHelper(); Class clas = helper.loadClass( diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/sound/midi/Synthesizer.java --- a/j2se/src/share/classes/javax/sound/midi/Synthesizer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/sound/midi/Synthesizer.java Thu Jul 05 23:47:33 2007 +0000 @@ -73,7 +73,7 @@ * @see Transmitter * @see MidiDevice * - * @version 1.35, 07/05/05 + * @version 1.36, 07/06/09 * @author Kara Kytle */ public interface Synthesizer extends MidiDevice { @@ -252,7 +252,8 @@ * isSoundbankSupported(), and if the instrument's * Soundbank is supported, you can try loading the instrument. * - * @return list of available instruments. + * @return list of available instruments. If the synthesizer + * has no instruments coming with it, an array of length 0 is returned. * @see #getLoadedInstruments * @see #isSoundbankSupported(Soundbank) * @see #loadInstrument diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/sql/rowset/serial/SerialClob.java --- a/j2se/src/share/classes/javax/sql/rowset/serial/SerialClob.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/sql/rowset/serial/SerialClob.java Thu Jul 05 23:47:33 2007 +0000 @@ -329,15 +329,7 @@ public long position(Clob searchStr, long start) throws SerialException, SQLException { - char cPattern[] = null; - try { - java.io.Reader r = searchStr.getCharacterStream(); - cPattern = new char[(int)searchStr.length()]; - r.read(cPattern); - } catch (IOException e) { - throw new SerialException("Error streaming Clob search data"); - } - return position(new String(cPattern), start); + return position(searchStr.getSubString(1,(int)searchStr.length()), start); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/JFileChooser.java --- a/j2se/src/share/classes/javax/swing/JFileChooser.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/JFileChooser.java Thu Jul 05 23:47:33 2007 +0000 @@ -33,7 +33,6 @@ import java.io.File; import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.IOException; import java.util.Vector; @@ -86,7 +85,7 @@ * attribute: isContainer false * description: A component which allows for the interactive selection of a file. * - * @version 1.122 05/05/07 + * @version 1.123 05/09/07 * @author Jeff Dinkins * */ @@ -250,8 +249,6 @@ private String approveButtonToolTipText = null; private int approveButtonMnemonic = 0; - private ActionListener actionListener = null; - private Vector filters = new Vector(5); private JDialog dialog = null; private int dialogType = OPEN_DIALOG; @@ -461,7 +458,7 @@ /** * Returns the selected file. This can be set either by the - * programmer via setFile or by a user action, such as + * programmer via setSelectedFile or by a user action, such as * either typing the filename into the UI or selecting the * file from a list in the UI. * @@ -521,12 +518,15 @@ */ public void setSelectedFiles(File[] selectedFiles) { File[] oldValue = this.selectedFiles; - if (selectedFiles != null && selectedFiles.length == 0) { - selectedFiles = null; - } - this.selectedFiles = selectedFiles; - setSelectedFile((selectedFiles != null) ? selectedFiles[0] : null); - firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, this.selectedFiles); + if (selectedFiles == null || selectedFiles.length == 0) { + selectedFiles = null; + this.selectedFiles = null; + setSelectedFile(null); + } else { + this.selectedFiles = selectedFiles.clone(); + setSelectedFile(this.selectedFiles[0]); + } + firePropertyChange(SELECTED_FILES_CHANGED_PROPERTY, oldValue, selectedFiles); } /** @@ -1124,8 +1124,10 @@ FileFilter[] oldValue = getChoosableFileFilters(); filters.addElement(filter); firePropertyChange(CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY, oldValue, getChoosableFileFilters()); + if (fileFilter == null && filters.size() == 1) { + setFileFilter(filter); + } } - setFileFilter(filter); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/JPopupMenu.java --- a/j2se/src/share/classes/javax/swing/JPopupMenu.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/JPopupMenu.java Thu Jul 05 23:47:33 2007 +0000 @@ -76,7 +76,7 @@ * attribute: isContainer false * description: A small window that pops up and displays a series of choices. * - * @version 1.204 @(#)JPopupMenu.java 1.204 + * @version 1.205 @(#)JPopupMenu.java 1.205 * @author Georges Saab * @author David Karlton * @author Arnaud Weber @@ -863,7 +863,7 @@ * @return true if this menu is a standalone popup menu, otherwise false */ private boolean isPopupMenu() { - return !(invoker instanceof JMenu); + return ((invoker != null) && !(invoker instanceof JMenu)); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/JTabbedPane.java --- a/j2se/src/share/classes/javax/swing/JTabbedPane.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/JTabbedPane.java Thu Jul 05 23:47:33 2007 +0000 @@ -100,7 +100,7 @@ * description: A component which provides a tab folder metaphor for * displaying one component from a set of components. * - * @version 1.161 05/05/07 + * @version 1.162 05/09/07 * @author Dave Moore * @author Philip Milne * @author Amy Fowler @@ -723,6 +723,8 @@ if (component != null) { addImpl(component, null, -1); component.setVisible(false); + } else { + firePropertyChange("indexForNullComponent", -1, index); } if (pages.size() == 1) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/RepaintManager.java --- a/j2se/src/share/classes/javax/swing/RepaintManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/RepaintManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -52,7 +52,7 @@ * Any calls to repaint on one of these will call into the * appropriate addDirtyRegion method. * - * @version 1.75 05/05/07 + * @version 1.76 05/09/07 * @author Arnaud Weber */ public class RepaintManager @@ -502,8 +502,6 @@ addDirtyRegion0(applet, x, y, w, h); } - // This is invoked from SystemEventQueueUtilities to flush any pending - // heavy weight regions into real paints. void scheduleHeavyWeightPaints() { Map hws; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/ToolTipManager.java --- a/j2se/src/share/classes/javax/swing/ToolTipManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/ToolTipManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -50,7 +50,7 @@ * tooltip will be shown again after initialDelay milliseconds. * * @see JComponent#createToolTip - * @version 1.81 05/05/07 + * @version 1.82 06/13/07 * @author Dave Moore * @author Rich Schiavi */ @@ -461,19 +461,22 @@ // if we get an exit and have a heavy window // we need to check if it if overlapping the inside component Container insideComponentWindow = insideComponent.getTopLevelAncestor(); - Point location = event.getPoint(); - SwingUtilities.convertPointToScreen(location, window); + // insideComponent may be removed after tooltip is made visible + if (insideComponentWindow != null) { + Point location = event.getPoint(); + SwingUtilities.convertPointToScreen(location, window); + + location.x -= insideComponentWindow.getX(); + location.y -= insideComponentWindow.getY(); - location.x -= insideComponentWindow.getX(); - location.y -= insideComponentWindow.getY(); - - location = SwingUtilities.convertPoint(null,location,insideComponent); - if (location.x >= 0 && location.x < insideComponent.getWidth() && - location.y >= 0 && location.y < insideComponent.getHeight()) { - shouldHide = false; - } else { - shouldHide = true; - } + location = SwingUtilities.convertPoint(null, location, insideComponent); + if (location.x >= 0 && location.x < insideComponent.getWidth() && + location.y >= 0 && location.y < insideComponent.getHeight()) { + shouldHide = false; + } else { + shouldHide = true; + } + } } else if(event.getSource() == insideComponent && tipWindow != null) { Window win = SwingUtilities.getWindowAncestor(insideComponent); if (win != null) { // insideComponent may have been hidden (e.g. in a menu) diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/UIManager.java --- a/j2se/src/share/classes/javax/swing/UIManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/UIManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,8 +25,6 @@ package javax.swing; import java.awt.Component; -import java.awt.Container; -import java.awt.Window; import java.awt.Font; import java.awt.Color; import java.awt.Insets; @@ -44,26 +42,19 @@ import javax.swing.event.SwingPropertyChangeSupport; import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeEvent; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; import java.io.Serializable; import java.io.File; import java.io.FileInputStream; -import java.io.BufferedInputStream; import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Hashtable; import java.util.Properties; import java.util.StringTokenizer; import java.util.Vector; import java.util.Locale; import sun.awt.SunToolkit; +import sun.awt.OSInfo; import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2; import java.lang.reflect.Method; @@ -176,7 +167,7 @@ * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. * - * @version 1.133 05/05/07 + * @version 1.134 06/07/07 * @author Thomas Ball * @author Hans Muller */ @@ -395,9 +386,8 @@ "com.sun.java.swing.plaf.motif.MotifLookAndFeel")); // Only include windows on Windows boxs. - String osName = (String)AccessController.doPrivileged( - new GetPropertyAction("os.name")); - if (osName != null && osName.indexOf("Windows") != -1) { + OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction()); + if (osType == OSInfo.OSType.WINDOWS) { iLAFs.add(new LookAndFeelInfo("Windows", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel")); if (Toolkit.getDefaultToolkit().getDesktopProperty( @@ -615,33 +605,25 @@ * @see #getCrossPlatformLookAndFeelClassName */ public static String getSystemLookAndFeelClassName() { - String systemLAF = (String)AccessController.doPrivileged( + String systemLAF = AccessController.doPrivileged( new GetPropertyAction("swing.systemlaf")); if (systemLAF != null) { return systemLAF; } - String osName = (String)AccessController.doPrivileged( - new GetPropertyAction("os.name")); - - if (osName != null) { - if (osName.indexOf("Windows") != -1) { - return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction()); + if (osType == OSInfo.OSType.WINDOWS) { + return "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + } else { + String desktop = AccessController.doPrivileged(new GetPropertyAction("sun.desktop")); + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if ("gnome".equals(desktop) && + toolkit instanceof SunToolkit && + ((SunToolkit) toolkit).isNativeGTKAvailable()) { + // May be set on Linux and Solaris boxs. + return "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; } - else { - String desktop = (String)AccessController.doPrivileged( - new GetPropertyAction("sun.desktop")); - Toolkit toolkit = Toolkit.getDefaultToolkit(); - if ("gnome".equals(desktop) && - toolkit instanceof SunToolkit && - ((SunToolkit)toolkit).isNativeGTKAvailable()) - { - // May be set on Linux and Solaris boxs. - return "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"; - } - if ((osName.indexOf("Solaris") != -1) || - (osName.indexOf("SunOS") != -1)) { - return "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; - } + if (osType == OSInfo.OSType.SOLARIS) { + return "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; } } return getCrossPlatformLookAndFeelClassName(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/border/LineBorder.java --- a/j2se/src/share/classes/javax/swing/border/LineBorder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/border/LineBorder.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,9 +26,13 @@ import java.awt.Graphics; import java.awt.Insets; -import java.awt.Rectangle; import java.awt.Color; import java.awt.Component; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; import java.beans.ConstructorProperties; /** @@ -44,7 +48,7 @@ * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. * - * @version 1.30 05/05/07 + * @version 1.31 05/09/07 * @author David Kloba */ public class LineBorder extends AbstractBorder @@ -118,18 +122,32 @@ * @param height the height of the painted border */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Color oldColor = g.getColor(); - int i; + if ((this.thickness > 0) && (g instanceof Graphics2D)) { + Graphics2D g2d = (Graphics2D) g; + + Color oldColor = g2d.getColor(); + g2d.setColor(this.lineColor); + + Shape outer; + Shape inner; - /// PENDING(klobad) How/should do we support Roundtangles? - g.setColor(lineColor); - for(i = 0; i < thickness; i++) { - if(!roundedCorners) - g.drawRect(x+i, y+i, width-i-i-1, height-i-i-1); - else - g.drawRoundRect(x+i, y+i, width-i-i-1, height-i-i-1, thickness, thickness); + int offs = this.thickness; + int size = offs + offs; + if (this.roundedCorners) { + int arc = offs + size; + outer = new RoundRectangle2D.Float(x, y, width, height, arc, arc); + inner = new RoundRectangle2D.Float(x + offs, y + offs, width - size, height - size, arc, arc); + } + else { + outer = new Rectangle2D.Float(x, y, width, height); + inner = new Rectangle2D.Float(x + offs, y + offs, width - size, height - size); + } + Path2D path = new Path2D.Float(Path2D.WIND_EVEN_ODD); + path.append(outer, false); + path.append(inner, false); + g2d.fill(path); + g2d.setColor(oldColor); } - g.setColor(oldColor); } /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicComboBoxUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -59,7 +59,7 @@ * KeyStroke bindings. See the article Keyboard Bindings in Swing * at The Swing Connection. * - * @version 1.193 05/05/07 + * @version 1.194 06/13/07 * @author Arnaud Weber * @author Tom Santos * @author Mark Davidson @@ -1506,7 +1506,8 @@ // Forces the selection of the list item boolean isEnterSelectablePopup = UIManager.getBoolean("ComboBox.isEnterSelectablePopup"); - if (!comboBox.isEditable() || isEnterSelectablePopup) { + if (!comboBox.isEditable() || isEnterSelectablePopup + || ui.isTableCellEditor) { Object listItem = ui.popup.getList().getSelectedValue(); if (listItem != null) { comboBox.getModel().setSelectedItem(listItem); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -61,6 +61,7 @@ protected Icon homeFolderIcon = null; protected Icon listViewIcon = null; protected Icon detailsViewIcon = null; + protected Icon viewMenuIcon = null; protected int saveButtonMnemonic = 0; protected int openButtonMnemonic = 0; @@ -257,6 +258,7 @@ homeFolderIcon = UIManager.getIcon("FileChooser.homeFolderIcon"); detailsViewIcon = UIManager.getIcon("FileChooser.detailsViewIcon"); listViewIcon = UIManager.getIcon("FileChooser.listViewIcon"); + viewMenuIcon = UIManager.getIcon("FileChooser.viewMenuIcon"); } protected void installStrings(JFileChooser fc) { @@ -312,6 +314,7 @@ homeFolderIcon = null; detailsViewIcon = null; listViewIcon = null; + viewMenuIcon = null; } protected void uninstallStrings(JFileChooser fc) { @@ -880,11 +883,12 @@ // check for wildcard pattern FileFilter currentFilter = chooser.getFileFilter(); if (!selectedFile.exists() && isGlobPattern(filename)) { + changeDirectory(selectedFile.getParentFile()); if (globFilter == null) { globFilter = new GlobFilter(); } try { - globFilter.setPattern(filename); + globFilter.setPattern(selectedFile.getName()); if (!(currentFilter instanceof GlobFilter)) { actualFileFilter = currentFilter; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicListUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicListUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicListUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -36,12 +36,8 @@ import java.awt.*; import java.awt.event.*; import java.awt.datatransfer.Transferable; -import java.awt.dnd.*; import java.awt.geom.Point2D; -import java.util.ArrayList; -import java.util.TooManyListenersException; - import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; @@ -54,7 +50,7 @@ * {@code BasicListUI} instances cannot be shared between multiple * lists. * - * @version 1.129 05/05/07 + * @version 1.130 05/09/07 * @author Hans Muller * @author Philip Milne * @author Shannon Hickey (drag and drop) @@ -2361,7 +2357,7 @@ * if it is not defined). Subsequent same key presses move the keyboard * focus to the next object that starts with the same letter until another * key is pressed, then it is treated as the prefix with appropriate number - * of the same letters followed by first typed anothe letter. + * of the same letters followed by first typed another letter. */ public void keyTyped(KeyEvent e) { JList src = (JList)e.getSource(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -99,7 +99,7 @@ * has been added to the java.beans package. * Please see {@link java.beans.XMLEncoder}. * - * @version 1.282 05/05/07 + * @version 1.283 05/09/07 * @author unattributed */ public abstract class BasicLookAndFeel extends LookAndFeel implements Serializable @@ -2304,7 +2304,6 @@ // Activate the frame. try { ((JInternalFrame)parent).setSelected(true); } catch (PropertyVetoException e1) { } - break; } parent = parent.getParent(); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,7 +44,7 @@ /** * BasicMenuItem implementation * - * @version 1.148 05/05/07 + * @version 1.149 06/07/07 * @author Georges Saab * @author David Karlton * @author Arnaud Weber @@ -435,11 +435,13 @@ /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. + * That is if useCheckAndArrow() is true. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); - if (iconFactory == null + if (! useCheckAndArrow() + || iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } @@ -659,11 +661,13 @@ /* * in case .checkIconFactory is defined for this UI and the icon is * compatible with it then the icon is handled by the checkIcon. + * That is if useCheckAndArrow() is true. */ MenuItemCheckIconFactory iconFactory = (MenuItemCheckIconFactory) UIManager.get(getPropertyPrefix() + ".checkIconFactory"); - if (iconFactory == null + if (! useCheckAndArrow() + || iconFactory == null || ! iconFactory.isCompatible(checkIcon, getPropertyPrefix())) { icon = b.getIcon(); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -56,7 +56,7 @@ * A Windows L&F implementation of PopupMenuUI. This implementation * is a "combined" view/controller. * - * @version 1.142 05/05/07 + * @version 1.144 06/14/07 * @author Georges Saab * @author David Karlton * @author Arnaud Weber @@ -736,9 +736,11 @@ } void uninstall() { - MenuSelectionManager.defaultManager().removeChangeListener(this); - ungrabWindow(); - AppContext.getAppContext().put(MOUSE_GRABBER_KEY, null); + synchronized (MOUSE_GRABBER_KEY) { + MenuSelectionManager.defaultManager().removeChangeListener(this); + ungrabWindow(); + AppContext.getAppContext().remove(MOUSE_GRABBER_KEY); + } } void grabWindow(MenuElement[] newPath) { @@ -761,7 +763,7 @@ if (invoker instanceof JPopupMenu) { invoker = ((JPopupMenu)invoker).getInvoker(); } - grabbedWindow = (invoker == null || invoker instanceof Window)? + grabbedWindow = invoker instanceof Window? (Window)invoker : SwingUtilities.getWindowAncestor(invoker); if(grabbedWindow != null) { @@ -851,7 +853,9 @@ src = (Component)ev.getSource(); if(!(src instanceof MenuElement)) { // Do not forward event to MSM, let component handle it - break; + if (isInPopup(src)) { + break; + } } if(src instanceof JMenu || !(src instanceof JMenuItem)) { MenuSelectionManager.defaultManager(). @@ -1137,6 +1141,8 @@ Component c = popup.getInvoker(); if(c instanceof JFrame) { invoker = ((JFrame)c).getRootPane(); + } else if(c instanceof JDialog) { + invoker = ((JDialog)c).getRootPane(); } else if(c instanceof JApplet) { invoker = ((JApplet)c).getRootPane(); } else { @@ -1203,8 +1209,10 @@ } void uninstall() { - MenuSelectionManager.defaultManager().removeChangeListener(this); - AppContext.getAppContext().put(MENU_KEYBOARD_HELPER_KEY, null); + synchronized (MENU_KEYBOARD_HELPER_KEY) { + MenuSelectionManager.defaultManager().removeChangeListener(this); + AppContext.getAppContext().remove(MENU_KEYBOARD_HELPER_KEY); + } } } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java --- a/j2se/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -3518,22 +3518,8 @@ pane.repaint(); } else if (name =="indexForTitle") { - int index = ((Integer)e.getNewValue()).intValue(); - String title = tabPane.getTitleAt(index); - if (BasicHTML.isHTMLString(title)) { - if (htmlViews==null) { // Initialize vector - htmlViews = createHTMLVector(); - } else { // Vector already exists - View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.setElementAt(v, index); - } - } else { - if (htmlViews != null && htmlViews.elementAt(index) != null) { - htmlViews.setElementAt(null, index); - } - } calculatedBaseline = false; - updateMnemonics(); + updateHtmlViews((Integer)e.getNewValue()); } else if (name == "tabLayoutPolicy") { BasicTabbedPaneUI.this.uninstallUI(pane); BasicTabbedPaneUI.this.installUI(pane); @@ -3570,10 +3556,32 @@ tabPane.revalidate(); tabPane.repaint(); calculatedBaseline = false; + } else if (name == "indexForNullComponent") { + isRunsDirty = true; + updateHtmlViews((Integer)e.getNewValue()); } else if (name == "font") { calculatedBaseline = false; } } + + private void updateHtmlViews(int index) { + String title = tabPane.getTitleAt(index); + boolean isHTML = BasicHTML.isHTMLString(title); + if (isHTML) { + if (htmlViews==null) { // Initialize vector + htmlViews = createHTMLVector(); + } else { // Vector already exists + View v = BasicHTML.createHTMLView(tabPane, title); + htmlViews.insertElementAt(v, index); + } + } else { // Not HTML + if (htmlViews!=null) { // Add placeholder + htmlViews.insertElementAt(null, index); + } // else nada! + } + updateMnemonics(); + } + // // ChangeListener // @@ -3691,23 +3699,8 @@ if (child instanceof UIResource) { return; } - int index = tp.indexOfComponent(child); - String title = tp.getTitleAt(index); - boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { - if (htmlViews==null) { // Initialize vector - htmlViews = createHTMLVector(); - } else { // Vector already exists - View v = BasicHTML.createHTMLView(tp, title); - htmlViews.insertElementAt(v, index); - } - } else { // Not HTML - if (htmlViews!=null) { // Add placeholder - htmlViews.insertElementAt(null, index); - } // else nada! - } isRunsDirty = true; - updateMnemonics(); + updateHtmlViews(tp.indexOfComponent(child)); } public void componentRemoved(ContainerEvent e) { JTabbedPane tp = (JTabbedPane)e.getContainer(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java --- a/j2se/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,7 +31,6 @@ import javax.swing.event.*; import javax.swing.plaf.*; import javax.swing.plaf.basic.*; -import javax.swing.table.*; import java.awt.*; import java.awt.event.*; import java.beans.*; @@ -43,12 +42,11 @@ import sun.awt.shell.ShellFolder; import sun.swing.*; -import sun.swing.SwingUtilities2; /** * Metal L&F implementation of a FileChooser. * - * @version 1.99 05/05/07 + * @version 1.100 05/09/07 * @author Jeff Dinkins */ public class MetalFileChooserUI extends BasicFileChooserUI { @@ -108,6 +106,8 @@ private int fileNameLabelMnemonic = 0; private String fileNameLabelText = null; + private int folderNameLabelMnemonic = 0; + private String folderNameLabelText = null; private int filesOfTypeLabelMnemonic = 0; private String filesOfTypeLabelText = null; @@ -127,6 +127,25 @@ private String detailsViewButtonToolTipText = null; private String detailsViewButtonAccessibleName = null; + private AlignedLabel fileNameLabel; + private final PropertyChangeListener modeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fileNameLabel != null) { + populateFileNameLabel(); + } + } + }; + + private void populateFileNameLabel() { + if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { + fileNameLabel.setText(folderNameLabelText); + fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic); + } else { + fileNameLabel.setText(fileNameLabelText); + fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + } + } + // // ComponentUI Interface Implementation methods // @@ -193,6 +212,10 @@ public ListSelectionListener createListSelectionListener() { return MetalFileChooserUI.this.createListSelectionListener(getFileChooser()); } + + public boolean usesShellFolder() { + return useShellFolder; + } } public void installComponents(JFileChooser fc) { @@ -367,8 +390,8 @@ bottomPanel.add(fileNamePanel); bottomPanel.add(Box.createRigidArea(vstrut5)); - AlignedLabel fileNameLabel = new AlignedLabel(fileNameLabelText); - fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + fileNameLabel = new AlignedLabel(); + populateFileNameLabel(); fileNamePanel.add(fileNameLabel); fileNameTextField = new JTextField(35) { @@ -480,6 +503,8 @@ fileNameLabelMnemonic = UIManager.getInt("FileChooser.fileNameLabelMnemonic"); fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText",l); + folderNameLabelMnemonic = UIManager.getInt("FileChooser.folderNameLabelMnemonic"); + folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText",l); filesOfTypeLabelMnemonic = UIManager.getInt("FileChooser.filesOfTypeLabelMnemonic"); filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText",l); @@ -504,6 +529,12 @@ super.installListeners(fc); ActionMap actionMap = getActionMap(); SwingUtilities.replaceUIActionMap(fc, actionMap); + fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + } + + protected void uninstallListeners(JFileChooser fc) { + fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + super.uninstallListeners(fc); } protected ActionMap getActionMap() { @@ -1247,6 +1278,12 @@ private AlignedLabel[] group; private int maxWidth = 0; + AlignedLabel() { + super(); + setAlignmentX(JComponent.LEFT_ALIGNMENT); + } + + AlignedLabel(String text) { super(text); setAlignmentX(JComponent.LEFT_ALIGNMENT); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java --- a/j2se/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,26 +31,18 @@ import javax.swing.plaf.*; import javax.swing.*; import javax.swing.plaf.basic.*; -import javax.swing.border.*; -import javax.swing.text.JTextComponent; import javax.swing.text.DefaultEditorKit; -import java.util.*; -import java.awt.Font; import java.awt.Color; -import java.awt.SystemColor; import java.awt.event.KeyEvent; -import java.awt.event.InputEvent; import java.lang.reflect.*; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; -import java.net.URL; -import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; -import sun.awt.AppContext; -import sun.awt.SunToolkit; + +import sun.awt.*; import sun.security.action.GetPropertyAction; import sun.swing.DefaultLayoutStyle; import sun.swing.SwingLazyValue; @@ -88,7 +80,7 @@ * @see DefaultMetalTheme * @see OceanTheme * - * @version @(#)MetalLookAndFeel.java 1.212 07/05/05 + * @version @(#)MetalLookAndFeel.java 1.213 07/06/07 * @author Steve Wilson */ public class MetalLookAndFeel extends BasicLookAndFeel @@ -126,11 +118,10 @@ */ static boolean isWindows() { if (!checkedWindows) { - String osName = (String)AccessController.doPrivileged( - new GetPropertyAction("os.name")); - if (osName != null && osName.indexOf("Windows") != -1) { + OSInfo.OSType osType = AccessController.doPrivileged(OSInfo.getOSTypeAction()); + if (osType == OSInfo.OSType.WINDOWS) { isWindows = true; - String systemFonts = (String)AccessController.doPrivileged( + String systemFonts = AccessController.doPrivileged( new GetPropertyAction("swing.useSystemFontSettings")); useSystemFonts = (systemFonts != null && (Boolean.valueOf(systemFonts).booleanValue())); @@ -657,7 +648,7 @@ new SwingLazyValue( "javax.swing.plaf.metal.MetalBorders$MenuItemBorder"); - Object menuItemAcceleratorDelimiter = new String("-"); + Object menuItemAcceleratorDelimiter = "-"; Object toolBarBorder = new SwingLazyValue("javax.swing.plaf.metal.MetalBorders$ToolBarBorder"); Object progressBarBorder = new SwingLazyValue( @@ -1682,7 +1673,7 @@ else { // Create the default theme. We prefer Ocean, but will // use DefaultMetalTheme if told to. - String theme = (String)AccessController.doPrivileged( + String theme = AccessController.doPrivileged( new GetPropertyAction("swing.metalTheme")); if ("steel".equals(theme)) { currentTheme = new DefaultMetalTheme(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java --- a/j2se/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/synth/SynthSliderUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -54,7 +54,7 @@ /** * Synth's SliderUI. * - * @version 1.35, 05/05/07 + * @version 1.36, 05/09/07 * @author Joshua Outwater */ class SynthSliderUI extends BasicSliderUI implements PropertyChangeListener, @@ -246,6 +246,9 @@ } else { d.width = 200; } + Insets i = slider.getInsets(); + d.width += i.left + i.right; + d.height += i.top + i.bottom; return d; } @@ -635,6 +638,9 @@ protected void recalculateIfInsetsChanged() { SynthContext context = getContext(slider); Insets newInsets = style.getInsets(context, null); + Insets compInsets = slider.getInsets(); + newInsets.left += compInsets.left; newInsets.right += compInsets.right; + newInsets.top += compInsets.top; newInsets.bottom += compInsets.bottom; if (!newInsets.equals(insetCache)) { insetCache = newInsets; calculateGeometry(); @@ -713,8 +719,8 @@ // For horizontal sliders, make sure value is not painted // outside slider bounds. if (slider.getOrientation() == JSlider.HORIZONTAL) { - if (valueRect.x + labelWidth > contentDim.width) { - valueRect.x = contentDim.width - labelWidth; + if (valueRect.x + labelWidth > insetCache.left + contentDim.width) { + valueRect.x = (insetCache.left + contentDim.width) - labelWidth; } valueRect.x = Math.max(valueRect.x, 0); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java --- a/j2se/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java Thu Jul 05 23:47:33 2007 +0000 @@ -42,7 +42,7 @@ /** * Synth's SpinnerUI. * - * @version 1.20, 05/05/07 + * @version 1.21, 05/09/07 * @author Hans Muller * @author Joshua Outwater */ @@ -321,7 +321,7 @@ public void removeLayoutComponent(Component c) { if (c == nextButton) { - c = null; + nextButton = null; } else if (c == previousButton) { previousButton = null; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/plaf/synth/doc-files/componentProperties.html --- a/j2se/src/share/classes/javax/swing/plaf/synth/doc-files/componentProperties.html Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/plaf/synth/doc-files/componentProperties.html Thu Jul 05 23:47:33 2007 +0000 @@ -325,6 +325,17 @@ file and directory. +

+ + + + +
KeyDescription of Associated Value
FileChooser.viewMenuIcon
+
Icon
+
null
+
Icon used by the button that shows popup menu + for selection of a view mode. +

diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/text/DefaultHighlighter.java --- a/j2se/src/share/classes/javax/swing/text/DefaultHighlighter.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/text/DefaultHighlighter.java Thu Jul 05 23:47:33 2007 +0000 @@ -34,7 +34,7 @@ * painter that renders in a solid color. * * @author Timothy Prinzing - * @version 1.46 05/05/07 + * @version 1.47 05/21/07 * @see Highlighter */ public class DefaultHighlighter extends LayeredHighlighter { @@ -444,18 +444,18 @@ else { g.setColor(color); } + + Rectangle r; + if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) { // Contained in view, can just use bounds. - Rectangle alloc; if (bounds instanceof Rectangle) { - alloc = (Rectangle)bounds; + r = (Rectangle) bounds; } else { - alloc = bounds.getBounds(); + r = bounds.getBounds(); } - g.fillRect(alloc.x, alloc.y, alloc.width, alloc.height); - return alloc; } else { // Should only render part of View. @@ -464,16 +464,23 @@ Shape shape = view.modelToView(offs0, Position.Bias.Forward, offs1,Position.Bias.Backward, bounds); - Rectangle r = (shape instanceof Rectangle) ? + r = (shape instanceof Rectangle) ? (Rectangle)shape : shape.getBounds(); - g.fillRect(r.x, r.y, r.width, r.height); - return r; } catch (BadLocationException e) { // can't render + r = null; } } - // Only if exception - return null; + + if (r != null) { + // If we are asked to highlight, we should draw something even + // if the model-to-view projection is of zero width (6340106). + r.width = Math.max(r.width, 1); + + g.fillRect(r.x, r.y, r.width, r.height); + } + + return r; } private Color color; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/text/WrappedPlainView.java --- a/j2se/src/share/classes/javax/swing/text/WrappedPlainView.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/text/WrappedPlainView.java Thu Jul 05 23:47:33 2007 +0000 @@ -50,7 +50,7 @@ * without concern for the layout aspects. * * @author Timothy Prinzing - * @version 1.48 05/05/07 + * @version 1.49 05/23/07 * @see View */ public class WrappedPlainView extends BoxView implements TabExpander { @@ -237,6 +237,9 @@ Segment segment = SegmentCache.getSharedSegment(); loadText(segment, p0, p1); int currentWidth = getWidth(); + if (currentWidth == Integer.MAX_VALUE) { + currentWidth = (int) getDefaultSpan(View.X_AXIS); + } if (wordWrap) { p = p0 + Utilities.getBreakLocation(segment, metrics, tabBase, tabBase + currentWidth, @@ -321,6 +324,21 @@ metrics = host.getFontMetrics(f); tabSize = getTabSize() * metrics.charWidth('m'); } + + /** + * Return reasonable default values for the view dimensions. The standard + * text terminal size 80x24 is pretty suitable for the wrapped plain view. + */ + private float getDefaultSpan(int axis) { + switch (axis) { + case View.X_AXIS: + return 80 * metrics.getWidths()['M']; + case View.Y_AXIS: + return 24 * metrics.getHeight(); + default: + throw new IllegalArgumentException("Invalid axis: " + axis); + } + } // --- TabExpander methods ------------------------------------------ @@ -556,15 +574,18 @@ if (width == Integer.MAX_VALUE) { // We have been initially set to MAX_VALUE, but we don't // want this as our preferred. - return 100f; + width = getDefaultSpan(axis); } return width; case View.Y_AXIS: - if (lineCount < 0 || widthChanging) { - breakLines(getStartOffset()); - } - int h = lineCount * metrics.getHeight(); - return h; + if (getDocument().getLength() > 0) { + if ((lineCount < 0) || widthChanging) { + breakLines(getStartOffset()); + } + return lineCount * metrics.getHeight(); + } else { + return getDefaultSpan(axis); + } default: throw new IllegalArgumentException("Invalid axis: " + axis); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/swing/text/html/parser/Parser.java --- a/j2se/src/share/classes/javax/swing/text/html/parser/Parser.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/swing/text/html/parser/Parser.java Thu Jul 05 23:47:33 2007 +0000 @@ -74,7 +74,7 @@ * @see DTD * @see TagElement * @see SimpleAttributeSet - * @version 1.54, 05/05/07 + * @version 1.55, 05/21/07 * @author Arthur van Hoff * @author Sunita Mani */ @@ -400,7 +400,9 @@ // start tag that needs to be processed before // handling the tag. // - if (!elem.isEmpty() || !last.breaksFlow() || textpos != 0) { + if (!elem.isEmpty() || + ((last != null) && !last.breaksFlow()) || + (textpos != 0)) { handleText(tag); } else { // this variable gets updated in handleText(). diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/xml/datatype/FactoryFinder.java --- a/j2se/src/share/classes/javax/xml/datatype/FactoryFinder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/xml/datatype/FactoryFinder.java Thu Jul 05 23:47:33 2007 +0000 @@ -143,8 +143,10 @@ try { Class providerClass = getProviderClass(className, cl, doFallback); Object instance = providerClass.newInstance(); - dPrint("created new instance of " + providerClass + - " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("created new instance of " + providerClass + + " using ClassLoader: " + cl); + } return instance; } catch (ClassNotFoundException x) { @@ -261,7 +263,9 @@ return null; } - dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + } BufferedReader rd; try { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/xml/parsers/FactoryFinder.java --- a/j2se/src/share/classes/javax/xml/parsers/FactoryFinder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/xml/parsers/FactoryFinder.java Thu Jul 05 23:47:33 2007 +0000 @@ -143,8 +143,10 @@ try { Class providerClass = getProviderClass(className, cl, doFallback); Object instance = providerClass.newInstance(); - dPrint("created new instance of " + providerClass + - " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("created new instance of " + providerClass + + " using ClassLoader: " + cl); + } return instance; } catch (ClassNotFoundException x) { @@ -261,7 +263,9 @@ return null; } - dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + } BufferedReader rd; try { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/xml/parsers/SAXParser.java --- a/j2se/src/share/classes/javax/xml/parsers/SAXParser.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/xml/parsers/SAXParser.java Thu Jul 05 23:47:33 2007 +0000 @@ -71,11 +71,11 @@ * * Implementors of this class which wrap an underlaying implementation * can consider using the {@link org.xml.sax.helpers.ParserAdapter} - * class to initially adapt their SAX1 impelemntation to work under + * class to initially adapt their SAX1 implementation to work under * this revised class. * * @author Jeff Suttor - * @version $Revision: 1.4 $, $Date: 2005/11/03 19:34:15 $ + * @version $Revision: 1.6 $, $Date: 2007/01/27 01:26:27 $ */ public abstract class SAXParser { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/xml/stream/FactoryFinder.java --- a/j2se/src/share/classes/javax/xml/stream/FactoryFinder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/xml/stream/FactoryFinder.java Thu Jul 05 23:47:33 2007 +0000 @@ -22,305 +22,309 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ - -package javax.xml.stream; - -import java.io.InputStream; -import java.io.IOException; -import java.io.File; -import java.io.FileInputStream; - -import java.util.Properties; -import java.io.BufferedReader; -import java.io.InputStreamReader; - -/** - *

Implements pluggable Datatypes.

- * - *

This class is duplicated for each JAXP subpackage so keep it in - * sync. It is package private for secure class loading.

- * - * @author Santiago.PericasGeertsen@sun.com - */ -class FactoryFinder { - - /** - * Internal debug flag. - */ - private static boolean debug = false; - - /** - * Cache for properties in java.home/lib/jaxp.properties - */ - static Properties cacheProps = new Properties(); - - /** - * Flag indicating if properties from java.home/lib/jaxp.properties - * have been cached. - */ - static boolean firstTime = true; - - /** - * Security support class use to check access control before - * getting certain system resources. - */ - static SecuritySupport ss = new SecuritySupport(); - - // Define system property "jaxp.debug" to get output - static { - // Use try/catch block to support applets, which throws - // SecurityException out of this code. - try { - String val = ss.getSystemProperty("jaxp.debug"); - // Allow simply setting the prop to turn on debug - debug = val != null && !"false".equals(val); - } - catch (SecurityException se) { - debug = false; - } - } - - private static void dPrint(String msg) { - if (debug) { - System.err.println("JAXP: " + msg); - } - } - - /** - * Attempt to load a class using the class loader supplied. If that fails - * and fall back is enabled, the current (i.e. bootstrap) class loader is - * tried. - * - * If the class loader supplied is null, first try using the - * context class loader followed by the current (i.e. bootstrap) class - * loader. - */ - static private Class getProviderClass(String className, ClassLoader cl, - boolean doFallback) throws ClassNotFoundException - { - try { - if (cl == null) { - cl = ss.getContextClassLoader(); - if (cl == null) { - throw new ClassNotFoundException(); - } - else { - return cl.loadClass(className); - } - } - else { - return cl.loadClass(className); - } - } - catch (ClassNotFoundException e1) { - if (doFallback) { - // Use current class loader - should always be bootstrap CL - return Class.forName(className, true, FactoryFinder.class.getClassLoader()); - } - else { - throw e1; - } - } - } - - /** - * Create an instance of a class. Delegates to method - * getProviderClass() in order to load the class. - * - * @param className Name of the concrete class corresponding to the - * service provider - * - * @param cl ClassLoader to use to load the class, null means to use - * the bootstrap ClassLoader - * - * @param doFallback True if the current ClassLoader should be tried as - * a fallback if the class is not found using cl - */ - static Object newInstance(String className, ClassLoader cl, boolean doFallback) - throws ConfigurationError - { - try { - Class providerClass = getProviderClass(className, cl, doFallback); - Object instance = providerClass.newInstance(); - dPrint("created new instance of " + providerClass + - " using ClassLoader: " + cl); - return instance; - } - catch (ClassNotFoundException x) { - throw new ConfigurationError( - "Provider " + className + " not found", x); - } - catch (Exception x) { - throw new ConfigurationError( - "Provider " + className + " could not be instantiated: " + x, - x); - } - } - - /** - * Finds the implementation Class object in the specified order. Main - * entry point. - * @return Class object of factory, never null - * - * @param factoryId Name of the factory to find, same as - * a property name - * @param fallbackClassName Implementation class name, if nothing else - * is found. Use null to mean no fallback. - * - * Package private so this code can be shared. - */ - static Object find(String factoryId, String fallbackClassName) - throws ConfigurationError - { - dPrint("find factoryId =" + factoryId); - - // Use the system property first - try { - String systemProp = ss.getSystemProperty(factoryId); - if (systemProp != null) { - dPrint("found system property, value=" + systemProp); - return newInstance(systemProp, null, true); - } - } - catch (SecurityException se) { - if (debug) se.printStackTrace(); - } - - // Try read $java.home/lib/stax.properties followed by - // $java.home/lib/jaxp.properties if former not present - String configFile = null; - try { - String factoryClassName = null; - if (firstTime) { - synchronized (cacheProps) { - if (firstTime) { - configFile = ss.getSystemProperty("java.home") + File.separator + - "lib" + File.separator + "stax.properties"; - File f = new File(configFile); - firstTime = false; - if (ss.doesFileExist(f)) { - dPrint("Read properties file "+f); - cacheProps.load(ss.getFileInputStream(f)); - } - else { - configFile = ss.getSystemProperty("java.home") + File.separator + - "lib" + File.separator + "jaxp.properties"; - f = new File(configFile); - if (ss.doesFileExist(f)) { - dPrint("Read properties file "+f); - cacheProps.load(ss.getFileInputStream(f)); - } - } - } - } - } - factoryClassName = cacheProps.getProperty(factoryId); - - if (factoryClassName != null) { - dPrint("found in " + configFile + " value=" + factoryClassName); - return newInstance(factoryClassName, null, true); - } - } - catch (Exception ex) { - if (debug) ex.printStackTrace(); - } - - // Try Jar Service Provider Mechanism - Object provider = findJarServiceProvider(factoryId); - if (provider != null) { - return provider; - } - if (fallbackClassName == null) { - throw new ConfigurationError( - "Provider for " + factoryId + " cannot be found", null); - } - - dPrint("loaded from fallback value: " + fallbackClassName); - return newInstance(fallbackClassName, null, true); - } - - /* - * Try to find provider using Jar Service Provider Mechanism - * - * @return instance of provider class if found or null - */ - private static Object findJarServiceProvider(String factoryId) - throws ConfigurationError - { - String serviceId = "META-INF/services/" + factoryId; - InputStream is = null; - - // First try the Context ClassLoader - ClassLoader cl = ss.getContextClassLoader(); - if (cl != null) { - is = ss.getResourceAsStream(cl, serviceId); - - // If no provider found then try the current ClassLoader - if (is == null) { - cl = FactoryFinder.class.getClassLoader(); - is = ss.getResourceAsStream(cl, serviceId); - } - } else { - // No Context ClassLoader, try the current ClassLoader - cl = FactoryFinder.class.getClassLoader(); - is = ss.getResourceAsStream(cl, serviceId); - } - - if (is == null) { - // No provider found - return null; - } - - dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); - - BufferedReader rd; - try { - rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); - } - catch (java.io.UnsupportedEncodingException e) { - rd = new BufferedReader(new InputStreamReader(is)); - } - - String factoryClassName = null; - try { - // XXX Does not handle all possible input as specified by the - // Jar Service Provider specification - factoryClassName = rd.readLine(); - rd.close(); - } catch (IOException x) { - // No provider found - return null; - } - - if (factoryClassName != null && !"".equals(factoryClassName)) { - dPrint("found in resource, value=" + factoryClassName); - - // Note: here we do not want to fall back to the current - // ClassLoader because we want to avoid the case where the - // resource file was found using one ClassLoader and the - // provider class was instantiated using a different one. - return newInstance(factoryClassName, cl, false); - } - - // No provider found - return null; - } - - static class ConfigurationError extends Error { - private Exception exception; - - /** - * Construct a new instance with the specified detail string and - * exception. - */ - ConfigurationError(String msg, Exception x) { - super(msg); - this.exception = x; - } - - Exception getException() { - return exception; - } - } - -} + +package javax.xml.stream; + +import java.io.InputStream; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; + +import java.util.Properties; +import java.io.BufferedReader; +import java.io.InputStreamReader; + +/** + *

Implements pluggable Datatypes.

+ * + *

This class is duplicated for each JAXP subpackage so keep it in + * sync. It is package private for secure class loading.

+ * + * @author Santiago.PericasGeertsen@sun.com + */ +class FactoryFinder { + + /** + * Internal debug flag. + */ + private static boolean debug = false; + + /** + * Cache for properties in java.home/lib/jaxp.properties + */ + static Properties cacheProps = new Properties(); + + /** + * Flag indicating if properties from java.home/lib/jaxp.properties + * have been cached. + */ + static boolean firstTime = true; + + /** + * Security support class use to check access control before + * getting certain system resources. + */ + static SecuritySupport ss = new SecuritySupport(); + + // Define system property "jaxp.debug" to get output + static { + // Use try/catch block to support applets, which throws + // SecurityException out of this code. + try { + String val = ss.getSystemProperty("jaxp.debug"); + // Allow simply setting the prop to turn on debug + debug = val != null && !"false".equals(val); + } + catch (SecurityException se) { + debug = false; + } + } + + private static void dPrint(String msg) { + if (debug) { + System.err.println("JAXP: " + msg); + } + } + + /** + * Attempt to load a class using the class loader supplied. If that fails + * and fall back is enabled, the current (i.e. bootstrap) class loader is + * tried. + * + * If the class loader supplied is null, first try using the + * context class loader followed by the current (i.e. bootstrap) class + * loader. + */ + static private Class getProviderClass(String className, ClassLoader cl, + boolean doFallback) throws ClassNotFoundException + { + try { + if (cl == null) { + cl = ss.getContextClassLoader(); + if (cl == null) { + throw new ClassNotFoundException(); + } + else { + return cl.loadClass(className); + } + } + else { + return cl.loadClass(className); + } + } + catch (ClassNotFoundException e1) { + if (doFallback) { + // Use current class loader - should always be bootstrap CL + return Class.forName(className, true, FactoryFinder.class.getClassLoader()); + } + else { + throw e1; + } + } + } + + /** + * Create an instance of a class. Delegates to method + * getProviderClass() in order to load the class. + * + * @param className Name of the concrete class corresponding to the + * service provider + * + * @param cl ClassLoader to use to load the class, null means to use + * the bootstrap ClassLoader + * + * @param doFallback True if the current ClassLoader should be tried as + * a fallback if the class is not found using cl + */ + static Object newInstance(String className, ClassLoader cl, boolean doFallback) + throws ConfigurationError + { + try { + Class providerClass = getProviderClass(className, cl, doFallback); + Object instance = providerClass.newInstance(); + if (debug) { // Extra check to avoid computing cl strings + dPrint("created new instance of " + providerClass + + " using ClassLoader: " + cl); + } + return instance; + } + catch (ClassNotFoundException x) { + throw new ConfigurationError( + "Provider " + className + " not found", x); + } + catch (Exception x) { + throw new ConfigurationError( + "Provider " + className + " could not be instantiated: " + x, + x); + } + } + + /** + * Finds the implementation Class object in the specified order. Main + * entry point. + * @return Class object of factory, never null + * + * @param factoryId Name of the factory to find, same as + * a property name + * @param fallbackClassName Implementation class name, if nothing else + * is found. Use null to mean no fallback. + * + * Package private so this code can be shared. + */ + static Object find(String factoryId, String fallbackClassName) + throws ConfigurationError + { + dPrint("find factoryId =" + factoryId); + + // Use the system property first + try { + String systemProp = ss.getSystemProperty(factoryId); + if (systemProp != null) { + dPrint("found system property, value=" + systemProp); + return newInstance(systemProp, null, true); + } + } + catch (SecurityException se) { + if (debug) se.printStackTrace(); + } + + // Try read $java.home/lib/stax.properties followed by + // $java.home/lib/jaxp.properties if former not present + String configFile = null; + try { + String factoryClassName = null; + if (firstTime) { + synchronized (cacheProps) { + if (firstTime) { + configFile = ss.getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "stax.properties"; + File f = new File(configFile); + firstTime = false; + if (ss.doesFileExist(f)) { + dPrint("Read properties file "+f); + cacheProps.load(ss.getFileInputStream(f)); + } + else { + configFile = ss.getSystemProperty("java.home") + File.separator + + "lib" + File.separator + "jaxp.properties"; + f = new File(configFile); + if (ss.doesFileExist(f)) { + dPrint("Read properties file "+f); + cacheProps.load(ss.getFileInputStream(f)); + } + } + } + } + } + factoryClassName = cacheProps.getProperty(factoryId); + + if (factoryClassName != null) { + dPrint("found in " + configFile + " value=" + factoryClassName); + return newInstance(factoryClassName, null, true); + } + } + catch (Exception ex) { + if (debug) ex.printStackTrace(); + } + + // Try Jar Service Provider Mechanism + Object provider = findJarServiceProvider(factoryId); + if (provider != null) { + return provider; + } + if (fallbackClassName == null) { + throw new ConfigurationError( + "Provider for " + factoryId + " cannot be found", null); + } + + dPrint("loaded from fallback value: " + fallbackClassName); + return newInstance(fallbackClassName, null, true); + } + + /* + * Try to find provider using Jar Service Provider Mechanism + * + * @return instance of provider class if found or null + */ + private static Object findJarServiceProvider(String factoryId) + throws ConfigurationError + { + String serviceId = "META-INF/services/" + factoryId; + InputStream is = null; + + // First try the Context ClassLoader + ClassLoader cl = ss.getContextClassLoader(); + if (cl != null) { + is = ss.getResourceAsStream(cl, serviceId); + + // If no provider found then try the current ClassLoader + if (is == null) { + cl = FactoryFinder.class.getClassLoader(); + is = ss.getResourceAsStream(cl, serviceId); + } + } else { + // No Context ClassLoader, try the current ClassLoader + cl = FactoryFinder.class.getClassLoader(); + is = ss.getResourceAsStream(cl, serviceId); + } + + if (is == null) { + // No provider found + return null; + } + + if (debug) { // Extra check to avoid computing cl strings + dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + } + + BufferedReader rd; + try { + rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); + } + catch (java.io.UnsupportedEncodingException e) { + rd = new BufferedReader(new InputStreamReader(is)); + } + + String factoryClassName = null; + try { + // XXX Does not handle all possible input as specified by the + // Jar Service Provider specification + factoryClassName = rd.readLine(); + rd.close(); + } catch (IOException x) { + // No provider found + return null; + } + + if (factoryClassName != null && !"".equals(factoryClassName)) { + dPrint("found in resource, value=" + factoryClassName); + + // Note: here we do not want to fall back to the current + // ClassLoader because we want to avoid the case where the + // resource file was found using one ClassLoader and the + // provider class was instantiated using a different one. + return newInstance(factoryClassName, cl, false); + } + + // No provider found + return null; + } + + static class ConfigurationError extends Error { + private Exception exception; + + /** + * Construct a new instance with the specified detail string and + * exception. + */ + ConfigurationError(String msg, Exception x) { + super(msg); + this.exception = x; + } + + Exception getException() { + return exception; + } + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/javax/xml/transform/FactoryFinder.java --- a/j2se/src/share/classes/javax/xml/transform/FactoryFinder.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/javax/xml/transform/FactoryFinder.java Thu Jul 05 23:47:33 2007 +0000 @@ -143,8 +143,10 @@ try { Class providerClass = getProviderClass(className, cl, doFallback); Object instance = providerClass.newInstance(); - dPrint("created new instance of " + providerClass + - " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("created new instance of " + providerClass + + " using ClassLoader: " + cl); + } return instance; } catch (ClassNotFoundException x) { @@ -261,7 +263,9 @@ return null; } - dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + if (debug) { // Extra check to avoid computing cl strings + dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl); + } BufferedReader rd; try { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/org/w3c/dom/TypeInfo.java --- a/j2se/src/share/classes/org/w3c/dom/TypeInfo.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/org/w3c/dom/TypeInfo.java Thu Jul 05 23:47:33 2007 +0000 @@ -197,7 +197,7 @@ * in this interface. * @return If the document's schema is a DTD or no schema is associated * with the document, this method will always return false - * . If the document's schema is an XML Schema, the method will + * . If the document's schema is an XML Schema, the method will return * true if the reference type definition is derived from * the other type definition according to the derivation parameter. If * the value of the parameter is 0 (no bit is set to diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/GlobalCursorManager.java --- a/j2se/src/share/classes/sun/awt/GlobalCursorManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/GlobalCursorManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -85,11 +85,6 @@ private final Object lastUpdateLock = new Object(); /** - * The AWT Tree Lock. - */ - private final Object treeLock = new Container().getTreeLock(); - - /** * Should be called for any activity at the Java level which may affect * the global cursor, except for Java MOUSE_MOVED events. */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/HorizBagLayout.java --- a/j2se/src/share/classes/sun/awt/HorizBagLayout.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/HorizBagLayout.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-1996 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,12 @@ package sun.awt; import java.awt.*; -import java.util.Vector; /** * A horizontal 'bag' of Components. Allocates space for each Component * from left to right. * - * @version 1.18 05/05/07 + * @version 1.20 06/05/07 * @author Herb Jellinek */ public class HorizBagLayout implements LayoutManager { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/ModalityEvent.java --- a/j2se/src/share/classes/sun/awt/ModalityEvent.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/ModalityEvent.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.awt; import java.awt.*; -import java.util.*; /** * Event object describing changes in AWT modality diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/OSInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/sun/awt/OSInfo.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,185 @@ +/* + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.awt; + +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + +import static sun.awt.OSInfo.OSType.*; + +/** + * @author Pavel Porvatov + * @version 1.2 06/15/07 + */ +public class OSInfo { + public static enum OSType { + WINDOWS, + LINUX, + SOLARIS, + UNKNOWN + } + + /* + The map windowsVersionMap must contain all windows version constants except WINDOWS_UNKNOWN, + and so the method getWindowsVersion() will return the constant for known OS. + It allows compare objects by "==" instead of "equals". + */ + public static final WindowsVersion WINDOWS_UNKNOWN = new WindowsVersion(-1, -1); + public static final WindowsVersion WINDOWS_95 = new WindowsVersion(4, 0); + public static final WindowsVersion WINDOWS_98 = new WindowsVersion(4, 10); + public static final WindowsVersion WINDOWS_ME = new WindowsVersion(4, 90); + public static final WindowsVersion WINDOWS_2000 = new WindowsVersion(5, 0); + public static final WindowsVersion WINDOWS_XP = new WindowsVersion(5, 1); + public static final WindowsVersion WINDOWS_2003 = new WindowsVersion(5, 2); + public static final WindowsVersion WINDOWS_VISTA = new WindowsVersion(6, 0); + + private static final String OS_NAME = "os.name"; + private static final String OS_VERSION = "os.version"; + + private final static Map windowsVersionMap = new HashMap(); + + static { + windowsVersionMap.put(WINDOWS_95.toString(), WINDOWS_95); + windowsVersionMap.put(WINDOWS_98.toString(), WINDOWS_98); + windowsVersionMap.put(WINDOWS_ME.toString(), WINDOWS_ME); + windowsVersionMap.put(WINDOWS_2000.toString(), WINDOWS_2000); + windowsVersionMap.put(WINDOWS_XP.toString(), WINDOWS_XP); + windowsVersionMap.put(WINDOWS_2003.toString(), WINDOWS_2003); + windowsVersionMap.put(WINDOWS_VISTA.toString(), WINDOWS_VISTA); + } + + private static final PrivilegedAction osTypeAction = new PrivilegedAction() { + public OSType run() { + return getOSType(); + } + }; + + private OSInfo() { + // Don't allow to create instances + } + + /** + * Returns type of operating system. + */ + public static OSType getOSType() throws SecurityException { + String osName = System.getProperty(OS_NAME); + + if (osName != null) { + if (osName.contains("Windows")) { + return WINDOWS; + } + + if (osName.contains("Linux")) { + return LINUX; + } + + if (osName.contains("Solaris") || osName.contains("SunOS")) { + return SOLARIS; + } + + // determine another OS here + } + + return UNKNOWN; + } + + public static PrivilegedAction getOSTypeAction() { + return osTypeAction; + } + + public static WindowsVersion getWindowsVersion() throws SecurityException { + String osVersion = System.getProperty(OS_VERSION); + + if (osVersion == null) { + return WINDOWS_UNKNOWN; + } + + synchronized (windowsVersionMap) { + WindowsVersion result = windowsVersionMap.get(osVersion); + + if (result == null) { + // Try parse version and put object into windowsVersionMap + String[] arr = osVersion.split("\\."); + + if (arr.length == 2) { + try { + result = new WindowsVersion(Integer.parseInt(arr[0]), Integer.parseInt(arr[1])); + } catch (NumberFormatException e) { + return WINDOWS_UNKNOWN; + } + } else { + return WINDOWS_UNKNOWN; + } + + windowsVersionMap.put(osVersion, result); + } + + return result; + } + } + + public static class WindowsVersion implements Comparable { + private final int major; + + private final int minor; + + private WindowsVersion(int major, int minor) { + this.major = major; + this.minor = minor; + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int compareTo(WindowsVersion o) { + int result = major - o.getMajor(); + + if (result == 0) { + result = minor - o.getMinor(); + } + + return result; + } + + public boolean equals(Object obj) { + return obj instanceof WindowsVersion && compareTo((WindowsVersion) obj) == 0; + } + + public int hashCode() { + return 31 * major + minor; + } + + public String toString() { + return major + "." + minor; + } + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/PlatformFont.java --- a/j2se/src/share/classes/sun/awt/PlatformFont.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/PlatformFont.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt; -import java.awt.Font; import java.awt.GraphicsEnvironment; import java.awt.peer.FontPeer; import java.util.Locale; @@ -395,7 +394,7 @@ } result[resultIndex++] = lastFontDescriptor; - result[resultIndex++] = convertedData; + result[resultIndex] = convertedData; // Add the size to the converted data field. if(convertedData != null) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/RepaintArea.java --- a/j2se/src/share/classes/sun/awt/RepaintArea.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/RepaintArea.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import java.awt.Component; import java.awt.Graphics; -import java.awt.Point; import java.awt.Rectangle; import java.awt.event.PaintEvent; @@ -38,7 +37,7 @@ * that painting may still be executed asynchronously. * * @author Eric Hawkes - * @version 1.29 05/05/07 + * @version 1.31 06/05/07 * @since 1.3 */ public class RepaintArea { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/ScrollPaneWheelScroller.java --- a/j2se/src/share/classes/sun/awt/ScrollPaneWheelScroller.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/ScrollPaneWheelScroller.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt; -import java.awt.Toolkit; import java.awt.ScrollPane; import java.awt.Insets; import java.awt.Adjustable; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/SunDisplayChanger.java --- a/j2se/src/share/classes/sun/awt/SunDisplayChanger.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/SunDisplayChanger.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package sun.awt; -import java.awt.Component; -import java.awt.peer.ComponentPeer; -import java.awt.Container; import java.awt.IllegalComponentStateException; import java.util.Collections; import java.util.Iterator; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/SunToolkit.java --- a/j2se/src/share/classes/sun/awt/SunToolkit.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/SunToolkit.java Thu Jul 05 23:47:33 2007 +0000 @@ -834,6 +834,22 @@ } } + /** + * Returns the value of "sun.awt.noerasebackground" property. Default + * value is {@code false}. + */ + public static boolean getSunAwtNoerasebackground() { + return AccessController.doPrivileged(new GetBooleanAction("sun.awt.noerasebackground")); + } + + /** + * Returns the value of "sun.awt.erasebackgroundonresize" property. Default + * value is {@code false}. + */ + public static boolean getSunAwtErasebackgroundonresize() { + return AccessController.doPrivileged(new GetBooleanAction("sun.awt.erasebackgroundonresize")); + } + static SoftCache imgCache = new SoftCache(); static synchronized Image getImageFromHash(Toolkit tk, URL url) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/WindowClosingSupport.java --- a/j2se/src/share/classes/sun/awt/WindowClosingSupport.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/WindowClosingSupport.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package sun.awt; -import java.awt.Window; -import java.awt.event.WindowEvent; - /** * Interface for identifying and casting toolkits that support * WindowClosingListeners. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/dnd/SunDragSourceContextPeer.java --- a/j2se/src/share/classes/sun/awt/dnd/SunDragSourceContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/dnd/SunDragSourceContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,11 +32,9 @@ import java.awt.Image; import java.awt.Point; -import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceContext; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceDropEvent; @@ -51,8 +49,6 @@ import java.util.Map; import java.util.SortedMap; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import sun.awt.SunToolkit; import sun.awt.datatransfer.DataTransferer; @@ -62,7 +58,7 @@ * TBC *

* - * @version 1.25.05/05/07 + * @version 1.27.06/05/07 * @since JDK1.3.1 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java --- a/j2se/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/dnd/SunDropTargetContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt.dnd; -import java.awt.AWTPermission; import java.awt.Component; import java.awt.Point; @@ -47,6 +46,7 @@ import java.util.HashSet; import java.util.Map; +import java.util.Arrays; import java.io.IOException; import java.io.InputStream; @@ -733,7 +733,7 @@ this.nativeCtxt = nativeCtxt; this.dropAction = dropAction; this.actions = actions; - this.formats = formats; + this.formats = Arrays.copyOf(formats, formats.length); this.dispatchType = dispatchType; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/awt/im/InputMethodManager.java --- a/j2se/src/share/classes/sun/awt/im/InputMethodManager.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/awt/im/InputMethodManager.java Thu Jul 05 23:47:33 2007 +0000 @@ -35,8 +35,10 @@ import java.awt.Menu; import java.awt.MenuItem; import java.awt.Toolkit; +import sun.awt.AppContext; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.InvocationEvent; import java.awt.im.spi.InputMethodDescriptor; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; @@ -48,9 +50,11 @@ import java.util.Locale; import java.util.ServiceLoader; import java.util.Vector; +import java.util.Set; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; import sun.awt.InputMethodSupport; +import sun.awt.SunToolkit; /** * InputMethodManager is an abstract class that manages the input @@ -118,7 +122,7 @@ * as above. * * - * @version 1.44 05/10/07 + * @version 1.45 06/21/07 * @see java.awt.im.spi.InputMethod * @see sun.awt.im.InputContext * @see sun.awt.im.InputMethodAdapter @@ -313,12 +317,20 @@ waitForChangeRequest(); initializeInputMethodLocatorList(); try { - // show the popup menu within the event thread - EventQueue.invokeAndWait(new Runnable() { - public void run() { - showInputMethodMenu(); - } - }); + if (requestComponent != null) { + try { + showInputMethodMenuOnRequesterEDT(requestComponent); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } else { + // show the popup menu within the event thread + EventQueue.invokeAndWait(new Runnable() { + public void run() { + showInputMethodMenu(); + } + }); + } } catch (InterruptedException ie) { } catch (InvocationTargetException ite) { // should we do anything under these exceptions? @@ -326,6 +338,39 @@ } } + // Shows Input Method Menu on the EDT of requester component + // to avoid side effects. See 6544309. + private void showInputMethodMenuOnRequesterEDT(Component requester) + throws InterruptedException, InvocationTargetException { + + if (requester == null){ + return; + } + + class AWTInvocationLock {} + Object lock = new AWTInvocationLock(); + + InvocationEvent event = + new InvocationEvent(requester, + new Runnable() { + public void run() { + showInputMethodMenu(); + } + }, + lock, + true); + + AppContext requesterAppContext = SunToolkit.targetToAppContext(requester); + synchronized (lock) { + SunToolkit.postEvent(requesterAppContext, event); + } + + Throwable eventThrowable = event.getThrowable(); + if (eventThrowable != null) { + throw new InvocationTargetException(eventThrowable); + } + } + void setInputContext(InputContext inputContext) { if (currentInputContext != null && inputContext != null) { // don't throw this exception until 4237852 is fixed diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/beans/editors/FontEditor.java --- a/j2se/src/share/classes/sun/beans/editors/FontEditor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/beans/editors/FontEditor.java Thu Jul 05 23:47:33 2007 +0000 @@ -119,7 +119,7 @@ if (this.font == null) return "null"; - return "new java.awt.Font(\"" + font.getFamily() + "\", " + + return "new java.awt.Font(\"" + font.getName() + "\", " + font.getStyle() + ", " + font.getSize() + ")"; } @@ -157,7 +157,7 @@ return null; } StringBuilder sb = new StringBuilder(); - sb.append(this.font.getFamily()); + sb.append(this.font.getName()); sb.append(' '); boolean b = this.font.isBold(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/io/ByteToCharISCII91.java --- a/j2se/src/share/classes/sun/io/ByteToCharISCII91.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/io/ByteToCharISCII91.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,9 +1,33 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + package sun.io; import sun.nio.cs.ext.ISCII91; -/* @(#)ByteToCharISCII91.java 1.4 03/10/30 - * +/* * Copyright (c) 1998 International Business Machines. * All Rights Reserved. * @@ -13,8 +37,8 @@ * Purpose : Defines class ByteToCharISCII91. * * - * Revision History - * ======== ======= + * Revision History + * ======== ======= * * Date By Description * ---- -- ----------- @@ -27,27 +51,27 @@ * ISCII91 is the character encoding as defined in Indian Standard document * IS 13194:1991 ( Indian Script Code for Information Interchange ). * - * @see sun.io.ByteToCharConverter + * @see sun.io.ByteToCharConverter */ public class ByteToCharISCII91 extends ByteToCharConverter { private static final char[] directMapTable = ISCII91.getDirectMapTable(); private static final char NUKTA_CHAR = '\u093c'; - private static final char HALANT_CHAR = '\u094d'; + private static final char HALANT_CHAR = '\u094d'; private static final char ZWNJ_CHAR = '\u200c'; private static final char ZWJ_CHAR = '\u200d'; - private static final char INVALID_CHAR = '\uffff'; - + private static final char INVALID_CHAR = '\uffff'; + private char contextChar = INVALID_CHAR; private boolean needFlushing = false; - + /** * Converts ISCII91 characters to Unicode. * @see sun.io.ByteToCharConverter#convert */ - public int convert(byte input[], int inStart, int inEnd, - char output[], int outStart, int outEnd) + public int convert(byte input[], int inStart, int inEnd, + char output[], int outStart, int outEnd) throws ConversionBufferFullException, UnknownCharacterException { /*Rules: * 1)ATR,EXT,following character to be replaced with '\ufffd' @@ -75,20 +99,20 @@ switch(currentChar) { case '\u0901': case '\u0907': - case '\u0908': + case '\u0908': case '\u090b': case '\u093f': case '\u0940': case '\u0943': case '\u0964': - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; } contextChar = currentChar; needFlushing = true; - continue; + continue; case NUKTA_CHAR: switch(contextChar) { case '\u0901': @@ -116,7 +140,7 @@ output[charOff] = '\u093d'; break; case HALANT_CHAR: - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; @@ -124,16 +148,16 @@ output[charOff] = ZWJ_CHAR; break; default: - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; } - output[charOff] = NUKTA_CHAR; + output[charOff] = NUKTA_CHAR; } break; case HALANT_CHAR: - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; @@ -145,7 +169,7 @@ output[charOff] = HALANT_CHAR; break; case INVALID_CHAR: - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; @@ -158,7 +182,7 @@ throw new UnknownCharacterException(); } default: - if(needFlushing) { + if(needFlushing) { output[charOff++] = contextChar; contextChar = currentChar; continue; @@ -166,8 +190,8 @@ output[charOff] = currentChar; break; }//end switch - - contextChar = currentChar; + + contextChar = currentChar; needFlushing = false; charOff++; }//end while diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/io/CharToByteISCII91.java --- a/j2se/src/share/classes/sun/io/CharToByteISCII91.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/io/CharToByteISCII91.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,9 +1,33 @@ +/* + * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + package sun.io; import sun.nio.cs.ext.ISCII91; -/* @(#)CharToByteISCII91.java 1.5 03/10/30 - * +/* * Copyright (c) 1998 International Business Machines. * All Rights Reserved. * diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/management/snmp/jvminstr/README --- a/j2se/src/share/classes/sun/management/snmp/jvminstr/README Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/management/snmp/jvminstr/README Thu Jul 05 23:47:33 2007 +0000 @@ -1,6 +1,6 @@ #============================================================================== # JVM Management MIB - Instrumentation Classes -# Date: 07/06/21, Version: 1.5 +# Date: 07/07/05, Version: 1.5 #============================================================================== In this directory: diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.misc; + +import java.io.FileDescriptor; + +/* + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +public interface JavaIOFileDescriptorAccess { + public void set(FileDescriptor obj, int fd); + public int get(FileDescriptor fd); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/misc/PerformanceLogger.java --- a/j2se/src/share/classes/sun/misc/PerformanceLogger.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/misc/PerformanceLogger.java Thu Jul 05 23:47:33 2007 +0000 @@ -57,6 +57,11 @@ * to the console and a value of "file:" will cause * that given filename to be created and used for all output. *

+ * By default, times are measured using System.currentTimeMillis(). To use + * System.nanoTime() instead, add the command-line parameter:
+ -Dsun.perflog.nano=true + *
+ *

* Warning: Use at your own risk! * This class is intended for internal testing * purposes only and may be removed at any time. More @@ -72,6 +77,7 @@ private static final int LAST_RESERVED = START_INDEX; private static boolean perfLoggingOn = false; + private static boolean useNanoTime = false; private static Vector times; private static String logFileName = null; private static Writer logWriter = null; @@ -82,6 +88,15 @@ new sun.security.action.GetPropertyAction("sun.perflog")); if (perfLoggingProp != null) { perfLoggingOn = true; + + // Check if we should use nanoTime + String perfNanoProp = + (String) java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("sun.perflog.nano")); + if (perfNanoProp != null) { + useNanoTime = true; + } + // Now, figure out what the user wants to do with the data if (perfLoggingProp.regionMatches(true, 0, "file:", 0, 5)) { logFileName = perfLoggingProp.substring(5); @@ -149,6 +164,17 @@ } /** + * Return the current time, in millis or nanos as appropriate + */ + private static long getCurrentTime() { + if (useNanoTime) { + return System.nanoTime(); + } else { + return System.currentTimeMillis(); + } + } + + /** * Sets the start time. Ideally, this is the earliest time available * during the startup of a Java applet or application. This time is * later used to analyze the difference between the initial startup @@ -156,7 +182,7 @@ */ public static void setStartTime(String message) { if (loggingEnabled()) { - long nowTime = System.currentTimeMillis(); + long nowTime = getCurrentTime(); setStartTime(message, nowTime); } } @@ -193,7 +219,7 @@ */ public static int setTime(String message) { if (loggingEnabled()) { - long nowTime = System.currentTimeMillis(); + long nowTime = getCurrentTime(); return setTime(message, nowTime); } else { return 0; @@ -234,7 +260,7 @@ } /** - * Returns time at given index. + * Returns message at given index. */ public static String getMessageAtIndex(int index) { if (loggingEnabled()) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/misc/SharedSecrets.java --- a/j2se/src/share/classes/sun/misc/SharedSecrets.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/misc/SharedSecrets.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.jar.JarFile; import java.io.Console; import java.io.File; +import java.io.FileDescriptor; /** A repository of "shared secrets", which are a mechanism for calling implementation-private methods in another package without @@ -45,6 +46,7 @@ private static JavaIOAccess javaIOAccess; private static JavaIODeleteOnExitAccess javaIODeleteOnExitAccess; private static JavaNetAccess javaNetAccess; + private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess; public static JavaUtilJarAccess javaUtilJarAccess() { if (javaUtilJarAccess == null) { @@ -96,4 +98,16 @@ } return javaIODeleteOnExitAccess; } + + public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) { + javaIOFileDescriptorAccess = jiofda; + } + + public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() { + if (javaIOFileDescriptorAccess == null) + unsafe.ensureClassInitialized(FileDescriptor.class); + + return javaIOFileDescriptorAccess; + } + } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java --- a/j2se/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,7 +44,7 @@ * * @author Mayank Upadhyay * @author Ram Marti - * @version 1.32, 05/05/07 + * @version 1.33, 06/13/07 * @since 1.4 */ @@ -311,7 +311,7 @@ throws GSSException { String realm = null; - final String clientPrincipal; + final String clientPrincipal, tgsPrincipal = null; /* * Find the TGT for the realm that the client is in. If the client @@ -335,11 +335,8 @@ } } - final String tgsPrincipal = new String("krbtgt/" + realm + "@" + realm); - // System.out.println("Will look for ticket for: " + tgsPrincipal); - final AccessControlContext acc = AccessController.getContext(); - + try { final int realCaller = (caller == GSSUtil.CALLER_UNKNOWN) ? GSSUtil.CALLER_INITIATE diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/security/jgss/krb5/SubjectComber.java --- a/j2se/src/share/classes/sun/security/jgss/krb5/SubjectComber.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/security/jgss/krb5/SubjectComber.java Thu Jul 05 23:47:33 2007 +0000 @@ -39,7 +39,7 @@ * for the desired client/server principals. * * @author Ram Marti - * @version 1.19, 05/05/07 + * @version 1.20, 06/13/07 * @since 1.4.2 */ @@ -149,8 +149,8 @@ } } else { - if (ticket.getServer().getName().equals - (serverPrincipal)) { + if (serverPrincipal == null || + ticket.getServer().getName().equals(serverPrincipal)) { if (clientPrincipal == null || clientPrincipal.equals( diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/swing/FilePane.java --- a/j2se/src/share/classes/sun/swing/FilePane.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/swing/FilePane.java Thu Jul 05 23:47:33 2007 +0000 @@ -44,7 +44,6 @@ import javax.swing.table.*; import javax.swing.text.*; -import sun.swing.SwingUtilities2; import sun.awt.shell.*; /** @@ -57,7 +56,7 @@ * implementation of BasicFileChooserUI, and is intended to be API compatible * with earlier implementations of MetalFileChooserUI and WindowsFileChooserUI. * - * @version 1.40, 05/05/07 + * @version 1.41, 05/09/07 * @author Leif Samuelsson */ public class FilePane extends JPanel implements PropertyChangeListener { @@ -100,6 +99,116 @@ private static final Cursor waitCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + private final KeyListener detailsKeyListener = new KeyAdapter() { + private final long timeFactor; + + private final StringBuilder typedString = new StringBuilder(); + + private long lastTime = 1000L; + + { + Long l = (Long) UIManager.get("Table.timeFactor"); + timeFactor = (l != null) ? l : 1000L; + } + + /** + * Moves the keyboard focus to the first element whose prefix matches + * the sequence of alphanumeric keys pressed by the user with delay + * less than value of timeFactor. Subsequent same key + * presses move the keyboard focus to the next object that starts with + * the same letter until another key is pressed, then it is treated + * as the prefix with appropriate number of the same letters followed + * by first typed another letter. + */ + public void keyTyped(KeyEvent e) { + BasicDirectoryModel model = getModel(); + int rowCount = model.getSize(); + + if (detailsTable == null || rowCount == 0 || + e.isAltDown() || e.isControlDown() || e.isMetaDown()) { + return; + } + + InputMap inputMap = detailsTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + KeyStroke key = KeyStroke.getKeyStrokeForEvent(e); + + if (inputMap != null && inputMap.get(key) != null) { + return; + } + + int startIndex = detailsTable.getSelectionModel().getLeadSelectionIndex(); + + if (startIndex < 0) { + startIndex = 0; + } + + if (startIndex >= rowCount) { + startIndex = rowCount - 1; + } + + char c = e.getKeyChar(); + + long time = e.getWhen(); + + if (time - lastTime < timeFactor) { + if (typedString.length() == 1 && typedString.charAt(0) == c) { + // Subsequent same key presses move the keyboard focus to the next + // object that starts with the same letter. + startIndex++; + } else { + typedString.append(c); + } + } else { + startIndex++; + + typedString.setLength(0); + typedString.append(c); + } + + lastTime = time; + + if (startIndex >= rowCount) { + startIndex = 0; + } + + // Find next file + int index = getNextMatch(startIndex, rowCount - 1); + + if (index < 0 && startIndex > 0) { // wrap + index = getNextMatch(0, startIndex - 1); + } + + if (index >= 0) { + detailsTable.getSelectionModel().setSelectionInterval(index, index); + + Rectangle cellRect = detailsTable.getCellRect(index, + detailsTable.convertColumnIndexToView(COLUMN_FILENAME), false); + detailsTable.scrollRectToVisible(cellRect); + } + } + + private int getNextMatch(int startIndex, int finishIndex) { + BasicDirectoryModel model = getModel(); + JFileChooser fileChooser = getFileChooser(); + DetailsTableRowSorter rowSorter = getRowSorter(); + + String prefix = typedString.toString().toLowerCase(); + + // Search element + for (int index = startIndex; index <= finishIndex; index++) { + File file = (File) model.getElementAt(rowSorter.convertRowIndexToModel(index)); + + String fileName = fileChooser.getName(file).toLowerCase(); + + if (fileName.startsWith(prefix)) { + return index; + } + } + + return -1; + } + }; + private FocusListener editorFocusListener = new FocusAdapter() { public void focusLost(FocusEvent e) { if (! e.isTemporary()) { @@ -575,8 +684,16 @@ } void updateColumnInfo() { - ShellFolderColumnInfo[] allColumns = - ShellFolder.getFolderColumns(chooser.getCurrentDirectory()); + File dir = chooser.getCurrentDirectory(); + if (dir != null && fileChooserUIAccessor.usesShellFolder()) { + try { + dir = ShellFolder.getShellFolder(dir); + } catch (FileNotFoundException e) { + // Leave dir without changing + } + } + + ShellFolderColumnInfo[] allColumns = ShellFolder.getFolderColumns(dir); ArrayList visibleColumns = new ArrayList(); @@ -687,9 +804,9 @@ public void contentsChanged(ListDataEvent e) { // Update the selection after the model has been updated new DelayedSelectionUpdater(); - - updateColumnInfo(); + fireTableDataChanged(); } + public void intervalAdded(ListDataEvent e) { int i0 = e.getIndex0(); int i1 = e.getIndex1(); @@ -926,7 +1043,7 @@ // formatting cell text // TODO: it's rather a temporary trick, to be revised - String text = null; + String text; if (value == null) { text = ""; @@ -998,6 +1115,7 @@ detailsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); detailsTable.setShowGrid(false); detailsTable.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE); + detailsTable.addKeyListener(detailsKeyListener); Font font = list.getFont(); detailsTable.setFont(font); @@ -1384,15 +1502,14 @@ if (listSelectionModel instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)listSelectionModel). moveLeadSelectionIndex(lead); - ((DefaultListSelectionModel)listSelectionModel). - setAnchorSelectionIndex(anchor); + listSelectionModel.setAnchorSelectionIndex(anchor); } } finally { listSelectionModel.setValueIsAdjusting(false); } } else { JFileChooser chooser = getFileChooser(); - File f = null; + File f; if (isDirectorySelected()) { f = getDirectory(); } else { @@ -1450,6 +1567,8 @@ } private void doDirectoryChanged(PropertyChangeEvent e) { + getDetailsTableModel().updateColumnInfo(); + JFileChooser fc = getFileChooser(); FileSystemView fsv = fc.getFileSystemView(); @@ -1516,7 +1635,7 @@ } else if (s.equals("componentOrientation")) { ComponentOrientation o = (ComponentOrientation)e.getNewValue(); JFileChooser cc = (JFileChooser)e.getSource(); - if (o != (ComponentOrientation)e.getOldValue()) { + if (o != e.getOldValue()) { cc.applyComponentOrientation(o); } if (detailsTable != null) { @@ -1553,7 +1672,7 @@ listSelectionModel.clearSelection(); if (listSelectionModel instanceof DefaultListSelectionModel) { ((DefaultListSelectionModel)listSelectionModel).moveLeadSelectionIndex(0); - ((DefaultListSelectionModel)listSelectionModel).setAnchorSelectionIndex(0); + listSelectionModel.setAnchorSelectionIndex(0); } } } @@ -1824,5 +1943,6 @@ public Action getNewFolderAction(); public MouseListener createDoubleClickListener(JList list); public ListSelectionListener createListSelectionListener(); + public boolean usesShellFolder(); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/swing/SwingUtilities2.java --- a/j2se/src/share/classes/sun/swing/SwingUtilities2.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/swing/SwingUtilities2.java Thu Jul 05 23:47:33 2007 +0000 @@ -48,8 +48,7 @@ import sun.swing.PrintColorUIResource; import sun.swing.ImageIconUIResource; import sun.print.ProxyPrintGraphics; -import sun.awt.AppContext; -import sun.awt.SunToolkit; +import sun.awt.*; import sun.security.action.GetPropertyAction; import sun.security.util.SecurityConstants; import java.io.*; @@ -69,7 +68,7 @@ * releases and even patch releases. You should not rely on this class even * existing. * - * @version 1.59 05/23/07 + * @version 1.60 06/21/07 */ public class SwingUtilities2 { /** @@ -1482,7 +1481,7 @@ try { // On Windows just return true. Permission to read os.name // is granted to all code but wrapped in try to be safe. - if (System.getProperty("os.name").startsWith("Windows")) { + if (OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { return true; } // Else probably Solaris or Linux in which case may be remote X11 diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/swing/WindowsPlacesBar.java --- a/j2se/src/share/classes/sun/swing/WindowsPlacesBar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/swing/WindowsPlacesBar.java Thu Jul 05 23:47:33 2007 +0000 @@ -35,6 +35,7 @@ import javax.swing.filechooser.*; import sun.awt.shell.*; +import sun.awt.OSInfo; /** * WARNING: This class is an implementation detail and is only @@ -42,7 +43,7 @@ * this public API. *

* - * @version 1.14, 05/05/07 + * @version 1.15, 06/07/07 * @author Leif Samuelsson */ public class WindowsPlacesBar extends JToolBar @@ -59,8 +60,8 @@ setFloatable(false); putClientProperty("JToolBar.isRollover", Boolean.TRUE); - boolean isXPPlatform = (System.getProperty("os.name").startsWith("Windows") && - System.getProperty("os.version").compareTo("5.1") >= 0); + boolean isXPPlatform = (OSInfo.getOSType() == OSInfo.OSType.WINDOWS && + OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0); if (isXPStyle) { buttonSize = new Dimension(83, 69); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java --- a/j2se/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUIImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -54,7 +54,7 @@ * incompatible ways between releases. While this class is public, it * shoud be considered an implementation detail, and subject to change. * - * @version 1.14, 05/05/07 + * @version 1.15, 05/09/07 * @author Leif Samuelsson * @author Jeff Dinkins */ @@ -94,6 +94,8 @@ private int fileNameLabelMnemonic = 0; private String fileNameLabelText = null; + private int folderNameLabelMnemonic = 0; + private String folderNameLabelText = null; private int filesOfTypeLabelMnemonic = 0; private String filesOfTypeLabelText = null; @@ -113,6 +115,25 @@ private String detailsViewButtonToolTipText = null; private String detailsViewButtonAccessibleName = null; + private AlignedLabel fileNameLabel; + private final PropertyChangeListener modeListener = new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (fileNameLabel != null) { + populateFileNameLabel(); + } + } + }; + + private void populateFileNameLabel() { + if (getFileChooser().getFileSelectionMode() == JFileChooser.DIRECTORIES_ONLY) { + fileNameLabel.setText(folderNameLabelText); + fileNameLabel.setDisplayedMnemonic(folderNameLabelMnemonic); + } else { + fileNameLabel.setText(fileNameLabelText); + fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + } + } + public SynthFileChooserUIImpl(JFileChooser b) { super(b); } @@ -163,6 +184,10 @@ public ListSelectionListener createListSelectionListener() { return SynthFileChooserUIImpl.this.createListSelectionListener(getFileChooser()); } + + public boolean usesShellFolder() { + return useShellFolder; + } } public void installComponents(JFileChooser fc) { @@ -332,8 +357,8 @@ bottomPanel.add(fileNamePanel); bottomPanel.add(Box.createRigidArea(new Dimension(1, 5))); - AlignedLabel fileNameLabel = new AlignedLabel(fileNameLabelText); - fileNameLabel.setDisplayedMnemonic(fileNameLabelMnemonic); + fileNameLabel = new AlignedLabel(); + populateFileNameLabel(); fileNamePanel.add(fileNameLabel); fileNameTextField = new JTextField(35) { @@ -391,6 +416,16 @@ groupLabels(new AlignedLabel[] { fileNameLabel, filesOfTypeLabel }); } + protected void installListeners(JFileChooser fc) { + super.installListeners(fc); + fc.addPropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + } + + protected void uninstallListeners(JFileChooser fc) { + fc.removePropertyChangeListener(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY, modeListener); + super.uninstallListeners(fc); + } + private void updateUseShellFolder() { // Decide whether to use the ShellFolder class to populate shortcut // panel and combobox. @@ -468,6 +503,8 @@ fileNameLabelMnemonic = getMnemonic("FileChooser.fileNameLabelMnemonic", l); fileNameLabelText = UIManager.getString("FileChooser.fileNameLabelText", l); + folderNameLabelMnemonic = getMnemonic("FileChooser.folderNameLabelMnemonic", l); + folderNameLabelText = UIManager.getString("FileChooser.folderNameLabelText", l); filesOfTypeLabelMnemonic = getMnemonic("FileChooser.filesOfTypeLabelMnemonic", l); filesOfTypeLabelText = UIManager.getString("FileChooser.filesOfTypeLabelText", l); @@ -1022,6 +1059,11 @@ private AlignedLabel[] group; private int maxWidth = 0; + AlignedLabel() { + super(); + setAlignmentX(JComponent.LEFT_ALIGNMENT); + } + AlignedLabel(String text) { super(text); setAlignmentX(JComponent.LEFT_ALIGNMENT); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/build.properties --- a/j2se/src/share/demo/nbproject/jfc/Java2D/build.properties Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -main.dir=${basedir}/../../../jfc/Java2D - -src.dir=${main.dir}/src - -build.dir=build -classes.dir=${build.dir}/classes -jar=${main.dir}/Java2D.jar -javadoc.dir=${build.dir}/javadoc - -build.sysclasspath=ignore -# E.g.: cp=lib/x.jar:lib/y.jar -cp= -extra.run.cp= - -main.class=java2d.Java2Demo - -run.cp=${cp}:${classes.dir}:${extra.run.cp} - -debug=true -deprecation=false - -nbjdk.home=${basedir}/../../../.. - -applet.html=${main.dir}/Java2Demo.html diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/build.xml --- a/j2se/src/share/demo/nbproject/jfc/Java2D/build.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set property 'main.class' (e.g. in build.properties) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/file-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/file-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ - - - - - - - - - - Must set property 'includes' - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/jdk.xml --- a/j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/jdk.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/netbeans-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/netbeans-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/project.xml --- a/j2se/src/share/demo/nbproject/jfc/Java2D/nbproject/project.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ - - - - - - org.netbeans.modules.ant.freeform - - - Java2D - - user.build.properties - build.properties - ${nbjdk.home}/jre/lib/rt.jar - - - - - ${main.dir} - - - - java - ${src.dir} - - - ${build.dir} - - - - - jar - - - clean - - - clean - jar - - - run - - - - show-javadoc - - - - debug - - - - compile-selected - - includes - ${src.dir} - \.java$ - relative-path - - , - - - - - run - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug-fix - - class - ${src.dir} - \.java$ - relative-path-noext - - - - - - - - jar - ${jar} - jar - clean - - - - - - ${src.dir} - - - ${applet.html} - - - ${main.dir}/README.txt - - - - - - - - - - - - run-applet - - - - - - - - - ${src.dir} - ${cp} - ${run.cp} - ${nbjdk.bootclasspath} - ${classes.dir} - ${jar} - ${javadoc.dir} - 1.5 - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/build.properties --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/build.properties Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -main.dir=${basedir}/../../../jfc/Stylepad - -src.dir=${main.dir}/src - -build.dir=build -classes.dir=${build.dir}/classes -jar=${main.dir}/Stylepad.jar -javadoc.dir=${build.dir}/javadoc - -build.sysclasspath=ignore -# E.g.: cp=lib/x.jar:lib/y.jar -cp= -extra.run.cp= - -main.class=Stylepad - -run.cp=${cp}:${classes.dir}:${extra.run.cp} - -debug=true -deprecation=false - -nbjdk.home=${basedir}/../../../.. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/build.xml --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/build.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set property 'main.class' (e.g. in build.properties) - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/file-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/file-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ - - - - - - - - - - Must set property 'includes' - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/jdk.xml --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/jdk.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/netbeans-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/netbeans-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/project.xml --- a/j2se/src/share/demo/nbproject/jfc/Stylepad/nbproject/project.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ - - - - - - org.netbeans.modules.ant.freeform - - - Stylepad - - user.build.properties - build.properties - ${nbjdk.home}/jre/lib/rt.jar - - - - - ${main.dir} - - - - java - ${src.dir} - - - ${build.dir} - - - - - jar - - - clean - - - clean - jar - - - run - - - - show-javadoc - - - - debug - - - - compile-selected - - includes - ${src.dir} - \.java$ - relative-path - - , - - - - - run - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug-fix - - class - ${src.dir} - \.java$ - relative-path-noext - - - - - - - - jar - ${jar} - jar - clean - - - - - - ${src.dir} - - - ${main.dir}/README.txt - - - - - - - - - - - - - - - - - ${src.dir} - ${cp} - ${run.cp} - ${nbjdk.bootclasspath} - ${classes.dir} - ${jar} - ${javadoc.dir} - 1.5 - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/build.properties --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/build.properties Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -main.dir=${basedir}/../../../jfc/SwingSet2 - -src.dir=${main.dir}/src - -build.dir=build -classes.dir=${build.dir}/classes -jar=${main.dir}/SwingSet2.jar -javadoc.dir=${build.dir}/javadoc - -build.sysclasspath=ignore -# E.g.: cp=lib/x.jar:lib/y.jar -cp= -extra.run.cp= - -main.class=SwingSet2 - -run.cp=${cp}:${classes.dir}:${extra.run.cp} - -debug=true -deprecation=false - -nbjdk.home=${basedir}/../../../.. - -applet.html=${main.dir}/SwingSet2.html diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/build.xml --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/build.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Must set property 'main.class' (e.g. in build.properties) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/file-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/file-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ - - - - - - - - - - Must set property 'includes' - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/jdk.xml --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/jdk.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/netbeans-targets.xml --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/netbeans-targets.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/project.xml --- a/j2se/src/share/demo/nbproject/jfc/SwingSet2/nbproject/project.xml Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ - - - - - - org.netbeans.modules.ant.freeform - - - SwingSet2 - - user.build.properties - build.properties - ${nbjdk.home}/jre/lib/rt.jar - - - - - ${main.dir} - - - - java - ${src.dir} - - - ${build.dir} - - - - - jar - - - clean - - - clean - jar - - - run - - - - show-javadoc - - - - debug - - - - compile-selected - - includes - ${src.dir} - \.java$ - relative-path - - , - - - - - run - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug - - main.class - ${src.dir} - \.java$ - java-name - - - - - - - - debug-fix - - class - ${src.dir} - \.java$ - relative-path-noext - - - - - - - - jar - ${jar} - jar - clean - - - - - - ${src.dir} - - - ${applet.html} - - - ${main.dir}/README.txt - - - - - - - - - - - - run-applet - - - - - - - - - ${src.dir} - ${cp} - ${run.cp} - ${nbjdk.bootclasspath} - ${classes.dir} - ${jar} - ${javadoc.dir} - 1.5 - - - - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/share/native/java/net/net_util.h --- a/j2se/src/share/native/java/net/net_util.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/share/native/java/net/net_util.h Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,7 @@ NET_AllocSockaddr(struct sockaddr **him, int *len); JNIEXPORT int JNICALL -NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len); +NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress); jobject NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/java/io/FileDescriptor.java --- a/j2se/src/solaris/classes/java/io/FileDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/java/io/FileDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ * Applications should not create their own file descriptors. * * @author Pavani Diwanji - * @version 1.28, 05/05/07 + * @version 1.30, 06/14/07 * @see java.io.FileInputStream * @see java.io.FileOutputStream * @since JDK1.0 @@ -60,12 +60,12 @@ */ public /**/ FileDescriptor() { fd = -1; - useCount = new AtomicInteger(1); + useCount = new AtomicInteger(); } private /* */ FileDescriptor(int fd) { this.fd = fd; - useCount = new AtomicInteger(1); + useCount = new AtomicInteger(); } /** @@ -142,6 +142,21 @@ initIDs(); } + // Set up JavaIOFileDescriptorAccess in SharedSecrets + static { + sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess( + new sun.misc.JavaIOFileDescriptorAccess() { + public void set(FileDescriptor obj, int fd) { + obj.fd = fd; + } + + public int get(FileDescriptor obj) { + return obj.fd; + } + } + ); + } + // pacakge private methods used by FIS,FOS and RAF int incrementAndGetUseCount() { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/solaris/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.security.AccessController; + +/** + * This class defines a factory for creating DatagramSocketImpls. It defaults + * to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls + * by setting the impl.prefix system property. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class DefaultDatagramSocketImplFactory { + static Class prefixImplClass = null; + + static { + String prefix = null; + try { + prefix = (String) AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("impl.prefix", null)); + if (prefix != null) + prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); + } catch (Exception e) { + System.err.println("Can't find class: java.net." + + prefix + + "DatagramSocketImpl: check impl.prefix property"); + //prefixImplClass = null; + } + } + + /** + * Creates a new DatagramSocketImpl instance. + * + * @param isMulticast true if this impl if for a MutlicastSocket + * @return a new instance of a DatagramSocketImpl. + */ + static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast /*unused on unix*/) + throws SocketException { + if (prefixImplClass != null) { + try { + return (DatagramSocketImpl)prefixImplClass.newInstance(); + } catch (Exception e) { + throw new SocketException("can't instantiate DatagramSocketImpl"); + } + } else { + return new java.net.PlainDatagramSocketImpl(); + } + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/java/net/PlainDatagramSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/solaris/classes/java/net/PlainDatagramSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; + +/* + * On Unix systems we simply delegate to native methods. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl +{ + static { + init(); + } + + protected synchronized native void bind0(int lport, InetAddress laddr) + throws SocketException; + + protected native void send(DatagramPacket p) throws IOException; + + protected synchronized native int peek(InetAddress i) throws IOException; + + protected synchronized native int peekData(DatagramPacket p) throws IOException; + + protected synchronized native void receive0(DatagramPacket p) + throws IOException; + + protected native void setTimeToLive(int ttl) throws IOException; + + protected native int getTimeToLive() throws IOException; + + protected native void setTTL(byte ttl) throws IOException; + + protected native byte getTTL() throws IOException; + + protected native void join(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + protected native void leave(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + protected native void datagramSocketCreate() throws SocketException; + + protected native void datagramSocketClose(); + + protected native void socketSetOption(int opt, Object val) + throws SocketException; + + protected native Object socketGetOption(int opt) throws SocketException; + + protected native void connect0(InetAddress address, int port) throws SocketException; + + protected native void disconnect0(int family); + + /** + * Perform class load-time initializations. + */ + private native static void init(); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/java/net/PlainSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/solaris/classes/java/net/PlainSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; +import java.io.FileDescriptor; + +/* + * On Unix systems we simply delegate to native methods. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class PlainSocketImpl extends AbstractPlainSocketImpl +{ + static { + initProto(); + } + + /** + * Constructs an empty instance. + */ + PlainSocketImpl() { } + + /** + * Constructs an instance with the given file descriptor. + */ + PlainSocketImpl(FileDescriptor fd) { + this.fd = fd; + } + + native void socketCreate(boolean isServer) throws IOException; + + native void socketConnect(InetAddress address, int port, int timeout) + throws IOException; + + native void socketBind(InetAddress address, int port) + throws IOException; + + native void socketListen(int count) throws IOException; + + native void socketAccept(SocketImpl s) throws IOException; + + native int socketAvailable() throws IOException; + + native void socketClose0(boolean useDeferredClose) throws IOException; + + native void socketShutdown(int howto) throws IOException; + + static native void initProto(); + + native void socketSetOption(int cmd, boolean on, Object value) + throws SocketException; + + native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; + + native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) + throws SocketException; + + native void socketSendUrgentData(int data) throws IOException; + +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XAWTLookAndFeel.java --- a/j2se/src/solaris/classes/sun/awt/X11/XAWTLookAndFeel.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XAWTLookAndFeel.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,27 +25,16 @@ package sun.awt.X11; -import java.awt.Toolkit; import java.awt.Color; import java.awt.Font; -import java.awt.Insets; -import java.awt.event.KeyEvent; -import java.awt.event.InputEvent; import java.awt.SystemColor; -import java.util.*; - -import java.lang.reflect.*; import javax.swing.*; import javax.swing.plaf.*; import javax.swing.border.*; -import javax.swing.text.JTextComponent; import javax.swing.text.DefaultEditorKit; -import javax.swing.plaf.basic.BasicLookAndFeel; import javax.swing.plaf.basic.BasicBorders; -import javax.swing.plaf.basic.BasicComboBoxRenderer; -import javax.swing.plaf.basic.BasicComboBoxEditor; import com.sun.java.swing.plaf.motif.*; import sun.awt.X11.XComponentPeer; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XCanvasPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XCanvasPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XCanvasPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,16 @@ import java.awt.*; import java.awt.peer.*; -import sun.awt.DisplayChangedListener; + +import sun.awt.ComponentAccessor; +import sun.awt.SunToolkit; + import sun.awt.X11GraphicsConfig; import sun.awt.X11GraphicsDevice; -import sun.awt.X11GraphicsEnvironment; -class XCanvasPeer extends XComponentPeer implements CanvasPeer, - DisplayChangedListener { +class XCanvasPeer extends XComponentPeer implements CanvasPeer { + + private boolean eraseBackgroundDisabled; XCanvasPeer() {} @@ -44,10 +47,17 @@ super(target); } - /* --- DisplayChangedListener Stuff --- */ - public void displayChanged() {} - public void paletteChanged() {} - void resetTargetGC(Component target) {} + void preInit(XCreateWindowParams params) { + super.preInit(params); + if (SunToolkit.getSunAwtNoerasebackground()) { + disableBackgroundErase(); + } + } + + void resetTargetGC(Component target) { + ComponentAccessor.resetGC(target); + } + /* * Called when the Window this * Canvas is on is moved onto another Xinerama screen. @@ -62,7 +72,7 @@ */ public void displayChanged(int screenNum) { resetLocalGC(screenNum); - resetTargetGC(target); /* call Canvas.setGCFromPeer() via native */ + resetTargetGC(target); } /* Set graphicsConfig to a GraphicsConfig with the same visual on the new @@ -102,6 +112,13 @@ // Canvas should always be able to be focused by mouse clicks. return true; } + + public void disableBackgroundErase() { + eraseBackgroundDisabled = true; + } + protected boolean doEraseBackground() { + return !eraseBackgroundDisabled; + } public void setBackground(Color c) { boolean doRepaint = false; if( getPeerBackground() == null || diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XCheckboxMenuItemPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XCheckboxMenuItemPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XCheckboxMenuItemPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -32,8 +32,6 @@ import java.util.logging.*; import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import sun.awt.SunToolkit; class XCheckboxMenuItemPeer extends XMenuItemPeer implements CheckboxMenuItemPeer { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XCheckboxPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XCheckboxPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XCheckboxPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ import java.awt.event.*; import java.awt.image.BufferedImage; import javax.swing.plaf.basic.BasicGraphicsUtils; -import java.awt.geom.Rectangle2D; import java.awt.geom.AffineTransform; import java.util.logging.*; @@ -137,9 +136,10 @@ public void keyReleased(KeyEvent e) {} public void setLabel(java.lang.String label) { - this.label = label; if ( label == null ) { - label = ""; + this.label = ""; + } else { + this.label = label; } layout(); repaint(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XChoicePeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XChoicePeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XChoicePeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -28,8 +28,6 @@ import java.awt.*; import java.awt.peer.*; import java.awt.event.*; -import java.util.Vector; -import java.util.List; import java.util.logging.*; // FIXME: tab traversal should be disabled when mouse is captured (4816336) @@ -60,7 +58,6 @@ // SHARE THESE! private static final Insets focusInsets = new Insets(0,0,0,0); - private static final Insets borderInsets = new Insets(2,2,2,2); static final int WIDGET_OFFSET = 18; @@ -106,9 +103,6 @@ // TODO: Choice remembers where it was scrolled to when unfurled - it's not // always to the currently selected item. - private Rectangle textRect; - private Rectangle focusRect; - // Indicates whether or not to paint selected item in the choice. // Default is to paint private boolean drawSelectedItem = true; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XClipboard.java --- a/j2se/src/solaris/classes/sun/awt/X11/XClipboard.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XClipboard.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ import java.awt.datatransfer.Transferable; import java.util.SortedMap; -import java.util.Map; import java.util.Set; import java.util.Iterator; import java.util.HashSet; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XCustomCursor.java --- a/j2se/src/solaris/classes/sun/awt/X11/XCustomCursor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XCustomCursor.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,6 @@ import sun.awt.X11CustomCursor; import java.awt.*; -import java.awt.image.*; -import sun.awt.image.ImageRepresentation; /** * A class to encapsulate a custom image-based cursor. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XDecoratedPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1126,7 +1126,7 @@ } } - private XWindowPeer actualFocusedWindow = null; + XWindowPeer actualFocusedWindow = null; void setActualFocusedWindow(XWindowPeer actualFocusedWindow) { synchronized(getStateLock()) { this.actualFocusedWindow = actualFocusedWindow; @@ -1140,8 +1140,9 @@ return requestWindowFocus(time, timeProvided); } public void handleWindowFocusIn(long serial) { - super.handleWindowFocusIn(serial); - if (actualFocusedWindow != null) { + if (null == actualFocusedWindow) { + super.handleWindowFocusIn(serial); + } else { /* * Fix for 6314575. * If this is a result of clicking on one of the Frame's component @@ -1155,16 +1156,18 @@ * definetely before the Frame gets FocusIn event (when this method is called). */ postEvent(new InvocationEvent(target, new Runnable() { - public void run() { - XWindowPeer fw = null; - synchronized (getStateLock()) { - fw = actualFocusedWindow; - actualFocusedWindow = null; + public void run() { + XWindowPeer fw = null; + synchronized (getStateLock()) { + fw = actualFocusedWindow; + actualFocusedWindow = null; + if (null == fw || !fw.isVisible() || !fw.isFocusableWindow()) { + fw = XDecoratedPeer.this; } - if (fw != null && fw.isVisible()) { - fw.handleWindowFocusIn_Dispatch(); - } - }})); + } + fw.handleWindowFocusIn_Dispatch(); + } + })); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XDragAndDropProtocols.java --- a/j2se/src/solaris/classes/sun/awt/X11/XDragAndDropProtocols.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XDragAndDropProtocols.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,8 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; /** * This class is a registry for the supported drag and drop protocols. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XDropTargetEventProcessor.java --- a/j2se/src/solaris/classes/sun/awt/X11/XDropTargetEventProcessor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XDropTargetEventProcessor.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,12 +25,7 @@ package sun.awt.X11; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; -import java.util.List; -import java.util.Set; /** * This class is a registry for the supported drag and drop protocols. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java --- a/j2se/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XEmbedClientHelper.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,6 @@ package sun.awt.X11; -import sun.misc.Unsafe; import java.awt.AWTKeyStroke; import java.util.logging.*; import sun.awt.SunToolkit; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java --- a/j2se/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XEmbeddedFrame.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,14 +25,9 @@ package sun.awt.X11; -import java.awt.Component; -import java.awt.peer.FramePeer; import sun.awt.EmbeddedFrame; -import java.awt.peer.ComponentPeer; -import sun.awt.*; import java.awt.*; import java.awt.AWTKeyStroke; -import java.lang.reflect.Field; public class XEmbeddedFrame extends EmbeddedFrame { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -299,7 +299,7 @@ target.addWindowListener( new WindowAdapter(){ public void windowClosing(WindowEvent e){ - handleQuitButton(); + handleCancel(); } } ); @@ -405,7 +405,7 @@ directoryList.clear(); fileList.clear(); target.setFile(null); - target.setDirectory(savedDir); + target.setDirectory(null); handleQuitButton(); } @@ -871,12 +871,11 @@ } } -/** -* checks the filename and directory with the specified filter -* checks with multiple "*". -* the filter has to start with a '*' character. -* this to keep the search the same as in the motif version -*/ +/* + * Motif file dialogs let the user specify a filter that controls the files that + * are displayed in the dialog. This filter is generally specified as a regular + * expression. The class is used to implement Motif-like filtering. + */ class FileDialogFilter implements FilenameFilter { String filter; @@ -885,8 +884,8 @@ filter = f; } - /** - * return true if match + /* + * Tells whether or not the specified file should be included in a file list */ public boolean accept(File dir, String fileName) { @@ -895,90 +894,27 @@ if (f.isDirectory()) { return true; } else { - return searchPattern(fileName, filter); + return matches(fileName, filter); } } - /** - * start searching - */ - boolean searchPattern(String fileName, String filter) { - int filterCursor = 0; - int fileNameCursor = 0; - - int filterChar = filter.charAt(filterCursor); - - if (filterCursor == 0 && filterChar != '*') { - return false; - } - String ls = filter.substring(filterCursor + 1); - return handleStar(fileName, ls); - } - - /** - * call this method when character was an * + /* + * Tells whether or not the input string matches the given filter */ - boolean handleStar(String fileName, String filter) { - int ftLen = filter.length(); - int flLen = fileName.length(); - char ftChar; - char flChar; - int ftCur = 0; - int flCur = 0; - int c = 0; - - if (ftLen == 0) { - return true; - } - - while (c < flLen) { - ftChar = filter.charAt(ftCur); - - if (ftChar == '*') { - String ls = filter.substring(ftCur + 1); - String fs = fileName.substring(flCur); - if (handleStar(fs, ls)) { - return true; - } - c++; - flCur = c; - ftCur = 0; - continue; - } - flChar = fileName.charAt(flCur); - - if (ftChar == flChar) { - ftCur++; - flCur++; - - if (flCur == flLen && ftCur == ftLen) { - return true; - } - - if (flCur < flLen && ftCur == ftLen) { - return false; - } - - if (flCur == flLen) { - c = flLen; - } - } else { - c++; - flCur = c; - ftCur = 0; - if (c == flLen) { - return false; - } - } - } - - for (int i = ftCur ; i < ftLen ; i++) { - ftChar = filter.charAt(i); - if (ftChar != '*') { - return false; - } - } - return true; + private boolean matches(String input, String filter) { + String regex = convert(filter); + return input.matches(regex); + } + + /* + * Converts the filter into the form which is acceptable by Java's regexps + */ + private String convert(String filter) { + String regex = new String("^" + filter + "$"); + regex = regex.replaceAll("\\.", "\\\\."); + regex = regex.replaceAll("\\?", "."); + regex = regex.replaceAll("\\*", ".*"); + return regex; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XFocusProxyWindow.java --- a/j2se/src/solaris/classes/sun/awt/X11/XFocusProxyWindow.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XFocusProxyWindow.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,7 +26,6 @@ package sun.awt.X11; import java.awt.*; -import java.awt.event.*; import java.util.logging.*; /** diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XHorizontalScrollbar.java --- a/j2se/src/solaris/classes/sun/awt/X11/XHorizontalScrollbar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XHorizontalScrollbar.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.awt.X11; import java.awt.*; -import java.awt.event.*; /** * A simple horizontal scroll bar. The scrollbar is made horizontal diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XIconInfo.java --- a/j2se/src/solaris/classes/sun/awt/X11/XIconInfo.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XIconInfo.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2006-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.awt.image.*; import sun.awt.image.ToolkitImage; import sun.awt.image.ImageRepresentation; +import java.util.Arrays; class XIconInfo { /** @@ -68,7 +69,7 @@ private int rawLength; XIconInfo(int[] intIconData) { - this.intIconData = intIconData; + this.intIconData = Arrays.copyOf(intIconData, intIconData.length); this.width = intIconData[0]; this.height = intIconData[1]; this.scaledWidth = width; @@ -77,7 +78,7 @@ } XIconInfo(long[] longIconData) { - this.longIconData = longIconData; + this.longIconData = Arrays.copyOf(longIconData, longIconData.length); this.width = (int)longIconData[0]; this.height = (int)longIconData[1]; this.scaledWidth = width; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XMSelection.java --- a/j2se/src/solaris/classes/sun/awt/X11/XMSelection.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XMSelection.java Thu Jul 05 23:47:33 2007 +0000 @@ -31,11 +31,7 @@ package sun.awt.X11; -import sun.misc.Unsafe; import java.util.*; -import java.awt.*; -import sun.awt.XSettings; -import sun.awt.*; import java.util.logging.*; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -125,8 +125,6 @@ private int shortcutWidth; private int textBaseline; - private XMenuItemPeer[] items; - TextMetrics(Dimension textDimension, int shortcutWidth, int textBaseline) { this.textDimension = textDimension; this.shortcutWidth = shortcutWidth; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XMenuPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XMenuPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XMenuPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,7 +26,6 @@ import java.awt.*; import java.awt.peer.*; -import java.awt.event.*; import java.lang.reflect.Field; import java.util.Vector; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XPanelPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XPanelPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XPanelPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import java.awt.*; import java.awt.peer.*; + import sun.awt.SunGraphicsCallback; public class XPanelPeer extends XCanvasPeer implements PanelPeer { @@ -129,41 +130,36 @@ return getInsets(); } - /** - * Recursive method that handles the propagation of the displayChanged - * event into the entire hierarchy of peers. - * Unlike on win32, on X we don't worry about handling on-the-fly - * display settings changes, only windows being dragged across Xinerama - * screens. Thus, we only need to tell XCanvasPeers, not all - * XComponentPeers. + /* + * This method is called from XWindowPeer.displayChanged, when + * the window this Panel is on is moved to the new screen, or + * display mode is changed. + * + * The notification is propagated to the child Canvas components. + * Top-level windows and other Panels are notified too as their + * peers are subclasses of XCanvasPeer. */ - private void recursiveDisplayChanged(Component c, int screenNum) { - if (c instanceof Container) { - Component children[] = ((Container)c).getComponents(); - for (int i = 0; i < children.length; ++i) { - recursiveDisplayChanged(children[i], screenNum); - } - } - ComponentPeer peer = c.getPeer(); - if (peer != null && peer instanceof XCanvasPeer) { - XCanvasPeer mPeer = (XCanvasPeer)peer; - mPeer.displayChanged(screenNum); - } + public void displayChanged(int screenNum) { + super.displayChanged(screenNum); + displayChanged((Container)target, screenNum); } /* - * Often up-called from a XWindowPeer instance. - * Calls displayChanged() on all child canvas' peers. - * Recurses into Container children to ensure all canvases - * get the message. + * Recursively iterates through all the HW and LW children + * of the container and calls displayChanged() for HW peers. + * Iteration through children peers only is not enough as the + * displayChanged notification may not be propagated to HW + * components inside LW containers, see 4452373 for details. */ - public void displayChanged(int screenNum) { - // Don't do super call because XWindowPeer has already updated its GC - + private static void displayChanged(Container target, int screenNum) { Component children[] = ((Container)target).getComponents(); - - for (int i = 0; i < children.length; i++) { - recursiveDisplayChanged(children[i], screenNum); + for (Component child : children) { + ComponentPeer cpeer = child.getPeer(); + if (cpeer instanceof XCanvasPeer) { + ((XCanvasPeer)cpeer).displayChanged(screenNum); + } else if (child instanceof Container) { + displayChanged((Container)child, screenNum); + } } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XRobotPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XRobotPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XRobotPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,7 +26,6 @@ import java.awt.*; import java.awt.peer.*; -import java.security.*; import sun.awt.X11GraphicsConfig; class XRobotPeer implements RobotPeer { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XScrollbar.java --- a/j2se/src/solaris/classes/sun/awt/X11/XScrollbar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XScrollbar.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -757,15 +757,6 @@ } /** - * Returns true if thumb is long enough to display it and - * false otherwise - * @see #getArrowAreaSize - */ - private boolean paintThumb(int arrAreaH){ - return (barLength >= 2*arrAreaH+MIN_THUMB_H); - } - - /** * Method to calculate the scroll thumb's size and position. This is * based on CalcSliderRect in ScrollBar.c of Motif source. * diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XSystemTrayPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -27,9 +27,6 @@ import java.awt.*; import java.awt.peer.SystemTrayPeer; -import java.awt.peer.TrayIconPeer; -import java.util.HashMap; -import java.util.Map; public class XSystemTrayPeer implements SystemTrayPeer { SystemTray target; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XToolkit.java --- a/j2se/src/solaris/classes/sun/awt/X11/XToolkit.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Jul 05 23:47:33 2007 +0000 @@ -564,7 +564,7 @@ Component owner = XKeyboardFocusManagerPeer.getCurrentNativeFocusOwner(); if (owner != null) { - XWindow ownerWindow = (XWindow)owner.getPeer(); + XWindow ownerWindow = (XWindow) ComponentAccessor.getPeer(owner); if (ownerWindow != null) { w = ownerWindow.getContentWindow(); } @@ -792,6 +792,26 @@ return insets; } + /* + * The current implementation of disabling background erasing for + * canvases is that we don't set any native background color + * (with XSetWindowBackground) for the canvas window. However, + * this color is set in the peer constructor - see + * XWindow.postInit() for details. That's why this method from + * SunToolkit is not overridden in XToolkit: it's too late to + * disable background erasing :( + */ + /* + @Override + public void disableBackgroundErase(Canvas canvas) { + XCanvasPeer peer = (XCanvasPeer)canvas.getPeer(); + if (peer == null) { + throw new IllegalStateException("Canvas must have a valid peer"); + } + peer.disableBackgroundErase(); + } + */ + // Need this for XMenuItemPeer. protected static final Object targetToPeer(Object target) { Object p=null; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XVerticalScrollbar.java --- a/j2se/src/solaris/classes/sun/awt/X11/XVerticalScrollbar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XVerticalScrollbar.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,6 @@ package sun.awt.X11; import java.awt.*; -import java.awt.event.*; -import sun.awt.SunToolkit; -import java.util.logging.*; /** * A simple vertical scroll bar. diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XWINProtocol.java --- a/j2se/src/solaris/classes/sun/awt/X11/XWINProtocol.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XWINProtocol.java Thu Jul 05 23:47:33 2007 +0000 @@ -28,7 +28,6 @@ import java.awt.*; import java.util.logging.Level; -import java.util.logging.LogManager; import java.util.logging.Logger; class XWINProtocol extends XProtocol implements XStateProtocol, XLayerProtocol { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XWarningWindow.java --- a/j2se/src/solaris/classes/sun/awt/X11/XWarningWindow.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XWarningWindow.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,8 +25,6 @@ package sun.awt.X11; import java.awt.*; -import java.awt.event.*; -import sun.java2d.SunGraphics2D; class XWarningWindow extends XWindow { final static int defaultHeight = 27; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XWindow.java --- a/j2se/src/solaris/classes/sun/awt/X11/XWindow.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XWindow.java Thu Jul 05 23:47:33 2007 +0000 @@ -404,6 +404,11 @@ } } + // overriden in XCanvasPeer + protected boolean doEraseBackground() { + return true; + } + // We need a version of setBackground that does not call repaint !! // and one that does not get overridden. The problem is that in postInit // we call setBackground and we dont have all the stuff initialized to @@ -412,6 +417,11 @@ XToolkit.awtLock(); try { winBackground(c); + // fix for 6558510: handle sun.awt.noerasebackground flag, + // see doEraseBackground() and preInit() methods in XCanvasPeer + if (!doEraseBackground()) { + return; + } // 6304250: XAWT: Items in choice show a blue border on OpenGL + Solaris10 when background color is set // Note: When OGL is enabled, surfaceData.pixelFor() will not // return a pixel value appropriate for passing to diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/XWindowPeer.java --- a/j2se/src/solaris/classes/sun/awt/X11/XWindowPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/XWindowPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -612,10 +612,6 @@ /* --- DisplayChangedListener Stuff --- */ - void resetTargetGC(Component target) { - ComponentAccessor.resetGC(target); - } - /* Xinerama * called to check if we've been moved onto a different screen * Based on checkNewXineramaScreen() in awt_GraphicsEnv.c @@ -674,28 +670,16 @@ } /** - * Called to update our GraphicsConfig when dragged onto another screen - * (in the Xinerama case), or after changing the display mode. - */ - public void displayChanged(int screenNum) { - // update our GC - resetLocalGC(screenNum); /* upcall to XCanvasPeer */ - resetTargetGC(target); /* call Window.resetGC() via native */ - - //propagate to children - super.displayChanged(screenNum); /* upcall to XPanelPeer */ - } - - /** * Helper method that executes the displayChanged(screen) method on * the event dispatch thread. This method is used in the Xinerama case * and after display mode change events. */ - private void executeDisplayChangedOnEDT(int screenNum) { - final int finalScreenNum = screenNum; + private void executeDisplayChangedOnEDT(final int screenNum) { Runnable dc = new Runnable() { public void run() { - displayChanged(finalScreenNum); + // Updates this window's GC and notifies all the children. + // See XPanelPeer/XCanvasPeer.displayChanged(int) for details. + displayChanged(screenNum); } }; SunToolkit.executeOnEventHandlerThread((Component)target, dc); @@ -817,6 +801,17 @@ } if (this == oppositeXWindow) { oppositeWindow = null; + } else if (oppositeXWindow instanceof XDecoratedPeer) { + if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) { + oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow; + oppositeTarget = oppositeXWindow.getTarget(); + if (oppositeTarget instanceof Window + && oppositeXWindow.isVisible() + && oppositeXWindow.isNativelyNonFocusableWindow()) + { + oppositeWindow = ((Window) oppositeTarget); + } + } } handleWindowFocusOut(oppositeWindow, xfe.get_serial()); } @@ -1088,6 +1083,19 @@ removeRootPropertyEventDispatcher(); mustControlStackPosition = false; super.dispose(); + + /* + * Fix for 6457980. + * When disposing an owned Window we should implicitly + * return focus to its decorated owner because it won't + * receive WM_TAKE_FOCUS. + */ + if (isSimpleWindow()) { + if (target == XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow()) { + Window owner = getDecoratedOwner((Window)target); + ((XWindowPeer)ComponentAccessor.getPeer(owner)).requestWindowFocus(); + } + } } boolean isResizable() { return winAttr.isResizable; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java --- a/j2se/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/classes/sun/awt/X11/generator/WrapperGenerator.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,10 +25,7 @@ import java.util.*; import java.io.*; -import java.nio.*; -import java.nio.channels.*; import java.nio.charset.*; -import java.util.regex.*; import java.text.MessageFormat; import java.util.logging.*; @@ -40,7 +37,6 @@ boolean generateLog = true; boolean wide; private static Charset charset = Charset.forName("ISO-8859-15"); - private static CharsetDecoder decoder = charset.newDecoder(); String package_name = "sun.awt.X11"; String package_path = "sun/awt/X11"; @@ -49,7 +45,6 @@ String compile_options = "-lX11"; static Hashtable symbolTable = new Hashtable(); - private Hashtable defines = new Hashtable(); static Hashtable sizeTable32bit = new Hashtable(); static Hashtable sizeTable64bit = new Hashtable(); static Hashtable knownSizes32 = new Hashtable(); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/java/net/PlainDatagramSocketImpl.c --- a/j2se/src/solaris/native/java/net/PlainDatagramSocketImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/java/net/PlainDatagramSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,6 @@ static jfieldID IO_fd_fdID; static jfieldID pdsi_fdID; -static jfieldID pdsi_fd1ID; static jfieldID pdsi_timeoutID; static jfieldID pdsi_trafficClassID; static jfieldID pdsi_localPortID; @@ -154,9 +153,6 @@ pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); CHECK_NULL(pdsi_fdID); - pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", - "Ljava/io/FileDescriptor;"); - CHECK_NULL(pdsi_fd1ID); pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); CHECK_NULL(pdsi_timeoutID); pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); @@ -245,7 +241,7 @@ } /* bind */ - if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) { return; } @@ -278,8 +274,6 @@ } else { (*env)->SetIntField(env, this, pdsi_localPortID, localport); } - /* fd1 not used for solaris/linux */ - (*env)->SetObjectField(env, this, pdsi_fd1ID, 0); } /* @@ -310,7 +304,7 @@ return; } - if (NET_InetAddressToSockaddr(env, address, port, (struct sockaddr *)&rmtaddr, &len) != 0) { + if (NET_InetAddressToSockaddr(env, address, port, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) { return; } @@ -460,7 +454,7 @@ rmtaddrP = 0; } else { packetPort = (*env)->GetIntField(env, packet, dp_portID); - if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, (struct sockaddr *)&rmtaddr, &len) != 0) { + if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) { return; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/java/net/PlainSocketImpl.c --- a/j2se/src/solaris/native/java/net/PlainSocketImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/java/net/PlainSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,6 @@ static jfieldID IO_fd_fdID; jfieldID psi_fdID; -jfieldID psi_fd1ID; jfieldID psi_addressID; jfieldID psi_ipaddressID; jfieldID psi_portID; @@ -211,8 +210,6 @@ psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); - psi_fd1ID = (*env)->GetFieldID(env, cls , "fd1", - "Ljava/io/FileDescriptor;"); CHECK_NULL(psi_fdID); psi_addressID = (*env)->GetFieldID(env, cls, "address", "Ljava/net/InetAddress;"); @@ -289,9 +286,6 @@ (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); } - /* fd1 not used in solaris/linux */ - (*env)->SetObjectField(env, this, psi_fd1ID, 0); - /* * If this is a server socket then enable SO_REUSEADDR * automatically @@ -345,7 +339,7 @@ } /* connect */ - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) { return; } @@ -638,7 +632,7 @@ } /* bind */ - if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len) != 0) { + if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) { return; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/java/net/net_util_md.c --- a/j2se/src/solaris/native/java/net/net_util_md.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/java/net/net_util_md.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -646,13 +646,18 @@ #endif +/* In the case of an IPv4 Inetaddress this method will return an + * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE. + * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress. +*/ JNIEXPORT int JNICALL -NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len) { +NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, + int *len, jboolean v4MappedAddress) { jint family; family = (*env)->GetIntField(env, iaObj, ia_familyID); #ifdef AF_INET6 /* needs work. 1. family 2. clean up him6 etc deallocate memory */ - if (ipv6_available()) { + if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) { struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; jbyteArray ipaddress; jbyte caddr[16]; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/sun/awt/gtk2_interface.c --- a/j2se/src/solaris/native/sun/awt/gtk2_interface.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/sun/awt/gtk2_interface.c Thu Jul 05 23:47:33 2007 +0000 @@ -65,8 +65,6 @@ #define NO_SYMBOL_EXCEPTION 1 -#define GTK_TOGGLE_MENU_ITEM_SIZE 12 - /* SynthConstants */ const gint ENABLED = 1 << 0; const gint MOUSE_OVER = 1 << 1; @@ -1430,20 +1428,6 @@ widget_type != INTERNAL_FRAME && widget_type != OPTION_PANE) { - if (widget_type == CHECK_BOX_MENU_ITEM || - widget_type == RADIO_BUTTON_MENU_ITEM ) - { - GParamSpec* param = (*fp_gtk_widget_class_find_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, - "indicator_size" ); - if( !param ) - { - param = (*fp_g_param_spec_int)("indicator_size", NULL, NULL, 0, - INT_MAX, 12, G_PARAM_READABLE); - (*fp_gtk_widget_class_install_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, param); - } - } (*fp_gtk_container_add)((GtkContainer *)gtk2_fixed, result); } (*fp_gtk_widget_realize)(result); @@ -1683,33 +1667,18 @@ void gtk2_paint_check(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { - gint size = 0, offset = 0; GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); gtk2_widget = gtk2_get_widget(widget_type); init_toggle_widget(widget_type, synth_state); - if((*fp_gtk_widget_class_find_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, "indicator_size")) { - (*fp_gtk_widget_style_get)(gtk2_widget, "indicator_size", &size, NULL); - } else { - // indicator_size property may not be available pre-GTK 2.4, so fall - // back on hardcoded size in this case - size = GTK_TOGGLE_MENU_ITEM_SIZE; - } - - if (widget_type == CHECK_BOX) { - (*fp_gtk_widget_style_get)(gtk2_widget, "indicator_spacing", - &offset, NULL); - } - (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_white_pixmap, state_type, shadow_type, NULL, gtk2_widget, detail, - x + offset, y + offset, size, size); + x, y, width, height); (*fp_gtk_paint_check)(gtk2_widget->style, gtk2_black_pixmap, state_type, shadow_type, NULL, gtk2_widget, detail, - x + offset, y + offset, size, size); + x, y, width, height); } void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type, @@ -1806,33 +1775,18 @@ void gtk2_paint_option(WidgetType widget_type, gint synth_state, const gchar *detail, gint x, gint y, gint width, gint height) { - gint size = 0, offset = 0; GtkStateType state_type = get_gtk_state_type(widget_type, synth_state); GtkShadowType shadow_type = get_gtk_shadow_type(widget_type, synth_state); gtk2_widget = gtk2_get_widget(widget_type); init_toggle_widget(widget_type, synth_state); - if((*fp_gtk_widget_class_find_style_property)( - ((GTypeInstance*)gtk2_widget)->g_class, "indicator_size")) { - (*fp_gtk_widget_style_get)(gtk2_widget, "indicator_size", &size, NULL); - } else { - // indicator_size property may not be available pre-GTK 2.4, so fall - // back on hardcoded size in this case - size = GTK_TOGGLE_MENU_ITEM_SIZE; - } - - if (widget_type == RADIO_BUTTON) { - (*fp_gtk_widget_style_get)(gtk2_widget, "indicator_spacing", - &offset, NULL); - } - (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_white_pixmap, state_type, shadow_type, NULL, gtk2_widget, detail, - x + offset, y + offset, size, size); + x, y, width, height); (*fp_gtk_paint_option)(gtk2_widget->style, gtk2_black_pixmap, state_type, shadow_type, NULL, gtk2_widget, detail, - x + offset, y + offset, size, size); + x, y, width, height); } void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type, diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c --- a/j2se/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/sun/nio/ch/DatagramChannelImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,7 +215,7 @@ if (NET_InetAddressToSockaddr(env, destAddress, destPort, (struct sockaddr *)&sa, - &sa_len) != 0) { + &sa_len, JNI_TRUE) != 0) { return IOS_THROWN; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/solaris/native/sun/nio/ch/Net.c --- a/j2se/src/solaris/native/sun/nio/ch/Net.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/solaris/native/sun/nio/ch/Net.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ int sa_len = SOCKADDR_LEN; int rv = 0; - if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len) != 0) { + if (NET_InetAddressToSockaddr(env, ia, port, (struct sockaddr *)&sa, &sa_len, JNI_TRUE) != 0) { return; } @@ -110,7 +110,7 @@ int sa_len = SOCKADDR_LEN; int rv; - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len) != 0) { + if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *) &sa, &sa_len, JNI_TRUE) != 0) { return IOS_THROWN; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/io/FileDescriptor.java --- a/j2se/src/windows/classes/java/io/FileDescriptor.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/java/io/FileDescriptor.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,7 +38,7 @@ * Applications should not create their own file descriptors. * * @author Pavani Diwanji - * @version 1.10, 05/05/07 + * @version 1.12, 06/14/07 * @see java.io.FileInputStream * @see java.io.FileOutputStream * @since JDK1.0 @@ -64,13 +64,28 @@ public /**/ FileDescriptor() { fd = -1; handle = -1; - useCount = new AtomicInteger(1); + useCount = new AtomicInteger(); } static { initIDs(); } + // Set up JavaIOFileDescriptorAccess in SharedSecrets + static { + sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess( + new sun.misc.JavaIOFileDescriptorAccess() { + public void set(FileDescriptor obj, int fd) { + obj.fd = fd; + } + + public int get(FileDescriptor obj) { + return obj.fd; + } + } + ); + } + /** * A handle to the standard input stream. Usually, this file * descriptor is not used directly, but rather via the input stream diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/lang/ProcessImpl.java --- a/j2se/src/windows/classes/java/lang/ProcessImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/java/lang/ProcessImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * create new processes. * * @author Martin Buchholz - * @version 1.37, 07/05/05 + * @version 1.38, 07/06/11 * @since 1.5 */ @@ -126,21 +126,39 @@ } public void finalize() { - close(); + closeHandle(handle); } - public native int exitValue(); - public native int waitFor(); - public native void destroy(); + private static final int STILL_ACTIVE = getStillActive(); + private static native int getStillActive(); + + public int exitValue() { + int exitCode = getExitCodeProcess(handle); + if (exitCode == STILL_ACTIVE) + throw new IllegalThreadStateException("process has not exited"); + return exitCode; + } + private static native int getExitCodeProcess(long handle); - private native long create(String cmdstr, - String envblock, - String dir, - boolean redirectErrorStream, - FileDescriptor in_fd, - FileDescriptor out_fd, - FileDescriptor err_fd) + public int waitFor() throws InterruptedException { + waitForInterruptibly(handle); + if (Thread.interrupted()) + throw new InterruptedException(); + return exitValue(); + } + private static native void waitForInterruptibly(long handle); + + public void destroy() { terminateProcess(handle); } + private static native void terminateProcess(long handle); + + private static native long create(String cmdstr, + String envblock, + String dir, + boolean redirectErrorStream, + FileDescriptor in_fd, + FileDescriptor out_fd, + FileDescriptor err_fd) throws IOException; - private native void close(); + private static native boolean closeHandle(long handle); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,115 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * This class defines a factory for creating DatagramSocketImpls. It defaults + * to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls + * by setting the impl.prefix system property. + * + * For Windows versions lower than Windows Vista a TwoStacksPlainDatagramSocketImpl + * is always created. This impl supports IPv6 on these platform where available. + * + * On Windows platforms greater than Vista that support a dual layer TCP/IP stack + * a DualStackPlainDatagramSocketImpl is created for DatagramSockets. For MulticastSockets + * a TwoStacksPlainDatagramSocketImpl is always created. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class DefaultDatagramSocketImplFactory +{ + static Class prefixImplClass = null; + + /* the windows version. */ + private static float version; + + /* java.net.preferIPv4Stack */ + private static boolean preferIPv4Stack = false; + + /* If the version supports a dual stack TCP implementation */ + private static boolean useDualStackImpl = false; + + static { + // Determine Windows Version. + java.security.AccessController.doPrivileged( new PrivilegedAction() { + public Object run() { + version = 0; + try { + version = Float.parseFloat(System.getProperties().getProperty("os.version")); + preferIPv4Stack = Boolean.parseBoolean( + System.getProperties().getProperty("java.net.preferIPv4Stack")); + } catch (NumberFormatException e ) { + assert false : e; + } + return null; // nothing to return + } }); + + // (version >= 6.0) implies Vista or greater. + if (version >= 6.0 && !preferIPv4Stack) { + useDualStackImpl = true; + } + + // impl.prefix + String prefix = null; + try { + prefix = (String) AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("impl.prefix", null)); + if (prefix != null) + prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl"); + } catch (Exception e) { + System.err.println("Can't find class: java.net." + + prefix + + "DatagramSocketImpl: check impl.prefix property"); + } + } + + /** + * Creates a new DatagramSocketImpl instance. + * + * @param isMulticast true if this impl is to be used for a MutlicastSocket + * @return a new instance of PlainDatagramSocketImpl. + */ + static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast) + throws SocketException { + if (prefixImplClass != null) { + try { + return (DatagramSocketImpl) prefixImplClass.newInstance(); + } catch (Exception e) { + throw new SocketException("can't instantiate DatagramSocketImpl"); + } + } else { + if (useDualStackImpl && !isMulticast) + return new DualStackPlainDatagramSocketImpl(); + else + return new TwoStacksPlainDatagramSocketImpl(); + } + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,266 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; +import java.io.FileDescriptor; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; + +/** + * This class defines the plain DatagramSocketImpl that is used on + * Windows platforms greater than or equal to Windows Vista. These + * platforms have a dual layer TCP/IP stack and can handle both IPv4 + * and IPV6 through a single file descriptor. + *

+ * Note: Multicasting on a dual layer TCP/IP stack is always done with + * TwoStacksPlainDatagramSocketImpl. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl +{ + static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); + + protected void datagramSocketCreate() throws SocketException { + if (fd == null) + throw new SocketException("Socket closed"); + + int newfd = socketCreate(false /* v6Only */); + + fdAccess.set(fd, newfd); + } + + protected synchronized void bind0(int lport, InetAddress laddr) + throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + if (laddr == null) + throw new NullPointerException("argument address"); + + socketBind(nativefd, laddr, lport); + if (lport == 0) { + localPort = socketLocalPort(nativefd); + } else { + localPort = lport; + } + } + + protected synchronized int peek(InetAddress address) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("Null address in peek()"); + + // Use peekData() + DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); + int peekPort = peekData(peekPacket); + address = peekPacket.getAddress(); + return peekPort; + } + + protected synchronized int peekData(DatagramPacket p) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("packet"); + if (p.getData() == null) + throw new NullPointerException("packet buffer"); + + return socketReceiveOrPeekData(nativefd, p, timeout, connected, true /*peek*/); + } + + protected synchronized void receive0(DatagramPacket p) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("packet"); + if (p.getData() == null) + throw new NullPointerException("packet buffer"); + + socketReceiveOrPeekData(nativefd, p, timeout, connected, false /*receive*/); + } + + protected void send(DatagramPacket p) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (p == null) + throw new NullPointerException("null packet"); + + if (p.getAddress() == null ||p.getData() ==null) + throw new NullPointerException("null address || null buffer"); + + socketSend(nativefd, p.getData(), p.getOffset(), p.getLength(), + p.getAddress(), p.getPort(), connected); + } + + protected void connect0(InetAddress address, int port) throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("address"); + + socketConnect(nativefd, address, port); + } + + protected void disconnect0(int family /*unused*/) { + if (fd == null || !fd.valid()) + return; // disconnect doesn't throw any exceptions + + socketDisconnect(fdAccess.get(fd)); + } + + protected void datagramSocketClose() { + if (fd == null || !fd.valid()) + return; // close doesn't throw any exceptions + + socketClose(fdAccess.get(fd)); + fdAccess.set(fd, -1); + } + + protected void socketSetOption(int opt, Object val) throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + int optionValue = 0; + + switch(opt) { + case IP_TOS : + case SO_RCVBUF : + case SO_SNDBUF : + optionValue = ((Integer)val).intValue(); + break; + case SO_REUSEADDR : + case SO_BROADCAST : + optionValue = ((Boolean)val).booleanValue() ? 1 : 0; + break; + default: /* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + socketSetIntOption(nativefd, opt, optionValue); + } + + protected Object socketGetOption(int opt) throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + // SO_BINDADDR is not a socket option. + if (opt == SO_BINDADDR) { + return socketLocalAddress(nativefd); + } + + int value = socketGetIntOption(nativefd, opt); + Object returnValue = null; + + switch (opt) { + case SO_REUSEADDR : + case SO_BROADCAST : + returnValue = (value == 0) ? Boolean.FALSE : Boolean.TRUE; + break; + case IP_TOS : + case SO_RCVBUF : + case SO_SNDBUF : + returnValue = new Integer(value); + break; + default: /* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + return returnValue; + } + + /* Multicast specific methods. + * Multicasting on a dual layer TCP/IP stack is always done with + * TwoStacksPlainDatagramSocketImpl. This is to overcome the lack + * of behavior defined for multicasting over a dual layer socket by the RFC. + */ + protected void join(InetAddress inetaddr, NetworkInterface netIf) + throws IOException { + throw new IOException("Method not implemented!"); + } + + protected void leave(InetAddress inetaddr, NetworkInterface netIf) + throws IOException { + throw new IOException("Method not implemented!"); + } + + protected void setTimeToLive(int ttl) throws IOException { + throw new IOException("Method not implemented!"); + } + + protected int getTimeToLive() throws IOException { + throw new IOException("Method not implemented!"); + } + + + protected void setTTL(byte ttl) throws IOException { + throw new IOException("Method not implemented!"); + } + + protected byte getTTL() throws IOException { + throw new IOException("Method not implemented!"); + } + /* END Multicast specific methods */ + + private int checkAndReturnNativeFD() throws SocketException { + if (fd == null || !fd.valid()) + throw new SocketException("Socket closed"); + + return fdAccess.get(fd); + } + + /* Native methods */ + + private static native void initIDs(); + + private static native int socketCreate(boolean v6Only); + + private static native void socketBind(int fd, InetAddress localAddress, int localport) + throws SocketException; + + private static native void socketConnect(int fd, InetAddress address, int port) + throws SocketException; + + private static native void socketDisconnect(int fd); + + private static native void socketClose(int fd); + + private static native int socketLocalPort(int fd) throws SocketException; + + private static native Object socketLocalAddress(int fd) throws SocketException; + + private static native int socketReceiveOrPeekData(int fd, DatagramPacket packet, + int timeout, boolean connected, boolean peek) throws IOException; + + private static native void socketSend(int fd, byte[] data, int offset, int length, + InetAddress address, int port, boolean connected) throws IOException; + + private static native void socketSetIntOption(int fd, int cmd, + int optionValue) throws SocketException; + + private static native int socketGetIntOption(int fd, int cmd) throws SocketException; +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/DualStackPlainSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/DualStackPlainSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,280 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; +import java.io.FileDescriptor; +import sun.misc.SharedSecrets; +import sun.misc.JavaIOFileDescriptorAccess; + +/** + * This class defines the plain SocketImpl that is used on Windows platforms + * greater or equal to Windows Vista. These platforms have a dual + * layer TCP/IP stack and can handle both IPv4 and IPV6 through a + * single file descriptor. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class DualStackPlainSocketImpl extends AbstractPlainSocketImpl +{ + static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); + + public DualStackPlainSocketImpl() {} + + public DualStackPlainSocketImpl(FileDescriptor fd) { + this.fd = fd; + } + + void socketCreate(boolean stream) throws IOException { + if (fd == null) + throw new SocketException("Socket closed"); + + int newfd = socket0(stream, false /*v6 Only*/); + + fdAccess.set(fd, newfd); + } + + void socketConnect(InetAddress address, int port, int timeout) + throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("inet address argument is null."); + + int connectResult; + if (timeout <= 0) { + connectResult = connect0(nativefd, address, port); + } else { + configureBlocking(nativefd, false); + try { + connectResult = connect0(nativefd, address, port); + if (connectResult == WOULDBLOCK) { + waitForConnect(nativefd, timeout); + } + } finally { + configureBlocking(nativefd, true); + } + } + /* + * We need to set the local port field. If bind was called + * previous to the connect (by the client) then localport field + * will already be set. + */ + if (localport == 0) + localport = localPort0(nativefd); + } + + void socketBind(InetAddress address, int port) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (address == null) + throw new NullPointerException("inet address argument is null."); + + bind0(nativefd, address, port); + if (port == 0) { + localport = localPort0(nativefd); + } else { + localport = port; + } + + this.address = address; + } + + void socketListen(int backlog) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + listen0(nativefd, backlog); + } + + void socketAccept(SocketImpl s) throws IOException { + int nativefd = checkAndReturnNativeFD(); + + if (s == null) + throw new NullPointerException("socket is null"); + + int newfd = -1; + InetSocketAddress[] isaa = new InetSocketAddress[1]; + if (timeout <= 0) { + newfd = accept0(nativefd, isaa); + } else { + configureBlocking(nativefd, false); + try { + waitForNewConnection(nativefd, timeout); + newfd = accept0(nativefd, isaa); + if (newfd != -1) { + configureBlocking(newfd, true); + } + } finally { + configureBlocking(nativefd, true); + } + } + /* Update (SocketImpl)s' fd */ + fdAccess.set(s.fd, newfd); + /* Update socketImpls remote port, address and localport */ + InetSocketAddress isa = isaa[0]; + s.port = isa.getPort(); + s.address = isa.getAddress(); + s.localport = localport; + } + + int socketAvailable() throws IOException { + int nativefd = checkAndReturnNativeFD(); + return available0(nativefd); + } + + void socketClose0(boolean useDeferredClose/*unused*/) throws IOException { + if (fd == null) + throw new SocketException("Socket closed"); + + if (!fd.valid()) + return; + + close0(fdAccess.get(fd)); + fdAccess.set(fd, -1); + } + + void socketShutdown(int howto) throws IOException { + int nativefd = checkAndReturnNativeFD(); + shutdown0(nativefd, howto); + } + + void socketSetOption(int opt, boolean on, Object value) + throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + if (opt == SO_TIMEOUT) { // timeout implemented through select. + return; + } + + int optionValue = 0; + + switch(opt) { + case TCP_NODELAY : + case SO_OOBINLINE : + case SO_KEEPALIVE : + case SO_REUSEADDR : + optionValue = on ? 1 : 0; + break; + case SO_SNDBUF : + case SO_RCVBUF : + case IP_TOS : + optionValue = ((Integer)value).intValue(); + break; + case SO_LINGER : + if (on) { + optionValue = ((Integer)value).intValue(); + } else { + optionValue = -1; + } + break; + default :/* shouldn't get here */ + throw new SocketException("Option not supported"); + } + + setIntOption(nativefd, opt, optionValue); + } + + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + int nativefd = checkAndReturnNativeFD(); + + // SO_BINDADDR is not a socket option. + if (opt == SO_BINDADDR) { + localAddress(nativefd, (InetAddressContainer)iaContainerObj); + return 0; // return value doesn't matter. + } + + int value = getIntOption(nativefd, opt); + + switch (opt) { + case TCP_NODELAY : + case SO_OOBINLINE : + case SO_KEEPALIVE : + case SO_REUSEADDR : + return (value == 0) ? -1 : 1; + } + return value; + } + + int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) + throws SocketException {return 0;} // un-implemented REMOVE + + void socketSendUrgentData(int data) throws IOException { + int nativefd = checkAndReturnNativeFD(); + sendOOB(nativefd, data); + } + + private int checkAndReturnNativeFD() throws SocketException { + if (fd == null || !fd.valid()) + throw new SocketException("Socket closed"); + + return fdAccess.get(fd); + } + + static final int WOULDBLOCK = -2; // Nothing available (non-blocking) + + static { + initIDs(); + } + + /* Native methods */ + + static native void initIDs(); + + static native int socket0(boolean stream, boolean v6Only) throws IOException; + + static native void bind0(int fd, InetAddress localAddress, int localport) + throws IOException; + + static native int connect0(int fd, InetAddress remote, int remotePort) + throws IOException; + + static native void waitForConnect(int fd, int timeout) throws IOException; + + static native int localPort0(int fd) throws IOException; + + static native void localAddress(int fd, InetAddressContainer in) throws SocketException; + + static native void listen0(int fd, int backlog) throws IOException; + + static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException; + + static native void waitForNewConnection(int fd, int timeout) throws IOException; + + static native int available0(int fd) throws IOException; + + static native void close0(int fd) throws IOException; + + static native void shutdown0(int fd, int howto) throws IOException; + + static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException; + + static native int getIntOption(int fd, int cmd) throws SocketException; + + static native void sendOOB(int fd, int data) throws IOException; + + static native void configureBlocking(int fd, boolean blocking) throws IOException; +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/PlainSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/PlainSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,316 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.*; +import java.security.PrivilegedAction; + +/* + * This class PlainSocketImpl simply delegates to the appropriate real + * SocketImpl. We do this because PlainSocketImpl is already extended + * by SocksSocketImpl. + *

+ * There are two possibilities for the real SocketImpl, + * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use + * DualStackPlainSocketImpl on systems that have a dual stack + * TCP implementation. Otherwise we create an instance of + * TwoStacksPlainSocketImpl and delegate to it. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class PlainSocketImpl extends AbstractPlainSocketImpl +{ + private AbstractPlainSocketImpl impl; + + /* the windows version. */ + private static float version; + + /* java.net.preferIPv4Stack */ + private static boolean preferIPv4Stack = false; + + /* If the version supports a dual stack TCP implementation */ + private static boolean useDualStackImpl = false; + + static { + java.security.AccessController.doPrivileged( new PrivilegedAction() { + public Object run() { + version = 0; + try { + version = Float.parseFloat(System.getProperties().getProperty("os.version")); + preferIPv4Stack = Boolean.parseBoolean( + System.getProperties().getProperty("java.net.preferIPv4Stack")); + } catch (NumberFormatException e ) { + assert false : e; + } + return null; // nothing to return + } }); + + // (version >= 6.0) implies Vista or greater. + if (version >= 6.0 && !preferIPv4Stack) { + useDualStackImpl = true; + } + } + + /** + * Constructs an empty instance. + */ + PlainSocketImpl() { + if (useDualStackImpl) { + impl = new DualStackPlainSocketImpl(); + } else { + impl = new TwoStacksPlainSocketImpl(); + } + } + + /** + * Constructs an instance with the given file descriptor. + */ + PlainSocketImpl(FileDescriptor fd) { + if (useDualStackImpl) { + impl = new DualStackPlainSocketImpl(fd); + } else { + impl = new TwoStacksPlainSocketImpl(fd); + } + } + + // Override methods in SocketImpl that access impl's fields. + + protected FileDescriptor getFileDescriptor() { + return impl.getFileDescriptor(); + } + + protected InetAddress getInetAddress() { + return impl.getInetAddress(); + } + + protected int getPort() { + return impl.getPort(); + } + + protected int getLocalPort() { + return impl.getLocalPort(); + } + + void setSocket(Socket soc) { + impl.setSocket(soc); + } + + Socket getSocket() { + return impl.getSocket(); + } + + void setServerSocket(ServerSocket soc) { + impl.setServerSocket(soc); + } + + ServerSocket getServerSocket() { + return impl.getServerSocket(); + } + + public String toString() { + return impl.toString(); + } + + // Override methods in AbstractPlainSocketImpl that access impl's fields. + + protected synchronized void create(boolean stream) throws IOException { + impl.create(stream); + } + + protected void connect(String host, int port) + throws UnknownHostException, IOException + { + impl.connect(host, port); + } + + protected void connect(InetAddress address, int port) throws IOException { + impl.connect(address, port); + } + + protected void connect(SocketAddress address, int timeout) throws IOException { + impl.connect(address, timeout); + } + + public void setOption(int opt, Object val) throws SocketException { + impl.setOption(opt, val); + } + + public Object getOption(int opt) throws SocketException { + return impl.getOption(opt); + } + + synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { + impl.doConnect(address, port, timeout); + } + + protected synchronized void bind(InetAddress address, int lport) + throws IOException + { + impl.bind(address, lport); + } + + protected synchronized void accept(SocketImpl s) throws IOException { + // pass in the real impl not the wrapper. + ((PlainSocketImpl)s).impl.address = new InetAddress(); + ((PlainSocketImpl)s).impl.fd = new FileDescriptor(); + impl.accept(((PlainSocketImpl)s).impl); + } + + void setFileDescriptor(FileDescriptor fd) { + impl.setFileDescriptor(fd); + } + + void setAddress(InetAddress address) { + impl.setAddress(address); + } + + void setPort(int port) { + impl.setPort(port); + } + + void setLocalPort(int localPort) { + impl.setLocalPort(localPort); + } + + protected synchronized InputStream getInputStream() throws IOException { + return impl.getInputStream(); + } + + void setInputStream(SocketInputStream in) { + impl.setInputStream(in); + } + + protected synchronized OutputStream getOutputStream() throws IOException { + return impl.getOutputStream(); + } + + protected void close() throws IOException { + impl.close(); + } + + void reset() throws IOException { + impl.reset(); + } + + protected void shutdownInput() throws IOException { + impl.shutdownInput(); + } + + protected void shutdownOutput() throws IOException { + impl.shutdownOutput(); + } + + protected void sendUrgentData(int data) throws IOException { + impl.sendUrgentData(data); + } + + FileDescriptor acquireFD() { + return impl.acquireFD(); + } + + void releaseFD() { + impl.releaseFD(); + } + + public boolean isConnectionReset() { + return impl.isConnectionReset(); + } + + public boolean isConnectionResetPending() { + return impl.isConnectionResetPending(); + } + + public void setConnectionReset() { + impl.setConnectionReset(); + } + + public void setConnectionResetPending() { + impl.setConnectionResetPending(); + } + + public boolean isClosedOrPending() { + return impl.isClosedOrPending(); + } + + public int getTimeout() { + return impl.getTimeout(); + } + + // Override methods in AbstractPlainSocketImpl that need to be implemented. + + void socketCreate(boolean isServer) throws IOException { + impl.socketCreate(isServer); + } + + void socketConnect(InetAddress address, int port, int timeout) + throws IOException { + impl.socketConnect(address, port, timeout); + } + + void socketBind(InetAddress address, int port) + throws IOException { + impl.socketBind(address, port); + } + + void socketListen(int count) throws IOException { + impl.socketListen(count); + } + + void socketAccept(SocketImpl s) throws IOException { + impl.socketAccept(s); + } + + int socketAvailable() throws IOException { + return impl.socketAvailable(); + } + + void socketClose0(boolean useDeferredClose) throws IOException { + impl.socketClose0(useDeferredClose); + } + + void socketShutdown(int howto) throws IOException { + impl.socketShutdown(howto); + } + + void socketSetOption(int cmd, boolean on, Object value) + throws SocketException { + socketSetOption(cmd, on, value); + } + + int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + return impl.socketGetOption(opt, iaContainerObj); + } + + int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) + throws SocketException { + return impl.socketGetOption1(opt, iaContainerObj, fd); + } + + void socketSendUrgentData(int data) throws IOException { + impl.socketSendUrgentData(data); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,162 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; +import java.io.FileDescriptor; + +/** + * This class defines the plain DatagramSocketImpl that is used for all + * Windows versions lower than Vista. It adds support for IPv6 on + * these platforms where available. + * + * For backward compatibility windows platforms that do not have IPv6 + * support also use this implementation, and fd1 gets set to null + * during socket creation. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl +{ + /* Used for IPv6 on Windows only */ + private FileDescriptor fd1; + + /* + * Needed for ipv6 on windows because we need to know + * if the socket was bound to ::0 or 0.0.0.0, when a caller + * asks for it. In this case, both sockets are used, but we + * don't know whether the caller requested ::0 or 0.0.0.0 + * and need to remember it here. + */ + private InetAddress anyLocalBoundAddr=null; + + private int fduse=-1; /* saved between peek() and receive() calls */ + + /* saved between successive calls to receive, if data is detected + * on both sockets at same time. To ensure that one socket is not + * starved, they rotate using this field + */ + private int lastfd=-1; + + static { + init(); + } + + protected synchronized void create() throws SocketException { + fd1 = new FileDescriptor(); + super.create(); + } + + protected synchronized void bind(int lport, InetAddress laddr) + throws SocketException { + super.bind(lport, laddr); + if (laddr.isAnyLocalAddress()) { + anyLocalBoundAddr = laddr; + } + } + + protected synchronized void receive(DatagramPacket p) + throws IOException { + try { + receive0(p); + } finally { + fduse = -1; + } + } + + public Object getOption(int optID) throws SocketException { + if (isClosed()) { + throw new SocketException("Socket Closed"); + } + + if (optID == SO_BINDADDR) { + if (fd != null && fd1 != null) { + return anyLocalBoundAddr; + } + return socketGetOption(optID); + } else + return super.getOption(optID); + } + + protected boolean isClosed() { + return (fd == null && fd1 == null) ? true : false; + } + + protected void close() { + if (fd != null || fd1 != null) { + datagramSocketClose(); + fd = null; + fd1 = null; + } + } + + /* Native methods */ + + protected synchronized native void bind0(int lport, InetAddress laddr) + throws SocketException; + + protected native void send(DatagramPacket p) throws IOException; + + protected synchronized native int peek(InetAddress i) throws IOException; + + protected synchronized native int peekData(DatagramPacket p) throws IOException; + + protected synchronized native void receive0(DatagramPacket p) + throws IOException; + + protected native void setTimeToLive(int ttl) throws IOException; + + protected native int getTimeToLive() throws IOException; + + protected native void setTTL(byte ttl) throws IOException; + + protected native byte getTTL() throws IOException; + + protected native void join(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + protected native void leave(InetAddress inetaddr, NetworkInterface netIf) + throws IOException; + + protected native void datagramSocketCreate() throws SocketException; + + protected native void datagramSocketClose(); + + protected native void socketSetOption(int opt, Object val) + throws SocketException; + + protected native Object socketGetOption(int opt) throws SocketException; + + protected native void connect0(InetAddress address, int port) throws SocketException; + + protected native void disconnect0(int family); + + /** + * Perform class load-time initializations. + */ + private native static void init(); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,207 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package java.net; + +import java.io.IOException; +import java.io.FileDescriptor; + +/* + * This class defines the plain SocketImpl that is used for all + * Windows version lower than Vista. It adds support for IPv6 on + * these platforms where available. + * + * For backward compatibility Windows platforms that do not have IPv6 + * support also use this implementation, and fd1 gets set to null + * during socket creation. + * + * @version 1.2, 06/11/07 + * @author Chris Hegarty + */ + +class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl +{ + /* second fd, used for ipv6 on windows only. + * fd1 is used for listeners and for client sockets at initialization + * until the socket is connected. Up to this point fd always refers + * to the ipv4 socket and fd1 to the ipv6 socket. After the socket + * becomes connected, fd always refers to the connected socket + * (either v4 or v6) and fd1 is closed. + * + * For ServerSockets, fd always refers to the v4 listener and + * fd1 the v6 listener. + */ + private FileDescriptor fd1; + + /* + * Needed for ipv6 on windows because we need to know + * if the socket is bound to ::0 or 0.0.0.0, when a caller + * asks for it. Otherwise we don't know which socket to ask. + */ + private InetAddress anyLocalBoundAddr = null; + + /* to prevent starvation when listening on two sockets, this is + * is used to hold the id of the last socket we accepted on. + */ + private int lastfd = -1; + + static { + initProto(); + } + + public TwoStacksPlainSocketImpl() {} + + public TwoStacksPlainSocketImpl(FileDescriptor fd) { + this.fd = fd; + } + + /** + * Creates a socket with a boolean that specifies whether this + * is a stream socket (true) or an unconnected UDP socket (false). + */ + protected synchronized void create(boolean stream) throws IOException { + fd1 = new FileDescriptor(); + super.create(stream); + } + + /** + * Binds the socket to the specified address of the specified local port. + * @param address the address + * @param port the port + */ + protected synchronized void bind(InetAddress address, int lport) + throws IOException + { + super.bind(address, lport); + if (address.isAnyLocalAddress()) { + anyLocalBoundAddr = address; + } + } + + public Object getOption(int opt) throws SocketException { + if (isClosedOrPending()) { + throw new SocketException("Socket Closed"); + } + if (opt == SO_BINDADDR) { + if (fd != null && fd1 != null ) { + /* must be unbound or else bound to anyLocal */ + return anyLocalBoundAddr; + } + InetAddressContainer in = new InetAddressContainer(); + socketGetOption(opt, in); + return in.addr; + } else + return super.getOption(opt); + } + + /** + * Closes the socket. + */ + protected void close() throws IOException { + synchronized(fdLock) { + if (fd != null || fd1 != null) { + if (fdUseCount == 0) { + if (closePending) { + return; + } + closePending = true; + socketClose(); + fd = null; + fd1 = null; + return; + } else { + /* + * If a thread has acquired the fd and a close + * isn't pending then use a deferred close. + * Also decrement fdUseCount to signal the last + * thread that releases the fd to close it. + */ + if (!closePending) { + closePending = true; + fdUseCount--; + socketClose(); + } + } + } + } + } + + void reset() throws IOException { + if (fd != null || fd1 != null) { + socketClose(); + } + fd = null; + fd1 = null; + super.reset(); + } + + /* + * Return true if already closed or close is pending + */ + public boolean isClosedOrPending() { + /* + * Lock on fdLock to ensure that we wait if a + * close is in progress. + */ + synchronized (fdLock) { + if (closePending || (fd == null && fd1 == null)) { + return true; + } else { + return false; + } + } + } + + /* Native methods */ + + static native void initProto(); + + native void socketCreate(boolean isServer) throws IOException; + + native void socketConnect(InetAddress address, int port, int timeout) + throws IOException; + + native void socketBind(InetAddress address, int port) + throws IOException; + + native void socketListen(int count) throws IOException; + + native void socketAccept(SocketImpl s) throws IOException; + + native int socketAvailable() throws IOException; + + native void socketClose0(boolean useDeferredClose) throws IOException; + + native void socketShutdown(int howto) throws IOException; + + native void socketSetOption(int cmd, boolean on, Object value) + throws SocketException; + + native int socketGetOption(int opt, Object iaContainerObj) throws SocketException; + + native int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) + throws SocketException; + + native void socketSendUrgentData(int data) throws IOException; +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java --- a/j2se/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Thu Jul 05 23:47:33 2007 +0000 @@ -284,7 +284,7 @@ Win32ShellFolder2(Win32ShellFolder2 parent, long relativePIDL) { super(parent, getFileSystemPath(parent.getIShellFolder(), relativePIDL)); this.disposer.relativePIDL = relativePIDL; - String absolutePath = getAbsolutePath(); + getAbsolutePath(); sun.java2d.Disposer.addRecord(this, disposer); } @@ -460,10 +460,12 @@ } if (isFileSystem() && rhs.isFileSystem()) { - return pathsEqual(getPath(), rhs.getPath()); - } + // Only folders with identical parents can be equal + return (pathsEqual(getPath(), rhs.getPath()) && + (parent == rhs.parent || parent.equals(rhs.parent))); + } - if (parent == null || parent == rhs.parent || parent.equals(rhs.parent)) { + if (parent == rhs.parent || parent.equals(rhs.parent)) { return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL); } @@ -593,7 +595,6 @@ Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop(); Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal(); - File[] children = null; // If we are a directory, we have a parent and (at least) a // relative PIDL. We must first ensure we are bound to the @@ -933,8 +934,6 @@ return this; } - private List topFolderList = null; - /* * Indicates whether this is a special folder (includes My Documents) */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java --- a/j2se/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Thu Jul 05 23:47:33 2007 +0000 @@ -286,6 +286,8 @@ i = (useShell32Icons) ? 28 : 8; } else if (name.equals("NewFolder")) { i = (useShell32Icons) ? 31 : 11; + } else if (name.equals("ViewMenu")) { + i = (useShell32Icons) ? 21 : 2; } } if (i >= 0) { @@ -357,8 +359,18 @@ private Comparator driveComparator = new Comparator() { public int compare(Object o1, Object o2) { - return ((ShellFolder)o1).getPath().compareTo(((ShellFolder)o2).getPath()); - } + Win32ShellFolder2 shellFolder1 = (Win32ShellFolder2) o1; + Win32ShellFolder2 shellFolder2 = (Win32ShellFolder2) o2; + + // Put drives at first + boolean isDrive1 = shellFolder1.getPath().endsWith(":\\"); + + if (isDrive1 ^ shellFolder2.getPath().endsWith(":\\")) { + return isDrive1 ? -1 : 1; + } else { + return shellFolder1.getPath().compareTo(shellFolder2.getPath()); + } + } }; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WCanvasPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WCanvasPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WCanvasPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -28,29 +28,14 @@ import java.awt.peer.*; import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import sun.awt.ComponentAccessor; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; import sun.awt.PaintEventDispatcher; class WCanvasPeer extends WComponentPeer implements CanvasPeer { - private boolean eraseBackgroundDisabledOnThis; - - private static boolean eraseBackgroundDisabled; - private static boolean eraseBackgroundOnResize; - static { - String prop; - prop = (String)java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.awt.noerasebackground")); - eraseBackgroundDisabled = (prop != null - && prop.length() > 0 - && prop.charAt(0) == 't'); - prop = (String)java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("sun.awt.erasebackgroundonresize")); - eraseBackgroundOnResize = (prop != null - && prop.length() > 0 - && prop.charAt(0) == 't'); - } + private boolean eraseBackground; Method resetGCMethod; @@ -79,16 +64,7 @@ * through reflection. */ public void resetTargetGC() { - synchronized (this) { - if (resetGCMethod == null) { - resetGCMethod = SunToolkit.getMethod(Component.class, "resetGC", null); - } - } - try { - resetGCMethod.invoke(target); - } catch (Exception z) { - z.printStackTrace(); - } + ComponentAccessor.resetGC((Component)target); } /* @@ -101,20 +77,21 @@ native void create(WComponentPeer parent); - private native void setNativeBackgroundErase(boolean doErase); - void initialize() { + eraseBackground = !SunToolkit.getSunAwtNoerasebackground(); + boolean eraseBackgroundOnResize = SunToolkit.getSunAwtErasebackgroundonresize(); // Optimization: the default value in the native code is true, so we // call setNativeBackgroundErase only when the value changes to false if (!PaintEventDispatcher.getPaintEventDispatcher(). shouldDoNativeBackgroundErase((Component)target)) { - setNativeBackgroundErase(false); + eraseBackground = false; } + setNativeBackgroundErase(eraseBackground, eraseBackgroundOnResize); super.initialize(); - Color bg = ((Component)target).getBackground(); - if (bg != null) { - setBackground(bg); - } + Color bg = ((Component)target).getBackground(); + if (bg != null) { + setBackground(bg); + } } public void paint(Graphics g) { @@ -148,14 +125,26 @@ } public boolean shouldClearRectBeforePaint() { - return (eraseBackgroundDisabled == false) && (eraseBackgroundDisabledOnThis == false); + return eraseBackground; + } + + /* + * Disables background erasing for this canvas, both for resizing + * and not-resizing repaints. + */ + void disableBackgroundErase() { + eraseBackground = false; + setNativeBackgroundErase(false, false); } - void disableBackgroundErase() { - eraseBackgroundDisabledOnThis = true; - disableNativeBackgroundErase(); - } - - private native void disableNativeBackgroundErase(); - + /* + * Sets background erasing flags at the native level. If {@code + * doErase} is set to {@code true}, canvas background is erased on + * every repaint. If {@code doErase} is {@code false} and {@code + * doEraseOnResize} is {@code true}, then background is only erased + * on resizing repaints. If both {@code doErase} and {@code + * doEraseOnResize} are false, then background is never erased. + */ + private native void setNativeBackgroundErase(boolean doErase, + boolean doEraseOnResize); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WChoicePeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WChoicePeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WChoicePeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2001 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,7 @@ } public native void addItems(String[] items, int index); - public native void reshape(int x, int y, int width, int height); + public synchronized native void reshape(int x, int y, int width, int height); // Toolkit & peer internals diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WClipboard.java --- a/j2se/src/windows/classes/sun/awt/windows/WClipboard.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WClipboard.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt.windows; -import java.awt.datatransfer.ClipboardOwner; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; @@ -35,9 +34,7 @@ import java.util.Iterator; import java.util.Map; -import sun.awt.AppContext; import sun.awt.datatransfer.SunClipboard; -import sun.awt.datatransfer.TransferableProxy; import sun.awt.datatransfer.DataTransferer; @@ -50,7 +47,7 @@ * @author David Mendenhall * @author Danila Sinopalnikov * @author Alexander Gerasimov - * @version 1.34, 05/05/07 + * @version 1.36, 06/05/07 * * @since JDK1.1 */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WComponentPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WComponentPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WComponentPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -59,7 +59,7 @@ /** * Handle to native window */ - protected long hwnd; + protected volatile long hwnd; private static final DebugHelper dbg = DebugHelper.create(WComponentPeer.class); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WDefaultFontCharset.java --- a/j2se/src/windows/classes/sun/awt/windows/WDefaultFontCharset.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WDefaultFontCharset.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,6 @@ */ package sun.awt.windows; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; import java.nio.charset.*; import sun.awt.AWTCharset; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WDragSourceContextPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WDragSourceContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WDragSourceContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,6 @@ import java.util.Map; -import sun.awt.Mutex; - import sun.awt.dnd.SunDragSourceContextPeer; /** @@ -46,7 +44,7 @@ * TBC *

* - * @version 1.37 + * @version 1.39 * @since JDK1.2 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WDropTargetContextPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WDropTargetContextPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WDropTargetContextPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,11 @@ package sun.awt.windows; -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.UnsupportedFlavorException; - -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DropTarget; -import java.awt.dnd.InvalidDnDOperationException; - import java.io.InputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.Map; - import sun.awt.PeerEvent; import sun.awt.SunToolkit; import sun.awt.dnd.SunDropTargetContextPeer; @@ -50,7 +41,7 @@ * the interaction between the win32 DnD system and Java. *

* - * @version 1.44 + * @version 1.46 * */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java --- a/j2se/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WEmbeddedFrame.java Thu Jul 05 23:47:33 2007 +0000 @@ -50,9 +50,6 @@ private static final int MAX_BAND_SIZE = (1024*30); - // 'peer' field of java.awt.Component class - private static Field peerField = SunToolkit.getField(Component.class, "peer"); - public WEmbeddedFrame() { this((long)0); } @@ -207,7 +204,9 @@ */ public void notifyModalBlocked(Dialog blocker, boolean blocked) { try { - notifyModalBlockedImpl((WEmbeddedFramePeer)(peerField.get(this)), (WWindowPeer)(peerField.get(blocker)), blocked); + notifyModalBlockedImpl((WEmbeddedFramePeer)ComponentAccessor.getPeer(this), + (WWindowPeer)ComponentAccessor.getPeer(blocker), + blocked); } catch (Exception z) { z.printStackTrace(System.err); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WEmbeddedFramePeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt.windows; -import java.awt.Component; import java.awt.Dialog; import java.awt.Graphics; import java.awt.Rectangle; @@ -46,19 +45,17 @@ // supress calling native setMinSize() public void updateMinimumSize() {} - // override WWindowPeer's method to let the embedded frame to block - // the containing window - public void setModalBlocked(Dialog blocker, boolean blocked) { - super.setModalBlocked(blocker, blocked); - - WWindowPeer blockerPeer = (WWindowPeer)blocker.getPeer(); - if (!blocked || - !((blockerPeer instanceof WFileDialogPeer) || - (blockerPeer instanceof WPrintDialogPeer))) - { - EmbeddedFrame frame = (EmbeddedFrame)target; - frame.notifyModalBlocked(blocker, blocked); - } + @Override + public void modalDisable(Dialog blocker, long blockerHWnd) + { + super.modalDisable(blocker, blockerHWnd); + ((EmbeddedFrame)target).notifyModalBlocked(blocker, true); + } + @Override + public void modalEnable(Dialog blocker) + { + super.modalEnable(blocker); + ((EmbeddedFrame)target).notifyModalBlocked(blocker, false); } public void setBoundsPrivate(int x, int y, int width, int height) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WFileDialogPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -34,7 +34,6 @@ import java.util.ResourceBundle; import java.util.MissingResourceException; import java.util.Vector; -import sun.awt.EmbeddedFrame; import sun.awt.AppContext; import sun.awt.ComponentAccessor; @@ -103,15 +102,17 @@ _hide(); } - // called from native code when the dialog is shown on the screen + // called from native code when the dialog is shown or hidden void setHWnd(long hwnd) { + if (this.hwnd == hwnd) { + return; + } this.hwnd = hwnd; - if (hwnd != 0) { - for (WWindowPeer window : blockedWindows) { - window.modalDisableByHWnd(hwnd); - if (window.target instanceof EmbeddedFrame) { - ((EmbeddedFrame)window.target).notifyModalBlocked((Dialog)target, true); - } + for (WWindowPeer window : blockedWindows) { + if (hwnd != 0) { + window.modalDisable((Dialog)target, hwnd); + } else { + window.modalEnable((Dialog)target); } } } @@ -168,14 +169,20 @@ } void blockWindow(WWindowPeer window) { + blockedWindows.add(window); + // if this dialog hasn't got an HWND, notification is + // postponed until setHWnd() is called if (hwnd != 0) { - window.modalDisableByHWnd(hwnd); - } else { - blockedWindows.add(window); + window.modalDisable((Dialog)target, hwnd); } } void unblockWindow(WWindowPeer window) { blockedWindows.remove(window); + // if this dialog hasn't got an HWND or has been already + // closed, don't send notification + if (hwnd != 0) { + window.modalEnable((Dialog)target); + } } public void blockWindows(java.util.List toBlock) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WFontPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WFontPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WFontPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package sun.awt.windows; -import java.awt.GraphicsEnvironment; import sun.awt.PlatformFont; public class WFontPeer extends PlatformFont { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WInputMethod.java --- a/j2se/src/windows/classes/sun/awt/windows/WInputMethod.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WInputMethod.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,14 +30,12 @@ import java.awt.peer.*; import java.awt.event.*; import java.awt.im.*; -import java.awt.im.spi.InputMethod; import java.awt.im.spi.InputMethodContext; import java.awt.font.*; import java.text.*; import java.text.AttributedCharacterIterator.Attribute; import java.lang.Character.Subset; import java.lang.Character.UnicodeBlock; -import java.lang.System; import java.util.Collections; import java.util.HashMap; import java.util.Locale; @@ -501,11 +499,6 @@ for (int i=0; i toBlock) { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WTrayIconPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WTrayIconPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WTrayIconPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,7 @@ package sun.awt.windows; -import java.awt.Image; -import java.awt.Component; import java.awt.Graphics2D; -import java.awt.Graphics; import java.awt.AWTEvent; import java.awt.Frame; import java.awt.PopupMenu; @@ -36,15 +33,10 @@ import java.awt.TrayIcon; import java.awt.Image; import java.awt.peer.TrayIconPeer; -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.event.InvocationEvent; -import java.awt.Toolkit; import java.awt.image.*; import sun.awt.SunToolkit; import sun.awt.image.IntegerComponentRaster; import sun.awt.windows.WPopupMenuPeer; -import java.lang.reflect.Field; public class WTrayIconPeer extends WObjectPeer implements TrayIconPeer { final static int TRAY_ICON_WIDTH = 16; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/classes/sun/awt/windows/WWindowPeer.java --- a/j2se/src/windows/classes/sun/awt/windows/WWindowPeer.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/classes/sun/awt/windows/WWindowPeer.java Thu Jul 05 23:47:33 2007 +0000 @@ -29,12 +29,15 @@ import java.awt.image.*; import java.awt.peer.*; +import java.beans.*; + import java.lang.ref.*; import java.lang.reflect.*; import java.security.*; import java.util.*; +import java.util.List; import java.util.logging.*; import sun.awt.*; @@ -50,6 +53,26 @@ // extends WWindowPeer, not WDialogPeer private WWindowPeer modalBlocker = null; + /* + * A key used for storing a list of active windows in AppContext. The value + * is a list of windows, sorted by the time of activation: later a window is + * activated, greater its index is in the list. + */ + private final static StringBuffer ACTIVE_WINDOWS_KEY = + new StringBuffer("active_windows_list"); + + /* + * Listener for 'activeWindow' KFM property changes. It is added to each + * AppContext KFM. See ActiveWindowListener inner class below. + */ + private static PropertyChangeListener activeWindowListener = + new ActiveWindowListener(); + + /* + * Contains all the AppContexts where activeWindowListener is added to. + */ + private static Set trackedAppContexts = new HashSet(); + /** * Initialize JNI field IDs */ @@ -58,19 +81,19 @@ initIDs(); } - // 'peer' field of java.awt.Component class - private static Field peerField = SunToolkit.getField(Component.class, "peer"); - // 'getWindows()' method of java.awt.Window class - private static Method getWindowsMethod = - SunToolkit.getMethod(Window.class, "getWindows", new Class[] {AppContext.class}); - // WComponentPeer overrides protected void disposeImpl() { + AppContext appContext = SunToolkit.targetToAppContext(target); + synchronized (appContext) { + List l = (List)appContext.get(ACTIVE_WINDOWS_KEY); + if (l != null) { + l.remove(this); + } + } // Remove ourself from the Map of DisplayChangeListeners GraphicsConfiguration gc = getGraphicsConfiguration(); ((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this); - allWindows.removeElement(this); super.disposeImpl(); } @@ -113,8 +136,6 @@ // Toolkit & peer internals - static Vector allWindows = new Vector(); //!CQ for anchoring windows, frames, dialogs - WWindowPeer(Window target) { super(target); } @@ -133,6 +154,16 @@ // Express our interest in display changes GraphicsConfiguration gc = getGraphicsConfiguration(); ((Win32GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this); + + AppContext appContext = AppContext.getAppContext(); + synchronized (appContext) { + if (!trackedAppContexts.contains(appContext)) { + KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); + kfm.addPropertyChangeListener("activeWindow", activeWindowListener); + trackedAppContexts.add(appContext); + } + } + updateIconImages(); } @@ -272,12 +303,15 @@ if (blocked) { modalBlocker = blockerPeer; + // handle native dialogs separately, as they may have not + // got HWND yet; modalEnable/modalDisable is called from + // their setHWnd() methods if (blockerPeer instanceof WFileDialogPeer) { ((WFileDialogPeer)blockerPeer).blockWindow(this); } else if (blockerPeer instanceof WPrintDialogPeer) { ((WPrintDialogPeer)blockerPeer).blockWindow(this); } else { - modalDisable(modalBlocker); + modalDisable(dialog, blockerPeer.getHWnd()); } } else { modalBlocker = null; @@ -285,71 +319,34 @@ ((WFileDialogPeer)blockerPeer).unblockWindow(this); } else if (blockerPeer instanceof WPrintDialogPeer) { ((WPrintDialogPeer)blockerPeer).unblockWindow(this); + } else { + modalEnable(dialog); } - modalEnable(); } } } - native void modalDisable(WWindowPeer dialog); - native void modalDisableByHWnd(long hwnd); // used from WFileDialogPeer and WPrintDialogPeer - native void modalEnable(); + native void modalDisable(Dialog blocker, long blockerHWnd); + native void modalEnable(Dialog blocker); /* - * Returns all the windows from this window's app context. - * All the embedded frames are collected at the beginning of the result array. + * Returns all the ever active windows from the current AppContext. + * The list is sorted by the time of activation, so the latest + * active window is always at the end. */ - public long[] getWindowHandles() { - Window[] ws = null; - try { - AppContext appContext = SunToolkit.targetToAppContext(target); - if (appContext != null) { - ws = (Window[])getWindowsMethod.invoke(Window.class, appContext); + public static long[] getActiveWindowHandles() { + AppContext appContext = AppContext.getAppContext(); + synchronized (appContext) { + List l = (List)appContext.get(ACTIVE_WINDOWS_KEY); + if (l == null) { + return null; } - } catch (Exception z) { - if (log.isLoggable(Level.FINER)) { - log.log(Level.FINER, "Exception occured in WWindowPeer.getWindowHandles()", z); + long[] result = new long[l.size()]; + for (int j = 0; j < l.size(); j++) { + result[j] = l.get(j).getHWnd(); } - } - if (ws == null) { - return null; + return result; } - long[] result = new long[ws.length]; - Arrays.fill(result, 0); - - int j = 0; - // collect embedded frames - for (Window w : ws) { - if ((w instanceof EmbeddedFrame)) { - try { - WEmbeddedFramePeer peer = (WEmbeddedFramePeer)peerField.get(w); - if (peer != null) { - result[j++] = peer.getHWnd(); - } - } catch (Exception z) { - if (log.isLoggable(Level.FINER)) { - log.log(Level.FINER, "Exception occured in WWindowPeer.getWindowHandles()", z); - } - } - } - } - // then non-embedded windows - for (Window w : ws) { - if (!(w instanceof EmbeddedFrame)) { - try { - WWindowPeer peer = (WWindowPeer)peerField.get(w); - if (peer != null) { - result[j++] = peer.getHWnd(); - } - } catch (Exception z) { - if (log.isLoggable(Level.FINER)) { - log.log(Level.FINER, "Exception occured in WWindowPeer.getWindowHandles()", z); - } - } - } - } - - return result; } /* @@ -438,4 +435,30 @@ } private native void nativeGrab(); private native void nativeUngrab(); + + /* + * Static inner class, listens for 'activeWindow' KFM property changes and + * updates the list of active windows per AppContext, so the latest active + * window is always at the end of the list. The list is stored in AppContext. + */ + private static class ActiveWindowListener implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent e) { + Window w = (Window)e.getNewValue(); + if (w == null) { + return; + } + AppContext appContext = SunToolkit.targetToAppContext(w); + synchronized (appContext) { + List l = (List)appContext.get(ACTIVE_WINDOWS_KEY); + if (l == null) { + l = new LinkedList(); + appContext.put(ACTIVE_WINDOWS_KEY, l); + } + WWindowPeer wp = (WWindowPeer)w.getPeer(); + // add/move wp to the end of the list + l.remove(wp); + l.add(wp); + } + } + } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/lang/ProcessImpl_md.c --- a/j2se/src/windows/native/java/lang/ProcessImpl_md.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/java/lang/ProcessImpl_md.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ #include #include -#define PIPE_SIZE 512 +#define PIPE_SIZE 4096 char * extractExecutablePath(JNIEnv *env, char *source) @@ -102,14 +102,18 @@ } static void -throwIOException(JNIEnv *env, const char *defaultDetail) +win32Error(JNIEnv *env, const char *functionName) { - static const char * const format = "CreateProcess error=%d, %s"; + static const char * const format = "%s error=%d, %s"; + static const char * const fallbackFormat = "%s failed, error=%d"; char buf[256]; char errmsg[sizeof(buf) + 100]; - int errnum = GetLastError(); - int n = JVM_GetLastErrorString(buf, sizeof(buf)); - sprintf(errmsg, format, errnum, (n > 0) ? buf : defaultDetail); + const int errnum = GetLastError(); + const int n = JVM_GetLastErrorString(buf, sizeof(buf)); + if (n > 0) + sprintf(errmsg, format, functionName, errnum, buf); + else + sprintf(errmsg, fallbackFormat, functionName, errnum); JNU_ThrowIOException(env, errmsg); } @@ -121,7 +125,7 @@ } JNIEXPORT jlong JNICALL -Java_java_lang_ProcessImpl_create(JNIEnv *env, jobject process, +Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored, jstring cmd, jstring envBlock, jstring dir, @@ -159,7 +163,7 @@ if (!(CreatePipe(&inRead, &inWrite, &sa, PIPE_SIZE) && CreatePipe(&outRead, &outWrite, &sa, PIPE_SIZE) && CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE))) { - throwIOException(env, "CreatePipe failed"); + win32Error(env, "CreatePipe"); goto Catch; } @@ -222,7 +226,7 @@ &pi); /* (out) process information */ if (!ret) { - throwIOException(env, "CreateProcess failed"); + win32Error(env, "CreateProcess"); goto Catch; } @@ -259,73 +263,42 @@ } JNIEXPORT jint JNICALL -Java_java_lang_ProcessImpl_exitValue(JNIEnv *env, jobject process) +Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle) { - jint exit_code; - jboolean exc; - jlong handle = JNU_GetFieldByName(env, &exc, process, "handle", "J").j; - if (exc) { - return 0; - } - - GetExitCodeProcess((void *)handle, &exit_code); - if (exit_code == STILL_ACTIVE) { - JNU_ThrowByName(env, "java/lang/IllegalThreadStateException", - "process has not exited"); - return -1; - } + DWORD exit_code; + if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0) + win32Error(env, "GetExitCodeProcess"); return exit_code; } -#define PROCESS_EVENT 0 -#define INTERRUPT_EVENT 1 - JNIEXPORT jint JNICALL -Java_java_lang_ProcessImpl_waitFor(JNIEnv *env, jobject process) +Java_java_lang_ProcessImpl_getStillActive(JNIEnv *env, jclass ignored) { - long exit_code; - int which; - HANDLE events[2]; - jboolean exc; - jlong handle = JNU_GetFieldByName(env, &exc, process, "handle", "J").j; - if (exc) { - return 0; - } - - events[PROCESS_EVENT] = (void *)handle; - events[INTERRUPT_EVENT] = JVM_GetThreadInterruptEvent(); - - which = WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (which == PROCESS_EVENT) { - GetExitCodeProcess((void *)handle, &exit_code); - } else { - JNU_ThrowByName(env, "java/lang/InterruptedException", 0); - } - - return exit_code; -} - -#undef PROCESS_EVENT -#undef INTERRUPT_EVENT - -JNIEXPORT void JNICALL -Java_java_lang_ProcessImpl_destroy(JNIEnv *env, jobject process) -{ - jboolean exc; - jlong handle = JNU_GetFieldByName(env, &exc, process, "handle", "J").j; - if (exc) { - return; - } - TerminateProcess((void *)handle, 1); + return STILL_ACTIVE; } JNIEXPORT void JNICALL -Java_java_lang_ProcessImpl_close(JNIEnv *env, jobject process) +Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle) { - jboolean exc; - jlong handle = JNU_GetFieldByName(env, &exc, process, "handle", "J").j; - if (exc) { - return; - } - CloseHandle((void *)handle); + HANDLE events[2]; + events[0] = (HANDLE) handle; + events[1] = JVM_GetThreadInterruptEvent(); + + if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events, + FALSE, /* Wait for ANY event */ + INFINITE) /* Wait forever */ + == WAIT_FAILED) + win32Error(env, "WaitForMultipleObjects"); } + +JNIEXPORT void JNICALL +Java_java_lang_ProcessImpl_terminateProcess(JNIEnv *env, jclass ignored, jlong handle) +{ + TerminateProcess((HANDLE) handle, 1); +} + +JNIEXPORT jboolean JNICALL +Java_java_lang_ProcessImpl_closeHandle(JNIEnv *env, jclass ignored, jlong handle) +{ + return CloseHandle((HANDLE) handle); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,497 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +#include +#include +#include "jni.h" +#include "net_util.h" +#include "java_net_DualStackPlainDatagramSocketImpl.h" + +/* + * This function "purges" all outstanding ICMP port unreachable packets + * outstanding on a socket and returns JNI_TRUE if any ICMP messages + * have been purged. The rational for purging is to emulate normal BSD + * behaviour whereby receiving a "connection reset" status resets the + * socket. + */ +static jboolean purgeOutstandingICMP(JNIEnv *env, jint fd) +{ + jboolean got_icmp = JNI_FALSE; + char buf[1]; + fd_set tbl; + struct timeval t = { 0, 0 }; + struct sockaddr_in rmtaddr; + int addrlen = sizeof(rmtaddr); + + /* + * Peek at the queue to see if there is an ICMP port unreachable. If there + * is then receive it. + */ + FD_ZERO(&tbl); + FD_SET(fd, &tbl); + while(1) { + if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) { + break; + } + if (recvfrom(fd, buf, 1, MSG_PEEK, + (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) { + break; + } + if (WSAGetLastError() != WSAECONNRESET) { + /* some other error - we don't care here */ + break; + } + + recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); + got_icmp = JNI_TRUE; + } + + return got_icmp; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketCreate + * Signature: (Z)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate + (JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) { + int fd, rv, opt=0, t=TRUE; + DWORD x1, x2; /* ignored result codes */ + + fd = (int) socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == INVALID_SOCKET) { + NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); + return -1; + } + + rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed"); + return -1; + } + + SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); + + /* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which + * returns connection reset errors on unconnected UDP sockets (as well + * as connected sockets). The solution is to only enable this feature + * when the socket is connected. + */ + t = FALSE; + WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0); + + return fd; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketBind + * Signature: (ILjava/net/InetAddress;I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind + (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { + SOCKETADDRESS sa; + int rv; + int sa_len = sizeof(sa); + + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + &sa_len, JNI_TRUE) != 0) { + return; + } + + rv = bind(fd, (struct sockaddr *)&sa, sa_len); + + if (rv == SOCKET_ERROR) { + if (WSAGetLastError() == WSAEACCES) { + WSASetLastError(WSAEADDRINUSE); + } + NET_ThrowNew(env, WSAGetLastError(), "Cannot bind"); + } +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketConnect + * Signature: (ILjava/net/InetAddress;I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect + (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { + SOCKETADDRESS sa; + int rv; + int sa_len = sizeof(sa); + DWORD x1, x2; /* ignored result codes */ + int t = TRUE; + + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + &sa_len, JNI_TRUE) != 0) { + return; + } + + rv = connect(fd, (struct sockaddr *)&sa, sa_len); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "connect"); + return; + } + + /* see comment in socketCreate */ + WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketDisconnect + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketDisconnect + (JNIEnv *env, jclass clazz, jint fd ) { + SOCKETADDRESS sa; + int sa_len = sizeof(sa); + DWORD x1, x2; /* ignored result codes */ + int t = FALSE; + + memset(&sa, 0, sa_len); + connect(fd, (struct sockaddr *)&sa, sa_len); + + /* see comment in socketCreate */ + WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketClose + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketClose + (JNIEnv *env, jclass clazz , jint fd) { + NET_SocketClose(fd); +} + + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketLocalPort + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalPort + (JNIEnv *env, jclass clazz, jint fd) { + SOCKETADDRESS sa; + int len = sizeof(sa); + + if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "JVM_GetSockName"); + return -1; + } + return (int) ntohs((u_short)GET_PORT(&sa)); +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketLocalAddress + * Signature: (I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketLocalAddress + (JNIEnv *env , jclass clazz, jint fd) { + SOCKETADDRESS sa; + int len = sizeof(sa); + jobject iaObj; + int port; + + if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); + return NULL; + } + + iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + return iaObj; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketReceiveOrPeekData + * Signature: (ILjava/net/DatagramPacket;IZZ)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketReceiveOrPeekData + (JNIEnv *env, jclass clazz, jint fd, jobject dpObj, + jint timeout, jboolean connected, jboolean peek) { + SOCKETADDRESS sa; + int sa_len = sizeof(sa); + int port, rv, flags=0; + char BUF[MAX_BUFFER_LEN]; + char *fullPacket; + BOOL retry; + jlong prevTime = 0; + + jint packetBufferOffset, packetBufferLen; + jbyteArray packetBuffer; + + /* if we are only peeking. Called from peekData */ + if (peek) { + flags = MSG_PEEK; + } + + packetBuffer = (*env)->GetObjectField(env, dpObj, dp_bufID); + packetBufferOffset = (*env)->GetIntField(env, dpObj, dp_offsetID); + packetBufferLen = (*env)->GetIntField(env, dpObj, dp_bufLengthID); + + if (packetBufferLen > MAX_BUFFER_LEN) { + /* Note: the buffer needn't be greater than 65,536 (0xFFFF) + * the max size of an IP packet. Anything bigger is truncated anyway. + */ + if (packetBufferLen > MAX_PACKET_LEN) { + packetBufferLen = MAX_PACKET_LEN; + } + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return -1; + } + } else { + fullPacket = &(BUF[0]); + } + + do { + retry = FALSE; + + if (timeout) { + if (prevTime == 0) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + rv = NET_Timeout(fd, timeout); + if (rv <= 0) { + if (rv == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + } else if (rv == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else if (rv == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; + } + } + + /* receive the packet */ + rv = recvfrom(fd, fullPacket, packetBufferLen, flags, + (struct sockaddr *)&sa, &sa_len); + + if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) { + /* An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(env, fd); + + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + "ICMP Port Unreachable"); + if (packetBufferLen > MAX_BUFFER_LEN) + free(fullPacket); + return -1; + } else if (timeout) { + /* Adjust timeout */ + jlong newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (jint)(newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + if (packetBufferLen > MAX_BUFFER_LEN) + free(fullPacket); + return -1; + } + prevTime = newTime; + } + retry = TRUE; + } + } while (retry); + + port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&sa)); + + /* truncate the data if the packet's length is too small */ + if (rv > packetBufferLen) { + rv = packetBufferLen; + } + if (rv < 0) { + if (WSAGetLastError() == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + rv = packetBufferLen; + } else { + /* failure */ + (*env)->SetIntField(env, dpObj, dp_lengthID, 0); + } + } + + if (rv == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + } else if (rv == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } else if (rv < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + jobject packetAddress; + /* + * Check if there is an InetAddress already associated with this + * packet. If so, we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = (*env)->GetObjectField(env, dpObj, dp_addressID); + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&sa, + packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = NULL; + } + } + if (packetAddress == NULL) { + packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, + &port); + /* stuff the new Inetaddress into the packet */ + (*env)->SetObjectField(env, dpObj, dp_addressID, packetAddress); + } + + /* populate the packet */ + (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, rv, + (jbyte *)fullPacket); + (*env)->SetIntField(env, dpObj, dp_portID, port); + (*env)->SetIntField(env, dpObj, dp_lengthID, rv); + } + + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return port; +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketSend + * Signature: (I[BIILjava/net/InetAddress;IZ)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSend + (JNIEnv *env, jclass clazz, jint fd, jbyteArray data, jint offset, jint length, + jobject iaObj, jint port, jboolean connected) { + SOCKETADDRESS sa; + int sa_len = sizeof(sa); + SOCKETADDRESS *sap = &sa; + char BUF[MAX_BUFFER_LEN]; + char *fullPacket; + int rv; + + if (connected) { + sap = 0; /* arg to JVM_Sendto () null in this case */ + sa_len = 0; + } else { + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + &sa_len, JNI_TRUE) != 0) { + return; + } + } + + if (length > MAX_BUFFER_LEN) { + /* Note: the buffer needn't be greater than 65,536 (0xFFFF) + * the max size of an IP packet. Anything bigger is truncated anyway. + */ + if (length > MAX_PACKET_LEN) { + length = MAX_PACKET_LEN; + } + fullPacket = (char *)malloc(length); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + + (*env)->GetByteArrayRegion(env, data, offset, length, + (jbyte *)fullPacket); + rv = sendto(fd, fullPacket, length, 0, (struct sockaddr *)sap, sa_len); + if (rv == SOCKET_ERROR) { + if (rv == JVM_IO_ERR) { + NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed"); + } else if (rv == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + } + + if (length > MAX_BUFFER_LEN) { + free(fullPacket); + } +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketSetIntOption + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketSetIntOption + (JNIEnv *env, jclass clazz, jint fd , jint cmd, jint value) { + int level, opt; + + if (NET_MapSocketOption(cmd, &level, &opt) < 0) { + JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Invalid option"); + return; + } + + if (NET_SetSockOpt(fd, level, opt, (char *)&value, sizeof(value)) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "setsockopt"); + } +} + +/* + * Class: java_net_DualStackPlainDatagramSocketImpl + * Method: socketGetIntOption + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketGetIntOption + (JNIEnv *env, jclass clazz, jint fd, jint cmd) { + int level, opt, result=0; + int result_len = sizeof(result); + + if (NET_MapSocketOption(cmd, &level, &opt) < 0) { + JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Invalid option"); + return -1; + } + + if (NET_GetSockOpt(fd, level, opt, (void *)&result, &result_len) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); + return -1; + } + + return result; +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/DualStackPlainSocketImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/native/java/net/DualStackPlainSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,479 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +#include +#include +#include "jni.h" +#include "net_util.h" +#include "java_net_DualStackPlainSocketImpl.h" + +#define SET_BLOCKING 0 +#define SET_NONBLOCKING 1 + +static jclass isa_class; /* java.net.InetSocketAddress */ +static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */ + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: initIDs + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs + (JNIEnv *env, jclass clazz) { + + jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress"); + isa_class = (*env)->NewGlobalRef(env, cls); + isa_ctorID = (*env)->GetMethodID(env, cls, "", + "(Ljava/net/InetAddress;I)V"); + + // implement read timeout with select. + isRcvTimeoutSupported = 0; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: socket0 + * Signature: (ZZ)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0 + (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) { + int fd, rv, opt=0; + + fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0); + if (fd == INVALID_SOCKET) { + NET_ThrowNew(env, WSAGetLastError(), "create"); + return -1; + } + + rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)); + if (rv == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "create"); + } + + SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + + return fd; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: bind0 + * Signature: (ILjava/net/InetAddress;I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0 + (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { + SOCKETADDRESS sa; + int rv; + int sa_len = sizeof(sa); + + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + &sa_len, JNI_TRUE) != 0) { + return; + } + + rv = NET_Bind(fd, (struct sockaddr *)&sa, sa_len); + + if (rv == SOCKET_ERROR) + NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind"); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: connect0 + * Signature: (ILjava/net/InetAddress;I)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0 + (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) { + SOCKETADDRESS sa; + int rv; + int sa_len = sizeof(sa); + + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&sa, + &sa_len, JNI_TRUE) != 0) { + return -1; + } + + rv = connect(fd, (struct sockaddr *)&sa, sa_len); + if (rv == SOCKET_ERROR) { + int err = WSAGetLastError(); + if (err == WSAEWOULDBLOCK) { + return java_net_DualStackPlainSocketImpl_WOULDBLOCK; + } else if (err == WSAEADDRNOTAVAIL) { + JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", + "connect: Address is invalid on local machine, or port is not valid on remote machine"); + } else { + NET_ThrowNew(env, err, "connect"); + } + return -1; // return value not important. + } + return rv; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: waitForConnect + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect + (JNIEnv *env, jclass clazz, jint fd, jint timeout) { + int rv, retry; + int optlen = sizeof(rv); + fd_set wr, ex; + struct timeval t; + + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(fd, &wr); + FD_SET(fd, &ex); + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + + /* + * Wait for timeout, connection established or + * connection failed. + */ + rv = select(fd+1, 0, &wr, &ex, &t); + + /* + * Timeout before connection is established/failed so + * we throw exception and shutdown input/output to prevent + * socket from being used. + * The socket should be closed immediately by the caller. + */ + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "connect timed out"); + shutdown( fd, SD_BOTH ); + return; + } + + /* + * Socket is writable or error occured. On some Windows editions + * the socket will appear writable when the connect fails so we + * check for error rather than writable. + */ + if (!FD_ISSET(fd, &ex)) { + return; /* connection established */ + } + + /* + * Connection failed. The logic here is designed to work around + * bug on Windows NT whereby using getsockopt to obtain the + * last error (SO_ERROR) indicates there is no error. The workaround + * on NT is to allow winsock to be scheduled and this is done by + * yielding and retrying. As yielding is problematic in heavy + * load conditions we attempt up to 3 times to get the error reason. + */ + for (retry=0; retry<3; retry++) { + NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, + (char*)&rv, &optlen); + if (rv) { + break; + } + Sleep(0); + } + + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Unable to establish connection"); + } else { + NET_ThrowNew(env, rv, "connect"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: localPort0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0 + (JNIEnv *env, jclass clazz, jint fd) { + SOCKETADDRESS sa; + int len = sizeof(sa); + + if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else { + NET_ThrowNew(env, WSAGetLastError(), "getsockname failed"); + } + return -1; + } + return (int) ntohs((u_short)GET_PORT(&sa)); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: localAddress + * Signature: (ILjava/net/InetAddressContainer;)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress + (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) { + int port; + SOCKETADDRESS sa; + int len = sizeof(sa); + jobject iaObj; + jclass iaContainerClass; + jfieldID iaFieldID; + + if (getsockname(fd, (struct sockaddr *)&sa, &len) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); + return; + } + iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + CHECK_NULL(iaObj); + + iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj); + iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;"); + CHECK_NULL(iaFieldID); + (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: listen0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0 + (JNIEnv *env, jclass clazz, jint fd, jint backlog) { + if (listen(fd, backlog) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "listen failed"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: accept0 + * Signature: (I[Ljava/net/InetSocketAddress;)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0 + (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) { + int newfd, port=0; + jobject isa; + jobject ia; + SOCKETADDRESS sa; + int len = sizeof(sa); + + memset((char *)&sa, 0, len); + newfd = accept(fd, (struct sockaddr *)&sa, &len); + + if (newfd == INVALID_SOCKET) { + if (WSAGetLastError() == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + } + return -1; + } + + ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port); + isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port); + (*env)->SetObjectArrayElement(env, isaa, 0, isa); + + return newfd; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: waitForNewConnection + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnection + (JNIEnv *env, jclass clazz, jint fd, jint timeout) { + int rv; + + rv = NET_Timeout(fd, timeout); + if (rv == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Accept timed out"); + } else if (rv == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + } else if (rv == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: available0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0 + (JNIEnv *env, jclass clazz, jint fd) { + jint available = -1; + + if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "socket available"); + } + + return available; +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: close0 + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0 + (JNIEnv *env, jclass clazz, jint fd) { + NET_SocketClose(fd); +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: shutdown0 + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0 + (JNIEnv *env, jclass clazz, jint fd, jint howto) { + shutdown(fd, howto); +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: setIntOption + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_setIntOption + (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value) { + + int level, opt; + struct linger linger; + char *parg; + int arglen; + + if (NET_MapSocketOption(cmd, &level, &opt) < 0) { + JNU_ThrowByNameWithLastError(env, + JNU_JAVANETPKG "SocketException", + "Invalid option"); + return; + } + + if (opt == java_net_SocketOptions_SO_LINGER) { + parg = (char *)&linger; + arglen = sizeof(linger); + if (value >= 0) { + linger.l_onoff = 1; + linger.l_linger = (unsigned short)value; + } else { + linger.l_onoff = 0; + linger.l_linger = 0; + } + } else { + parg = (char *)&value; + arglen = sizeof(value); + } + + if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "setsockopt"); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: getIntOption + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption + (JNIEnv *env, jclass clazz, jint fd, jint cmd) { + + int level, opt; + int result=0; + struct linger linger; + char *arg; + int arglen; + + if (NET_MapSocketOption(cmd, &level, &opt) < 0) { + JNU_ThrowByNameWithLastError(env, + JNU_JAVANETPKG "SocketException", + "Unsupported socket option"); + return -1; + } + + if (opt == java_net_SocketOptions_SO_LINGER) { + arg = (char *)&linger; + arglen = sizeof(linger); + } else { + arg = (char *)&result; + arglen = sizeof(result); + } + + if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); + return -1; + } + + if (opt == java_net_SocketOptions_SO_LINGER) + return linger.l_onoff ? linger.l_linger : -1; + else + return result; +} + + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: sendOOB + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB + (JNIEnv *env, jclass clazz, jint fd, jint data) { + jint n; + unsigned char d = (unsigned char) data & 0xff; + + n = send(fd, (char *)&data, 1, MSG_OOB); + if (n == JVM_IO_ERR) { + NET_ThrowNew(env, WSAGetLastError(), "send"); + } else if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); + } +} + +/* + * Class: java_net_DualStackPlainSocketImpl + * Method: configureBlocking + * Signature: (IZ)V + */ +JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking + (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) { + u_long arg; + int result; + + if (blocking == JNI_TRUE) { + arg = SET_BLOCKING; // 0 + } else { + arg = SET_NONBLOCKING; // 1 + } + + result = ioctlsocket(fd, FIONBIO, &arg); + if (result == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "configureBlocking"); + } +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/PlainDatagramSocketImpl.c --- a/j2se/src/windows/native/java/net/PlainDatagramSocketImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2524 +0,0 @@ -/* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef IPTOS_TOS_MASK -#define IPTOS_TOS_MASK 0x1e -#endif -#ifndef IPTOS_PREC_MASK -#define IPTOS_PREC_MASK 0xe0 -#endif - -#include "java_net_PlainDatagramSocketImpl.h" -#include "java_net_SocketOptions.h" -#include "java_net_NetworkInterface.h" - -#include "jvm.h" -#include "jni_util.h" -#include "net_util.h" - -#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) -#define IN_MULTICAST(i) IN_CLASSD(i) - -/************************************************************************ - * PlainDatagramSocketImpl - */ - -static jfieldID IO_fd_fdID; -static jfieldID pdsi_trafficClassID; -jfieldID pdsi_fdID; -jfieldID pdsi_fd1ID; -jfieldID pdsi_fduseID; -jfieldID pdsi_lastfdID; -jfieldID pdsi_timeoutID; - -jfieldID pdsi_localPortID; -jfieldID pdsi_connected; - -static jclass ia4_clazz; -static jmethodID ia4_ctor; - -static CRITICAL_SECTION sizeCheckLock; - -/* Windows OS version is XP or better */ -static int xp_or_later = 0; -/* Windows OS version is Windows 2000 or better */ -static int w2k_or_later = 0; - -/* - * Notes about UDP/IPV6 on Windows (XP and 2003 server): - * - * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd. - * Both fds are used when we bind to a wild-card address. When a specific - * address is used, only one of them is used. - */ - -/* - * Returns a java.lang.Integer based on 'i' - */ -jobject createInteger(JNIEnv *env, int i) { - static jclass i_class; - static jmethodID i_ctrID; - static jfieldID i_valueID; - - if (i_class == NULL) { - jclass c = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL_RETURN(c, NULL); - i_ctrID = (*env)->GetMethodID(env, c, "", "(I)V"); - CHECK_NULL_RETURN(i_ctrID, NULL); - i_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(i_class, NULL); - } - - return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); -} - -/* - * Returns a java.lang.Boolean based on 'b' - */ -jobject createBoolean(JNIEnv *env, int b) { - static jclass b_class; - static jmethodID b_ctrID; - static jfieldID b_valueID; - - if (b_class == NULL) { - jclass c = (*env)->FindClass(env, "java/lang/Boolean"); - CHECK_NULL_RETURN(c, NULL); - b_ctrID = (*env)->GetMethodID(env, c, "", "(Z)V"); - CHECK_NULL_RETURN(b_ctrID, NULL); - b_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(b_class, NULL); - } - - return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); -} - - -static int getFD(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - - if (fdObj == NULL) { - return -1; - } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); -} - -static int getFD1(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - - if (fdObj == NULL) { - return -1; - } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); -} - -/* - * This function returns JNI_TRUE if the datagram size exceeds the underlying - * provider's ability to send to the target address. The following OS - * oddies have been observed :- - * - * 1. On Windows 95/98 if we try to send a datagram > 12k to an application - * on the same machine then the send will fail silently. - * - * 2. On Windows ME if we try to send a datagram > supported by underlying - * provider then send will not return an error. - * - * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail - * with WSAEADDRNOTAVAIL. - * - * 4. On Windows 95/98 if we exceed the maximum size when sending to - * another machine then WSAEINVAL is returned. - * - */ -jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) -{ -#define DEFAULT_MSG_SIZE 65527 - static jboolean initDone; - static jboolean is95or98; - static int maxmsg; - - typedef struct _netaddr { /* Windows 95/98 only */ - unsigned long addr; - struct _netaddr *next; - } netaddr; - static netaddr *addrList; - netaddr *curr; - - /* - * First time we are called we must determine which OS this is and also - * get the maximum size supported by the underlying provider. - * - * In addition on 95/98 we must enumerate our IP addresses. - */ - if (!initDone) { - EnterCriticalSection(&sizeCheckLock); - - if (initDone) { - /* another thread got there first */ - LeaveCriticalSection(&sizeCheckLock); - - } else { - OSVERSIONINFO ver; - int len; - - /* - * Step 1: Determine which OS this is. - */ - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - - is95or98 = JNI_FALSE; - if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && - ver.dwMajorVersion == 4 && - (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) { - - is95or98 = JNI_TRUE; - } - - /* - * Step 2: Determine the maximum datagram supported by the - * underlying provider. On Windows 95 if winsock hasn't been - * upgraded (ie: unsupported configuration) then we assume - * the default 64k limit. - */ - len = sizeof(maxmsg); - if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) { - maxmsg = DEFAULT_MSG_SIZE; - } - - /* - * Step 3: On Windows 95/98 then enumerate the IP addresses on - * this machine. This is necesary because we need to check if the - * datagram is being sent to an application on the same machine. - */ - if (is95or98) { - char hostname[255]; - struct hostent *hp; - - if (gethostname(hostname, sizeof(hostname)) == -1) { - LeaveCriticalSection(&sizeCheckLock); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname"); - return JNI_TRUE; - } - hp = (struct hostent *)gethostbyname(hostname); - if (hp != NULL) { - struct in_addr **addrp = (struct in_addr **) hp->h_addr_list; - - while (*addrp != (struct in_addr *) 0) { - curr = (netaddr *)malloc(sizeof(netaddr)); - if (curr == NULL) { - while (addrList != NULL) { - curr = addrList->next; - free(addrList); - addrList = curr; - } - LeaveCriticalSection(&sizeCheckLock); - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return JNI_TRUE; - } - curr->addr = htonl((*addrp)->S_un.S_addr); - curr->next = addrList; - addrList = curr; - addrp++; - } - } - } - - /* - * Step 4: initialization is done so set flag and unlock cs - */ - initDone = JNI_TRUE; - LeaveCriticalSection(&sizeCheckLock); - } - } - - /* - * Now examine the size of the datagram :- - * - * (a) If exceeds size of service provider return 'false' to indicate that - * we exceed the limit. - * (b) If not 95/98 then return 'true' to indicate that the size is okay. - * (c) On 95/98 if the size is <12k we are okay. - * (d) On 95/98 if size > 12k then check if the destination is the current - * machine. - */ - if (size > maxmsg) { /* step (a) */ - return JNI_TRUE; - } - if (!is95or98) { /* step (b) */ - return JNI_FALSE; - } - if (size <= 12280) { /* step (c) */ - return JNI_FALSE; - } - - /* step (d) */ - - if ((addr & 0x7f000000) == 0x7f000000) { - return JNI_TRUE; - } - curr = addrList; - while (curr != NULL) { - if (curr->addr == addr) { - return JNI_TRUE; - } - curr = curr->next; - } - return JNI_FALSE; -} - -/* - * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable - */ -__inline static jboolean supportPortUnreachable() { - static jboolean initDone; - static jboolean portUnreachableSupported; - - if (!initDone) { - OSVERSIONINFO ver; - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) { - portUnreachableSupported = JNI_TRUE; - } else { - portUnreachableSupported = JNI_FALSE; - } - initDone = JNI_TRUE; - } - return portUnreachableSupported; -} - -/* - * This function "purges" all outstanding ICMP port unreachable packets - * outstanding on a socket and returns JNI_TRUE if any ICMP messages - * have been purged. The rational for purging is to emulate normal BSD - * behaviour whereby receiving a "connection reset" status resets the - * socket. - */ -static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) -{ - jboolean got_icmp = JNI_FALSE; - char buf[1]; - fd_set tbl; - struct timeval t = { 0, 0 }; - struct sockaddr_in rmtaddr; - int addrlen = sizeof(rmtaddr); - - /* - * A no-op if this OS doesn't support it. - */ - if (!supportPortUnreachable()) { - return JNI_FALSE; - } - - /* - * Peek at the queue to see if there is an ICMP port unreachable. If there - * is then receive it. - */ - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - while(1) { - if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) { - break; - } - if (recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) { - break; - } - if (WSAGetLastError() != WSAECONNRESET) { - /* some other error - we don't care here */ - break; - } - - recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); - got_icmp = JNI_TRUE; - } - - return got_icmp; -} - - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: init - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { - - OSVERSIONINFO ver; - int version; - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - - version = ver.dwMajorVersion * 10 + ver.dwMinorVersion; - xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51); - w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50); - - /* get fieldIDs */ - pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); - CHECK_NULL(pdsi_fdID); - pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;"); - CHECK_NULL(pdsi_fd1ID); - pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); - CHECK_NULL(pdsi_timeoutID); - pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I"); - CHECK_NULL(pdsi_fduseID); - pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(pdsi_lastfdID); - pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); - CHECK_NULL(pdsi_trafficClassID); - pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I"); - CHECK_NULL(pdsi_localPortID); - pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z"); - CHECK_NULL(pdsi_connected); - - cls = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(cls); - IO_fd_fdID = NET_GetFileDescriptorID(env); - CHECK_NULL(IO_fd_fdID); - - ia4_clazz = (*env)->FindClass(env, "java/net/Inet4Address"); - CHECK_NULL(ia4_clazz); - ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz); - CHECK_NULL(ia4_clazz); - ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "", "()V"); - CHECK_NULL(ia4_ctor); - - - InitializeCriticalSection(&sizeCheckLock); -} - -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, - jint port, jobject addressObj) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - - int fd, fd1, family; - int ipv6_supported = ipv6_available(); - - SOCKETADDRESS lcladdr; - int lcladdrlen; - int address; - - family = (*env)->GetIntField(env, addressObj, ia_familyID); - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Protocol family not supported"); - return; - } - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (ipv6_supported) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - } - if (IS_NULL(addressObj)) { - JNU_ThrowNullPointerException(env, "argument address"); - return; - } else { - address = (*env)->GetIntField(env, addressObj, ia_addressID); - } - - if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen) != 0) { - return; - } - - if (ipv6_supported) { - struct ipv6bind v6bind; - v6bind.addr = &lcladdr; - v6bind.ipv4_fd = fd; - v6bind.ipv6_fd = fd1; - if (NET_BindV6(&v6bind) != -1) { - /* check if the fds have changed */ - if (v6bind.ipv4_fd != fd) { - fd = v6bind.ipv4_fd; - if (fd == -1) { - /* socket is closed. */ - (*env)->SetObjectField(env, this, pdsi_fdID, NULL); - } else { - /* socket was re-created */ - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); - } - } - if (v6bind.ipv6_fd != fd1) { - fd1 = v6bind.ipv6_fd; - if (fd1 == -1) { - /* socket is closed. */ - (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); - } else { - /* socket was re-created */ - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); - } - } - } else { - NET_ThrowCurrent (env, "Cannot bind"); - return; - } - } else { - if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) { - if (WSAGetLastError() == WSAEACCES) { - WSASetLastError(WSAEADDRINUSE); - } - NET_ThrowCurrent(env, "Cannot bind"); - return; - } - } - - if (port == 0) { - if (fd == -1) { - /* must be an IPV6 only socket. */ - fd = fd1; - } - if (getsockname(fd, (struct sockaddr *)&lcladdr, &lcladdrlen) == -1) { - NET_ThrowCurrent(env, "JVM_GetSockName"); - return; - } - port = ntohs((u_short) GET_PORT (&lcladdr)); - } - (*env)->SetIntField(env, this, pdsi_localPortID, port); -} - - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: connect0 - * Signature: (Ljava/net/InetAddress;I)V - */ - -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this, - jobject address, jint port) { - /* The object's field */ - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - /* The fdObj'fd */ - jint fd=-1, fd1=-1, fdc; - /* The packetAddress address, family and port */ - jint addr, family; - SOCKETADDRESS rmtaddr; - int rmtaddrlen; - int ipv6_supported = ipv6_available(); - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - - if (IS_NULL(address)) { - JNU_ThrowNullPointerException(env, "address"); - return; - } - - addr = (*env)->GetIntField(env, address, ia_addressID); - - family = (*env)->GetIntField(env, address, ia_familyID); - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Protocol family not supported"); - return; - } - - fdc = family == IPv4? fd: fd1; - - if (xp_or_later) { - /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which - * returns connection reset errors un connected UDP sockets (as well - * as connected sockets. The solution is to only enable this feature - * when the socket is connected - */ - DWORD x1, x2; /* ignored result codes */ - int res, t = TRUE; - res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - } - - if (NET_InetAddressToSockaddr(env, address, port,(struct sockaddr *)&rmtaddr, &rmtaddrlen) != 0) { - return; - } - - if (connect(fdc, (struct sockaddr *)&rmtaddr, sizeof(rmtaddr)) == -1) { - NET_ThrowCurrent(env, "connect"); - return; - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: disconnect0 - * Signature: ()V - */ - -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jint family) { - /* The object's field */ - jobject fdObj; - /* The fdObj'fd */ - jint fd, len; - SOCKETADDRESS addr; - - if (family == IPv4) { - fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - len = sizeof (struct sockaddr_in); - } else { - fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - len = sizeof (struct SOCKADDR_IN6); - } - - if (IS_NULL(fdObj)) { - /* disconnect doesn't throw any exceptions */ - return; - } - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - - memset(&addr, 0, len); - connect(fd, (struct sockaddr *)&addr, len); - - /* - * use SIO_UDP_CONNRESET - * to disable ICMP port unreachable handling here. - */ - if (xp_or_later) { - DWORD x1, x2; /* ignored result codes */ - int t = FALSE; - WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: send - * Signature: (Ljava/net/DatagramPacket;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this, - jobject packet) { - - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj; - jint fd; - - jobject iaObj; - jint address; - jint family; - - jint packetBufferOffset, packetBufferLen, packetPort; - jbyteArray packetBuffer; - jboolean connected; - - SOCKETADDRESS rmtaddr; - SOCKETADDRESS *addrp = &rmtaddr; - int addrlen; - int x; /* DELETE ME */ - - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "null packet"); - return; - } - - iaObj = (*env)->GetObjectField(env, packet, dp_addressID); - - packetPort = (*env)->GetIntField(env, packet, dp_portID); - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBuffer = (jbyteArray)(*env)->GetObjectField(env, packet, dp_bufID); - connected = (*env)->GetBooleanField(env, this, pdsi_connected); - - if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "null address || null buffer"); - return; - } - - family = (*env)->GetIntField(env, iaObj, ia_familyID); - if (family == IPv4) { - fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - } else { - if (!ipv6_available()) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Protocol not allowed"); - return; - } - fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - } - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - - packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID); - - if (connected) { - addrp = 0; /* arg to JVM_Sendto () null in this case */ - addrlen = 0; - } else { - if (NET_InetAddressToSockaddr(env, iaObj, packetPort, (struct sockaddr *)&rmtaddr, &addrlen) != 0) { - return; - } - } - - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* - * On 95/98 if we try to send a datagram >12k to an application - * on the same machine then this will fail silently. Thus we - * catch this situation here so that we can throw an exception - * when this arises. - * On ME if we try to send a datagram with a size greater than - * that supported by the service provider then no error is - * returned. - */ - if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6. - * Check is not necessary on these OSes */ - if (connected) { - address = (*env)->GetIntField(env, iaObj, ia_addressID); - } else { - address = ntohl(rmtaddr.him4.sin_addr.s_addr); - } - - if (exceedSizeLimit(env, fd, address, packetBufferLen)) { - if (!((*env)->ExceptionOccurred(env))) { - NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed"); - } - return; - } - } - - /* When JNI-ifying the JDK's IO routines, we turned - * read's and write's of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - */ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return; - } - } else { - fullPacket = &(BUF[0]); - } - - (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen, - (jbyte *)fullPacket); - switch (sendto(fd, fullPacket, packetBufferLen, 0, - (struct sockaddr *)addrp, addrlen)) { - case JVM_IO_ERR: - NET_ThrowCurrent(env, "Datagram send failed"); - break; - - case JVM_IO_INTR: - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } -} - -/* - * check which socket was last serviced when there was data on both sockets. - * Only call this if sure that there is data on both sockets. - */ -static int checkLastFD (JNIEnv *env, jobject this, int fd, int fd1) { - int nextfd, lastfd = (*env)->GetIntField(env, this, pdsi_lastfdID); - if (lastfd == -1) { - /* arbitrary. Choose fd */ - (*env)->SetIntField(env, this, pdsi_lastfdID, fd); - return fd; - } else { - if (lastfd == fd) { - nextfd = fd1; - } else { - nextfd = fd; - } - (*env)->SetIntField(env, this, pdsi_lastfdID, nextfd); - return nextfd; - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: peek - * Signature: (Ljava/net/InetAddress;)I - */ -JNIEXPORT jint JNICALL -Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, - jobject addressObj) { - - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); - jint fd; - - /* The address and family fields of addressObj */ - jint address, family; - - int n; - struct sockaddr_in remote_addr; - jint remote_addrsize = sizeof (remote_addr); - char buf[1]; - BOOL retry; - jlong prevTime = 0; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - return -1; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - return -1; - } - } - if (IS_NULL(addressObj)) { - JNU_ThrowNullPointerException(env, "Null address in peek()"); - } else { - address = (*env)->GetIntField(env, addressObj, ia_addressID); - /* We only handle IPv4 for now. Will support IPv6 once its in the os */ - family = AF_INET; - } - - do { - retry = FALSE; - - /* - * If a timeout has been specified then we select on the socket - * waiting for a read event or a timeout. - */ - if (timeout) { - int ret; - prevTime = JVM_CurrentTimeMillis(env, 0); - ret = NET_Timeout (fd, timeout); - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Peek timed out"); - return ret; - } else if (ret == JVM_IO_ERR) { - NET_ThrowCurrent(env, "timeout in datagram socket peek"); - return ret; - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - return ret; - } - } - - /* now try the peek */ - n = recvfrom(fd, buf, 1, MSG_PEEK, - (struct sockaddr *)&remote_addr, &remote_addrsize); - - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - jboolean connected; - - /* - * An icmp port unreachable - we must receive this as Windows - * does not reset the state of the socket until this has been - * received. - */ - purgeOutstandingICMP(env, this, fd); - - connected = (*env)->GetBooleanField(env, this, pdsi_connected); - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", - "ICMP Port Unreachable"); - return 0; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout befor the icmp port - * unreachable arrived. - */ - if (timeout) { - jlong newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - return 0; - } - prevTime = newTime; - } - - /* Need to retry the recv */ - retry = TRUE; - } - } - } while (retry); - - if (n == JVM_IO_ERR && WSAGetLastError() != WSAEMSGSIZE) { - NET_ThrowCurrent(env, "Datagram peek failed"); - return 0; - } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", 0); - return 0; - } - (*env)->SetIntField(env, addressObj, ia_addressID, - ntohl(remote_addr.sin_addr.s_addr)); - (*env)->SetIntField(env, addressObj, ia_familyID, IPv4); - - /* return port */ - return ntohs(remote_addr.sin_port); -} - -JNIEXPORT jint JNICALL -Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this, - jobject packet) { - - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); - - jbyteArray packetBuffer; - jint packetBufferOffset, packetBufferLen; - - int fd, fd1, fduse, nsockets=0, errorCode; - int port; - jbyteArray data; - - int checkBoth = 0, datalen; - int n; - SOCKETADDRESS remote_addr; - jint remote_addrsize=sizeof(remote_addr); - BOOL retry; - jlong prevTime = 0; - - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - return -1; - } - nsockets = 1; - } - - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - if (fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - return -1; - } - nsockets ++; - } - - switch (nsockets) { - case 0: - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - return -1; - case 1: - if (!IS_NULL(fdObj)) { - fduse = fd; - } else { - fduse = fd1; - } - break; - case 2: - checkBoth = TRUE; - break; - } - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "packet"); - return -1; - } - - packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); - - if (IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "packet buffer"); - return -1; - } - - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); - - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* When JNI-ifying the JDK's IO routines, we turned - * read's and write's of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - */ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return -1; - } - } else { - fullPacket = &(BUF[0]); - } - - do { - int ret; - retry = FALSE; - - /* - * If a timeout has been specified then we select on the socket - * waiting for a read event or a timeout. - */ - if (checkBoth) { - int t = timeout == 0 ? -1: timeout; - prevTime = JVM_CurrentTimeMillis(env, 0); - ret = NET_Timeout2 (fd, fd1, t, &fduse); - /* all subsequent calls to recv() or select() will use the same fd - * for this call to peek() */ - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", - "Peek timed out"); - } else if (ret == JVM_IO_ERR) { - NET_ThrowCurrent(env, "timeout in datagram socket peek"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return -1; - } - if (ret == 2) { - fduse = checkLastFD (env, this, fd, fd1); - } - checkBoth = FALSE; - } else if (timeout) { - if (prevTime == 0) { - prevTime = JVM_CurrentTimeMillis(env, 0); - } - ret = NET_Timeout (fduse, timeout); - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return -1; - } - } - - /* receive the packet */ - n = recvfrom(fduse, fullPacket, packetBufferLen, MSG_PEEK, - (struct sockaddr *)&remote_addr, &remote_addrsize); - port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&remote_addr)); - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - jboolean connected; - - /* - * An icmp port unreachable - we must receive this as Windows - * does not reset the state of the socket until this has been - * received. - */ - purgeOutstandingICMP(env, this, fduse); - - connected = (*env)->GetBooleanField(env, this, pdsi_connected); - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", - "ICMP Port Unreachable"); - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return -1; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout befor the icmp port - * unreachable arrived. - */ - if (timeout) { - jlong newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return -1; - } - prevTime = newTime; - } - retry = TRUE; - } - } - } while (retry); - - /* truncate the data if the packet's length is too small */ - if (n > packetBufferLen) { - n = packetBufferLen; - } - if (n < 0) { - errorCode = WSAGetLastError(); - /* check to see if it's because the buffer was too small */ - if (errorCode == WSAEMSGSIZE) { - /* it is because the buffer is too small. It's UDP, it's - * unreliable, it's all good. discard the rest of the - * data.. - */ - n = packetBufferLen; - } else { - /* failure */ - (*env)->SetIntField(env, packet, dp_lengthID, 0); - } - } - if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); - } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } else if (n < 0) { - NET_ThrowCurrent(env, "Datagram receive failed"); - } else { - jobject packetAddress; - - /* - * Check if there is an InetAddress already associated with this - * packet. If so we check if it is the same source address. We - * can't update any existing InetAddress because it is immutable - */ - packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); - if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *) - &remote_addr, packetAddress)) { - /* force a new InetAddress to be created */ - packetAddress = NULL; - } - } - if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *) - &remote_addr, &port); - /* stuff the new Inetaddress in the packet */ - (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); - } - - /* populate the packet */ - (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, - (jbyte *)fullPacket); - (*env)->SetIntField(env, packet, dp_portID, port); - (*env)->SetIntField(env, packet, dp_lengthID, n); - } - - /* make sure receive() picks up the right fd */ - (*env)->SetIntField(env, this, pdsi_fduseID, fduse); - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return port; -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: receive - * Signature: (Ljava/net/DatagramPacket;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this, - jobject packet) { - - char BUF[MAX_BUFFER_LEN]; - char *fullPacket; - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); - jbyteArray packetBuffer; - jint packetBufferOffset, packetBufferLen; - int ipv6_supported = ipv6_available(); - - /* as a result of the changes for ipv6, peek() or peekData() - * must be called prior to receive() so that fduse can be set. - */ - int fd, fd1, fduse, errorCode; - jbyteArray data; - - int datalen; - int n, nsockets=0; - SOCKETADDRESS remote_addr; - jint remote_addrsize=sizeof(remote_addr); - BOOL retry; - jlong prevTime = 0, selectTime=0; - jboolean connected; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } - - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - nsockets ++; - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - nsockets ++; - } - - if (nsockets == 2) { /* need to choose one of them */ - /* was fduse set in peek? */ - fduse = (*env)->GetIntField(env, this, pdsi_fduseID); - if (fduse == -1) { - /* not set in peek(), must select on both sockets */ - int ret, t = (timeout == 0) ? -1: timeout; - ret = NET_Timeout2 (fd, fd1, t, &fduse); - if (ret == 2) { - fduse = checkLastFD (env, this, fd, fd1); - } else if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - return; - } - } - } else if (!ipv6_supported) { - fduse = fd; - } else if (IS_NULL(fdObj)) { - /* ipv6 supported: and this socket bound to an IPV6 only address */ - fduse = fd1; - } else { - /* ipv6 supported: and this socket bound to an IPV4 only address */ - fduse = fd; - } - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "packet"); - return; - } - - packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); - - if (IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "packet buffer"); - return; - } - - packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); - packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); - - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* When JNI-ifying the JDK's IO routines, we turned - * read's and write's of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - */ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return; - } - } else { - fullPacket = &(BUF[0]); - } - - - - /* - * If this Windows edition supports ICMP port unreachable and if we - * are not connected then we need to know if a timeout has been specified - * and if so we need to pick up the current time. These are required in - * order to implement the semantics of timeout, viz :- - * timeout set to t1 but ICMP port unreachable arrives in t2 where - * t2 < t1. In this case we must discard the ICMP packets and then - * wait for the next packet up to a maximum of t1 minus t2. - */ - connected = (*env)->GetBooleanField(env, this, pdsi_connected); - if (supportPortUnreachable() && !connected && timeout &&!ipv6_supported) { - prevTime = JVM_CurrentTimeMillis(env, 0); - } - - if (timeout && nsockets == 1) { - int ret; - ret = NET_Timeout(fduse, timeout); - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return; - } - } - - /* - * Loop only if we discarding ICMP port unreachable packets - */ - do { - retry = FALSE; - - /* receive the packet */ - n = recvfrom(fduse, fullPacket, packetBufferLen, 0, - (struct sockaddr *)&remote_addr, &remote_addrsize); - - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - /* - * An icmp port unreachable has been received - consume any other - * outstanding packets. - */ - purgeOutstandingICMP(env, this, fduse); - - /* - * If connected throw a PortUnreachableException - */ - - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", - "ICMP Port Unreachable"); - - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - - return; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout before the icmp port - * unreachable arrived. - */ - if (timeout) { - int ret; - jlong newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - prevTime = newTime; - - if (timeout <= 0) { - ret = 0; - } else { - ret = NET_Timeout(fduse, timeout); - } - - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } - return; - } - } - - /* - * An ICMP port unreachable was received but we are - * not connected so ignore it. - */ - retry = TRUE; - } - } - } while (retry); - - /* truncate the data if the packet's length is too small */ - if (n > packetBufferLen) { - n = packetBufferLen; - } - if (n < 0) { - errorCode = WSAGetLastError(); - /* check to see if it's because the buffer was too small */ - if (errorCode == WSAEMSGSIZE) { - /* it is because the buffer is too small. It's UDP, it's - * unreliable, it's all good. discard the rest of the - * data.. - */ - n = packetBufferLen; - } else { - /* failure */ - (*env)->SetIntField(env, packet, dp_lengthID, 0); - } - } - if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); - } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } else if (n < 0) { - NET_ThrowCurrent(env, "Datagram receive failed"); - } else { - int port; - jobject packetAddress; - - /* - * Check if there is an InetAddress already associated with this - * packet. If so we check if it is the same source address. We - * can't update any existing InetAddress because it is immutable - */ - packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); - - if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) { - /* force a new InetAddress to be created */ - packetAddress = NULL; - } - } - if (packetAddress == NULL) { - packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port); - /* stuff the new Inetaddress in the packet */ - (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); - } else { - /* only get the new port number */ - port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr); - } - /* populate the packet */ - (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, - (jbyte *)fullPacket); - (*env)->SetIntField(env, packet, dp_portID, port); - (*env)->SetIntField(env, packet, dp_lengthID, n); - } - if (packetBufferLen > MAX_BUFFER_LEN) { - free(fullPacket); - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: datagramSocketCreate - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, - jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - - int fd, fd1; - int t = TRUE; - DWORD x1, x2; /* ignored result codes */ - int ipv6_supported = ipv6_available(); - - int arg = -1; - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - return; - } else { - fd = (int) socket (AF_INET, SOCK_DGRAM, 0); - } - if (fd == JVM_IO_ERR) { - NET_ThrowCurrent(env, "Socket creation failed"); - return; - } - SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); - NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); - - if (ipv6_supported) { - /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which - * returns connection reset errors un connected UDP sockets (as well - * as connected sockets. The solution is to only enable this feature - * when the socket is connected - */ - t = FALSE; - WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - t = TRUE; - fd1 = socket (AF_INET6, SOCK_DGRAM, 0); - if (fd1 == JVM_IO_ERR) { - NET_ThrowCurrent(env, "Socket creation failed"); - return; - } - NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); - t = FALSE; - WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); - SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE); - } else { - /* drop the second fd */ - (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: datagramSocketClose - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env, - jobject this) { - /* - * REMIND: PUT A LOCK AROUND THIS CODE - */ - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int ipv6_supported = ipv6_available(); - int fd=-1, fd1=-1; - - if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { - return; - } - - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (fd != -1) { - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); - NET_SocketClose(fd); - } - } - - if (ipv6_supported && fd1Obj != NULL) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - if (fd1 == -1) { - return; - } - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); - NET_SocketClose(fd1); - } -} - -/* - * check the addresses attached to the NetworkInterface object - * and return the first one (of the requested family Ipv4 or Ipv6) - * in *iaddr - */ - -static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iaddr) -{ - jobjectArray addrArray; - static jfieldID ni_addrsID=0; - static jfieldID ia_familyID=0; - jsize len; - jobject addr; - int i; - - if (ni_addrsID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN (c, -1); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN (ni_addrsID, -1); - c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL_RETURN (c, -1); - ia_familyID = (*env)->GetFieldID(env, c, "family", "I"); - CHECK_NULL_RETURN (ia_familyID, -1); - } - - addrArray = (*env)->GetObjectField(env, nif, ni_addrsID); - len = (*env)->GetArrayLength(env, addrArray); - - /* - * Check that there is at least one address bound to this - * interface. - */ - if (len < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface"); - return -1; - } - for (i=0; iGetObjectArrayElement(env, addrArray, i); - fam = (*env)->GetIntField(env, addr, ia_familyID); - if (fam == family) { - *iaddr = addr; - return 0; - } - } - return -1; -} - -static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr) -{ - jobject addr; - static jfieldID ia_addressID; - - int ret = getInetAddrFromIf (env, IPv4, nif, &addr); - if (ret == -1) { - return -1; - } - - if (ia_addressID == 0) { - jclass c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL_RETURN (c, -1); - ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL_RETURN (ia_addressID, -1); - } - iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID)); - return 0; -} - -/* Get the multicasting index from the interface */ - -static int getIndexFromIf (JNIEnv *env, jobject nif) { - static jfieldID ni_indexID; - - if (ni_indexID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, -1); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, -1); - } - - return (*env)->GetIntField(env, nif, ni_indexID); -} - -/* - * Sets the multicast interface. - * - * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :- - * IPv4: set outgoing multicast interface using - * IPPROTO_IP/IP_MULTICAST_IF - * - * IPv6: Get the interface to which the - * InetAddress is bound - * and do same as SockOptions.IF_MULTICAST_IF2 - * - * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :- - * For each stack: - * IPv4: Obtain IP address bound to network interface - * (NetworkInterface.addres[0]) - * set outgoing multicast interface using - * IPPROTO_IP/IP_MULTICAST_IF - * - * IPv6: Obtain NetworkInterface.index - * Set outgoing multicast interface using - * IPPROTO_IPV6/IPV6_MULTICAST_IF - * - */ -static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, - jint opt, jobject value) -{ - int ipv6_supported = ipv6_available(); - - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - /* - * value is an InetAddress. - * On IPv4 system use IP_MULTICAST_IF socket option - * On IPv6 system get the NetworkInterface that this IP - * address is bound to and use the IPV6_MULTICAST_IF - * option instead of IP_MULTICAST_IF - */ - if (ipv6_supported) { - static jclass ni_class; - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL(c); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL(ni_class); - } - - value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); - if (value == NULL) { - if (!(*env)->ExceptionOccurred(env)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "bad argument for IP_MULTICAST_IF" - ": address not bound to any interface"); - } - return; - } - opt = java_net_SocketOptions_IP_MULTICAST_IF2; - } else { - static jfieldID ia_addressID; - struct in_addr in; - - if (ia_addressID == NULL) { - jclass c = (*env)->FindClass(env,"java/net/InetAddress"); - CHECK_NULL(c); - ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL(ia_addressID); - } - - in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID)); - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error setting socket option"); - } - return; - } - } - - if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - /* - * value is a NetworkInterface. - * On IPv6 system get the index of the interface and use the - * IPV6_MULTICAST_IF socket option - * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF - * option. For IPv6 both must be done. - */ - if (ipv6_supported) { - static jfieldID ni_indexID; - struct in_addr in; - int index; - - if (ni_indexID == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL(c); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL(ni_indexID); - } - index = (*env)->GetIntField(env, value, ni_indexID); - - if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (const char*)&index, sizeof(index)) < 0) { - if (errno == EINVAL && index > 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "IPV6_MULTICAST_IF failed (interface has IPv4 " - "address only?)"); - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error setting socket option"); - } - return; - } - - /* If there are any IPv4 addresses on this interface then - * repeat the operation on the IPv4 fd */ - - if (getInet4AddrFromIf (env, value, &in) < 0) { - return; - } - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error setting socket option"); - } - return; - } else { - struct in_addr in; - - if (getInet4AddrFromIf (env, value, &in) < 0) { - if ((*env)->ExceptionOccurred(env)) { - return; - } - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "no InetAddress instances of requested type"); - return; - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char*)&in, sizeof(in)) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error setting socket option"); - } - return; - } - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: socketSetOption - * Signature: (ILjava/lang/Object;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobject this, - jint opt,jobject value) { - - int fd=-1, fd1=-1; - int levelv4, levelv6, optnamev4, optnamev6, optlen; - union { - int i; - char c; - } optval; - int ipv6_supported = ipv6_available(); - - fd = getFD(env, this); - - if (ipv6_supported) { - fd1 = getFD1(env, this); - } - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); - return; - } - - if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || - (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - - setMulticastInterface(env, this, fd, fd1, opt, value); - return; - } - - /* - * Map the Java level socket option to the platform specific - * level(s) and option name(s). - */ - if (fd1 != -1) { - if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); - return; - } - } - if (fd != -1) { - if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); - return; - } - } - - switch (opt) { - case java_net_SocketOptions_SO_SNDBUF : - case java_net_SocketOptions_SO_RCVBUF : - case java_net_SocketOptions_IP_TOS : - { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - - optval.i = (*env)->GetIntField(env, value, fid); - optlen = sizeof(optval.i); - } - break; - - case java_net_SocketOptions_SO_REUSEADDR: - case java_net_SocketOptions_SO_BROADCAST: - case java_net_SocketOptions_IP_MULTICAST_LOOP: - { - jclass cls; - jfieldID fid; - jboolean on; - - cls = (*env)->FindClass(env, "java/lang/Boolean"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "Z"); - CHECK_NULL(fid); - - on = (*env)->GetBooleanField(env, value, fid); - optval.i = (on ? 1 : 0); - /* - * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather - * than enabling it. - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { - optval.i = !optval.i; - } - optlen = sizeof(optval.i); - } - break; - - default : - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket option not supported by PlainDatagramSocketImp"); - break; - - } - - if (fd1 != -1) { - if (NET_SetSockOpt(fd1, levelv6, optnamev6, (void *)&optval, optlen) < 0) { - NET_ThrowCurrent(env, "setsockopt IPv6"); - return; - } - } - if (fd != -1) { - if (NET_SetSockOpt(fd, levelv4, optnamev4, (void *)&optval, optlen) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - return; - } - } -} - -/* - * Return the multicast interface: - * - * SocketOptions.IP_MULTICAST_IF - * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF - * Create InetAddress - * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 - * kernel but struct in_addr on 2.4 kernel - * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or - * obtain from impl is Linux 2.2 kernel - * If index == 0 return InetAddress representing - * anyLocalAddress. - * If index > 0 query NetworkInterface by index - * and returns addrs[0] - * - * SocketOptions.IP_MULTICAST_IF2 - * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF - * Query NetworkInterface by IP address and - * return the NetworkInterface that the address - * is bound too. - * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF - * (except Linux .2 kernel) - * Query NetworkInterface by index and - * return NetworkInterface. - */ -jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint opt) { - jboolean isIPV4 = !ipv6_available() || fd1 == -1; - - /* - * IPv4 implementation - */ - if (isIPV4) { - static jclass inet4_class; - static jmethodID inet4_ctrID; - static jfieldID inet4_addrID; - - static jclass ni_class; - static jmethodID ni_ctrID; - static jfieldID ni_indexID; - static jfieldID ni_addrsID; - - jobjectArray addrArray; - jobject addr; - jobject ni; - - struct in_addr in; - struct in_addr *inP = ∈ - int len = sizeof(struct in_addr); - - if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (char *)inP, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error getting socket option"); - return NULL; - } - - /* - * Construct and populate an Inet4Address - */ - if (inet4_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); - CHECK_NULL_RETURN(c, NULL); - inet4_ctrID = (*env)->GetMethodID(env, c, "", "()V"); - CHECK_NULL_RETURN(inet4_ctrID, NULL); - inet4_addrID = (*env)->GetFieldID(env, c, "address", "I"); - CHECK_NULL_RETURN(inet4_addrID, NULL); - inet4_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(inet4_class, NULL); - } - addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); - CHECK_NULL_RETURN(addr, NULL); - - (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr)); - - /* - * For IP_MULTICAST_IF return InetAddress - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - return addr; - } - - /* - * For IP_MULTICAST_IF2 we get the NetworkInterface for - * this address and return it - */ - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, NULL); - ni_ctrID = (*env)->GetMethodID(env, c, "", "()V"); - CHECK_NULL_RETURN(ni_ctrID, NULL); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, NULL); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ni_addrsID, NULL); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(ni_class, NULL); - } - ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); - if (ni) { - return ni; - } - - /* - * The address doesn't appear to be bound at any known - * NetworkInterface. Therefore we construct a NetworkInterface - * with this address. - */ - ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); - CHECK_NULL_RETURN(ni, NULL); - - (*env)->SetIntField(env, ni, ni_indexID, -1); - addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); - CHECK_NULL_RETURN(addrArray, NULL); - (*env)->SetObjectArrayElement(env, addrArray, 0, addr); - (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); - return ni; - } - - - /* - * IPv6 implementation - */ - if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || - (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - - static jclass ni_class; - static jmethodID ni_ctrID; - static jfieldID ni_indexID; - static jfieldID ni_addrsID; - static jclass ia_class; - static jmethodID ia_anyLocalAddressID; - - int index; - int len = sizeof(index); - - jobjectArray addrArray; - jobject addr; - jobject ni; - - { - if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (char*)&index, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error getting socket option"); - return NULL; - } - } - - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, NULL); - ni_ctrID = (*env)->GetMethodID(env, c, "", "()V"); - CHECK_NULL_RETURN(ni_ctrID, NULL); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, NULL); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ni_addrsID, NULL); - - ia_class = (*env)->FindClass(env, "java/net/InetAddress"); - CHECK_NULL_RETURN(ia_class, NULL); - ia_class = (*env)->NewGlobalRef(env, ia_class); - CHECK_NULL_RETURN(ia_class, NULL); - ia_anyLocalAddressID = (*env)->GetStaticMethodID(env, - ia_class, - "anyLocalAddress", - "()Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(ni_class, NULL); - } - - /* - * If multicast to a specific interface then return the - * interface (for IF2) or the any address on that interface - * (for IF). - */ - if (index > 0) { - ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, - index); - if (ni == NULL) { - char errmsg[255]; - sprintf(errmsg, - "IPV6_MULTICAST_IF returned index to unrecognized interface: %d", - index); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); - return NULL; - } - - /* - * For IP_MULTICAST_IF2 return the NetworkInterface - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - return ni; - } - - /* - * For IP_MULTICAST_IF return addrs[0] - */ - addrArray = (*env)->GetObjectField(env, ni, ni_addrsID); - if ((*env)->GetArrayLength(env, addrArray) < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "IPV6_MULTICAST_IF returned interface without IP bindings"); - return NULL; - } - - addr = (*env)->GetObjectArrayElement(env, addrArray, 0); - return addr; - } - - /* - * Multicast to any address - return anyLocalAddress - * or a NetworkInterface with addrs[0] set to anyLocalAddress - */ - - addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID, - NULL); - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - return addr; - } - - ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); - CHECK_NULL_RETURN(ni, NULL); - (*env)->SetIntField(env, ni, ni_indexID, -1); - addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL); - CHECK_NULL_RETURN(addrArray, NULL); - (*env)->SetObjectArrayElement(env, addrArray, 0, addr); - (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); - return ni; - } - return NULL; -} -/* - * Returns relevant info as a jint. - * - * Class: java_net_PlainDatagramSocketImpl - * Method: socketGetOption - * Signature: (I)Ljava/lang/Object; - */ -JNIEXPORT jobject JNICALL -Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, - jint opt) { - - int fd=-1, fd1=-1; - int level, optname, optlen; - union { - int i; - } optval; - int ipv6_supported = ipv6_available(); - - fd = getFD(env, this); - if (ipv6_supported) { - fd1 = getFD1(env, this); - } - - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return NULL; - } - - /* - * Handle IP_MULTICAST_IF separately - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF || - opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - return getMulticastInterface(env, this, fd, fd1, opt); - } - - if (opt == java_net_SocketOptions_SO_BINDADDR) { - /* find out local IP address */ - SOCKETADDRESS him; - int len = 0; - int port; - jobject iaObj; - - len = sizeof (struct sockaddr_in); - - if (fd == -1) { - fd = fd1; /* must be IPv6 only */ - len = sizeof (struct SOCKADDR_IN6); - } - - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error getting socket name"); - return NULL; - } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); - - return iaObj; - } - - /* - * Map the Java level socket option to the platform specific - * level and option name. - */ - if (NET_MapSocketOption(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); - return NULL; - } - - if (fd == -1) { - if (NET_MapSocketOptionV6(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); - return NULL; - } - fd = fd1; /* must be IPv6 only */ - } - - optlen = sizeof(optval.i); - if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { - char errmsg[255]; - sprintf(errmsg, "error getting socket option: %s\n", strerror(errno)); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); - return NULL; - } - - switch (opt) { - case java_net_SocketOptions_SO_BROADCAST: - case java_net_SocketOptions_SO_REUSEADDR: - return createBoolean(env, optval.i); - - case java_net_SocketOptions_IP_MULTICAST_LOOP: - /* getLoopbackMode() returns true if IP_MULTICAST_LOOP is disabled */ - return createBoolean(env, !optval.i); - - case java_net_SocketOptions_SO_SNDBUF: - case java_net_SocketOptions_SO_RCVBUF: - case java_net_SocketOptions_IP_TOS: - return createInteger(env, optval.i); - - default : - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket option not supported by PlainDatagramSocketImpl"); - return NULL; - - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: setTimeToLive - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this, - jint ttl) { - - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int fd = -1, fd1 = -1; - int ittl = (int)ttl; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } else { - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - } - - /* setsockopt to be correct ttl */ - if (fd >= 0) { - if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, - sizeof (ittl)) < 0) { - NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); - } - } - - if (fd1 >= 0) { - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ittl, - sizeof(ittl)) <0) { - NET_ThrowCurrent(env, "set IPV6_MULTICAST_HOPS failed"); - } - } -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: setTTL - * Signature: (B)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this, - jbyte ttl) { - Java_java_net_PlainDatagramSocketImpl_setTimeToLive(env, this, - (jint)ttl & 0xFF); -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: getTimeToLive - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_java_net_PlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - int fd = -1, fd1 = -1; - int ttl = 0; - int len = sizeof(ttl); - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return -1; - } else { - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - } - - /* getsockopt of ttl */ - if (fd >= 0) { - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, &len) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); - return -1; - } - return (jint)ttl; - } - if (fd1 >= 0) { - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl, &len) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); - return -1; - } - return (jint)ttl; - } - return -1; -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: getTTL - * Signature: ()B - */ -JNIEXPORT jbyte JNICALL -Java_java_net_PlainDatagramSocketImpl_getTTL(JNIEnv *env, jobject this) { - int result = Java_java_net_PlainDatagramSocketImpl_getTimeToLive(env, this); - - return (jbyte)result; -} - -/* join/leave the named group on the named interface, or if no interface specified - * then the interface set with setInterfac(), or the default interface otherwise */ - -static void mcast_join_leave(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj, - jboolean join) -{ - jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); - jint fd = -1, fd1 = -1; - - SOCKETADDRESS name; - struct ip_mreq mname; - struct ipv6_mreq mname6; - - struct in_addr in; - DWORD ifindex; - - int len, family; - int ipv6_supported = ipv6_available(); - int cmd ; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "address"); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, 0, (struct sockaddr *)&name, &len) != 0) { - return; - } - - /* Set the multicast group address in the ip_mreq field - * eventually this check should be done by the security manager - */ - family = name.him.sa_family; - - if (family == AF_INET) { - int address = name.him4.sin_addr.s_addr; - if (!IN_MULTICAST(ntohl(address))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in multicast"); - return; - } - mname.imr_multiaddr.s_addr = address; - if (fd < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv4 group on an IPv6 only socket"); - return; - } - if (IS_NULL(niObj)) { - len = sizeof (in); - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&in, &len) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed"); - return; - } - mname.imr_interface.s_addr = in.s_addr; - } else { - if (getInet4AddrFromIf (env, niObj, &mname.imr_interface) != 0) { - NET_ThrowCurrent(env, "no Inet4Address associated with interface"); - return; - } - } - - cmd = join ? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP; - - /* Join the multicast group */ - if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, (char *) &mname, sizeof (mname)) < 0) { - if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); - } - } - } else /* AF_INET6 */ { - if (ipv6_supported) { - struct in6_addr *address; - address = &name.him6.sin6_addr; - if (!IN6_IS_ADDR_MULTICAST(address)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in6 multicast"); - return; - } - mname6.ipv6mr_multiaddr = *address; - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPv6 not supported"); - return; - } - if (fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv6 group on a IPv4 socket"); - return; - } - if (IS_NULL(niObj)) { - len = sizeof (ifindex); - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, &len) < 0) { - NET_ThrowCurrent(env, "get IPV6_MULTICAST_IF failed"); - return; - } - } else { - ifindex = getIndexFromIf (env, niObj); - if (ifindex == -1) { - NET_ThrowCurrent(env, "get ifindex failed"); - return; - } - } - mname6.ipv6mr_interface = ifindex; - cmd = join ? IPV6_ADD_MEMBERSHIP: IPV6_DROP_MEMBERSHIP; - - /* Join the multicast group */ - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, (char *) &mname6, sizeof (mname6)) < 0) { - if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); - } - } - } - - return; -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: join - * Signature: (Ljava/net/InetAddress;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_join(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj) -{ - mcast_join_leave (env, this, iaObj, niObj, JNI_TRUE); -} - -/* - * Class: java_net_PlainDatagramSocketImpl - * Method: leave - * Signature: (Ljava/net/InetAddress;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainDatagramSocketImpl_leave(JNIEnv *env, jobject this, - jobject iaObj, jobject niObj) -{ - mcast_join_leave (env, this, iaObj, niObj, JNI_FALSE); -} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/PlainSocketImpl.c --- a/j2se/src/windows/native/java/net/PlainSocketImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1156 +0,0 @@ -/* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "java_net_SocketOptions.h" -#include "java_net_PlainSocketImpl.h" -#include "java_net_SocketImpl.h" -#include "java_net_InetAddress.h" -#include "java_io_FileDescriptor.h" -#include "java_lang_Integer.h" - -#include "jvm.h" -#include "net_util.h" -#include "jni_util.h" - -/************************************************************************ - * PlainSocketImpl - */ - -static jfieldID IO_fd_fdID; - -jfieldID psi_fdID; -jfieldID psi_fd1ID; -jfieldID psi_addressID; -jfieldID psi_portID; -jfieldID psi_localportID; -jfieldID psi_timeoutID; -jfieldID psi_trafficClassID; -jfieldID psi_serverSocketID; -jfieldID psi_lastfdID; - -/* - * the level of the TCP protocol for setsockopt and getsockopt - * we only want to look this up once, from the static initializer - * of PlainSocketImpl - */ -static int tcp_level = -1; - -static int getFD(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - - if (fdObj == NULL) { - return -1; - } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); -} - -static int getFD1(JNIEnv *env, jobject this) { - jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID); - - if (fdObj == NULL) { - return -1; - } - return (*env)->GetIntField(env, fdObj, IO_fd_fdID); -} - - -/* - * The initProto function is called whenever PlainSocketImpl is - * loaded, to cache fieldIds for efficiency. This is called everytime - * the Java class is loaded. - * - * Class: java_net_PlainSocketImpl - * Method: initProto - - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) { - - struct protoent *proto = getprotobyname("TCP"); - tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); - - psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); - CHECK_NULL(psi_fdID); - psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;"); - CHECK_NULL(psi_fd1ID); - psi_addressID = (*env)->GetFieldID(env, cls, "address", - "Ljava/net/InetAddress;"); - CHECK_NULL(psi_addressID); - psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); - CHECK_NULL(psi_portID); - psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(psi_portID); - psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); - CHECK_NULL(psi_localportID); - psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); - CHECK_NULL(psi_timeoutID); - psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); - CHECK_NULL(psi_trafficClassID); - psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket", - "Ljava/net/ServerSocket;"); - CHECK_NULL(psi_serverSocketID); - IO_fd_fdID = NET_GetFileDescriptorID(env); - CHECK_NULL(IO_fd_fdID); -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketCreate - * Signature: (Z)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this, - jboolean stream) { - jobject fdObj, fd1Obj; - int fd, fd1; - - fdObj = (*env)->GetObjectField(env, this, psi_fdID); - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "null fd object"); - return; - } - fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd == -1) { - NET_ThrowCurrent(env, "create"); - return; - } else { - /* Set socket attribute so it is not passed to any child process */ - SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); - } - if (ipv6_available()) { - fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - - if (IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "null fd1 object"); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); - NET_SocketClose(fd); - return; - } - fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd1 == -1) { - NET_ThrowCurrent(env, "create"); - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); - NET_SocketClose(fd); - return; - } else { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); - } - } else { - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); - } -} - -/* - * inetAddress is the address object passed to the socket connect - * call. - * - * Class: java_net_PlainSocketImpl - * Method: socketConnect - * Signature: (Ljava/net/InetAddress;I)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this, - jobject iaObj, jint port, - jint timeout) -{ - jint localport = (*env)->GetIntField(env, this, psi_localportID); - - /* family and localport are int fields of iaObj */ - int family; - jint fd, fd1=-1; - jint len; - int ipv6_supported = ipv6_available(); - - /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket - * If we want to connect to IPv6 then we swap the two sockets/objects - * This way, fd is always the connected socket, and fd1 always gets closed. - */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - - SOCKETADDRESS him; - - /* The result of the connection */ - int connect_res; - - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - - if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "inet address argument is null."); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len) != 0) { - return; - } - - family = him.him.sa_family; - if (family == AF_INET6) { - if (!ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Protocol family not supported"); - return; - } else { - if (fd1 == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Destination unreachable"); - return; - } - /* close the v4 socket, and set fd to be the v6 socket */ - (*env)->SetObjectField(env, this, psi_fdID, fd1Obj); - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); - NET_SocketClose(fd); - fd = fd1; fdObj = fd1Obj; - } - } else { - if (fd1 != -1) { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); - NET_SocketClose(fd1); - } - if (fd == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Destination unreachable"); - return; - } - } - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); - - if (timeout <= 0) { - connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); - if (connect_res == SOCKET_ERROR) { - connect_res = WSAGetLastError(); - } - } else { - int optval; - int optlen = sizeof(optval); - - /* make socket non-blocking */ - optval = 1; - ioctlsocket( fd, FIONBIO, &optval ); - - /* initiate the connect */ - connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); - if (connect_res == SOCKET_ERROR) { - if (WSAGetLastError() != WSAEWOULDBLOCK) { - connect_res = WSAGetLastError(); - } else { - fd_set wr, ex; - struct timeval t; - - FD_ZERO(&wr); - FD_ZERO(&ex); - FD_SET(fd, &wr); - FD_SET(fd, &ex); - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - /* - * Wait for timout, connection established or - * connection failed. - */ - connect_res = select(fd+1, 0, &wr, &ex, &t); - - /* - * Timeout before connection is established/failed so - * we throw exception and shutdown input/output to prevent - * socket from being used. - * The socket should be closed immediately by the caller. - */ - if (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "connect timed out"); - shutdown( fd, SD_BOTH ); - - /* make socket blocking again - just in case */ - optval = 0; - ioctlsocket( fd, FIONBIO, &optval ); - return; - } - - /* - * We must now determine if the connection has been established - * or if it has failed. The logic here is designed to work around - * bug on Windows NT whereby using getsockopt to obtain the - * last error (SO_ERROR) indicates there is no error. The workaround - * on NT is to allow winsock to be scheduled and this is done by - * yielding and retrying. As yielding is problematic in heavy - * load conditions we attempt up to 3 times to get the error reason. - */ - if (!FD_ISSET(fd, &ex)) { - connect_res = 0; - } else { - int retry; - for (retry=0; retry<3; retry++) { - NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, - (char*)&connect_res, &optlen); - if (connect_res) { - break; - } - Sleep(0); - } - - if (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Unable to establish connection"); - return; - } - } - } - } - - /* make socket blocking again */ - optval = 0; - ioctlsocket(fd, FIONBIO, &optval); - } - - if (connect_res) { - if (connect_res == WSAEADDRNOTAVAIL) { - JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", - "connect: Address is invalid on local machine, or port is not valid on remote machine"); - } else { - NET_ThrowNew(env, connect_res, "connect"); - } - return; - } - - (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); - - /* set the remote peer address and port */ - (*env)->SetObjectField(env, this, psi_addressID, iaObj); - (*env)->SetIntField(env, this, psi_portID, port); - - /* - * we need to initialize the local port field if bind was called - * previously to the connect (by the client) then localport field - * will already be initialized - */ - if (localport == 0) { - /* Now that we're a connected socket, let's extract the port number - * that the system chose for us and store it in the Socket object. - */ - u_short port; - int len = SOCKETADDRESS_LEN(&him); - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { - - if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - } else { - NET_ThrowCurrent(env, "getsockname failed"); - } - return; - } - port = ntohs ((u_short)GET_PORT(&him)); - (*env)->SetIntField(env, this, psi_localportID, (int) port); - } -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketBind - * Signature: (Ljava/net/InetAddress;I)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this, - jobject iaObj, jint localport) { - - /* fdObj is the FileDescriptor field on this */ - jobject fdObj, fd1Obj; - /* fd is an int field on fdObj */ - int fd, fd1, len; - int ipv6_supported = ipv6_available(); - - /* family is an int field of iaObj */ - int family; - int rv; - - SOCKETADDRESS him; - - fdObj = (*env)->GetObjectField(env, this, psi_fdID); - fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - - family = (*env)->GetIntField(env, iaObj, ia_familyID); - - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Protocol family not supported"); - return; - } - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - if (ipv6_supported) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - } - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "inet address argument"); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, localport, - (struct sockaddr *)&him, &len) != 0) { - return; - } - - if (ipv6_supported) { - struct ipv6bind v6bind; - v6bind.addr = &him; - v6bind.ipv4_fd = fd; - v6bind.ipv6_fd = fd1; - rv = NET_BindV6(&v6bind); - if (rv != -1) { - /* check if the fds have changed */ - if (v6bind.ipv4_fd != fd) { - fd = v6bind.ipv4_fd; - if (fd == -1) { - /* socket is closed. */ - (*env)->SetObjectField(env, this, psi_fdID, NULL); - } else { - /* socket was re-created */ - (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); - } - } - if (v6bind.ipv6_fd != fd1) { - fd1 = v6bind.ipv6_fd; - if (fd1 == -1) { - /* socket is closed. */ - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); - } else { - /* socket was re-created */ - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); - } - } - } - } else { - rv = NET_Bind(fd, (struct sockaddr *)&him, len); - } - - if (rv == -1) { - NET_ThrowCurrent(env, "JVM_Bind"); - return; - } - - /* set the address */ - (*env)->SetObjectField(env, this, psi_addressID, iaObj); - - /* intialize the local port */ - if (localport == 0) { - /* Now that we're a bound socket, let's extract the port number - * that the system chose for us and store it in the Socket object. - */ - int len = SOCKETADDRESS_LEN(&him); - u_short port; - fd = him.him.sa_family == AF_INET? fd: fd1; - - if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { - NET_ThrowCurrent(env, "getsockname in plain socketBind"); - return; - } - port = ntohs ((u_short) GET_PORT (&him)); - - (*env)->SetIntField(env, this, psi_localportID, (int) port); - } else { - (*env)->SetIntField(env, this, psi_localportID, localport); - } -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketListen - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this, - jint count) -{ - /* this FileDescriptor fd field */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - jobject address; - /* fdObj's int fd field */ - int fd, fd1; - SOCKETADDRESS addr; int addrlen; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - return; - } - - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - /* Listen on V4 if address type is v4 or if v6 and address is ::0. - * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. - * In cases, where we listen on one space only, we close the other socket. - */ - address = (*env)->GetObjectField(env, this, psi_addressID); - if (IS_NULL(address)) { - JNU_ThrowNullPointerException(env, "socket address"); - return; - } - if (NET_InetAddressToSockaddr(env, address, 0, (struct sockaddr *)&addr, - &addrlen) != 0) { - return; - } - - if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(&addr.him6)) { - /* listen on v4 */ - if (listen(fd, count) == -1) { - NET_ThrowCurrent(env, "listen failed"); - } - } else { - NET_SocketClose (fd); - (*env)->SetObjectField(env, this, psi_fdID, NULL); - } - if (ipv6_available() && !IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) { - /* listen on v6 */ - if (listen(fd1, count) == -1) { - NET_ThrowCurrent(env, "listen failed"); - } - } else { - NET_SocketClose (fd1); - (*env)->SetObjectField(env, this, psi_fd1ID, NULL); - } - } -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketAccept - * Signature: (Ljava/net/SocketImpl;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this, - jobject socket) -{ - /* fields on this */ - jint port; - jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - - /* the FileDescriptor field on socket */ - jobject socketFdObj; - - jclass inet4Cls, inet6Cls; - /* the InetAddress field on socket */ - jobject socketAddressObj; - - /* the fd int field on fdObj */ - jint fd=-1, fd1=-1; - - SOCKETADDRESS him; - jint len; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - if (IS_NULL(socket)) { - JNU_ThrowNullPointerException(env, "socket is null"); - return; - } else { - socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID); - socketAddressObj = (*env)->GetObjectField(env, socket, psi_addressID); - } - if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { - JNU_ThrowNullPointerException(env, "socket address or fd obj"); - return; - } - if (fd != -1 && fd1 != -1) { - fd_set rfds; - struct timeval t, *tP=&t; - int lastfd, res, fd2; - FD_ZERO(&rfds); - FD_SET(fd,&rfds); - FD_SET(fd1,&rfds); - if (timeout) { - t.tv_sec = timeout/1000; - t.tv_usec = (timeout%1000)*1000; - } else { - tP = NULL; - } - res = select (fd, &rfds, NULL, NULL, tP); - if (res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Accept timed out"); - return; - } else if (res == 1) { - fd2 = FD_ISSET(fd, &rfds)? fd: fd1; - } else if (res == 2) { - /* avoid starvation */ - lastfd = (*env)->GetIntField(env, this, psi_lastfdID); - if (lastfd != -1) { - fd2 = lastfd==fd? fd1: fd; - } else { - fd2 = fd; - } - (*env)->SetIntField(env, this, psi_lastfdID, fd2); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "select failed"); - return; - } - if (fd2 == fd) { /* v4 */ - len = sizeof (struct sockaddr_in); - } else { - len = sizeof (struct SOCKADDR_IN6); - } - fd = fd2; - } else { - int ret; - if (fd1 != -1) { - fd = fd1; - len = sizeof (struct SOCKADDR_IN6); - } else { - len = sizeof (struct sockaddr_in); - } - if (timeout) { - ret = NET_Timeout(fd, timeout); - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", - "Accept timed out"); - return; - } else if (ret == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); - /* REMIND: SOCKET CLOSED PROBLEM */ - /* NET_ThrowCurrent(env, "Accept failed"); */ - return; - } else if (ret == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - return; - } - } - } - fd = accept(fd, (struct sockaddr *)&him, &len); - if (fd < 0) { - /* REMIND: SOCKET CLOSED PROBLEM */ - if (fd == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", - "operation interrupted"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket closed"); - } - return; - } - (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); - - if (him.him.sa_family == AF_INET) { - /* - * fill up the remote peer port and address in the new socket structure - */ - inet4Cls = (*env)->FindClass(env, "java/net/Inet4Address"); - if (inet4Cls != NULL) { - socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); - } else { - socketAddressObj = NULL; - } - if (socketAddressObj == NULL) { - /* - * FindClass or NewObject failed so close connection and - * exist (there will be a pending exception). - */ - NET_SocketClose(fd); - return; - } - - (*env)->SetIntField(env, socketAddressObj, ia_addressID, - ntohl(him.him4.sin_addr.s_addr)); - (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv4); - (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); - } else { - jbyteArray addr; - /* AF_INET6 -> Inet6Address */ - inet6Cls = (*env)->FindClass(env, "java/net/Inet6Address"); - if (inet6Cls != NULL) { - socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); - } else { - socketAddressObj = NULL; - } - if (socketAddressObj == NULL) { - /* - * FindClass or NewObject failed so close connection and - * exist (there will be a pending exception). - */ - NET_SocketClose(fd); - return; - } - addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID); - (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr); - (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6); - (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id); - } - /* fields common to AF_INET and AF_INET6 */ - - port = ntohs ((u_short) GET_PORT (&him)); - (*env)->SetIntField(env, socket, psi_portID, (int)port); - port = (*env)->GetIntField(env, this, psi_localportID); - (*env)->SetIntField(env, socket, psi_localportID, port); - (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketAvailable - * Signature: ()I - */ -JNIEXPORT jint JNICALL -Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) { - - jint available = -1; - jint res; - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jint fd; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - return -1; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - res = ioctlsocket(fd, FIONREAD, &available); - /* if result isn't 0, it means an error */ - if (res != 0) { - NET_ThrowNew(env, res, "socket available"); - } - return available; -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketClose - * Signature: ()V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this, - jboolean useDeferredClose) { - - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); - jint fd=-1, fd1=-1; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket already closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - if (!IS_NULL(fd1Obj)) { - fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); - } - if (fd != -1) { - (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); - NET_SocketClose(fd); - } - if (fd1 != -1) { - (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); - NET_SocketClose(fd1); - } -} - -/* - * Socket options for plainsocketImpl - * - * - * Class: java_net_PlainSocketImpl - * Method: socketSetOption - * Signature: (IZLjava/lang/Object;)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this, - jint cmd, jboolean on, - jobject value) { - int fd, fd1; - int level, optname, optlen; - union { - int i; - struct linger ling; - } optval; - - /* - * Get SOCKET and check that it hasn't been closed - */ - fd = getFD(env, this); - fd1 = getFD1(env, this); - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - return; - } - - /* - * SO_TIMEOUT is the socket option used to specify the timeout - * for ServerSocket.accept and Socket.getInputStream().read. - * It does not typically map to a native level socket option. - * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO - * socket option to specify a receive timeout on the socket. This - * receive timeout is applicable to Socket only and the socket - * option should not be set on ServerSocket. - */ - if (cmd == java_net_SocketOptions_SO_TIMEOUT) { - - /* - * Don't enable the socket option on ServerSocket as it's - * meaningless (we don't receive on a ServerSocket). - */ - jobject ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID); - if (ssObj != NULL) { - return; - } - - /* - * SO_RCVTIMEO is only supported on Microsoft's implementation - * of Windows Sockets so if WSAENOPROTOOPT returned then - * reset flag and timeout will be implemented using - * select() -- see SocketInputStream.socketRead. - */ - if (isRcvTimeoutSupported) { - jclass iCls = (*env)->FindClass(env, "java/lang/Integer"); - jfieldID i_valueID; - jint timeout; - - CHECK_NULL(iCls); - i_valueID = (*env)->GetFieldID(env, iCls, "value", "I"); - CHECK_NULL(i_valueID); - timeout = (*env)->GetIntField(env, value, i_valueID); - - /* - * Disable SO_RCVTIMEO if timeout is <= 5 second. - */ - if (timeout <= 5000) { - timeout = 0; - } - - if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)) < 0) { - if (WSAGetLastError() == WSAENOPROTOOPT) { - isRcvTimeoutSupported = JNI_FALSE; - } else { - NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); - } - } - if (fd1 != -1) { - if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)) < 0) { - NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); - } - } - } - return; - } - - /* - * Map the Java level socket option to the platform specific - * level - */ - if (NET_MapSocketOption(cmd, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Invalid option"); - return; - } - - switch (cmd) { - - case java_net_SocketOptions_TCP_NODELAY : - case java_net_SocketOptions_SO_OOBINLINE : - case java_net_SocketOptions_SO_KEEPALIVE : - case java_net_SocketOptions_SO_REUSEADDR : - optval.i = (on ? 1 : 0); - optlen = sizeof(optval.i); - break; - - case java_net_SocketOptions_SO_SNDBUF : - case java_net_SocketOptions_SO_RCVBUF : - case java_net_SocketOptions_IP_TOS : - { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - - optval.i = (*env)->GetIntField(env, value, fid); - optlen = sizeof(optval.i); - } - break; - - case java_net_SocketOptions_SO_LINGER : - { - jclass cls; - jfieldID fid; - - cls = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL(cls); - fid = (*env)->GetFieldID(env, cls, "value", "I"); - CHECK_NULL(fid); - - if (on) { - optval.ling.l_onoff = 1; - optval.ling.l_linger = (*env)->GetIntField(env, value, fid); - } else { - optval.ling.l_onoff = 0; - optval.ling.l_linger = 0; - } - optlen = sizeof(optval.ling); - } - break; - - default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Option not supported by PlainSocketImpl"); - return; - } - - if (fd != -1) { - if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - } - } - - if (fd1 != -1) { - if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - } - } -} - - -/* - * Class: java_net_PlainSocketImpl - * Method: socketGetOption - * Signature: (I)I - */ -JNIEXPORT jint JNICALL -Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this, - jint opt, jobject iaContainerObj) { - - int fd, fd1; - int level, optname, optlen; - union { - int i; - struct linger ling; - } optval; - - /* - * Get SOCKET and check it hasn't been closed - */ - fd = getFD(env, this); - fd1 = getFD1(env, this); - - if (fd < 0 && fd1 < 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - return -1; - } - if (fd < 0) { - fd = fd1; - } - - /* For IPv6, we assume both sockets have the same setting always */ - - /* - * SO_BINDADDR isn't a socket option - */ - if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKET_ADDRESS him; - int len; - int port; - jobject iaObj; - jclass iaCntrClass; - jfieldID iaFieldID; - - len = sizeof(struct sockaddr_in); - - if (fd == -1) { - /* must be an IPV6 only socket. Case where both sockets are != -1 - * is handled in java - */ - fd = getFD1 (env, this); - len = sizeof(struct SOCKADDR_IN6); - } - - if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error getting socket name"); - return -1; - } - iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); - CHECK_NULL_RETURN(iaObj, -1); - - iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj); - iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(iaFieldID, -1); - (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); - return 0; /* notice change from before */ - } - - /* - * Map the Java level socket option to the platform specific - * level and option name. - */ - if (NET_MapSocketOption(opt, &level, &optname)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); - return -1; - } - - /* - * Args are int except for SO_LINGER - */ - if (opt == java_net_SocketOptions_SO_LINGER) { - optlen = sizeof(optval.ling); - } else { - optlen = sizeof(optval.i); - optval.i = 0; - } - - if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { - NET_ThrowCurrent(env, "getsockopt"); - return -1; - } - - switch (opt) { - case java_net_SocketOptions_SO_LINGER: - return (optval.ling.l_onoff ? optval.ling.l_linger: -1); - - case java_net_SocketOptions_SO_SNDBUF: - case java_net_SocketOptions_SO_RCVBUF: - case java_net_SocketOptions_IP_TOS: - return optval.i; - - case java_net_SocketOptions_TCP_NODELAY : - case java_net_SocketOptions_SO_OOBINLINE : - case java_net_SocketOptions_SO_KEEPALIVE : - case java_net_SocketOptions_SO_REUSEADDR : - return (optval.i == 0) ? -1 : 1; - - default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Option not supported by PlainSocketImpl"); - return -1; - } -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketShutdown - * Signature: (I)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this, - jint howto) -{ - - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - jint fd; - - /* - * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being - * -1 already? - */ - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "socket already closed"); - return; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - } - shutdown(fd, howto); -} - -/* - * Class: java_net_PlainSocketImpl - * Method: socketSendUrgentData - * Signature: (B)V - */ -JNIEXPORT void JNICALL -Java_java_net_PlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this, - jint data) { - /* The fd field */ - jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); - int n, fd; - unsigned char d = data & 0xff; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); - return; - } else { - fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); - /* Bug 4086704 - If the Socket associated with this file descriptor - * was closed (sysCloseFD), the the file descriptor is set to -1. - */ - if (fd == -1) { - JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); - return; - } - - } - n = send(fd, (char *)&data, 1, MSG_OOB); - if (n == JVM_IO_ERR) { - NET_ThrowCurrent(env, "send"); - return; - } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); - return; - } -} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,2524 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef IPTOS_TOS_MASK +#define IPTOS_TOS_MASK 0x1e +#endif +#ifndef IPTOS_PREC_MASK +#define IPTOS_PREC_MASK 0xe0 +#endif + +#include "java_net_TwoStacksPlainDatagramSocketImpl.h" +#include "java_net_SocketOptions.h" +#include "java_net_NetworkInterface.h" + +#include "jvm.h" +#include "jni_util.h" +#include "net_util.h" + +#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(i) IN_CLASSD(i) + +/************************************************************************ + * TwoStacksPlainDatagramSocketImpl + */ + +static jfieldID IO_fd_fdID; +static jfieldID pdsi_trafficClassID; +jfieldID pdsi_fdID; +jfieldID pdsi_fd1ID; +jfieldID pdsi_fduseID; +jfieldID pdsi_lastfdID; +jfieldID pdsi_timeoutID; + +jfieldID pdsi_localPortID; +jfieldID pdsi_connected; + +static jclass ia4_clazz; +static jmethodID ia4_ctor; + +static CRITICAL_SECTION sizeCheckLock; + +/* Windows OS version is XP or better */ +static int xp_or_later = 0; +/* Windows OS version is Windows 2000 or better */ +static int w2k_or_later = 0; + +/* + * Notes about UDP/IPV6 on Windows (XP and 2003 server): + * + * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd. + * Both fds are used when we bind to a wild-card address. When a specific + * address is used, only one of them is used. + */ + +/* + * Returns a java.lang.Integer based on 'i' + */ +jobject createInteger(JNIEnv *env, int i) { + static jclass i_class; + static jmethodID i_ctrID; + static jfieldID i_valueID; + + if (i_class == NULL) { + jclass c = (*env)->FindClass(env, "java/lang/Integer"); + CHECK_NULL_RETURN(c, NULL); + i_ctrID = (*env)->GetMethodID(env, c, "", "(I)V"); + CHECK_NULL_RETURN(i_ctrID, NULL); + i_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(i_class, NULL); + } + + return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); +} + +/* + * Returns a java.lang.Boolean based on 'b' + */ +jobject createBoolean(JNIEnv *env, int b) { + static jclass b_class; + static jmethodID b_ctrID; + static jfieldID b_valueID; + + if (b_class == NULL) { + jclass c = (*env)->FindClass(env, "java/lang/Boolean"); + CHECK_NULL_RETURN(c, NULL); + b_ctrID = (*env)->GetMethodID(env, c, "", "(Z)V"); + CHECK_NULL_RETURN(b_ctrID, NULL); + b_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(b_class, NULL); + } + + return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); +} + + +static int getFD(JNIEnv *env, jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + + if (fdObj == NULL) { + return -1; + } + return (*env)->GetIntField(env, fdObj, IO_fd_fdID); +} + +static int getFD1(JNIEnv *env, jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + + if (fdObj == NULL) { + return -1; + } + return (*env)->GetIntField(env, fdObj, IO_fd_fdID); +} + +/* + * This function returns JNI_TRUE if the datagram size exceeds the underlying + * provider's ability to send to the target address. The following OS + * oddies have been observed :- + * + * 1. On Windows 95/98 if we try to send a datagram > 12k to an application + * on the same machine then the send will fail silently. + * + * 2. On Windows ME if we try to send a datagram > supported by underlying + * provider then send will not return an error. + * + * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail + * with WSAEADDRNOTAVAIL. + * + * 4. On Windows 95/98 if we exceed the maximum size when sending to + * another machine then WSAEINVAL is returned. + * + */ +jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) +{ +#define DEFAULT_MSG_SIZE 65527 + static jboolean initDone; + static jboolean is95or98; + static int maxmsg; + + typedef struct _netaddr { /* Windows 95/98 only */ + unsigned long addr; + struct _netaddr *next; + } netaddr; + static netaddr *addrList; + netaddr *curr; + + /* + * First time we are called we must determine which OS this is and also + * get the maximum size supported by the underlying provider. + * + * In addition on 95/98 we must enumerate our IP addresses. + */ + if (!initDone) { + EnterCriticalSection(&sizeCheckLock); + + if (initDone) { + /* another thread got there first */ + LeaveCriticalSection(&sizeCheckLock); + + } else { + OSVERSIONINFO ver; + int len; + + /* + * Step 1: Determine which OS this is. + */ + ver.dwOSVersionInfoSize = sizeof(ver); + GetVersionEx(&ver); + + is95or98 = JNI_FALSE; + if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && + ver.dwMajorVersion == 4 && + (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) { + + is95or98 = JNI_TRUE; + } + + /* + * Step 2: Determine the maximum datagram supported by the + * underlying provider. On Windows 95 if winsock hasn't been + * upgraded (ie: unsupported configuration) then we assume + * the default 64k limit. + */ + len = sizeof(maxmsg); + if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) { + maxmsg = DEFAULT_MSG_SIZE; + } + + /* + * Step 3: On Windows 95/98 then enumerate the IP addresses on + * this machine. This is necesary because we need to check if the + * datagram is being sent to an application on the same machine. + */ + if (is95or98) { + char hostname[255]; + struct hostent *hp; + + if (gethostname(hostname, sizeof(hostname)) == -1) { + LeaveCriticalSection(&sizeCheckLock); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname"); + return JNI_TRUE; + } + hp = (struct hostent *)gethostbyname(hostname); + if (hp != NULL) { + struct in_addr **addrp = (struct in_addr **) hp->h_addr_list; + + while (*addrp != (struct in_addr *) 0) { + curr = (netaddr *)malloc(sizeof(netaddr)); + if (curr == NULL) { + while (addrList != NULL) { + curr = addrList->next; + free(addrList); + addrList = curr; + } + LeaveCriticalSection(&sizeCheckLock); + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return JNI_TRUE; + } + curr->addr = htonl((*addrp)->S_un.S_addr); + curr->next = addrList; + addrList = curr; + addrp++; + } + } + } + + /* + * Step 4: initialization is done so set flag and unlock cs + */ + initDone = JNI_TRUE; + LeaveCriticalSection(&sizeCheckLock); + } + } + + /* + * Now examine the size of the datagram :- + * + * (a) If exceeds size of service provider return 'false' to indicate that + * we exceed the limit. + * (b) If not 95/98 then return 'true' to indicate that the size is okay. + * (c) On 95/98 if the size is <12k we are okay. + * (d) On 95/98 if size > 12k then check if the destination is the current + * machine. + */ + if (size > maxmsg) { /* step (a) */ + return JNI_TRUE; + } + if (!is95or98) { /* step (b) */ + return JNI_FALSE; + } + if (size <= 12280) { /* step (c) */ + return JNI_FALSE; + } + + /* step (d) */ + + if ((addr & 0x7f000000) == 0x7f000000) { + return JNI_TRUE; + } + curr = addrList; + while (curr != NULL) { + if (curr->addr == addr) { + return JNI_TRUE; + } + curr = curr->next; + } + return JNI_FALSE; +} + +/* + * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable + */ +__inline static jboolean supportPortUnreachable() { + static jboolean initDone; + static jboolean portUnreachableSupported; + + if (!initDone) { + OSVERSIONINFO ver; + ver.dwOSVersionInfoSize = sizeof(ver); + GetVersionEx(&ver); + if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) { + portUnreachableSupported = JNI_TRUE; + } else { + portUnreachableSupported = JNI_FALSE; + } + initDone = JNI_TRUE; + } + return portUnreachableSupported; +} + +/* + * This function "purges" all outstanding ICMP port unreachable packets + * outstanding on a socket and returns JNI_TRUE if any ICMP messages + * have been purged. The rational for purging is to emulate normal BSD + * behaviour whereby receiving a "connection reset" status resets the + * socket. + */ +static jboolean purgeOutstandingICMP(JNIEnv *env, jobject this, jint fd) +{ + jboolean got_icmp = JNI_FALSE; + char buf[1]; + fd_set tbl; + struct timeval t = { 0, 0 }; + struct sockaddr_in rmtaddr; + int addrlen = sizeof(rmtaddr); + + /* + * A no-op if this OS doesn't support it. + */ + if (!supportPortUnreachable()) { + return JNI_FALSE; + } + + /* + * Peek at the queue to see if there is an ICMP port unreachable. If there + * is then receive it. + */ + FD_ZERO(&tbl); + FD_SET(fd, &tbl); + while(1) { + if (select(/*ignored*/fd+1, &tbl, 0, 0, &t) <= 0) { + break; + } + if (recvfrom(fd, buf, 1, MSG_PEEK, + (struct sockaddr *)&rmtaddr, &addrlen) != JVM_IO_ERR) { + break; + } + if (WSAGetLastError() != WSAECONNRESET) { + /* some other error - we don't care here */ + break; + } + + recvfrom(fd, buf, 1, 0, (struct sockaddr *)&rmtaddr, &addrlen); + got_icmp = JNI_TRUE; + } + + return got_icmp; +} + + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { + + OSVERSIONINFO ver; + int version; + ver.dwOSVersionInfoSize = sizeof(ver); + GetVersionEx(&ver); + + version = ver.dwMajorVersion * 10 + ver.dwMinorVersion; + xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51); + w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50); + + /* get fieldIDs */ + pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); + CHECK_NULL(pdsi_fdID); + pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;"); + CHECK_NULL(pdsi_fd1ID); + pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); + CHECK_NULL(pdsi_timeoutID); + pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I"); + CHECK_NULL(pdsi_fduseID); + pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); + CHECK_NULL(pdsi_lastfdID); + pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); + CHECK_NULL(pdsi_trafficClassID); + pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I"); + CHECK_NULL(pdsi_localPortID); + pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z"); + CHECK_NULL(pdsi_connected); + + cls = (*env)->FindClass(env, "java/io/FileDescriptor"); + CHECK_NULL(cls); + IO_fd_fdID = NET_GetFileDescriptorID(env); + CHECK_NULL(IO_fd_fdID); + + ia4_clazz = (*env)->FindClass(env, "java/net/Inet4Address"); + CHECK_NULL(ia4_clazz); + ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz); + CHECK_NULL(ia4_clazz); + ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "", "()V"); + CHECK_NULL(ia4_ctor); + + + InitializeCriticalSection(&sizeCheckLock); +} + +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, + jint port, jobject addressObj) { + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + + int fd, fd1, family; + int ipv6_supported = ipv6_available(); + + SOCKETADDRESS lcladdr; + int lcladdrlen; + int address; + + family = (*env)->GetIntField(env, addressObj, ia_familyID); + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Protocol family not supported"); + return; + } + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + if (ipv6_supported) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + } + if (IS_NULL(addressObj)) { + JNU_ThrowNullPointerException(env, "argument address"); + return; + } else { + address = (*env)->GetIntField(env, addressObj, ia_addressID); + } + + if (NET_InetAddressToSockaddr(env, addressObj, port, (struct sockaddr *)&lcladdr, &lcladdrlen, JNI_FALSE) != 0) { + return; + } + + if (ipv6_supported) { + struct ipv6bind v6bind; + v6bind.addr = &lcladdr; + v6bind.ipv4_fd = fd; + v6bind.ipv6_fd = fd1; + if (NET_BindV6(&v6bind) != -1) { + /* check if the fds have changed */ + if (v6bind.ipv4_fd != fd) { + fd = v6bind.ipv4_fd; + if (fd == -1) { + /* socket is closed. */ + (*env)->SetObjectField(env, this, pdsi_fdID, NULL); + } else { + /* socket was re-created */ + (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); + } + } + if (v6bind.ipv6_fd != fd1) { + fd1 = v6bind.ipv6_fd; + if (fd1 == -1) { + /* socket is closed. */ + (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); + } else { + /* socket was re-created */ + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + } + } + } else { + NET_ThrowCurrent (env, "Cannot bind"); + return; + } + } else { + if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) { + if (WSAGetLastError() == WSAEACCES) { + WSASetLastError(WSAEADDRINUSE); + } + NET_ThrowCurrent(env, "Cannot bind"); + return; + } + } + + if (port == 0) { + if (fd == -1) { + /* must be an IPV6 only socket. */ + fd = fd1; + } + if (getsockname(fd, (struct sockaddr *)&lcladdr, &lcladdrlen) == -1) { + NET_ThrowCurrent(env, "JVM_GetSockName"); + return; + } + port = ntohs((u_short) GET_PORT (&lcladdr)); + } + (*env)->SetIntField(env, this, pdsi_localPortID, port); +} + + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: connect0 + * Signature: (Ljava/net/InetAddress;I)V + */ + +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this, + jobject address, jint port) { + /* The object's field */ + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + /* The fdObj'fd */ + jint fd=-1, fd1=-1, fdc; + /* The packetAddress address, family and port */ + jint addr, family; + SOCKETADDRESS rmtaddr; + int rmtaddrlen; + int ipv6_supported = ipv6_available(); + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + + if (IS_NULL(address)) { + JNU_ThrowNullPointerException(env, "address"); + return; + } + + addr = (*env)->GetIntField(env, address, ia_addressID); + + family = (*env)->GetIntField(env, address, ia_familyID); + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Protocol family not supported"); + return; + } + + fdc = family == IPv4? fd: fd1; + + if (xp_or_later) { + /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which + * returns connection reset errors un connected UDP sockets (as well + * as connected sockets. The solution is to only enable this feature + * when the socket is connected + */ + DWORD x1, x2; /* ignored result codes */ + int res, t = TRUE; + res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + } + + if (NET_InetAddressToSockaddr(env, address, port,(struct sockaddr *)&rmtaddr, &rmtaddrlen, JNI_FALSE) != 0) { + return; + } + + if (connect(fdc, (struct sockaddr *)&rmtaddr, sizeof(rmtaddr)) == -1) { + NET_ThrowCurrent(env, "connect"); + return; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: disconnect0 + * Signature: ()V + */ + +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jint family) { + /* The object's field */ + jobject fdObj; + /* The fdObj'fd */ + jint fd, len; + SOCKETADDRESS addr; + + if (family == IPv4) { + fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + len = sizeof (struct sockaddr_in); + } else { + fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + len = sizeof (struct SOCKADDR_IN6); + } + + if (IS_NULL(fdObj)) { + /* disconnect doesn't throw any exceptions */ + return; + } + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + + memset(&addr, 0, len); + connect(fd, (struct sockaddr *)&addr, len); + + /* + * use SIO_UDP_CONNRESET + * to disable ICMP port unreachable handling here. + */ + if (xp_or_later) { + DWORD x1, x2; /* ignored result codes */ + int t = FALSE; + WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: send + * Signature: (Ljava/net/DatagramPacket;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_send(JNIEnv *env, jobject this, + jobject packet) { + + char BUF[MAX_BUFFER_LEN]; + char *fullPacket; + jobject fdObj; + jint fd; + + jobject iaObj; + jint address; + jint family; + + jint packetBufferOffset, packetBufferLen, packetPort; + jbyteArray packetBuffer; + jboolean connected; + + SOCKETADDRESS rmtaddr; + SOCKETADDRESS *addrp = &rmtaddr; + int addrlen; + int x; /* DELETE ME */ + + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "null packet"); + return; + } + + iaObj = (*env)->GetObjectField(env, packet, dp_addressID); + + packetPort = (*env)->GetIntField(env, packet, dp_portID); + packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); + packetBuffer = (jbyteArray)(*env)->GetObjectField(env, packet, dp_bufID); + connected = (*env)->GetBooleanField(env, this, pdsi_connected); + + if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "null address || null buffer"); + return; + } + + family = (*env)->GetIntField(env, iaObj, ia_familyID); + if (family == IPv4) { + fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + } else { + if (!ipv6_available()) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Protocol not allowed"); + return; + } + fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + } + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + + packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID); + + if (connected) { + addrp = 0; /* arg to JVM_Sendto () null in this case */ + addrlen = 0; + } else { + if (NET_InetAddressToSockaddr(env, iaObj, packetPort, (struct sockaddr *)&rmtaddr, &addrlen, JNI_FALSE) != 0) { + return; + } + } + + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* + * On 95/98 if we try to send a datagram >12k to an application + * on the same machine then this will fail silently. Thus we + * catch this situation here so that we can throw an exception + * when this arises. + * On ME if we try to send a datagram with a size greater than + * that supported by the service provider then no error is + * returned. + */ + if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6. + * Check is not necessary on these OSes */ + if (connected) { + address = (*env)->GetIntField(env, iaObj, ia_addressID); + } else { + address = ntohl(rmtaddr.him4.sin_addr.s_addr); + } + + if (exceedSizeLimit(env, fd, address, packetBufferLen)) { + if (!((*env)->ExceptionOccurred(env))) { + NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed"); + } + return; + } + } + + /* When JNI-ifying the JDK's IO routines, we turned + * read's and write's of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + */ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + + (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen, + (jbyte *)fullPacket); + switch (sendto(fd, fullPacket, packetBufferLen, 0, + (struct sockaddr *)addrp, addrlen)) { + case JVM_IO_ERR: + NET_ThrowCurrent(env, "Datagram send failed"); + break; + + case JVM_IO_INTR: + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } +} + +/* + * check which socket was last serviced when there was data on both sockets. + * Only call this if sure that there is data on both sockets. + */ +static int checkLastFD (JNIEnv *env, jobject this, int fd, int fd1) { + int nextfd, lastfd = (*env)->GetIntField(env, this, pdsi_lastfdID); + if (lastfd == -1) { + /* arbitrary. Choose fd */ + (*env)->SetIntField(env, this, pdsi_lastfdID, fd); + return fd; + } else { + if (lastfd == fd) { + nextfd = fd1; + } else { + nextfd = fd; + } + (*env)->SetIntField(env, this, pdsi_lastfdID, nextfd); + return nextfd; + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: peek + * Signature: (Ljava/net/InetAddress;)I + */ +JNIEXPORT jint JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_peek(JNIEnv *env, jobject this, + jobject addressObj) { + + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); + jint fd; + + /* The address and family fields of addressObj */ + jint address, family; + + int n; + struct sockaddr_in remote_addr; + jint remote_addrsize = sizeof (remote_addr); + char buf[1]; + BOOL retry; + jlong prevTime = 0; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return -1; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + if (fd < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + return -1; + } + } + if (IS_NULL(addressObj)) { + JNU_ThrowNullPointerException(env, "Null address in peek()"); + } else { + address = (*env)->GetIntField(env, addressObj, ia_addressID); + /* We only handle IPv4 for now. Will support IPv6 once its in the os */ + family = AF_INET; + } + + do { + retry = FALSE; + + /* + * If a timeout has been specified then we select on the socket + * waiting for a read event or a timeout. + */ + if (timeout) { + int ret; + prevTime = JVM_CurrentTimeMillis(env, 0); + ret = NET_Timeout (fd, timeout); + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Peek timed out"); + return ret; + } else if (ret == JVM_IO_ERR) { + NET_ThrowCurrent(env, "timeout in datagram socket peek"); + return ret; + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + return ret; + } + } + + /* now try the peek */ + n = recvfrom(fd, buf, 1, MSG_PEEK, + (struct sockaddr *)&remote_addr, &remote_addrsize); + + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + jboolean connected; + + /* + * An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(env, this, fd); + + connected = (*env)->GetBooleanField(env, this, pdsi_connected); + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + "ICMP Port Unreachable"); + return 0; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout befor the icmp port + * unreachable arrived. + */ + if (timeout) { + jlong newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + return 0; + } + prevTime = newTime; + } + + /* Need to retry the recv */ + retry = TRUE; + } + } + } while (retry); + + if (n == JVM_IO_ERR && WSAGetLastError() != WSAEMSGSIZE) { + NET_ThrowCurrent(env, "Datagram peek failed"); + return 0; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", 0); + return 0; + } + (*env)->SetIntField(env, addressObj, ia_addressID, + ntohl(remote_addr.sin_addr.s_addr)); + (*env)->SetIntField(env, addressObj, ia_familyID, IPv4); + + /* return port */ + return ntohs(remote_addr.sin_port); +} + +JNIEXPORT jint JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this, + jobject packet) { + + char BUF[MAX_BUFFER_LEN]; + char *fullPacket; + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); + + jbyteArray packetBuffer; + jint packetBufferOffset, packetBufferLen; + + int fd, fd1, fduse, nsockets=0, errorCode; + int port; + jbyteArray data; + + int checkBoth = 0, datalen; + int n; + SOCKETADDRESS remote_addr; + jint remote_addrsize=sizeof(remote_addr); + BOOL retry; + jlong prevTime = 0; + + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + if (fd < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + return -1; + } + nsockets = 1; + } + + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + if (fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + return -1; + } + nsockets ++; + } + + switch (nsockets) { + case 0: + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + return -1; + case 1: + if (!IS_NULL(fdObj)) { + fduse = fd; + } else { + fduse = fd1; + } + break; + case 2: + checkBoth = TRUE; + break; + } + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "packet"); + return -1; + } + + packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); + + if (IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "packet buffer"); + return -1; + } + + packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); + packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); + + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* When JNI-ifying the JDK's IO routines, we turned + * read's and write's of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + */ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return -1; + } + } else { + fullPacket = &(BUF[0]); + } + + do { + int ret; + retry = FALSE; + + /* + * If a timeout has been specified then we select on the socket + * waiting for a read event or a timeout. + */ + if (checkBoth) { + int t = timeout == 0 ? -1: timeout; + prevTime = JVM_CurrentTimeMillis(env, 0); + ret = NET_Timeout2 (fd, fd1, t, &fduse); + /* all subsequent calls to recv() or select() will use the same fd + * for this call to peek() */ + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", + "Peek timed out"); + } else if (ret == JVM_IO_ERR) { + NET_ThrowCurrent(env, "timeout in datagram socket peek"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; + } + if (ret == 2) { + fduse = checkLastFD (env, this, fd, fd1); + } + checkBoth = FALSE; + } else if (timeout) { + if (prevTime == 0) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + ret = NET_Timeout (fduse, timeout); + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env,JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; + } + } + + /* receive the packet */ + n = recvfrom(fduse, fullPacket, packetBufferLen, MSG_PEEK, + (struct sockaddr *)&remote_addr, &remote_addrsize); + port = (int) ntohs ((u_short) GET_PORT((SOCKETADDRESS *)&remote_addr)); + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + jboolean connected; + + /* + * An icmp port unreachable - we must receive this as Windows + * does not reset the state of the socket until this has been + * received. + */ + purgeOutstandingICMP(env, this, fduse); + + connected = (*env)->GetBooleanField(env, this, pdsi_connected); + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + "ICMP Port Unreachable"); + + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout befor the icmp port + * unreachable arrived. + */ + if (timeout) { + jlong newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + if (timeout <= 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return -1; + } + prevTime = newTime; + } + retry = TRUE; + } + } + } while (retry); + + /* truncate the data if the packet's length is too small */ + if (n > packetBufferLen) { + n = packetBufferLen; + } + if (n < 0) { + errorCode = WSAGetLastError(); + /* check to see if it's because the buffer was too small */ + if (errorCode == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + n = packetBufferLen; + } else { + /* failure */ + (*env)->SetIntField(env, packet, dp_lengthID, 0); + } + } + if (n == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + } else if (n == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } else if (n < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + jobject packetAddress; + + /* + * Check if there is an InetAddress already associated with this + * packet. If so we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *) + &remote_addr, packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = NULL; + } + } + if (packetAddress == NULL) { + packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *) + &remote_addr, &port); + /* stuff the new Inetaddress in the packet */ + (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); + } + + /* populate the packet */ + (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, + (jbyte *)fullPacket); + (*env)->SetIntField(env, packet, dp_portID, port); + (*env)->SetIntField(env, packet, dp_lengthID, n); + } + + /* make sure receive() picks up the right fd */ + (*env)->SetIntField(env, this, pdsi_fduseID, fduse); + + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return port; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: receive + * Signature: (Ljava/net/DatagramPacket;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this, + jobject packet) { + + char BUF[MAX_BUFFER_LEN]; + char *fullPacket; + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID); + jbyteArray packetBuffer; + jint packetBufferOffset, packetBufferLen; + int ipv6_supported = ipv6_available(); + + /* as a result of the changes for ipv6, peek() or peekData() + * must be called prior to receive() so that fduse can be set. + */ + int fd, fd1, fduse, errorCode; + jbyteArray data; + + int datalen; + int n, nsockets=0; + SOCKETADDRESS remote_addr; + jint remote_addrsize=sizeof(remote_addr); + BOOL retry; + jlong prevTime = 0, selectTime=0; + jboolean connected; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } + + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + nsockets ++; + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + nsockets ++; + } + + if (nsockets == 2) { /* need to choose one of them */ + /* was fduse set in peek? */ + fduse = (*env)->GetIntField(env, this, pdsi_fduseID); + if (fduse == -1) { + /* not set in peek(), must select on both sockets */ + int ret, t = (timeout == 0) ? -1: timeout; + ret = NET_Timeout2 (fd, fd1, t, &fduse); + if (ret == 2) { + fduse = checkLastFD (env, this, fd, fd1); + } else if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + return; + } + } + } else if (!ipv6_supported) { + fduse = fd; + } else if (IS_NULL(fdObj)) { + /* ipv6 supported: and this socket bound to an IPV6 only address */ + fduse = fd1; + } else { + /* ipv6 supported: and this socket bound to an IPV4 only address */ + fduse = fd; + } + + if (IS_NULL(packet)) { + JNU_ThrowNullPointerException(env, "packet"); + return; + } + + packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID); + + if (IS_NULL(packetBuffer)) { + JNU_ThrowNullPointerException(env, "packet buffer"); + return; + } + + packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID); + packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID); + + if (packetBufferLen > MAX_BUFFER_LEN) { + + /* When JNI-ifying the JDK's IO routines, we turned + * read's and write's of byte arrays of size greater + * than 2048 bytes into several operations of size 2048. + * This saves a malloc()/memcpy()/free() for big + * buffers. This is OK for file IO and TCP, but that + * strategy violates the semantics of a datagram protocol. + * (one big send) != (several smaller sends). So here + * we *must* alloc the buffer. Note it needn't be bigger + * than 65,536 (0xFFFF) the max size of an IP packet. + * anything bigger is truncated anyway. + */ + fullPacket = (char *)malloc(packetBufferLen); + if (!fullPacket) { + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + return; + } + } else { + fullPacket = &(BUF[0]); + } + + + + /* + * If this Windows edition supports ICMP port unreachable and if we + * are not connected then we need to know if a timeout has been specified + * and if so we need to pick up the current time. These are required in + * order to implement the semantics of timeout, viz :- + * timeout set to t1 but ICMP port unreachable arrives in t2 where + * t2 < t1. In this case we must discard the ICMP packets and then + * wait for the next packet up to a maximum of t1 minus t2. + */ + connected = (*env)->GetBooleanField(env, this, pdsi_connected); + if (supportPortUnreachable() && !connected && timeout &&!ipv6_supported) { + prevTime = JVM_CurrentTimeMillis(env, 0); + } + + if (timeout && nsockets == 1) { + int ret; + ret = NET_Timeout(fduse, timeout); + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return; + } + } + + /* + * Loop only if we discarding ICMP port unreachable packets + */ + do { + retry = FALSE; + + /* receive the packet */ + n = recvfrom(fduse, fullPacket, packetBufferLen, 0, + (struct sockaddr *)&remote_addr, &remote_addrsize); + + if (n == JVM_IO_ERR) { + if (WSAGetLastError() == WSAECONNRESET) { + /* + * An icmp port unreachable has been received - consume any other + * outstanding packets. + */ + purgeOutstandingICMP(env, this, fduse); + + /* + * If connected throw a PortUnreachableException + */ + + if (connected) { + JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException", + "ICMP Port Unreachable"); + + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + + return; + } + + /* + * If a timeout was specified then we need to adjust it because + * we may have used up some of the timeout before the icmp port + * unreachable arrived. + */ + if (timeout) { + int ret; + jlong newTime = JVM_CurrentTimeMillis(env, 0); + timeout -= (newTime - prevTime); + prevTime = newTime; + + if (timeout <= 0) { + ret = 0; + } else { + ret = NET_Timeout(fduse, timeout); + } + + if (ret <= 0) { + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Receive timed out"); + } else if (ret == JVM_IO_ERR) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else if (ret == JVM_IO_INTR) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } + return; + } + } + + /* + * An ICMP port unreachable was received but we are + * not connected so ignore it. + */ + retry = TRUE; + } + } + } while (retry); + + /* truncate the data if the packet's length is too small */ + if (n > packetBufferLen) { + n = packetBufferLen; + } + if (n < 0) { + errorCode = WSAGetLastError(); + /* check to see if it's because the buffer was too small */ + if (errorCode == WSAEMSGSIZE) { + /* it is because the buffer is too small. It's UDP, it's + * unreliable, it's all good. discard the rest of the + * data.. + */ + n = packetBufferLen; + } else { + /* failure */ + (*env)->SetIntField(env, packet, dp_lengthID, 0); + } + } + if (n == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + } else if (n == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } else if (n < 0) { + NET_ThrowCurrent(env, "Datagram receive failed"); + } else { + int port; + jobject packetAddress; + + /* + * Check if there is an InetAddress already associated with this + * packet. If so we check if it is the same source address. We + * can't update any existing InetAddress because it is immutable + */ + packetAddress = (*env)->GetObjectField(env, packet, dp_addressID); + + if (packetAddress != NULL) { + if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) { + /* force a new InetAddress to be created */ + packetAddress = NULL; + } + } + if (packetAddress == NULL) { + packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port); + /* stuff the new Inetaddress in the packet */ + (*env)->SetObjectField(env, packet, dp_addressID, packetAddress); + } else { + /* only get the new port number */ + port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr); + } + /* populate the packet */ + (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n, + (jbyte *)fullPacket); + (*env)->SetIntField(env, packet, dp_portID, port); + (*env)->SetIntField(env, packet, dp_lengthID, n); + } + if (packetBufferLen > MAX_BUFFER_LEN) { + free(fullPacket); + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: datagramSocketCreate + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env, + jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + + int fd, fd1; + int t = TRUE; + DWORD x1, x2; /* ignored result codes */ + int ipv6_supported = ipv6_available(); + + int arg = -1; + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return; + } else { + fd = (int) socket (AF_INET, SOCK_DGRAM, 0); + } + if (fd == JVM_IO_ERR) { + NET_ThrowCurrent(env, "Socket creation failed"); + return; + } + SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); + NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); + + if (ipv6_supported) { + /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which + * returns connection reset errors un connected UDP sockets (as well + * as connected sockets. The solution is to only enable this feature + * when the socket is connected + */ + t = FALSE; + WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + t = TRUE; + fd1 = socket (AF_INET6, SOCK_DGRAM, 0); + if (fd1 == JVM_IO_ERR) { + NET_ThrowCurrent(env, "Socket creation failed"); + return; + } + NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, (char*)&t, sizeof(BOOL)); + t = FALSE; + WSAIoctl(fd1,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0); + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + SetHandleInformation((HANDLE)(UINT_PTR)fd1, HANDLE_FLAG_INHERIT, FALSE); + } else { + /* drop the second fd */ + (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: datagramSocketClose + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env, + jobject this) { + /* + * REMIND: PUT A LOCK AROUND THIS CODE + */ + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + int ipv6_supported = ipv6_available(); + int fd=-1, fd1=-1; + + if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { + return; + } + + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + if (fd != -1) { + (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + NET_SocketClose(fd); + } + } + + if (ipv6_supported && fd1Obj != NULL) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + if (fd1 == -1) { + return; + } + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + NET_SocketClose(fd1); + } +} + +/* + * check the addresses attached to the NetworkInterface object + * and return the first one (of the requested family Ipv4 or Ipv6) + * in *iaddr + */ + +static int getInetAddrFromIf (JNIEnv *env, int family, jobject nif, jobject *iaddr) +{ + jobjectArray addrArray; + static jfieldID ni_addrsID=0; + static jfieldID ia_familyID=0; + jsize len; + jobject addr; + int i; + + if (ni_addrsID == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL_RETURN (c, -1); + ni_addrsID = (*env)->GetFieldID(env, c, "addrs", + "[Ljava/net/InetAddress;"); + CHECK_NULL_RETURN (ni_addrsID, -1); + c = (*env)->FindClass(env,"java/net/InetAddress"); + CHECK_NULL_RETURN (c, -1); + ia_familyID = (*env)->GetFieldID(env, c, "family", "I"); + CHECK_NULL_RETURN (ia_familyID, -1); + } + + addrArray = (*env)->GetObjectField(env, nif, ni_addrsID); + len = (*env)->GetArrayLength(env, addrArray); + + /* + * Check that there is at least one address bound to this + * interface. + */ + if (len < 1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface"); + return -1; + } + for (i=0; iGetObjectArrayElement(env, addrArray, i); + fam = (*env)->GetIntField(env, addr, ia_familyID); + if (fam == family) { + *iaddr = addr; + return 0; + } + } + return -1; +} + +static int getInet4AddrFromIf (JNIEnv *env, jobject nif, struct in_addr *iaddr) +{ + jobject addr; + static jfieldID ia_addressID; + + int ret = getInetAddrFromIf (env, IPv4, nif, &addr); + if (ret == -1) { + return -1; + } + + if (ia_addressID == 0) { + jclass c = (*env)->FindClass(env,"java/net/InetAddress"); + CHECK_NULL_RETURN (c, -1); + ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); + CHECK_NULL_RETURN (ia_addressID, -1); + } + iaddr->s_addr = htonl((*env)->GetIntField(env, addr, ia_addressID)); + return 0; +} + +/* Get the multicasting index from the interface */ + +static int getIndexFromIf (JNIEnv *env, jobject nif) { + static jfieldID ni_indexID; + + if (ni_indexID == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL_RETURN(c, -1); + ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); + CHECK_NULL_RETURN(ni_indexID, -1); + } + + return (*env)->GetIntField(env, nif, ni_indexID); +} + +/* + * Sets the multicast interface. + * + * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :- + * IPv4: set outgoing multicast interface using + * IPPROTO_IP/IP_MULTICAST_IF + * + * IPv6: Get the interface to which the + * InetAddress is bound + * and do same as SockOptions.IF_MULTICAST_IF2 + * + * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :- + * For each stack: + * IPv4: Obtain IP address bound to network interface + * (NetworkInterface.addres[0]) + * set outgoing multicast interface using + * IPPROTO_IP/IP_MULTICAST_IF + * + * IPv6: Obtain NetworkInterface.index + * Set outgoing multicast interface using + * IPPROTO_IPV6/IPV6_MULTICAST_IF + * + */ +static void setMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, + jint opt, jobject value) +{ + int ipv6_supported = ipv6_available(); + + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + /* + * value is an InetAddress. + * On IPv4 system use IP_MULTICAST_IF socket option + * On IPv6 system get the NetworkInterface that this IP + * address is bound to and use the IPV6_MULTICAST_IF + * option instead of IP_MULTICAST_IF + */ + if (ipv6_supported) { + static jclass ni_class; + if (ni_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL(c); + ni_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL(ni_class); + } + + value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); + if (value == NULL) { + if (!(*env)->ExceptionOccurred(env)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "bad argument for IP_MULTICAST_IF" + ": address not bound to any interface"); + } + return; + } + opt = java_net_SocketOptions_IP_MULTICAST_IF2; + } else { + static jfieldID ia_addressID; + struct in_addr in; + + if (ia_addressID == NULL) { + jclass c = (*env)->FindClass(env,"java/net/InetAddress"); + CHECK_NULL(c); + ia_addressID = (*env)->GetFieldID(env, c, "address", "I"); + CHECK_NULL(ia_addressID); + } + + in.s_addr = htonl((*env)->GetIntField(env, value, ia_addressID)); + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (const char*)&in, sizeof(in)) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error setting socket option"); + } + return; + } + } + + if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + /* + * value is a NetworkInterface. + * On IPv6 system get the index of the interface and use the + * IPV6_MULTICAST_IF socket option + * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF + * option. For IPv6 both must be done. + */ + if (ipv6_supported) { + static jfieldID ni_indexID; + struct in_addr in; + int index; + + if (ni_indexID == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL(c); + ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); + CHECK_NULL(ni_indexID); + } + index = (*env)->GetIntField(env, value, ni_indexID); + + if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, + (const char*)&index, sizeof(index)) < 0) { + if (errno == EINVAL && index > 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "IPV6_MULTICAST_IF failed (interface has IPv4 " + "address only?)"); + } else { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error setting socket option"); + } + return; + } + + /* If there are any IPv4 addresses on this interface then + * repeat the operation on the IPv4 fd */ + + if (getInet4AddrFromIf (env, value, &in) < 0) { + return; + } + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (const char*)&in, sizeof(in)) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error setting socket option"); + } + return; + } else { + struct in_addr in; + + if (getInet4AddrFromIf (env, value, &in) < 0) { + if ((*env)->ExceptionOccurred(env)) { + return; + } + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "no InetAddress instances of requested type"); + return; + } + + if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (const char*)&in, sizeof(in)) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error setting socket option"); + } + return; + } + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: socketSetOption + * Signature: (ILjava/lang/Object;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobject this, + jint opt,jobject value) { + + int fd=-1, fd1=-1; + int levelv4, levelv6, optnamev4, optnamev6, optlen; + union { + int i; + char c; + } optval; + int ipv6_supported = ipv6_available(); + + fd = getFD(env, this); + + if (ipv6_supported) { + fd1 = getFD1(env, this); + } + if (fd < 0 && fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + return; + } + + if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || + (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { + + setMulticastInterface(env, this, fd, fd1, opt, value); + return; + } + + /* + * Map the Java level socket option to the platform specific + * level(s) and option name(s). + */ + if (fd1 != -1) { + if (NET_MapSocketOptionV6(opt, &levelv6, &optnamev6)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + return; + } + } + if (fd != -1) { + if (NET_MapSocketOption(opt, &levelv4, &optnamev4)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + return; + } + } + + switch (opt) { + case java_net_SocketOptions_SO_SNDBUF : + case java_net_SocketOptions_SO_RCVBUF : + case java_net_SocketOptions_IP_TOS : + { + jclass cls; + jfieldID fid; + + cls = (*env)->FindClass(env, "java/lang/Integer"); + CHECK_NULL(cls); + fid = (*env)->GetFieldID(env, cls, "value", "I"); + CHECK_NULL(fid); + + optval.i = (*env)->GetIntField(env, value, fid); + optlen = sizeof(optval.i); + } + break; + + case java_net_SocketOptions_SO_REUSEADDR: + case java_net_SocketOptions_SO_BROADCAST: + case java_net_SocketOptions_IP_MULTICAST_LOOP: + { + jclass cls; + jfieldID fid; + jboolean on; + + cls = (*env)->FindClass(env, "java/lang/Boolean"); + CHECK_NULL(cls); + fid = (*env)->GetFieldID(env, cls, "value", "Z"); + CHECK_NULL(fid); + + on = (*env)->GetBooleanField(env, value, fid); + optval.i = (on ? 1 : 0); + /* + * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather + * than enabling it. + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { + optval.i = !optval.i; + } + optlen = sizeof(optval.i); + } + break; + + default : + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket option not supported by PlainDatagramSocketImp"); + break; + + } + + if (fd1 != -1) { + if (NET_SetSockOpt(fd1, levelv6, optnamev6, (void *)&optval, optlen) < 0) { + NET_ThrowCurrent(env, "setsockopt IPv6"); + return; + } + } + if (fd != -1) { + if (NET_SetSockOpt(fd, levelv4, optnamev4, (void *)&optval, optlen) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + return; + } + } +} + +/* + * Return the multicast interface: + * + * SocketOptions.IP_MULTICAST_IF + * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF + * Create InetAddress + * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 + * kernel but struct in_addr on 2.4 kernel + * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or + * obtain from impl is Linux 2.2 kernel + * If index == 0 return InetAddress representing + * anyLocalAddress. + * If index > 0 query NetworkInterface by index + * and returns addrs[0] + * + * SocketOptions.IP_MULTICAST_IF2 + * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF + * Query NetworkInterface by IP address and + * return the NetworkInterface that the address + * is bound too. + * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF + * (except Linux .2 kernel) + * Query NetworkInterface by index and + * return NetworkInterface. + */ +jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, int fd1, jint opt) { + jboolean isIPV4 = !ipv6_available() || fd1 == -1; + + /* + * IPv4 implementation + */ + if (isIPV4) { + static jclass inet4_class; + static jmethodID inet4_ctrID; + static jfieldID inet4_addrID; + + static jclass ni_class; + static jmethodID ni_ctrID; + static jfieldID ni_indexID; + static jfieldID ni_addrsID; + + jobjectArray addrArray; + jobject addr; + jobject ni; + + struct in_addr in; + struct in_addr *inP = ∈ + int len = sizeof(struct in_addr); + + if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (char *)inP, &len) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error getting socket option"); + return NULL; + } + + /* + * Construct and populate an Inet4Address + */ + if (inet4_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); + CHECK_NULL_RETURN(c, NULL); + inet4_ctrID = (*env)->GetMethodID(env, c, "", "()V"); + CHECK_NULL_RETURN(inet4_ctrID, NULL); + inet4_addrID = (*env)->GetFieldID(env, c, "address", "I"); + CHECK_NULL_RETURN(inet4_addrID, NULL); + inet4_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(inet4_class, NULL); + } + addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); + CHECK_NULL_RETURN(addr, NULL); + + (*env)->SetIntField(env, addr, inet4_addrID, ntohl(in.s_addr)); + + /* + * For IP_MULTICAST_IF return InetAddress + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + return addr; + } + + /* + * For IP_MULTICAST_IF2 we get the NetworkInterface for + * this address and return it + */ + if (ni_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL_RETURN(c, NULL); + ni_ctrID = (*env)->GetMethodID(env, c, "", "()V"); + CHECK_NULL_RETURN(ni_ctrID, NULL); + ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); + CHECK_NULL_RETURN(ni_indexID, NULL); + ni_addrsID = (*env)->GetFieldID(env, c, "addrs", + "[Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(ni_addrsID, NULL); + ni_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(ni_class, NULL); + } + ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); + if (ni) { + return ni; + } + + /* + * The address doesn't appear to be bound at any known + * NetworkInterface. Therefore we construct a NetworkInterface + * with this address. + */ + ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); + CHECK_NULL_RETURN(ni, NULL); + + (*env)->SetIntField(env, ni, ni_indexID, -1); + addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); + CHECK_NULL_RETURN(addrArray, NULL); + (*env)->SetObjectArrayElement(env, addrArray, 0, addr); + (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); + return ni; + } + + + /* + * IPv6 implementation + */ + if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || + (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { + + static jclass ni_class; + static jmethodID ni_ctrID; + static jfieldID ni_indexID; + static jfieldID ni_addrsID; + static jclass ia_class; + static jmethodID ia_anyLocalAddressID; + + int index; + int len = sizeof(index); + + jobjectArray addrArray; + jobject addr; + jobject ni; + + { + if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, + (char*)&index, &len) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error getting socket option"); + return NULL; + } + } + + if (ni_class == NULL) { + jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); + CHECK_NULL_RETURN(c, NULL); + ni_ctrID = (*env)->GetMethodID(env, c, "", "()V"); + CHECK_NULL_RETURN(ni_ctrID, NULL); + ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); + CHECK_NULL_RETURN(ni_indexID, NULL); + ni_addrsID = (*env)->GetFieldID(env, c, "addrs", + "[Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(ni_addrsID, NULL); + + ia_class = (*env)->FindClass(env, "java/net/InetAddress"); + CHECK_NULL_RETURN(ia_class, NULL); + ia_class = (*env)->NewGlobalRef(env, ia_class); + CHECK_NULL_RETURN(ia_class, NULL); + ia_anyLocalAddressID = (*env)->GetStaticMethodID(env, + ia_class, + "anyLocalAddress", + "()Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL); + ni_class = (*env)->NewGlobalRef(env, c); + CHECK_NULL_RETURN(ni_class, NULL); + } + + /* + * If multicast to a specific interface then return the + * interface (for IF2) or the any address on that interface + * (for IF). + */ + if (index > 0) { + ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, + index); + if (ni == NULL) { + char errmsg[255]; + sprintf(errmsg, + "IPV6_MULTICAST_IF returned index to unrecognized interface: %d", + index); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); + return NULL; + } + + /* + * For IP_MULTICAST_IF2 return the NetworkInterface + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + return ni; + } + + /* + * For IP_MULTICAST_IF return addrs[0] + */ + addrArray = (*env)->GetObjectField(env, ni, ni_addrsID); + if ((*env)->GetArrayLength(env, addrArray) < 1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "IPV6_MULTICAST_IF returned interface without IP bindings"); + return NULL; + } + + addr = (*env)->GetObjectArrayElement(env, addrArray, 0); + return addr; + } + + /* + * Multicast to any address - return anyLocalAddress + * or a NetworkInterface with addrs[0] set to anyLocalAddress + */ + + addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID, + NULL); + if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { + return addr; + } + + ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); + CHECK_NULL_RETURN(ni, NULL); + (*env)->SetIntField(env, ni, ni_indexID, -1); + addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL); + CHECK_NULL_RETURN(addrArray, NULL); + (*env)->SetObjectArrayElement(env, addrArray, 0, addr); + (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); + return ni; + } + return NULL; +} +/* + * Returns relevant info as a jint. + * + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: socketGetOption + * Signature: (I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, + jint opt) { + + int fd=-1, fd1=-1; + int level, optname, optlen; + union { + int i; + } optval; + int ipv6_supported = ipv6_available(); + + fd = getFD(env, this); + if (ipv6_supported) { + fd1 = getFD1(env, this); + } + + if (fd < 0 && fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return NULL; + } + + /* + * Handle IP_MULTICAST_IF separately + */ + if (opt == java_net_SocketOptions_IP_MULTICAST_IF || + opt == java_net_SocketOptions_IP_MULTICAST_IF2) { + return getMulticastInterface(env, this, fd, fd1, opt); + } + + if (opt == java_net_SocketOptions_SO_BINDADDR) { + /* find out local IP address */ + SOCKETADDRESS him; + int len = 0; + int port; + jobject iaObj; + + len = sizeof (struct sockaddr_in); + + if (fd == -1) { + fd = fd1; /* must be IPv6 only */ + len = sizeof (struct SOCKADDR_IN6); + } + + if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error getting socket name"); + return NULL; + } + iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); + + return iaObj; + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + if (NET_MapSocketOption(opt, &level, &optname)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + return NULL; + } + + if (fd == -1) { + if (NET_MapSocketOptionV6(opt, &level, &optname)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + return NULL; + } + fd = fd1; /* must be IPv6 only */ + } + + optlen = sizeof(optval.i); + if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { + char errmsg[255]; + sprintf(errmsg, "error getting socket option: %s\n", strerror(errno)); + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg); + return NULL; + } + + switch (opt) { + case java_net_SocketOptions_SO_BROADCAST: + case java_net_SocketOptions_SO_REUSEADDR: + return createBoolean(env, optval.i); + + case java_net_SocketOptions_IP_MULTICAST_LOOP: + /* getLoopbackMode() returns true if IP_MULTICAST_LOOP is disabled */ + return createBoolean(env, !optval.i); + + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: + return createInteger(env, optval.i); + + default : + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket option not supported by TwoStacksPlainDatagramSocketImpl"); + return NULL; + + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: setTimeToLive + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this, + jint ttl) { + + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + int fd = -1, fd1 = -1; + int ittl = (int)ttl; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } else { + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + } + + /* setsockopt to be correct ttl */ + if (fd >= 0) { + if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl, + sizeof (ittl)) < 0) { + NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); + } + } + + if (fd1 >= 0) { + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ittl, + sizeof(ittl)) <0) { + NET_ThrowCurrent(env, "set IPV6_MULTICAST_HOPS failed"); + } + } +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: setTTL + * Signature: (B)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this, + jbyte ttl) { + Java_java_net_TwoStacksPlainDatagramSocketImpl_setTimeToLive(env, this, + (jint)ttl & 0xFF); +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: getTimeToLive + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + int fd = -1, fd1 = -1; + int ttl = 0; + int len = sizeof(ttl); + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return -1; + } else { + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + } + + /* getsockopt of ttl */ + if (fd >= 0) { + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, &len) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); + return -1; + } + return (jint)ttl; + } + if (fd1 >= 0) { + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&ttl, &len) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); + return -1; + } + return (jint)ttl; + } + return -1; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: getTTL + * Signature: ()B + */ +JNIEXPORT jbyte JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_getTTL(JNIEnv *env, jobject this) { + int result = Java_java_net_TwoStacksPlainDatagramSocketImpl_getTimeToLive(env, this); + + return (jbyte)result; +} + +/* join/leave the named group on the named interface, or if no interface specified + * then the interface set with setInterfac(), or the default interface otherwise */ + +static void mcast_join_leave(JNIEnv *env, jobject this, + jobject iaObj, jobject niObj, + jboolean join) +{ + jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID); + jint fd = -1, fd1 = -1; + + SOCKETADDRESS name; + struct ip_mreq mname; + struct ipv6_mreq mname6; + + struct in_addr in; + DWORD ifindex; + + int len, family; + int ipv6_supported = ipv6_available(); + int cmd ; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (ipv6_supported && !IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "address"); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, 0, (struct sockaddr *)&name, &len, JNI_FALSE) != 0) { + return; + } + + /* Set the multicast group address in the ip_mreq field + * eventually this check should be done by the security manager + */ + family = name.him.sa_family; + + if (family == AF_INET) { + int address = name.him4.sin_addr.s_addr; + if (!IN_MULTICAST(ntohl(address))) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in multicast"); + return; + } + mname.imr_multiaddr.s_addr = address; + if (fd < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv4 group on an IPv6 only socket"); + return; + } + if (IS_NULL(niObj)) { + len = sizeof (in); + if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, + (char *)&in, &len) < 0) { + NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed"); + return; + } + mname.imr_interface.s_addr = in.s_addr; + } else { + if (getInet4AddrFromIf (env, niObj, &mname.imr_interface) != 0) { + NET_ThrowCurrent(env, "no Inet4Address associated with interface"); + return; + } + } + + cmd = join ? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP; + + /* Join the multicast group */ + if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, (char *) &mname, sizeof (mname)) < 0) { + if (WSAGetLastError() == WSAENOBUFS) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); + } + } + } else /* AF_INET6 */ { + if (ipv6_supported) { + struct in6_addr *address; + address = &name.him6.sin6_addr; + if (!IN6_IS_ADDR_MULTICAST(address)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "not in6 multicast"); + return; + } + mname6.ipv6mr_multiaddr = *address; + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "IPv6 not supported"); + return; + } + if (fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Can't join an IPv6 group on a IPv4 socket"); + return; + } + if (IS_NULL(niObj)) { + len = sizeof (ifindex); + if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, &len) < 0) { + NET_ThrowCurrent(env, "get IPV6_MULTICAST_IF failed"); + return; + } + } else { + ifindex = getIndexFromIf (env, niObj); + if (ifindex == -1) { + NET_ThrowCurrent(env, "get ifindex failed"); + return; + } + } + mname6.ipv6mr_interface = ifindex; + cmd = join ? IPV6_ADD_MEMBERSHIP: IPV6_DROP_MEMBERSHIP; + + /* Join the multicast group */ + if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, (char *) &mname6, sizeof (mname6)) < 0) { + if (WSAGetLastError() == WSAENOBUFS) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException","error setting options"); + } + } + } + + return; +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: join + * Signature: (Ljava/net/InetAddress;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_join(JNIEnv *env, jobject this, + jobject iaObj, jobject niObj) +{ + mcast_join_leave (env, this, iaObj, niObj, JNI_TRUE); +} + +/* + * Class: java_net_TwoStacksPlainDatagramSocketImpl + * Method: leave + * Signature: (Ljava/net/InetAddress;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainDatagramSocketImpl_leave(JNIEnv *env, jobject this, + jobject iaObj, jobject niObj) +{ + mcast_join_leave (env, this, iaObj, niObj, JNI_FALSE); +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/TwoStacksPlainSocketImpl.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,1156 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "java_net_SocketOptions.h" +#include "java_net_TwoStacksPlainSocketImpl.h" +#include "java_net_SocketImpl.h" +#include "java_net_InetAddress.h" +#include "java_io_FileDescriptor.h" +#include "java_lang_Integer.h" + +#include "jvm.h" +#include "net_util.h" +#include "jni_util.h" + +/************************************************************************ + * TwoStacksPlainSocketImpl + */ + +static jfieldID IO_fd_fdID; + +jfieldID psi_fdID; +jfieldID psi_fd1ID; +jfieldID psi_addressID; +jfieldID psi_portID; +jfieldID psi_localportID; +jfieldID psi_timeoutID; +jfieldID psi_trafficClassID; +jfieldID psi_serverSocketID; +jfieldID psi_lastfdID; + +/* + * the level of the TCP protocol for setsockopt and getsockopt + * we only want to look this up once, from the static initializer + * of TwoStacksPlainSocketImpl + */ +static int tcp_level = -1; + +static int getFD(JNIEnv *env, jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + + if (fdObj == NULL) { + return -1; + } + return (*env)->GetIntField(env, fdObj, IO_fd_fdID); +} + +static int getFD1(JNIEnv *env, jobject this) { + jobject fdObj = (*env)->GetObjectField(env, this, psi_fd1ID); + + if (fdObj == NULL) { + return -1; + } + return (*env)->GetIntField(env, fdObj, IO_fd_fdID); +} + + +/* + * The initProto function is called whenever TwoStacksPlainSocketImpl is + * loaded, to cache fieldIds for efficiency. This is called everytime + * the Java class is loaded. + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: initProto + + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { + + struct protoent *proto = getprotobyname("TCP"); + tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); + + psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); + CHECK_NULL(psi_fdID); + psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;"); + CHECK_NULL(psi_fd1ID); + psi_addressID = (*env)->GetFieldID(env, cls, "address", + "Ljava/net/InetAddress;"); + CHECK_NULL(psi_addressID); + psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); + CHECK_NULL(psi_portID); + psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); + CHECK_NULL(psi_portID); + psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); + CHECK_NULL(psi_localportID); + psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); + CHECK_NULL(psi_timeoutID); + psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); + CHECK_NULL(psi_trafficClassID); + psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket", + "Ljava/net/ServerSocket;"); + CHECK_NULL(psi_serverSocketID); + IO_fd_fdID = NET_GetFileDescriptorID(env); + CHECK_NULL(IO_fd_fdID); +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketCreate + * Signature: (Z)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketCreate(JNIEnv *env, jobject this, + jboolean stream) { + jobject fdObj, fd1Obj; + int fd, fd1; + + fdObj = (*env)->GetObjectField(env, this, psi_fdID); + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "null fd object"); + return; + } + fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); + if (fd == -1) { + NET_ThrowCurrent(env, "create"); + return; + } else { + /* Set socket attribute so it is not passed to any child process */ + SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); + (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); + } + if (ipv6_available()) { + fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + + if (IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "null fd1 object"); + (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + NET_SocketClose(fd); + return; + } + fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); + if (fd1 == -1) { + NET_ThrowCurrent(env, "create"); + (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + NET_SocketClose(fd); + return; + } else { + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + } + } else { + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + } +} + +/* + * inetAddress is the address object passed to the socket connect + * call. + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketConnect + * Signature: (Ljava/net/InetAddress;I)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketConnect(JNIEnv *env, jobject this, + jobject iaObj, jint port, + jint timeout) +{ + jint localport = (*env)->GetIntField(env, this, psi_localportID); + + /* family and localport are int fields of iaObj */ + int family; + jint fd, fd1=-1; + jint len; + int ipv6_supported = ipv6_available(); + + /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket + * If we want to connect to IPv6 then we swap the two sockets/objects + * This way, fd is always the connected socket, and fd1 always gets closed. + */ + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + + SOCKETADDRESS him; + + /* The result of the connection */ + int connect_res; + + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + + if (ipv6_supported && !IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "inet address argument is null."); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_FALSE) != 0) { + return; + } + + family = him.him.sa_family; + if (family == AF_INET6) { + if (!ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Protocol family not supported"); + return; + } else { + if (fd1 == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Destination unreachable"); + return; + } + /* close the v4 socket, and set fd to be the v6 socket */ + (*env)->SetObjectField(env, this, psi_fdID, fd1Obj); + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + NET_SocketClose(fd); + fd = fd1; fdObj = fd1Obj; + } + } else { + if (fd1 != -1) { + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + NET_SocketClose(fd1); + } + if (fd == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Destination unreachable"); + return; + } + } + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + + if (timeout <= 0) { + connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); + if (connect_res == SOCKET_ERROR) { + connect_res = WSAGetLastError(); + } + } else { + int optval; + int optlen = sizeof(optval); + + /* make socket non-blocking */ + optval = 1; + ioctlsocket( fd, FIONBIO, &optval ); + + /* initiate the connect */ + connect_res = connect(fd, (struct sockaddr *) &him, SOCKETADDRESS_LEN(&him)); + if (connect_res == SOCKET_ERROR) { + if (WSAGetLastError() != WSAEWOULDBLOCK) { + connect_res = WSAGetLastError(); + } else { + fd_set wr, ex; + struct timeval t; + + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(fd, &wr); + FD_SET(fd, &ex); + t.tv_sec = timeout / 1000; + t.tv_usec = (timeout % 1000) * 1000; + + /* + * Wait for timout, connection established or + * connection failed. + */ + connect_res = select(fd+1, 0, &wr, &ex, &t); + + /* + * Timeout before connection is established/failed so + * we throw exception and shutdown input/output to prevent + * socket from being used. + * The socket should be closed immediately by the caller. + */ + if (connect_res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "connect timed out"); + shutdown( fd, SD_BOTH ); + + /* make socket blocking again - just in case */ + optval = 0; + ioctlsocket( fd, FIONBIO, &optval ); + return; + } + + /* + * We must now determine if the connection has been established + * or if it has failed. The logic here is designed to work around + * bug on Windows NT whereby using getsockopt to obtain the + * last error (SO_ERROR) indicates there is no error. The workaround + * on NT is to allow winsock to be scheduled and this is done by + * yielding and retrying. As yielding is problematic in heavy + * load conditions we attempt up to 3 times to get the error reason. + */ + if (!FD_ISSET(fd, &ex)) { + connect_res = 0; + } else { + int retry; + for (retry=0; retry<3; retry++) { + NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, + (char*)&connect_res, &optlen); + if (connect_res) { + break; + } + Sleep(0); + } + + if (connect_res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Unable to establish connection"); + return; + } + } + } + } + + /* make socket blocking again */ + optval = 0; + ioctlsocket(fd, FIONBIO, &optval); + } + + if (connect_res) { + if (connect_res == WSAEADDRNOTAVAIL) { + JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException", + "connect: Address is invalid on local machine, or port is not valid on remote machine"); + } else { + NET_ThrowNew(env, connect_res, "connect"); + } + return; + } + + (*env)->SetIntField(env, fdObj, IO_fd_fdID, (int)fd); + + /* set the remote peer address and port */ + (*env)->SetObjectField(env, this, psi_addressID, iaObj); + (*env)->SetIntField(env, this, psi_portID, port); + + /* + * we need to initialize the local port field if bind was called + * previously to the connect (by the client) then localport field + * will already be initialized + */ + if (localport == 0) { + /* Now that we're a connected socket, let's extract the port number + * that the system chose for us and store it in the Socket object. + */ + u_short port; + int len = SOCKETADDRESS_LEN(&him); + if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { + + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + } else { + NET_ThrowCurrent(env, "getsockname failed"); + } + return; + } + port = ntohs ((u_short)GET_PORT(&him)); + (*env)->SetIntField(env, this, psi_localportID, (int) port); + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketBind + * Signature: (Ljava/net/InetAddress;I)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, + jobject iaObj, jint localport) { + + /* fdObj is the FileDescriptor field on this */ + jobject fdObj, fd1Obj; + /* fd is an int field on fdObj */ + int fd, fd1, len; + int ipv6_supported = ipv6_available(); + + /* family is an int field of iaObj */ + int family; + int rv; + + SOCKETADDRESS him; + + fdObj = (*env)->GetObjectField(env, this, psi_fdID); + fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + + family = (*env)->GetIntField(env, iaObj, ia_familyID); + + if (family == IPv6 && !ipv6_supported) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Protocol family not supported"); + return; + } + + if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + if (ipv6_supported) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + } + if (IS_NULL(iaObj)) { + JNU_ThrowNullPointerException(env, "inet address argument"); + return; + } + + if (NET_InetAddressToSockaddr(env, iaObj, localport, + (struct sockaddr *)&him, &len, JNI_FALSE) != 0) { + return; + } + + if (ipv6_supported) { + struct ipv6bind v6bind; + v6bind.addr = &him; + v6bind.ipv4_fd = fd; + v6bind.ipv6_fd = fd1; + rv = NET_BindV6(&v6bind); + if (rv != -1) { + /* check if the fds have changed */ + if (v6bind.ipv4_fd != fd) { + fd = v6bind.ipv4_fd; + if (fd == -1) { + /* socket is closed. */ + (*env)->SetObjectField(env, this, psi_fdID, NULL); + } else { + /* socket was re-created */ + (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd); + } + } + if (v6bind.ipv6_fd != fd1) { + fd1 = v6bind.ipv6_fd; + if (fd1 == -1) { + /* socket is closed. */ + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + } else { + /* socket was re-created */ + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); + } + } + } + } else { + rv = NET_Bind(fd, (struct sockaddr *)&him, len); + } + + if (rv == -1) { + NET_ThrowCurrent(env, "JVM_Bind"); + return; + } + + /* set the address */ + (*env)->SetObjectField(env, this, psi_addressID, iaObj); + + /* intialize the local port */ + if (localport == 0) { + /* Now that we're a bound socket, let's extract the port number + * that the system chose for us and store it in the Socket object. + */ + int len = SOCKETADDRESS_LEN(&him); + u_short port; + fd = him.him.sa_family == AF_INET? fd: fd1; + + if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) { + NET_ThrowCurrent(env, "getsockname in plain socketBind"); + return; + } + port = ntohs ((u_short) GET_PORT (&him)); + + (*env)->SetIntField(env, this, psi_localportID, (int) port); + } else { + (*env)->SetIntField(env, this, psi_localportID, localport); + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketListen + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketListen (JNIEnv *env, jobject this, + jint count) +{ + /* this FileDescriptor fd field */ + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + jobject address; + /* fdObj's int fd field */ + int fd, fd1; + SOCKETADDRESS addr; int addrlen; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + return; + } + + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + /* Listen on V4 if address type is v4 or if v6 and address is ::0. + * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. + * In cases, where we listen on one space only, we close the other socket. + */ + address = (*env)->GetObjectField(env, this, psi_addressID); + if (IS_NULL(address)) { + JNU_ThrowNullPointerException(env, "socket address"); + return; + } + if (NET_InetAddressToSockaddr(env, address, 0, (struct sockaddr *)&addr, + &addrlen, JNI_FALSE) != 0) { + return; + } + + if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(&addr.him6)) { + /* listen on v4 */ + if (listen(fd, count) == -1) { + NET_ThrowCurrent(env, "listen failed"); + } + } else { + NET_SocketClose (fd); + (*env)->SetObjectField(env, this, psi_fdID, NULL); + } + if (ipv6_available() && !IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) { + /* listen on v6 */ + if (listen(fd1, count) == -1) { + NET_ThrowCurrent(env, "listen failed"); + } + } else { + NET_SocketClose (fd1); + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); + } + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketAccept + * Signature: (Ljava/net/SocketImpl;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, + jobject socket) +{ + /* fields on this */ + jint port; + jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + + /* the FileDescriptor field on socket */ + jobject socketFdObj; + + jclass inet4Cls, inet6Cls; + /* the InetAddress field on socket */ + jobject socketAddressObj; + + /* the fd int field on fdObj */ + jint fd=-1, fd1=-1; + + SOCKETADDRESS him; + jint len; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + if (IS_NULL(socket)) { + JNU_ThrowNullPointerException(env, "socket is null"); + return; + } else { + socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID); + socketAddressObj = (*env)->GetObjectField(env, socket, psi_addressID); + } + if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { + JNU_ThrowNullPointerException(env, "socket address or fd obj"); + return; + } + if (fd != -1 && fd1 != -1) { + fd_set rfds; + struct timeval t, *tP=&t; + int lastfd, res, fd2; + FD_ZERO(&rfds); + FD_SET(fd,&rfds); + FD_SET(fd1,&rfds); + if (timeout) { + t.tv_sec = timeout/1000; + t.tv_usec = (timeout%1000)*1000; + } else { + tP = NULL; + } + res = select (fd, &rfds, NULL, NULL, tP); + if (res == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Accept timed out"); + return; + } else if (res == 1) { + fd2 = FD_ISSET(fd, &rfds)? fd: fd1; + } else if (res == 2) { + /* avoid starvation */ + lastfd = (*env)->GetIntField(env, this, psi_lastfdID); + if (lastfd != -1) { + fd2 = lastfd==fd? fd1: fd; + } else { + fd2 = fd; + } + (*env)->SetIntField(env, this, psi_lastfdID, fd2); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "select failed"); + return; + } + if (fd2 == fd) { /* v4 */ + len = sizeof (struct sockaddr_in); + } else { + len = sizeof (struct SOCKADDR_IN6); + } + fd = fd2; + } else { + int ret; + if (fd1 != -1) { + fd = fd1; + len = sizeof (struct SOCKADDR_IN6); + } else { + len = sizeof (struct sockaddr_in); + } + if (timeout) { + ret = NET_Timeout(fd, timeout); + if (ret == 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", + "Accept timed out"); + return; + } else if (ret == -1) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed"); + /* REMIND: SOCKET CLOSED PROBLEM */ + /* NET_ThrowCurrent(env, "Accept failed"); */ + return; + } else if (ret == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + return; + } + } + } + fd = accept(fd, (struct sockaddr *)&him, &len); + if (fd < 0) { + /* REMIND: SOCKET CLOSED PROBLEM */ + if (fd == -2) { + JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", + "operation interrupted"); + } else { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket closed"); + } + return; + } + (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd); + + if (him.him.sa_family == AF_INET) { + /* + * fill up the remote peer port and address in the new socket structure + */ + inet4Cls = (*env)->FindClass(env, "java/net/Inet4Address"); + if (inet4Cls != NULL) { + socketAddressObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); + } else { + socketAddressObj = NULL; + } + if (socketAddressObj == NULL) { + /* + * FindClass or NewObject failed so close connection and + * exist (there will be a pending exception). + */ + NET_SocketClose(fd); + return; + } + + (*env)->SetIntField(env, socketAddressObj, ia_addressID, + ntohl(him.him4.sin_addr.s_addr)); + (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv4); + (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); + } else { + jbyteArray addr; + /* AF_INET6 -> Inet6Address */ + inet6Cls = (*env)->FindClass(env, "java/net/Inet6Address"); + if (inet6Cls != NULL) { + socketAddressObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); + } else { + socketAddressObj = NULL; + } + if (socketAddressObj == NULL) { + /* + * FindClass or NewObject failed so close connection and + * exist (there will be a pending exception). + */ + NET_SocketClose(fd); + return; + } + addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID); + (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr); + (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6); + (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id); + } + /* fields common to AF_INET and AF_INET6 */ + + port = ntohs ((u_short) GET_PORT (&him)); + (*env)->SetIntField(env, socket, psi_portID, (int)port); + port = (*env)->GetIntField(env, this, psi_localportID); + (*env)->SetIntField(env, socket, psi_localportID, port); + (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketAvailable + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) { + + jint available = -1; + jint res; + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jint fd; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return -1; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + res = ioctlsocket(fd, FIONREAD, &available); + /* if result isn't 0, it means an error */ + if (res != 0) { + NET_ThrowNew(env, res, "socket available"); + } + return available; +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketClose + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketClose0(JNIEnv *env, jobject this, + jboolean useDeferredClose) { + + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); + jint fd=-1, fd1=-1; + + if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket already closed"); + return; + } + if (!IS_NULL(fdObj)) { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (!IS_NULL(fd1Obj)) { + fd1 = (*env)->GetIntField(env, fd1Obj, IO_fd_fdID); + } + if (fd != -1) { + (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1); + NET_SocketClose(fd); + } + if (fd1 != -1) { + (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, -1); + NET_SocketClose(fd1); + } +} + +/* + * Socket options for plainsocketImpl + * + * + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketSetOption + * Signature: (IZLjava/lang/Object;)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this, + jint cmd, jboolean on, + jobject value) { + int fd, fd1; + int level, optname, optlen; + union { + int i; + struct linger ling; + } optval; + + /* + * Get SOCKET and check that it hasn't been closed + */ + fd = getFD(env, this); + fd1 = getFD1(env, this); + if (fd < 0 && fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return; + } + + /* + * SO_TIMEOUT is the socket option used to specify the timeout + * for ServerSocket.accept and Socket.getInputStream().read. + * It does not typically map to a native level socket option. + * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO + * socket option to specify a receive timeout on the socket. This + * receive timeout is applicable to Socket only and the socket + * option should not be set on ServerSocket. + */ + if (cmd == java_net_SocketOptions_SO_TIMEOUT) { + + /* + * Don't enable the socket option on ServerSocket as it's + * meaningless (we don't receive on a ServerSocket). + */ + jobject ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID); + if (ssObj != NULL) { + return; + } + + /* + * SO_RCVTIMEO is only supported on Microsoft's implementation + * of Windows Sockets so if WSAENOPROTOOPT returned then + * reset flag and timeout will be implemented using + * select() -- see SocketInputStream.socketRead. + */ + if (isRcvTimeoutSupported) { + jclass iCls = (*env)->FindClass(env, "java/lang/Integer"); + jfieldID i_valueID; + jint timeout; + + CHECK_NULL(iCls); + i_valueID = (*env)->GetFieldID(env, iCls, "value", "I"); + CHECK_NULL(i_valueID); + timeout = (*env)->GetIntField(env, value, i_valueID); + + /* + * Disable SO_RCVTIMEO if timeout is <= 5 second. + */ + if (timeout <= 5000) { + timeout = 0; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)) < 0) { + if (WSAGetLastError() == WSAENOPROTOOPT) { + isRcvTimeoutSupported = JNI_FALSE; + } else { + NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + } + } + if (fd1 != -1) { + if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, + sizeof(timeout)) < 0) { + NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); + } + } + } + return; + } + + /* + * Map the Java level socket option to the platform specific + * level + */ + if (NET_MapSocketOption(cmd, &level, &optname)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Invalid option"); + return; + } + + switch (cmd) { + + case java_net_SocketOptions_TCP_NODELAY : + case java_net_SocketOptions_SO_OOBINLINE : + case java_net_SocketOptions_SO_KEEPALIVE : + case java_net_SocketOptions_SO_REUSEADDR : + optval.i = (on ? 1 : 0); + optlen = sizeof(optval.i); + break; + + case java_net_SocketOptions_SO_SNDBUF : + case java_net_SocketOptions_SO_RCVBUF : + case java_net_SocketOptions_IP_TOS : + { + jclass cls; + jfieldID fid; + + cls = (*env)->FindClass(env, "java/lang/Integer"); + CHECK_NULL(cls); + fid = (*env)->GetFieldID(env, cls, "value", "I"); + CHECK_NULL(fid); + + optval.i = (*env)->GetIntField(env, value, fid); + optlen = sizeof(optval.i); + } + break; + + case java_net_SocketOptions_SO_LINGER : + { + jclass cls; + jfieldID fid; + + cls = (*env)->FindClass(env, "java/lang/Integer"); + CHECK_NULL(cls); + fid = (*env)->GetFieldID(env, cls, "value", "I"); + CHECK_NULL(fid); + + if (on) { + optval.ling.l_onoff = 1; + optval.ling.l_linger = (*env)->GetIntField(env, value, fid); + } else { + optval.ling.l_onoff = 0; + optval.ling.l_linger = 0; + } + optlen = sizeof(optval.ling); + } + break; + + default: /* shouldn't get here */ + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Option not supported by TwoStacksPlainSocketImpl"); + return; + } + + if (fd != -1) { + if (NET_SetSockOpt(fd, level, optname, (void *)&optval, optlen) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + } + } + + if (fd1 != -1) { + if (NET_SetSockOpt(fd1, level, optname, (void *)&optval, optlen) < 0) { + NET_ThrowCurrent(env, "setsockopt"); + } + } +} + + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketGetOption + * Signature: (I)I + */ +JNIEXPORT jint JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this, + jint opt, jobject iaContainerObj) { + + int fd, fd1; + int level, optname, optlen; + union { + int i; + struct linger ling; + } optval; + + /* + * Get SOCKET and check it hasn't been closed + */ + fd = getFD(env, this); + fd1 = getFD1(env, this); + + if (fd < 0 && fd1 < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return -1; + } + if (fd < 0) { + fd = fd1; + } + + /* For IPv6, we assume both sockets have the same setting always */ + + /* + * SO_BINDADDR isn't a socket option + */ + if (opt == java_net_SocketOptions_SO_BINDADDR) { + SOCKET_ADDRESS him; + int len; + int port; + jobject iaObj; + jclass iaCntrClass; + jfieldID iaFieldID; + + len = sizeof(struct sockaddr_in); + + if (fd == -1) { + /* must be an IPV6 only socket. Case where both sockets are != -1 + * is handled in java + */ + fd = getFD1 (env, this); + len = sizeof(struct SOCKADDR_IN6); + } + + if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", + "Error getting socket name"); + return -1; + } + iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port); + CHECK_NULL_RETURN(iaObj, -1); + + iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj); + iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(iaFieldID, -1); + (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); + return 0; /* notice change from before */ + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + if (NET_MapSocketOption(opt, &level, &optname)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option"); + return -1; + } + + /* + * Args are int except for SO_LINGER + */ + if (opt == java_net_SocketOptions_SO_LINGER) { + optlen = sizeof(optval.ling); + } else { + optlen = sizeof(optval.i); + optval.i = 0; + } + + if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { + NET_ThrowCurrent(env, "getsockopt"); + return -1; + } + + switch (opt) { + case java_net_SocketOptions_SO_LINGER: + return (optval.ling.l_onoff ? optval.ling.l_linger: -1); + + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: + return optval.i; + + case java_net_SocketOptions_TCP_NODELAY : + case java_net_SocketOptions_SO_OOBINLINE : + case java_net_SocketOptions_SO_KEEPALIVE : + case java_net_SocketOptions_SO_REUSEADDR : + return (optval.i == 0) ? -1 : 1; + + default: /* shouldn't get here */ + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Option not supported by TwoStacksPlainSocketImpl"); + return -1; + } +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketShutdown + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketShutdown(JNIEnv *env, jobject this, + jint howto) +{ + + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + jint fd; + + /* + * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being + * -1 already? + */ + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "socket already closed"); + return; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + shutdown(fd, howto); +} + +/* + * Class: java_net_TwoStacksPlainSocketImpl + * Method: socketSendUrgentData + * Signature: (B)V + */ +JNIEXPORT void JNICALL +Java_java_net_TwoStacksPlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this, + jint data) { + /* The fd field */ + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + int n, fd; + unsigned char d = data & 0xff; + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); + return; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + /* Bug 4086704 - If the Socket associated with this file descriptor + * was closed (sysCloseFD), the the file descriptor is set to -1. + */ + if (fd == -1) { + JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); + return; + } + + } + n = send(fd, (char *)&data, 1, MSG_OOB); + if (n == JVM_IO_ERR) { + NET_ThrowCurrent(env, "send"); + return; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); + return; + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/net_util_md.c --- a/j2se/src/windows/native/java/net/net_util_md.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/java/net/net_util_md.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -822,31 +822,52 @@ } /* If address types is IPv6, then IPv6 must be available. Otherwise - * no address can be generated. Note if an IPv4 mapped address is passed - * an IPv4 sockaddr_in will be returned. - */ + * no address can be generated. In the case of an IPv4 Inetaddress this + * method will return an IPv4 mapped address where IPv6 is available and + * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in + * structure for an IPv4 InetAddress. +*/ JNIEXPORT int JNICALL -NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len) { +NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, + int *len, jboolean v4MappedAddress) { jint family, iafam; iafam = (*env)->GetIntField(env, iaObj, ia_familyID); family = (iafam == IPv4)? AF_INET : AF_INET6; - if (ipv6_available() && family==AF_INET6) { + if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) { struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; jbyteArray ipaddress; jbyte caddr[16]; - jint address, scopeid; - jint cached_scope_id; + jint address, scopeid = 0; + jint cached_scope_id = 0; - ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); - scopeid = (jint)(*env)->GetIntField(env, iaObj, ia6_scopeidID); - cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); + if (family == AF_INET) { /* will convert to IPv4-mapped address */ + memset((char *) caddr, 0, 16); + address = (*env)->GetIntField(env, iaObj, ia_addressID); + if (address == INADDR_ANY) { + /* we would always prefer IPv6 wildcard address + caddr[10] = 0xff; + caddr[11] = 0xff; */ + } else { + caddr[10] = 0xff; + caddr[11] = 0xff; + caddr[12] = ((address >> 24) & 0xff); + caddr[13] = ((address >> 16) & 0xff); + caddr[14] = ((address >> 8) & 0xff); + caddr[15] = (address & 0xff); + } + } else { + ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); + scopeid = (jint)(*env)->GetIntField(env, iaObj, ia6_scopeidID); + cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); + (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); + } memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6)); him6->sin6_port = (u_short) htons((u_short)port); memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) ); him6->sin6_family = AF_INET6; - if (!scopeid && !cached_scope_id) { + if ((family == AF_INET6) && IN6_IS_ADDR_LINKLOCAL( &(him6->sin6_addr) ) + && (!scopeid && !cached_scope_id)) { cached_scope_id = getDefaultIPv6Interface(env, him6); (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id); } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/java/net/net_util_md.h --- a/j2se/src/windows/native/java/net/net_util_md.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/java/net/net_util_md.h Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,6 +146,13 @@ return (a->s6_bytes[0] == 0xff); } +WS2TCPIP_INLINE int +IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *a) +{ + return (a->s6_bytes[0] == 0xfe + && a->s6_bytes[1] == 0x80); +} + #define NI_MAXHOST 1025 /* Max size of a fully-qualified domain name */ #define NI_MAXSERV 32 /* Max size of a service name */ @@ -218,6 +225,10 @@ ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0)) #endif +#ifndef IPV6_V6ONLY +#define IPV6_V6ONLY 27 /* Treat wildcard bind as AF_INET6-only. */ +#endif + #include "java_io_FileDescriptor.h" #include "java_net_SocketOptions.h" diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/nio/ch/DatagramChannelImpl.c --- a/j2se/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/nio/ch/DatagramChannelImpl.c Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -282,7 +282,7 @@ if (NET_InetAddressToSockaddr(env, destAddress, destPort, (struct sockaddr *)&psa, - &sa_len) != 0) { + &sa_len, JNI_FALSE) != 0) { return IOS_THROWN; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/nio/ch/Net.c --- a/j2se/src/windows/native/sun/nio/ch/Net.c Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/nio/ch/Net.c Thu Jul 05 23:47:33 2007 +0000 @@ -80,7 +80,7 @@ int rv; int sa_len = sizeof(sa); - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len) != 0) { + if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) { return; } @@ -97,7 +97,7 @@ int rv; int sa_len = sizeof(sa); - if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len) != 0) { + if (NET_InetAddressToSockaddr(env, iao, port, (struct sockaddr *)&sa, &sa_len, JNI_FALSE) != 0) { return IOS_THROWN; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Canvas.cpp --- a/j2se/src/windows/native/sun/windows/awt_Canvas.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Canvas.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -32,13 +32,20 @@ /* IMPORTANT! Read the README.JNI file for notes on JNI converted AWT code. */ +// Struct for _SetEraseBackground() method +struct SetEraseBackgroundStruct { + jobject canvas; + jboolean doErase; + jboolean doEraseOnResize; +}; + /************************************************************************ * AwtCanvas methods */ AwtCanvas::AwtCanvas() { - m_eraseBackground = JNI_TRUE; - m_eraseBackgroundAlways = JNI_TRUE; + m_eraseBackground = JNI_TRUE; + m_eraseBackgroundOnResize = JNI_TRUE; } AwtCanvas::~AwtCanvas() { @@ -144,27 +151,10 @@ CATCH_BAD_ALLOC_RET(0); } -static BOOL eraseBackgroundConfigured = FALSE; -static BOOL eraseBackgroundDisabled; -static BOOL eraseBackgroundOnResize; - MsgRouting AwtCanvas::WmEraseBkgnd(HDC hDC, BOOL& didErase) { - if (!eraseBackgroundConfigured) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jclass peerCls = env->FindClass("sun/awt/windows/WCanvasPeer"); - DASSERT(peerCls != NULL); - jfieldID fieldID; - fieldID = env->GetStaticFieldID(peerCls, "eraseBackgroundDisabled", "Z"); - eraseBackgroundDisabled = env->GetStaticBooleanField(peerCls, fieldID); - fieldID = env->GetStaticFieldID(peerCls, "eraseBackgroundOnResize", "Z"); - eraseBackgroundOnResize = env->GetStaticBooleanField(peerCls, fieldID); - env->DeleteLocalRef(peerCls); - eraseBackgroundConfigured = TRUE; - } - if ((m_eraseBackground || AwtWindow::IsResizing()) && - (!eraseBackgroundDisabled || - (AwtWindow::IsResizing() && eraseBackgroundOnResize)) && m_eraseBackgroundAlways) + if (m_eraseBackground || + (m_eraseBackgroundOnResize && AwtWindow::IsResizing())) { RECT rc; ::GetClipBox(hDC, &rc); @@ -211,28 +201,25 @@ return AwtComponent::HandleEvent(msg, synthetic); } -void AwtCanvas::disableBackgroundErase(void *param) { +void AwtCanvas::_SetEraseBackground(void *param) +{ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - jobject selfGlobalRef = (jobject)param; + SetEraseBackgroundStruct *sebs = (SetEraseBackgroundStruct *)param; + jobject canvas = sebs->canvas; + jboolean doErase = sebs->doErase; + jboolean doEraseOnResize = sebs->doEraseOnResize; - if (selfGlobalRef == NULL) { - JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", - "Peer null in JNI"); - return; - } - PDATA pData = JNI_GET_PDATA(selfGlobalRef); - if (pData == NULL) { - JNU_ThrowByName(env, "java/awt/IllegalComponentStateException", - "Native resources unavailable"); - env->DeleteGlobalRef(selfGlobalRef); - return; - } + PDATA pData; + JNI_CHECK_PEER_GOTO(canvas, ret); AwtCanvas *c = (AwtCanvas*)pData; - c->m_eraseBackgroundAlways = JNI_FALSE; + c->m_eraseBackground = doErase; + c->m_eraseBackgroundOnResize = doEraseOnResize; - env->DeleteGlobalRef(selfGlobalRef); +ret: + env->DeleteGlobalRef(canvas); + delete sebs; } @@ -266,33 +253,18 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WCanvasPeer_setNativeBackgroundErase(JNIEnv *env, jobject self, - jboolean doErase) + jboolean doErase, + jboolean doEraseOnResize) { TRY; - // This method is called only once during initialization so it is safe - // to call it directly on non-Toolkit thread. - AwtCanvas *c = (AwtCanvas *) JNI_GET_PDATA(self); - if (c != NULL) { - c->setEraseBackground(doErase); - } - CATCH_BAD_ALLOC; -} + SetEraseBackgroundStruct *sebs = new SetEraseBackgroundStruct; + sebs->canvas = env->NewGlobalRef(self); + sebs->doErase = doErase; + sebs->doEraseOnResize = doEraseOnResize; -/* - * Class: sun_awt_windows_WCanvasPeer - * Method: disableNativeBackgroundErase - * Signature: ()V - */ - JNIEXPORT void JNICALL - Java_sun_awt_windows_WCanvasPeer_disableNativeBackgroundErase(JNIEnv *env, - jobject self) -{ - TRY; - - jobject selfGlobalRef = env->NewGlobalRef(self); - AwtToolkit::GetInstance().SyncCall(AwtCanvas::disableBackgroundErase, selfGlobalRef); - // selfGlobalRef is deleted in disableBackgroundErase() + AwtToolkit::GetInstance().SyncCall(AwtCanvas::_SetEraseBackground, sebs); + // sebs and global ref are deleted in _SetEraseBackground() CATCH_BAD_ALLOC; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Canvas.h --- a/j2se/src/windows/native/sun/windows/awt_Canvas.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Canvas.h Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,16 +48,11 @@ virtual MsgRouting HandleEvent(MSG *msg, BOOL synthetic); static void _ResetTargetGC(void *); - - INLINE void setEraseBackground(jboolean doErase) { m_eraseBackground = doErase; } - - static void disableBackgroundErase(void *); + static void _SetEraseBackground(void *); private: - // for Swing heavyweights, if it's false, then the background is erased only on resize jboolean m_eraseBackground; - // for Canvas, if it's false, then the background is never erased - jboolean m_eraseBackgroundAlways; + jboolean m_eraseBackgroundOnResize; }; #endif /* AWT_CANVAS_H */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Component.cpp --- a/j2se/src/windows/native/sun/windows/awt_Component.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Component.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -2061,6 +2061,12 @@ if (comp && comp->IsEmbeddedFrame() && !((AwtFrame*)comp)->activateEmbeddedFrameOnSetFocus(hWndLostFocus)) { + // Fix for 6562716. + // In order that AwtSetFocus() returns FALSE. + sm_suppressFocusAndActivation = TRUE; + ::SetFocus(NULL); + sm_suppressFocusAndActivation = FALSE; + return mrConsume; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Dialog.cpp --- a/j2se/src/windows/native/sun/windows/awt_Dialog.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Dialog.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -47,8 +47,6 @@ jfieldID AwtDialog::titleID; jfieldID AwtDialog::undecoratedID; -jmethodID AwtDialog::getWindowsMID; - #if defined(DEBUG) // counts how many nested modal dialogs are open, a sanity // check to ensure the somewhat complicated disable/enable @@ -246,10 +244,10 @@ { ::ShowWindow(topMostBlocker, SW_SHOWNA); } + ::BringWindowToTop(blocker); blocker = AwtWindow::GetModalBlocker(blocker); } if (topMostBlocker != toolkitHWnd) { - ::BringWindowToTop(topMostBlocker); ::SetForegroundWindow(topMostBlocker); } return 1; @@ -277,12 +275,11 @@ HWND topMostBlocker = blocker; while (::IsWindow(blocker)) { topMostBlocker = blocker; + ::BringWindowToTop(blocker); blocker = AwtWindow::GetModalBlocker(blocker); } - if ((::IsWindow(topMostBlocker)) && - (topMostBlocker != AwtToolkit::GetInstance().GetHWnd())) - { - // no beep if the mouse was clicked in the taskbar menu + if (::IsWindow(topMostBlocker)) { + // no beep/flash if the mouse was clicked in the taskbar menu // or the dialog is currently inactive if ((::WindowFromPoint(mhs->pt) == hWnd) && (::GetForegroundWindow() == topMostBlocker)) @@ -291,8 +288,10 @@ // some heuristics: 3 times x 64 milliseconds AwtWindow::FlashWindowEx(topMostBlocker, 3, 64, FLASHW_CAPTION); } - ::BringWindowToTop(topMostBlocker); - ::SetForegroundWindow(topMostBlocker); + if (topMostBlocker != AwtToolkit::GetInstance().GetHWnd()) { + ::BringWindowToTop(topMostBlocker); + ::SetForegroundWindow(topMostBlocker); + } } } } @@ -419,18 +418,13 @@ } } -void AwtDialog::ModalActivateNextWindow(HWND dialogHWnd, HWND parentHWnd, +void AwtDialog::ModalActivateNextWindow(HWND dialogHWnd, jobject dialogTarget, jobject dialogPeer) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - // give parent the first chance - if (ModalCanBeActivated(parentHWnd)) { - AwtDialog::ModalPerformActivation(parentHWnd); - return; - } - - jlongArray windows = (jlongArray)(env->CallObjectMethod(dialogPeer, AwtDialog::getWindowsMID)); + jlongArray windows = (jlongArray)(env->CallStaticObjectMethod(AwtWindow::wwindowPeerCls, + AwtWindow::getActiveWindowsMID)); if (windows == NULL) { return; } @@ -485,7 +479,7 @@ jobject peer = GetPeer(env); jobject target = GetTarget(env); if (::GetForegroundWindow() == GetHWnd()) { - ModalActivateNextWindow(GetHWnd(), parentHWnd, target, peer); + ModalActivateNextWindow(GetHWnd(), target, peer); } // hide the dialog SendMessage(WM_AWT_COMPONENT_HIDE); @@ -715,15 +709,9 @@ AwtDialog::undecoratedID = env->GetFieldID(cls,"undecorated","Z"); - jclass wwindowPeerCls = env->FindClass("sun/awt/windows/WWindowPeer"); - AwtDialog::getWindowsMID = - env->GetMethodID(wwindowPeerCls, "getWindowHandles", "()[J"); - DASSERT(AwtDialog::undecoratedID != NULL); DASSERT(AwtDialog::titleID != NULL); - DASSERT(AwtDialog::getWindowsMID != NULL); - CATCH_BAD_ALLOC; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Dialog.h --- a/j2se/src/windows/native/sun/windows/awt_Dialog.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Dialog.h Thu Jul 05 23:47:33 2007 +0000 @@ -47,9 +47,6 @@ /* boolean undecorated field for java.awt.Dialog */ static jfieldID undecoratedID; - /* long[] getWindowHandles() method in WWindowPeer */ - static jmethodID getWindowsMID; - AwtDialog(); virtual ~AwtDialog(); @@ -83,7 +80,7 @@ } // finds and activates some window after the modal dialog is hidden - static void ModalActivateNextWindow(HWND dialogHWnd, HWND parentHWnd, + static void ModalActivateNextWindow(HWND dialogHWnd, jobject dialogTarget, jobject dialogPeer); // some methods called on Tookit thread diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_FileDialog.cpp --- a/j2se/src/windows/native/sun/windows/awt_FileDialog.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_FileDialog.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "awt_Dialog.h" #include "awt_Toolkit.h" #include "awt_dlls.h" +#include "ComCtl32Util.h" #include #include #include @@ -80,6 +81,30 @@ memcpy(s, s_additionalString, sizeof(s_additionalString)); } +LRESULT CALLBACK FileDialogWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + switch (message) { + case WM_COMMAND: { + if (LOWORD(wParam) == IDCANCEL) + { + // Unlike Print/Page dialogs, we only handle IDCANCEL here and + // don't handle IDOK. This is because user can press OK button + // when no file is selected, and the dialog is not closed. So + // OK button is handled in the CDN_FILEOK notification handler + // (see FileDialogHookProc below) + jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); + env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); + } + break; + } + } + + return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); +} + static UINT_PTR CALLBACK FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { @@ -87,40 +112,68 @@ TRY; + HWND parent = ::GetParent(hdlg); + switch(uiMsg) { case WM_INITDIALOG: { OPENFILENAME *ofn = (OPENFILENAME *)lParam; jobject peer = (jobject)(ofn->lCustData); env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, - (jlong)::GetParent(hdlg)); - ::SetWindowLongPtr(hdlg, DWLP_USER, (UINT_PTR)peer); + (jlong)parent); + ::SetProp(parent, ModalDialogPeerProp, reinterpret_cast(peer)); + // fix for 4508670 - disable CS_SAVEBITS DWORD style = ::GetClassLong(hdlg,GCL_STYLE); - ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS); + ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS); + + // set appropriate icon for parentless dialogs + jobject awtParent = env->GetObjectField(peer, AwtFileDialog::parentID); + if (awtParent == NULL) { + ::PostMessage(parent, WM_SETICON, (WPARAM)ICON_BIG, + (LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); + } else { + env->DeleteLocalRef(awtParent); + } + + // subclass dialog's parent to receive additional messages + ComCtl32Util::GetInstance().SubclassHWND(parent, + FileDialogWndProc); + break; } case WM_DESTROY: { - jobject peer = (jobject)::GetWindowLongPtr(hdlg, DWLP_USER); - env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); + ComCtl32Util::GetInstance().UnsubclassHWND(parent, + FileDialogWndProc, + NULL); + ::RemoveProp(parent, ModalDialogPeerProp); break; } case WM_NOTIFY: { - OFNOTIFYEX* notifyEx = (OFNOTIFYEX*)lParam; - if (notifyEx && notifyEx->hdr.code == CDN_INCLUDEITEM) { - jobject peer = (jobject)::GetWindowLongPtr(hdlg, DWLP_USER); - LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl; - // Get the filename and directory - TCHAR szPath[MAX_PATH]; - if (!get_path_from_idlist(pidl,szPath)) { - return TRUE; + OFNOTIFYEX *notifyEx = (OFNOTIFYEX *)lParam; + if (notifyEx) { + jobject peer = (jobject)(::GetProp(parent, ModalDialogPeerProp)); + if (notifyEx->hdr.code == CDN_INCLUDEITEM) { + LPITEMIDLIST pidl = (LPITEMIDLIST)notifyEx->pidl; + // Get the filename and directory + TCHAR szPath[MAX_PATH]; + if (!get_path_from_idlist(pidl,szPath)) { + return TRUE; + } + jstring strPath = JNU_NewStringPlatform(env, szPath); + // Call FilenameFilter.accept with path and filename + UINT uRes = (env->CallBooleanMethod(peer, + AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE); + env->DeleteLocalRef(strPath); + return uRes; + } else if (notifyEx->hdr.code == CDN_FILEOK) { + // This notification is sent when user selects some file and presses + // OK button; it is not sent when no file is selected. So it's time + // to unblock all the windows blocked by this dialog as it will + // be closed soon + env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); } - jstring strPath = JNU_NewStringPlatform(env, szPath); - // Call FilenameFilter.accept with path and filename - UINT uRes = (env->CallBooleanMethod(peer, - AwtFileDialog::checkFilenameFilterMID, strPath) == JNI_TRUE); - env->DeleteLocalRef(strPath); - return uRes; } + break; } } @@ -266,7 +319,7 @@ DASSERT(env->GetLongField(peer, AwtComponent::hwndID) == 0L); - AwtDialog::ModalActivateNextWindow(NULL, hwndOwner, target, peer); + AwtDialog::ModalActivateNextWindow(NULL, target, peer); VERIFY(::SetCurrentDirectory(currentDirectory)); @@ -328,31 +381,17 @@ BOOL AwtFileDialog::InheritsNativeMouseWheelBehavior() {return true;} -void AwtFileDialog::_Dispose(void *param) +void AwtFileDialog::_DisposeOrHide(void *param) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject self = (jobject)param; + HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); if (::IsWindow(hdlg)) { ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), - (LPARAM)hdlg); - } - - env->DeleteGlobalRef(self); -} - -void AwtFileDialog::_Hide(void *param) -{ - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - - jobject self = (jobject)param; - HWND hdlg = (HWND)(env->GetLongField(self, AwtComponent::hwndID)); - if (::IsWindow(hdlg)) - { - ::SendMessage(hdlg, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), - (LPARAM)hdlg); + (LPARAM)hdlg); } env->DeleteGlobalRef(self); @@ -470,9 +509,9 @@ jobject peerGlobal = env->NewGlobalRef(peer); - AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_Dispose, + AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, (void *)peerGlobal); - // peerGlobal ref is deleted in _Dispose + // peerGlobal ref is deleted in _DisposeOrHide CATCH_BAD_ALLOC; } @@ -484,9 +523,9 @@ jobject peerGlobal = env->NewGlobalRef(peer); - AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_Hide, + AwtToolkit::GetInstance().SyncCall(AwtFileDialog::_DisposeOrHide, (void *)peerGlobal); - // peerGlobal ref is deleted in _Hide + // peerGlobal ref is deleted in _DisposeOrHide CATCH_BAD_ALLOC; } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_FileDialog.h --- a/j2se/src/windows/native/sun/windows/awt_FileDialog.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_FileDialog.h Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,8 +102,7 @@ virtual BOOL InheritsNativeMouseWheelBehavior(); // some methods called on Toolkit thread - static void _Dispose(void *param); - static void _Hide(void *param); + static void _DisposeOrHide(void *param); static void _ToFront(void *param); static void _ToBack(void *param); }; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Frame.cpp --- a/j2se/src/windows/native/sun/windows/awt_Frame.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Frame.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -114,6 +114,7 @@ m_iconic = FALSE; m_zoomed = FALSE; m_maxBoundsSet = FALSE; + m_forceResetZoomed = FALSE; isInManualMoveOrSize = FALSE; grabbedHitTest = 0; @@ -780,7 +781,7 @@ if (m_ignoreWmSize) { return mrDoDefault; } - + DTRACE_PRINTLN6("AwtFrame::WmSize: %dx%d,%s visible, state%s%s%s", w, h, ::IsWindowVisible(GetHWnd()) ? "" : " not", @@ -788,55 +789,67 @@ m_zoomed ? " zoomed" : "", m_iconic || m_zoomed ? "" : " normal"); + BOOL iconify = type == SIZE_MINIMIZED; + + // Note that zoom may be set to TRUE in several cases: + // 1. type == SIZE_MAXIMIZED means that either the user or + // the developer (via setExtendedState(MAXIMIZED_BOTH) + // maximizes the frame. + // 2. type == SIZE_MINIMIZED && isZoomed() means that a maximized + // frame is to be minimized. If the user minimizes a maximized + // frame, we need to keep the zoomed property TRUE. However, + // if the developer calls setExtendedState(ICONIFIED), i.e. + // w/o combining the ICONIFIED state with the MAXIMIZED state, + // we MUST RESET the zoomed property. + // The flag m_forceResetZoomed identifies the latter case. + BOOL zoom = + ( + type == SIZE_MAXIMIZED + || + (type == SIZE_MINIMIZED && isZoomed()) + ) + && !m_forceResetZoomed; + + // Set the new state and send appropriate Java event jint oldState = java_awt_Frame_NORMAL; - if (m_iconic) { - oldState |= java_awt_Frame_ICONIFIED; + if (isIconic()) { + oldState |= java_awt_Frame_ICONIFIED; } - if (m_zoomed) { - oldState |= java_awt_Frame_MAXIMIZED_BOTH; + if (isZoomed()) { + oldState |= java_awt_Frame_MAXIMIZED_BOTH; } jint newState = java_awt_Frame_NORMAL; - if (type == SIZE_MINIMIZED) { - DTRACE_PRINTLN("AwtFrame::WmSize: SIZE_MINIMIZED"); - newState |= java_awt_Frame_ICONIFIED; - if (m_zoomed) { - newState |= java_awt_Frame_MAXIMIZED_BOTH; - } - m_iconic = TRUE; + if (iconify) { + newState |= java_awt_Frame_ICONIFIED; } - else if (type == SIZE_MAXIMIZED) { - DTRACE_PRINTLN("AwtFrame::WmSize: SIZE_MAXIMIZED"); - newState |= java_awt_Frame_MAXIMIZED_BOTH; - m_iconic = FALSE; - m_zoomed = TRUE; - } - else if (type == SIZE_RESTORED) { - DTRACE_PRINTLN("AwtFrame::WmSize: SIZE_RESTORED"); - m_iconic = FALSE; - m_zoomed = FALSE; + if (zoom) { + newState |= java_awt_Frame_MAXIMIZED_BOTH; } + setIconic(iconify); + setZoomed(zoom); + jint changed = oldState ^ newState; if (changed != 0) { - DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x -> %x", - oldState, newState); - // report (de)iconification to old clients - if (changed & java_awt_Frame_ICONIFIED) { - if (newState & java_awt_Frame_ICONIFIED) { - SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED); - } else { - SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED); - } - } + DTRACE_PRINTLN2("AwtFrame::WmSize: reporting state change %x -> %x", + oldState, newState); + // report (de)iconification to old clients + if (changed & java_awt_Frame_ICONIFIED) { + if (newState & java_awt_Frame_ICONIFIED) { + SendWindowEvent(java_awt_event_WindowEvent_WINDOW_ICONIFIED); + } else { + SendWindowEvent(java_awt_event_WindowEvent_WINDOW_DEICONIFIED); + } + } - // New (since 1.4) state change event - SendWindowStateEvent(oldState, newState); + // New (since 1.4) state change event + SendWindowStateEvent(oldState, newState); } // If window is in iconic state, do not send COMPONENT_RESIZED event - if (m_iconic) { - return mrDoDefault; + if (isIconic()) { + return mrDoDefault; } return AwtWindow::WmSize(type, w, h); @@ -1231,7 +1244,8 @@ PDATA pData; JNI_CHECK_PEER_GOTO(self, ret); f = (AwtFrame *)pData; - if (::IsWindow(f->GetHWnd())) + HWND hwnd = f->GetHWnd(); + if (::IsWindow(hwnd)) { DASSERT(!IsBadReadPtr(f, sizeof(AwtFrame))); @@ -1239,9 +1253,6 @@ BOOL zoom = (state & java_awt_Frame_MAXIMIZED_BOTH) == java_awt_Frame_MAXIMIZED_BOTH; - HWND hwnd = f->GetHWnd(); - BOOL focusable = f->IsFocusableWindow(); - DTRACE_PRINTLN4("WFramePeer.setState:%s%s ->%s%s", f->isIconic() ? " iconic" : "", f->isZoomed() ? " zoomed" : "", @@ -1249,60 +1260,46 @@ zoom ? " zoomed" : ""); if (::IsWindowVisible(hwnd)) { - // Iconify first if necessary, so that for a complex state - // transition zoom state is changed when we are iconified - to - // reduce window flicker. - if (!f->isIconic() && iconify) { - if (focusable) { - ::ShowWindow(hwnd, SW_MINIMIZE); - } else { - ::ShowWindow(hwnd, SW_SHOWMINNOACTIVE); - } + BOOL focusable = f->IsFocusableWindow(); + + WINDOWPLACEMENT wp; + ::ZeroMemory(&wp, sizeof(wp)); + wp.length = sizeof(wp); + ::GetWindowPlacement(hwnd, &wp); + + // Iconify first. + // If both iconify & zoom are TRUE, handle this case + // with wp.flags field below. + if (iconify) { + wp.showCmd = focusable ? SW_MINIMIZE : SW_SHOWMINNOACTIVE; + } else if (zoom) { + wp.showCmd = focusable ? SW_SHOWMAXIMIZED : SW_MAXIMIZE; + } else { // zoom == iconify == FALSE + wp.showCmd = focusable ? SW_RESTORE : SW_SHOWNOACTIVATE; } - // If iconified, handle zoom state change while/when in iconic state - if (zoom != f->isZoomed()) { - if (::IsIconic(hwnd)) { - // Arrange for window to be restored to specified state - WINDOWPLACEMENT wp; - ::ZeroMemory(&wp, sizeof(WINDOWPLACEMENT)); - wp.length = sizeof(WINDOWPLACEMENT); - ::GetWindowPlacement(hwnd, &wp); + if (zoom && iconify) { + wp.flags |= WPF_RESTORETOMAXIMIZED; + } else { + wp.flags &= ~WPF_RESTORETOMAXIMIZED; + } - if (zoom) { - wp.flags |= WPF_RESTORETOMAXIMIZED; - } else { - wp.flags &= ~WPF_RESTORETOMAXIMIZED; - } - ::SetWindowPlacement(hwnd, &wp); - } - else { - // Not iconified - just maximize it - if (focusable) { - ::ShowWindow(hwnd, zoom ? SW_SHOWMAXIMIZED : SW_RESTORE); - } else { - ::ShowWindow(hwnd, zoom ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); - } - } + if (!zoom) { + f->m_forceResetZoomed = TRUE; } - // Handle deiconify if necessary. - if (f->isIconic() && !iconify) { - if (focusable) { - ::ShowWindow(hwnd, SW_RESTORE); - } else { - ::ShowWindow(hwnd, SW_SHOWNOACTIVATE); - } - } + // The SetWindowPlacement() causes the WmSize() invocation + // which, in turn, actually updates the m_iconic & m_zoomed flags + // as well as sends Java event (WINDOW_STATE_CHANGED.) + ::SetWindowPlacement(hwnd, &wp); + + f->m_forceResetZoomed = FALSE; + } else { + DTRACE_PRINTLN(" not visible, just recording the requested state"); + + f->setIconic(iconify); + f->setZoomed(zoom); } -#ifdef DEBUG - else { - DTRACE_PRINTLN(" not visible, just recording the requested state"); - } -#endif - - f->setIconic(iconify); - f->setZoomed(zoom); } ret: env->DeleteGlobalRef(self); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Frame.h --- a/j2se/src/windows/native/sun/windows/awt_Frame.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Frame.h Thu Jul 05 23:47:33 2007 +0000 @@ -199,6 +199,9 @@ BOOL m_iconic; /* are we in an iconic state */ BOOL m_zoomed; /* are we in a zoomed state */ + + /* whether WmSize() must unconditionally reset zoomed state */ + BOOL m_forceResetZoomed; BOOL m_maxBoundsSet; POINT m_maxPos; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_PrintDialog.cpp --- a/j2se/src/windows/native/sun/windows/awt_PrintDialog.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_PrintDialog.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ #include "awt_Dialog.h" #include "awt_PrintControl.h" #include "awt_dlls.h" +#include "awt_Window.h" +#include "ComCtl32Util.h" #include #include @@ -44,6 +46,30 @@ data))); } +LRESULT CALLBACK PrintDialogWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + switch (message) { + case WM_COMMAND: { + if ((LOWORD(wParam) == IDOK) || + (LOWORD(wParam) == IDCANCEL)) + { + // If we recieve on of these two notifications, the dialog + // is about to be closed. It's time to unblock all the + // windows blocked by this dialog, as doing so from the + // WM_DESTROY handler is too late + jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); + env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)0); + } + break; + } + } + + return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); +} + static UINT_PTR CALLBACK PrintDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) { @@ -57,15 +83,34 @@ jobject peer = (jobject)(pd->lCustData); env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)hdlg); + ::SetProp(hdlg, ModalDialogPeerProp, reinterpret_cast(peer)); + // fix for 4632159 - disable CS_SAVEBITS - DWORD style = ::GetClassLong(hdlg,GCL_STYLE); - ::SetClassLong(hdlg,GCL_STYLE,style & ~CS_SAVEBITS); + DWORD style = ::GetClassLong(hdlg, GCL_STYLE); + ::SetClassLong(hdlg,GCL_STYLE, style & ~CS_SAVEBITS); + ::SetFocus(hdlg); + + // set appropriate icon for parentless dialogs + jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID); + if (awtParent == NULL) { + ::PostMessage(hdlg, WM_SETICON, (WPARAM)ICON_BIG, + (LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); + } else { + env->DeleteLocalRef(awtParent); + } + + // subclass dialog's parent to receive additional messages + ComCtl32Util::GetInstance().SubclassHWND(hdlg, + PrintDialogWndProc); + break; } case WM_DESTROY: { - jobject peer = (jobject)::GetWindowLongPtr(hdlg, DWLP_USER); - env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)0); + ComCtl32Util::GetInstance().UnsubclassHWND(hdlg, + PrintDialogWndProc, + NULL); + ::RemoveProp(hdlg, ModalDialogPeerProp); break; } } @@ -210,7 +255,7 @@ AwtDialog::CheckUninstallModalHook(); - AwtDialog::ModalActivateNextWindow(NULL, hwndOwner, target, peer); + AwtDialog::ModalActivateNextWindow(NULL, target, peer); } env->DeleteGlobalRef(peerGlobalRef); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_PrintJob.cpp --- a/j2se/src/windows/native/sun/windows/awt_PrintJob.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_PrintJob.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -37,6 +37,8 @@ #include "awt_Font.h" #include "awt_PrintDialog.h" #include "awt_PrintControl.h" +#include "awt_Window.h" +#include "ComCtl32Util.h" #include #include @@ -533,7 +535,7 @@ AwtDialog::CheckUninstallModalHook(); - AwtDialog::ModalActivateNextWindow(NULL, hwndOwner, target, peer); + AwtDialog::ModalActivateNextWindow(NULL, target, peer); HGLOBAL oldG = AwtPrintControl::getPrintHDMode(env, self); if (setup.hDevMode != oldG) { @@ -2768,6 +2770,30 @@ return result; } +LRESULT CALLBACK PageDialogWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + + switch (message) { + case WM_COMMAND: { + if ((LOWORD(wParam) == IDOK) || + (LOWORD(wParam) == IDCANCEL)) + { + // If we recieve on of these two notifications, the dialog + // is about to be closed. It's time to unblock all the + // windows blocked by this dialog, as doing so from the + // WM_DESTROY handler is too late + jobject peer = (jobject)(::GetProp(hWnd, ModalDialogPeerProp)); + env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)0); + } + break; + } + } + + return ComCtl32Util::GetInstance().DefWindowProc(NULL, hWnd, message, wParam, lParam); +} + /** * Called by the Page Setup dialog this routine makes sure the * print dialog becomes the front most window. @@ -2785,12 +2811,30 @@ jobject peer = (jobject)(psd->lCustData); env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)hDlg); + ::SetProp(hDlg, ModalDialogPeerProp, reinterpret_cast(peer)); + SetForegroundWindow(hDlg); + + // set appropriate icon for parentless dialogs + jobject awtParent = env->GetObjectField(peer, AwtPrintDialog::parentID); + if (awtParent == NULL) { + ::PostMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, + (LPARAM)AwtToolkit::GetInstance().GetAwtIcon()); + } else { + env->DeleteLocalRef(awtParent); + } + + // subclass dialog's parent to receive additional messages + ComCtl32Util::GetInstance().SubclassHWND(hDlg, + PageDialogWndProc); + break; } case WM_DESTROY: { - jobject peer = (jobject)::GetWindowLongPtr(hDlg, DWLP_USER); - env->CallVoidMethod(peer, AwtPrintDialog::setHWndMID, (jlong)0); + ComCtl32Util::GetInstance().UnsubclassHWND(hDlg, + PageDialogWndProc, + NULL); + ::RemoveProp(hDlg, ModalDialogPeerProp); break; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Toolkit.cpp --- a/j2se/src/windows/native/sun/windows/awt_Toolkit.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Toolkit.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -566,7 +566,7 @@ wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = AwtToolkit::GetInstance().GetModuleHandle(), - wc.hIcon = NULL; + wc.hIcon = AwtToolkit::GetInstance().GetAwtIcon(); wc.hCursor = NULL; wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Window.cpp --- a/j2se/src/windows/native/sun/windows/awt_Window.cpp Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Window.cpp Thu Jul 05 23:47:33 2007 +0000 @@ -112,11 +112,6 @@ // struct for _ModalDisable() method struct ModalDisableStruct { jobject window; - jobject blocker; -}; -// struct for _ModalDisableByHWnd() method -struct ModalDisableByHWndStruct { - jobject window; jlong blockerHWnd; }; /************************************************************************ @@ -127,6 +122,9 @@ jfieldID AwtWindow::locationByPlatformID; jfieldID AwtWindow::autoRequestFocusID; +jclass AwtWindow::wwindowPeerCls; +jmethodID AwtDialog::getActiveWindowsMID; + int AwtWindow::ms_instanceCounter = 0; HHOOK AwtWindow::ms_hCBTFilter; AwtWindow * AwtWindow::m_grabbedWindow = NULL; @@ -182,6 +180,7 @@ } ::RemoveProp(GetHWnd(), ModalBlockerProp); + ::RemoveProp(GetHWnd(), ModalSaveWSEXProp); if (m_grabbedWindow == this) { Ungrab(); @@ -1452,9 +1451,33 @@ return focusable; } +void AwtWindow::SetModalBlocker(HWND window, HWND blocker) { + if (!::IsWindow(window)) { + return; + } + DWORD exStyle = ::GetWindowLong(window, GWL_EXSTYLE); + if (::IsWindow(blocker)) { + // save WS_EX_NOACTIVATE and WS_EX_APPWINDOW styles + DWORD saveStyle = exStyle & (AWT_WS_EX_NOACTIVATE | WS_EX_APPWINDOW); + ::SetProp(window, ModalSaveWSEXProp, reinterpret_cast(saveStyle)); + ::SetWindowLong(window, GWL_EXSTYLE, (exStyle | AWT_WS_EX_NOACTIVATE) & ~WS_EX_APPWINDOW); + ::SetProp(window, ModalBlockerProp, reinterpret_cast(blocker)); + } else { + // restore WS_EX_NOACTIVATE and WS_EX_APPWINDOW styles + DWORD saveStyle = reinterpret_cast(::GetProp(window, ModalSaveWSEXProp)); + ::SetWindowLong(window, GWL_EXSTYLE, + (exStyle & ~(AWT_WS_EX_NOACTIVATE | WS_EX_APPWINDOW)) | saveStyle); + ::RemoveProp(window, ModalSaveWSEXProp); + ::RemoveProp(window, ModalBlockerProp); + } +} + void AwtWindow::SetAndActivateModalBlocker(HWND window, HWND blocker) { - if (::IsWindow(window) && ::IsWindow(blocker)) { - AwtWindow::SetModalBlocker(window, blocker); + if (!::IsWindow(window)) { + return; + } + AwtWindow::SetModalBlocker(window, blocker); + if (::IsWindow(blocker)) { // We must check for visibility. Otherwise invisible dialog will receive WM_ACTIVATE. if (::IsWindowVisible(blocker)) { ::BringWindowToTop(blocker); @@ -1998,69 +2021,19 @@ ModalDisableStruct *mds = (ModalDisableStruct *)param; jobject self = mds->window; - jobject bl = mds->blocker; - - AwtWindow *window = NULL; - HWND windowHWnd = 0; - AwtWindow *blocker = NULL; - HWND blockerHWnd = 0; - - PDATA pData; - JNI_CHECK_NULL_GOTO(self, "peer", ret); - pData = JNI_GET_PDATA(self); - if (pData == NULL) { - env->DeleteGlobalRef(self); - if (bl != NULL) { - env->DeleteGlobalRef(bl); - } - delete mds; - return; - } - window = (AwtWindow *)pData; - windowHWnd = window->GetHWnd(); - if (bl != NULL) { - if ((pData = JNI_GET_PDATA(bl)) != NULL) { - blocker = (AwtWindow *)pData; - blockerHWnd = blocker->GetHWnd(); - } else { // file and print dialogs have no pdata - blockerHWnd = AwtToolkit::GetInstance().GetHWnd(); - } - } - - AwtWindow::SetAndActivateModalBlocker(windowHWnd, blockerHWnd); - -ret: - env->DeleteGlobalRef(self); - if (bl != NULL) { - env->DeleteGlobalRef(bl); - } - - delete mds; -} - -void AwtWindow::_ModalDisableByHWnd(void *param) -{ - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - - ModalDisableByHWndStruct *mds = (ModalDisableByHWndStruct *)param; - jobject self = mds->window; HWND blockerHWnd = (HWND)mds->blockerHWnd; AwtWindow *window = NULL; HWND windowHWnd = 0; PDATA pData; - JNI_CHECK_NULL_GOTO(self, "peer", ret); - pData = JNI_GET_PDATA(self); - if (pData == NULL) { - env->DeleteGlobalRef(self); - delete mds; - return; - } + JNI_CHECK_PEER_GOTO(self, ret); + window = (AwtWindow *)pData; windowHWnd = window->GetHWnd(); - - AwtWindow::SetAndActivateModalBlocker(windowHWnd, blockerHWnd); + if (::IsWindow(windowHWnd)) { + AwtWindow::SetAndActivateModalBlocker(windowHWnd, blockerHWnd); + } ret: env->DeleteGlobalRef(self); @@ -2078,17 +2051,12 @@ HWND windowHWnd = 0; PDATA pData; - JNI_CHECK_NULL_GOTO(self, "peer", ret); - pData = JNI_GET_PDATA(self); - if (pData == NULL) { - env->DeleteGlobalRef(self); - return; - } JNI_CHECK_PEER_GOTO(self, ret); + window = (AwtWindow *)pData; windowHWnd = window->GetHWnd(); if (::IsWindow(windowHWnd)) { - ::RemoveProp(windowHWnd, ModalBlockerProp); + AwtWindow::SetModalBlocker(windowHWnd, NULL); } ret: @@ -2164,6 +2132,14 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WWindowPeer_initIDs(JNIEnv *env, jclass cls) { + TRY; + + AwtWindow::wwindowPeerCls = cls; + AwtWindow::getActiveWindowsMID = + env->GetStaticMethodID(cls, "getActiveWindowHandles", "()[J"); + DASSERT(AwtWindow::getActiveWindowsMID != NULL); + + CATCH_BAD_ALLOC; } /* @@ -2490,41 +2466,20 @@ /* * Class: sun_awt_windows_WWindowPeer * Method: modalDisable - * Signature: (Lsun/awt/windows/WWindowPeer;)V + * Signature: (J)V */ JNIEXPORT void JNICALL Java_sun_awt_windows_WWindowPeer_modalDisable(JNIEnv *env, jobject self, - jobject blocker) + jobject blocker, jlong blockerHWnd) { TRY; ModalDisableStruct *mds = new ModalDisableStruct; mds->window = env->NewGlobalRef(self); - mds->blocker = env->NewGlobalRef(blocker); + mds->blockerHWnd = blockerHWnd; AwtToolkit::GetInstance().SyncCall(AwtWindow::_ModalDisable, mds); - // global refs and mds are deleted in _ModalDisable - - CATCH_BAD_ALLOC; -} - -/* - * Class: sun_awt_windows_WWindowPeer - * Method: modalDisableByHWnd - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_sun_awt_windows_WWindowPeer_modalDisableByHWnd(JNIEnv *env, jobject self, - jlong blockerHWnd) -{ - TRY; - - ModalDisableByHWndStruct *mds = new ModalDisableByHWndStruct; - mds->window = env->NewGlobalRef(self); - mds->blockerHWnd = blockerHWnd; - - AwtToolkit::GetInstance().SyncCall(AwtWindow::_ModalDisableByHWnd, mds); - // global ref and mds are deleted in _ModalDisableByHWnd + // global ref and mds are deleted in _ModalDisable CATCH_BAD_ALLOC; } @@ -2535,7 +2490,7 @@ * Signature: ()V */ JNIEXPORT void JNICALL -Java_sun_awt_windows_WWindowPeer_modalEnable(JNIEnv *env, jobject self) +Java_sun_awt_windows_WWindowPeer_modalEnable(JNIEnv *env, jobject self, jobject blocker) { TRY; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/src/windows/native/sun/windows/awt_Window.h --- a/j2se/src/windows/native/sun/windows/awt_Window.h Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/src/windows/native/sun/windows/awt_Window.h Thu Jul 05 23:47:33 2007 +0000 @@ -33,6 +33,8 @@ // property name tagging windows disabled by modality static LPCTSTR ModalBlockerProp = TEXT("SunAwtModalBlockerProp"); +static LPCTSTR ModalSaveWSEXProp = TEXT("SunAwtModalSaveWSEXProp"); +static LPCTSTR ModalDialogPeerProp = TEXT("SunAwtModalDialogPeerProp"); #ifndef WH_MOUSE_LL #define WH_MOUSE_LL 14 @@ -56,6 +58,11 @@ static jfieldID screenID; /* screen number passed over from WindowPeer */ static jfieldID autoRequestFocusID; + /* WWindowPeer class */ + static jclass wwindowPeerCls; + /* long[] getActiveWindowHandles() method in WWindowPeer */ + static jmethodID getActiveWindowsMID; + AwtWindow(); virtual ~AwtWindow(); @@ -142,9 +149,7 @@ INLINE static HWND GetModalBlocker(HWND window) { return reinterpret_cast(::GetProp(window, ModalBlockerProp)); } - INLINE static void SetModalBlocker(HWND window, HWND blocker) { - ::SetProp(window, ModalBlockerProp, reinterpret_cast(blocker)); - } + static void SetModalBlocker(HWND window, HWND blocker); static void SetAndActivateModalBlocker(HWND window, HWND blocker); /* @@ -200,7 +205,6 @@ static void _SetFocusableWindow(void *param); static void _SetModalExcludedNativeProp(void *param); static void _ModalDisable(void *param); - static void _ModalDisableByHWnd(void *param); static void _ModalEnable(void *param); inline static BOOL IsResizing() { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/com/sun/jdi/BreakpointTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/com/sun/jdi/BreakpointTest.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,175 @@ +/* + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test @(#)BreakpointTest.java 1.2 07/06/22 + * @bug 6496524 + * @summary Setting breakpoint in jdb crashes Hotspot JVM + * + * @author jjh + * + * @run build TestScaffold VMConnection TargetListener TargetAdapter + * @run compile -g BreakpointTest.java + * @run main BreakpointTest + */ +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +import java.util.*; + +// The debuggee just runs in a loop. The debugger +// sets a bkpt on the Math.random call. When the +// bkpt is hit, the debugger disables it, resumes +// the debuggee, waits a bit, and enables the bkpt again. + +class BreakpointTarg { + public final static int BKPT_LINE = 54; + // LINE NUMBER SENSITIVE + + public static long count; + static void doit() { + Object[] roots = new Object[200000]; + while (true) { + int index = (int) (Math.random() * roots.length); // BKPT_LINE + // This println makes the test pass + //System.out.println("Debuggee: index = " + index); + roots[index] = new Object(); // bkpt here passes + // and null instead of new Object() + // passes + count++; + } + } + + public static void main(String[] args) { + doit(); + } +} + + /********** test program **********/ + +public class BreakpointTest extends TestScaffold { + ClassType targetClass; + ThreadReference mainThread; + + BreakpointTest (String args[]) { + super(args); + } + + public static void main(String[] args) throws Exception { + new BreakpointTest(args).startTests(); + } + + /********** event handlers **********/ + + static int maxBkpts = 50; + int bkptCount; + BreakpointRequest bkptRequest; + Field debuggeeCountField; + + // When we get a bkpt we want to disable the request, + // resume the debuggee, and then re-enable the request + public void breakpointReached(BreakpointEvent event) { + System.out.println("Got BreakpointEvent: " + bkptCount + + ", debuggeeCount = " + + ((LongValue)targetClass. + getValue(debuggeeCountField)).value() + ); + bkptRequest.disable(); + } + + public void eventSetComplete(EventSet set) { + set.resume(); + + // The main thread watchs the bkptCount to + // see if bkpts stop coming in. The + // test _should_ fail well before maxBkpts bkpts. + if (bkptCount++ < maxBkpts) { + try { + Thread.sleep(100); + } catch (InterruptedException ee) { + } + bkptRequest.enable(); + } + } + + public void vmDisconnected(VMDisconnectEvent event) { + println("Got VMDisconnectEvent"); + } + + /********** test core **********/ + + protected void runTests() throws Exception { + /* + * Get to the top of main() + * to determine targetClass and mainThread + */ + BreakpointEvent bpe = startToMain("BreakpointTarg"); + targetClass = (ClassType)bpe.location().declaringType(); + mainThread = bpe.thread(); + EventRequestManager erm = vm().eventRequestManager(); + + Location loc1 = findLocation( + targetClass, + BreakpointTarg.BKPT_LINE); + + bkptRequest = erm.createBreakpointRequest(loc1); + bkptRequest.enable(); + debuggeeCountField = targetClass.fieldByName("count"); + try { + + addListener (this); + } catch (Exception ex){ + ex.printStackTrace(); + failure("failure: Could not add listener"); + throw new Exception("BreakpointTest: failed"); + } + + int prevBkptCount; + vm().resume(); + while (!vmDisconnected && bkptCount < maxBkpts) { + try { + Thread.sleep(5000); + } catch (InterruptedException ee) { + } + } + + println("done with loop, final count = " + + ((LongValue)targetClass. + getValue(debuggeeCountField)).value()); + bkptRequest.disable(); + removeListener(this); + + + /* + * deal with results of test + * if anything has called failure("foo") testFailed will be true + */ + if (!testFailed) { + println("BreakpointTest: passed"); + } else { + throw new Exception("BreakpointTest: failed"); + } + } +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/com/sun/jdi/ShellScaffold.sh --- a/j2se/test/com/sun/jdi/ShellScaffold.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/com/sun/jdi/ShellScaffold.sh Thu Jul 05 23:47:33 2007 +0000 @@ -23,7 +23,7 @@ # have any questions. # -# @(#)ShellScaffold.sh 1.24 07/05/24 +# @(#)ShellScaffold.sh 1.26 07/06/22 # # jtreg runs this in a scratch dir. # It (and runregress -no) sets these env vars: @@ -121,7 +121,7 @@ # # pid usage: # debuggeepid: used in jdb process to detect if debuggee has died. -# - waitForDebuggeeMsg: faile if debuggee is gone +# - waitForDebuggeeMsg: fail if debuggee is gone # # jdbpid: dofail: used to detect if in main process or jdb process # waitforfinish: quit if the jdb process is gone @@ -132,14 +132,16 @@ # This can be increased if timing seems to be an issue. sleep_seconds=1 -echo "ShellScaffold.sh: Version 07/05/24" >& 2 +echo "ShellScaffold.sh: Version 07/06/22" >& 2 +topPid=$$ +# Be careful to echo to >& in these general functions. +# If they are called from the functions that are sending +# cmds to jdb, then stdout is redirected to jdb. cleanup() { - echo "ShellScaffold cleaning up at " `date` - if [ -r "$failFile" ] ; then - cat $failFile + cat $failFile >& 2 fi # Kill all processes that have our special @@ -154,14 +156,60 @@ { str=$2 - echo Killing orphan processes - toBeKilled=`$psCmd | grep -v grep | grep -i $str | awk '{print $1}' | tr '\n\r' ' '` + if [ -z "$isCygwin" ] ; then + toBeKilled=`$psCmd | $grep -v grep | $grep -i $str | awk '{print $1}' | tr '\n\r' ' '` + else + # The cygwin ps command doesn't show the options passed to a cmd. + # We will use jps to get the win PID of the command, and + # then use ps to find the cygwin pid to be killed. + # The form of a ps output line is + # ^ ddddd dddd dddd dddd.* + # where the 4th digits are the win pid and the first + # are the cygwin pid. + if [ -r "$jdk/bin/$jstack" ] ; then + winPid=`$jdk/bin/jps -v | $grep -i $str | sed -e 's@ .*@@'` + if [ ! -z "$winPid" ] ; then + # Here is a way to kill using a win cmd and the win PID. + #echo "$1: taskkill /F $winPid" >& 2 + #taskkill /F /PID $winPid + + toBeKilled=`$psCmd | $grep -v grep | \ + $grep '^ +[0-9]+ +[0-9]+ +[0-9]+ +'"$winPid" |\ + awk '{print $1}' | tr '\n\r' ' '` + fi + else + # Well, too bad - we can't find what to kill. + toBeKilled= + fi + fi + if [ ! -z "$toBeKilled" ] ; then - echo "$1: kill -9 $toBeKilled" + echo "$1: kill -9 $toBeKilled" >& 2 kill -9 $toBeKilled fi } +findPid() +{ + # Return 0 if $1 is the pid of a running process. + if [ -z "$isWin98" ] ; then + # Never use plain 'ps', which requires a "controlling terminal" + # and will fail with a "ps: no controlling terminal" error. + # Running under 'rsh' will cause this ps error. + # cygwin ps puts an I in column 1 for some reason. + $psCmd -e | $grep '^I* *'"$1 " > $devnull 2>&1 + return $? + fi + + # mks 6.2a on win98 has $! getting a negative + # number and in ps, it shows up as 0x... + # Thus, we can't search in ps output for + # PIDs gotten via $! + # We don't know if it is running or not - assume it is. + # We don't really care about win98 anymore. + return 0 +} + setup() { failed= @@ -190,6 +238,7 @@ ulimitCmd= osname=`uname -s` isWin98= + isCygwin= case "$osname" in Windows* | CYGWIN*) if [ "$osname" = Windows_98 -o "$osname" = Windows_ME ]; then @@ -197,7 +246,13 @@ debuggeeKeyword='we_cant_kill_debuggees_on_win98' jdbKeyword='jdb\.exe' fi - # MKS or cygwin + + case "$osname" in + CYGWIN*) + isCygwin=1 + ;; + esac + if [ -r $jdk/bin/dt_shmem.dll -o -r $jdk/jre/bin/dt_shmem.dll ] ; then transport=dt_shmem address=kkkk.$$ @@ -226,12 +281,14 @@ # on mks grep=egrep psCmd=ps + jstack=jstack.exe ;; SunOS | Linux) transport=dt_socket address= devnull=/dev/null grep=egrep + jstack=jstack # On linux, core files take a long time, and can leave # zombie processes if [ "$osname" = SunOS ] ; then @@ -286,9 +343,15 @@ jdb=$jdk/bin/jdb fi - - trap "exit" 1 2 3 4 6 9 10 15 - trap "cleanup" 0 +####################################################3 +####################################################3 +####################################################3 +####################################################3 +# sol: this gets all processes killed but +# no jstack +# linux same as above +# win mks: No dice; processes still running + trap "cleanup" 0 1 2 3 4 6 9 10 15 jdbOptions="$jdbOptions -J-D${jdbKeyword}" } @@ -436,7 +499,6 @@ # code will have to be modified. cmd() { - #sleep ${sleep_seconds} if [ $1 = quit -o -r "$failFile" ] ; then # if jdb got a cont cmd that caused the debuggee # to run to completion, jdb can be gone before @@ -448,7 +510,7 @@ sleep 5 exit 1 fi - + # $jdbOutFile always exists here and is non empty # because after starting jdb, we waited # for the prompt. @@ -539,11 +601,14 @@ # have access to $debuggeepid, so we have to read it from the file. nlines=$2 allowExit="$3" + myCount=0 + timeLimit=40 # wait a max of 40 secs for a response from a jdb command while [ 1 = 1 ] ; do if [ -r $jdbOutFile ] ; then # Something here causes jdb to complain about Unrecognized cmd on x86. tail -$nlines $jdbOutFile | $grep -s "$1" > $devnull 2>&1 if [ $? = 0 ] ; then + # Found desired string break fi fi @@ -563,61 +628,20 @@ dofail "Waited for jdb msg $1, but it never appeared" fi - # Stop waiting if the debuggee has disappeared. Get its PID - # out of the file if we haven't already done so, - if [ -z "$localdebuggeepid" ] ; then - if [ -r "$debuggeepidFile" ] ; then - localdebuggeepid=`cat $debuggeepidFile` - fi + sleep ${sleep_seconds} + findPid $topPid + if [ $? != 0 ] ; then + # Top process is dead. We better die too + dojstack + exit 1 fi - # And then break if this PID is not running. - if [ ! -z "$localdebuggeepid" ] ; then - ps -e | $grep "^ *$localdebuggeepid" > $devnull 2>&1 - if [ $? != 0 ] ; then - break - fi + myCount=`expr $myCount + ${sleep_seconds}` + if [ $myCount -gt $timeLimit ] ; then + dojstack + echo "--Fail: waitForJdbMsg timed out after $timeLimit seconds; exitting" >> $failFile + exit 1 fi - sleep ${sleep_seconds} - sleep ${sleep_seconds} - done - -} - -# Wait until string $1 appears in the debuggee output file, within the last $2 lines -waitForDebuggeeMsg() -{ - if [ $# = 1 ] ; then - nlines=4 - else - nlines=$2 - fi - while [ 1 = 1 ] ; do - if [ ! -r $debuggeeOutFile ] ; then - dofail "Missing debuggee output file: $debuggeeOutFile" - fi - tail -4 $debuggeeOutFile | $grep -s "$1" - if [ $? = 0 ] ; then - break - fi - - # This can be called from the jdb thread which doesn't - # have access to $debuggeepid, so we have to read it from the file. - # Fail if the debuggee has disappeared - if [ -z "$localdebuggeepid" ] ; then - if [ -r "$debuggeepidFile" ] ; then - localdebuggeepid=`cat $debuggeepidFile` - fi - fi - - if [ ! -z "$localdebuggeepid" ] ; then - ps -e | $grep "^ *$localdebuggeepid" > $devnull 2>&1 - if [ $? != 0 ] ; then - dofail "Waited for debuggee msg $1, but debuggee died" - fi - fi - sleep ${sleep_seconds} - sleep ${sleep_seconds} done } @@ -666,12 +690,6 @@ startJdb() { - ps -e | $grep '[0-9] [^ ]*jdb' > $devnull 2>&1 -# if [ $? = 0 ] ; then -# # $psCmd here on solaris causes all env vars to be dumped too :-( -# #echo "jdb is already running: " `$psCmd -e | $grep '[0-9] [^ ]*jdb'` -# echo "jdb is already running: " `ps -e | $grep '[0-9] [^ ]*jdb'` -# fi if [ ! -r "$jdb" -a ! -r "$jdb.exe" ] ; then dofail "$jdb does not exist" fi @@ -701,7 +719,7 @@ # This fails on linux because there is an entry for each thread in jdb # so we get a list of numbers in jdbpid - # jdbpid=`$psCmd | grep -v grep | grep ${orphanKeyword}_JDB | awk '{print $1}' | tr '\n\r' ' '` + # jdbpid=`$psCmd | $grep -v grep | $grep ${orphanKeyword}_JDB | awk '{print $1}' | tr '\n\r' ' '` } startDebuggee() @@ -731,6 +749,7 @@ $beOption \ $pkgDot$classname" echo "Cmd: $thecmd" + sh -c "$thecmd | tee $debuggeeOutFile" & # Note that the java cmd and the tee cmd will be children of @@ -743,35 +762,59 @@ echo $debuggeepid > $debuggeepidFile } +dojstack() +{ + if [ -r "$jdk/bin/$jstack" ] ; then + # If jstack exists, so will jps + # Show stack traces of jdb and debuggee as a possible debugging aid. + jdbCmd=`$jdk/bin/jps -v | $grep $jdbKeyword` + realJdbPid=`echo "$jdbCmd" | sed -e 's@ TTY.*@@'` + if [ ! -z "$realJdbPid" ] ; then + echo "-- jdb process info ----------------------" >&2 + echo " $jdbCmd" >&2 + echo "-- jdb threads: jstack $realJdbPid" >&2 + $jdk/bin/$jstack $realJdbPid >&2 + echo "------------------------------------------" >&2 + echo >&2 + fi + debuggeeCmd=`$jdk/bin/jps -v | $grep $debuggeeKeyword` + realDebuggeePid=`echo "$debuggeeCmd" | sed -e 's@ .*@@'` + if [ ! -z "$realDebuggeePid" ] ; then + if [ -r "$jdk/lib/sa-jdi.jar" ] ; then + # disableVersionCheck can be removed after 6475822 + # is fixed. + moption="-m -J-Dsun.jvm.hotspot.runtime.VM.disableVersionCheck" + else + moption= + fi + + echo "-- debuggee process info ----------------------" >&2 + echo " $debuggeeCmd" >&2 + echo "-- debuggee threads: jstack $moption $realDebuggeePid" >&2 + $jdk/bin/$jstack $moption $realDebuggeePid >&2 + echo "=============================================" >&2 + echo >&2 + fi + fi +} + waitForFinish() { # This is the main process # Wait for the jdb process to finish, or some error to occur - myCount=0 + while [ 1 = 1 ] ; do - # If the jdb process is gone, quit - if [ -z "$isWin98" ] ; then - # Never use plain 'ps', which requires a "controlling terminal" - # and will fail with a "ps: no controlling terminal" error. - # Running under 'rsh' will cause this ps error. - # cygwin ps puts an I in column 1 for some reason. - ps -e | $grep '^I* *'"$jdbpid " > $devnull 2>&1 - else - # mks 6.2a on win98 has $! getting a negative - # number and in ps, it shows up as 0x... - # Thus, we can't search in ps output for - # PIDs gotten via $! - ps | $grep -i 'JDB\.EXE' >$devnull 2>&1 - fi - xx=$? - if [ $xx != 0 ] ; then - # # On linux, the debuggee could be consuming lots of cycles - # # so kill it asap. - # killgroup $debuggeepid; $killcmd -9 $debuggeepid >$devnull 2>&1 + findPid $jdbpid + if [ $? != 0 ] ; then break fi - - fgrep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 + if [ ! -z "$isWin98" ] ; then + $psCmd | $grep -i 'JDB\.EXE' >$devnull 2>&1 + if [ $? != 0 ] ; then + break; + fi + fi + $grep -s 'Input stream closed' $jdbOutFile > $devnull 2>&1 if [ $? = 0 ] ; then #something went wrong dofail "jdb input stream closed prematurely" @@ -781,14 +824,10 @@ if [ -r "$failFile" ] ; then break fi + sleep ${sleep_seconds} - myCount=`expr $myCount + 1` - if [ $myCount = 30 ] ; then - echo "WaitForFinish waited for 30; jdb still running" >&2 - ps -e | $grep '^I* *'"$jdbpid " >&2 - myCount=0 - fi done + if [ -r "$failFile" ] ; then exit 1 fi @@ -801,11 +840,16 @@ if [ -r "$1" ] ; then if [ -z "$3" ] ;then $grep -s "$2" $1 > $devnull 2>&1 + stat=$? else tail -$3 $1 | $grep -s "$2" > $devnull 2>&1 + stat=$? fi - if [ $? = 0 ] ; then + if [ $stat = 0 ] ; then dofail "Error output found: \"$2\" in $1" + echo "---- contents of $1 follows -------" >> $failFile + cat "$1" >> $failFile + echo "---------------" fi fi } @@ -816,6 +860,9 @@ { if [ ! -r "$1" ] ; then dofail "Required output \"$2\" not found in $1" >& 2 + echo "---- contents of $1 follows -------" >> $failFile + cat "$1" >> $failFile + echo "---------------" fi if [ -z "$3" ] ;then $grep -s "$2" $1 > $devnull 2>&1 @@ -824,6 +871,9 @@ fi if [ $? != 0 ] ; then dofail "Required output \"$2\" not found in $1" >& 2 + echo "---- contents of $1 follows -------" >> $failFile + cat "$1" >> $failFile + echo "---------------" fi } @@ -859,9 +909,11 @@ # This should really be named 'done' instead of pass. pass() { - echo - echo "--Done: test passed" - exit 0 + if [ ! -r "$failFile" ] ; then + echo + echo "--Done: test passed" + exit 0 + fi } runit() diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetMaxFileDescriptorCount.sh --- a/j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetMaxFileDescriptorCount.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetMaxFileDescriptorCount.sh Thu Jul 05 23:47:33 2007 +0000 @@ -22,7 +22,7 @@ # # -# @test @(#)GetMaxFileDescriptorCount.sh 1.6 00:59:24 +# @test @(#)GetMaxFileDescriptorCount.sh 1.6 01:20:23 # @bug 4858522 # @summary # @author Steve Bohne diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetOpenFileDescriptorCount.sh --- a/j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetOpenFileDescriptorCount.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/com/sun/management/UnixOperatingSystemMXBean/GetOpenFileDescriptorCount.sh Thu Jul 05 23:47:33 2007 +0000 @@ -22,7 +22,7 @@ # # -# @test @(#)GetOpenFileDescriptorCount.sh 1.6 00:59:24 +# @test @(#)GetOpenFileDescriptorCount.sh 1.6 01:20:23 # @bug 4858522 # @summary # @author Steve Bohne diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.html Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,20 @@ + + + + FileDialogReturnTest + + + +

FileDialogReturnTest
Bug ID:

+ +

See the dialog box (usually in upper left corner) for instructions

+ + + + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/FileDialog/FileDialogReturnTest/FileDialogReturnTest.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,247 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + test @(#)FileDialogReturnTest.java 1.1 07/06/05 1.1, 06/05/07 + @bug 6260676 + @summary FileDialog.setDirectory() does not work properly, XToolkit + @author Dmitry.Cherepanov area=awt.filedialog + @run applet/manual=yesno FileDialogReturnTest.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; + +/* + * Current implementation of the FileDialog class doesn't provide + * any explicit method to get the return value after the user closes + * the dialog. The only way to detect whether the user cancels the + * dialog or the user selects any file is to use the getFile() method. + * The getFile() method should return null value if the user cancels + * the dialog or non-null value if the user selects any file. + */ +public class FileDialogReturnTest extends Applet +{ + + public static void main(String[] args) { + Applet a = new FileDialogReturnTest(); + a.init(); + a.start(); + } + + public void init() + { + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + " 1. The test shows the 'FileDialogReturnTest' applet which contains two text fields and one button, ", + " 2. Input something into the 'File:' text field or just keep the field empty, ", + " 3. Input something into the 'Dir:' text field or just keep the field empty, ", + " 4. Press the 'Show' button and a file dialog will appear, ", + " 5-1. Cancel the file dialog, e.g. by selecting the 'close' menu item, ", + " If the output window shows that 'file'/'dir' values is null then the test passes, otherwise the test fails, ", + " 5-2. Select any file, e.g. by pressing the 'OK' button, ", + " If the output window shows that 'file'/'dir' values is not-null then the test passes, otherwise the test fails. " + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + final TextField fileField = new TextField("", 20); + final TextField dirField = new TextField("", 20); + final Button button = new Button("Show"); + + public void start () + { + setLayout(new FlowLayout()); + + add(new Label("File:")); + add(fileField); + add(new Label("Dir:")); + add(dirField); + add(button); + + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + showDialog(); + } + }); + + setSize (200,200); + setVisible(true); + validate(); + } + + void showDialog() + { + FileDialog fd = new FileDialog(new Frame()); + fd.setFile(fileField.getText()); + fd.setDirectory(dirField.getText()); + fd.setVisible(true); + + Sysout.println("[file=" + fd.getFile()+"]"); + Sysout.println("[dir=" + fd.getDirectory()+"]"); + } + +} + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 100; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,20 @@ + + + + RegexpFilterTest + + + +


Bug ID:

+ +

See the dialog box (usually in upper left corner) for instructions

+ + + + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,227 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + test @(#)RegexpFilterTest.java 1.1 07/06/18 1.1, 06/18/07 + @bug 4934185 + @summary JCK1.5-runtime-interactive: XToolkit FileDialog does not work as expected + @author Dmitry.Cherepanov area=awt.filedialog + @run applet/manual=yesno RegexpFilterTest.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; + +/* + * Motif file dialogs let the user specify a filter that controls the files that + * are displayed in the dialog. This filter is generally specified as a regular + * expression. The test verifies that Motif-like filtering works fine using + * XAWT-toolkit also. + */ +public class RegexpFilterTest extends Applet +{ + + public static void main(String[] args) { + Applet a = new RegexpFilterTest(); + a.init(); + a.start(); + } + + public void init() + { + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + " 0. The test is only for X platforms", + " 1. Press the 'Show' button and a file dialog will appear, ", + " 2. Input any string into the 'Filter' text field, ", + " This filter is generally specified as a regular expression ", + " (e.g., * matches all files, while *.c matches all files that end in .c) ", + " 3. Press 'Enter' to refresh the displayed files with the filter, ", + " 4. If the list of the files contains all actual files matched the filter, ", + " then the test passed; otherwise it failed. " + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + public void start () + { + setLayout(new FlowLayout()); + Button button = new Button("Show"); + add(button); + + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FileDialog fd = new FileDialog(new Frame()); + fd.setVisible(true); + } + }); + + setSize (200,200); + setVisible(true); + validate(); + } + +} + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 100; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/Focus/TranserFocusToWindow/TranserFocusToWindow.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,123 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test @(#)TranserFocusToWindow.java 1.1 07/06/05 + @bug 1234567 + @summary Tests that focus transfered directy to window w/o transfering it to frame. + @author Oleg Sukhodolsky: area=awt.focus + @library ../../regtesthelpers + @build Util + @run main TranserFocusToWindow +*/ + +import java.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Window; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; + +import test.java.awt.regtesthelpers.Util; + +public class TranserFocusToWindow +{ + public static void main(String[] args) { + Robot robot = Util.createRobot(); + Frame owner_frame = new Frame("Owner frame"); + owner_frame.setBounds(0, 0, 200, 200); + owner_frame.setVisible(true); + Util.waitForIdle(robot); + + Window window = new Window(owner_frame); + Button btn1 = new Button("button for focus"); + window.add(btn1); + window.pack(); + window.setLocation(0, 300); + window.setVisible(true); + Util.waitForIdle(robot); + + Frame another_frame = new Frame("Another frame"); + Button btn2 = new Button("button in a frame"); + another_frame.add(btn2); + another_frame.pack(); + another_frame.setLocation(300, 0); + another_frame.setVisible(true); + Util.waitForIdle(robot); + + Util.clickOnTitle(owner_frame, robot); + Util.waitForIdle(robot); + + setFocus(btn1, robot); + + setFocus(btn2, robot); + + owner_frame.addWindowFocusListener(new WindowFocusListener() { + public void windowLostFocus(WindowEvent we) { + System.out.println(we); + } + public void windowGainedFocus(WindowEvent we) { + System.out.println(we); + throw new RuntimeException("owner frame must not receive WINDWO_GAINED_FOCUS"); + } + }); + window.addWindowFocusListener(new WindowFocusListener() { + public void windowLostFocus(WindowEvent we) { + System.out.println(we); + } + public void windowGainedFocus(WindowEvent we) { + System.out.println(we); + } + }); + another_frame.addWindowFocusListener(new WindowFocusListener() { + public void windowLostFocus(WindowEvent we) { + System.out.println(we); + } + public void windowGainedFocus(WindowEvent we) { + System.out.println(we); + } + }); + + // we need this delay so WM can not treat two clicks on title as double click + robot.delay(500); + Util.clickOnTitle(owner_frame, robot); + Util.waitForIdle(robot); + + System.out.println("test passed"); + } + + private static void setFocus(final Component comp, final Robot r) { + if (comp.hasFocus()) { + return; + } + + Util.clickOnComp(comp, r); + Util.waitForIdle(r); + + if (!comp.hasFocus()) { + throw new RuntimeException("can not set focus on " + comp); + } + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,435 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test @(#)MaximizedToIconified.java 1.2 07/06/04 + @bug 4977491 + @summary State changes should always be reported as events + @author anthony.petrov@...: area=awt.toplevel + @library ../../regtesthelpers + @build Util + @run main MaximizedToIconified +*/ + +/** + * MaximizedToIconified.java + * + * summary: Invoking setExtendedState(ICONIFIED) on a maximized + * frame should not combine the maximized and iconified + * states in the newState of the state change event. + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import test.java.awt.regtesthelpers.Util; + + +public class MaximizedToIconified +{ + static volatile int lastFrameState = Frame.NORMAL; + static volatile boolean failed = false; + static volatile Toolkit myKit; + + private static void checkState(Frame f, int state) { + f.setExtendedState(state); + Util.waitForIdle(null); + + System.out.println("state = " + state + "; getExtendedState() = " + f.getExtendedState()); + + if (failed) { + MaximizedToIconified.fail("getOldState() != previous getNewState() in WINDOW_STATE_CHANGED event."); + } + if (lastFrameState != f.getExtendedState()) { + MaximizedToIconified.fail("getExtendedState() != last getNewState() in WINDOW_STATE_CHANGED event."); + } + if (f.getExtendedState() != state) { + MaximizedToIconified.fail("getExtendedState() != " + state + " as expected."); + } + // Plain return means the check passed + } + + private static void examineStates(Frame f_arg, int states[]) { + Frame f = f_arg; + + if (f == null) { + f = new Frame("test"); + f.setSize(200, 200); + f.setVisible(true); + } + + Util.waitForIdle(null); + + f.addWindowStateListener(new WindowStateListener() { + public void windowStateChanged(WindowEvent e) { + System.out.println("last = " + lastFrameState + "; getOldState() = " + e.getOldState() + "; getNewState() = " + e.getNewState()); + if (e.getOldState() == lastFrameState) { + lastFrameState = e.getNewState(); + } else { + System.out.println("Wrong getOldState(): expected = " + lastFrameState + "; received = " + e.getOldState()); + failed = true; + } + } + }); + + for (int state: states) { + if (myKit.isFrameStateSupported(state)) { + checkState(f, state); + } else { + System.out.println("Frame state = " + state + " is NOT supported by the native system. The state is skipped."); + } + } + + if (f_arg == null) { + f.dispose(); + } + } + + private static void init() + { + String[] instructions = + { + "This is an AUTOMATIC test, simply wait until it is done.", + "The result (passed or failed) will be shown in the", + "message window below." + }; + Sysout.createDialog( ); + Sysout.printInstructions( instructions ); + + myKit = Toolkit.getDefaultToolkit(); + + // NOTE! Compound states (like MAXIMIZED_BOTH | ICONIFIED) CANNOT be used, + // because Toolkit.isFrameStateSupported() method reports these states + // as not supported. And such states will simply be skipped. + examineStates(null, new int[] {Frame.MAXIMIZED_BOTH, Frame.ICONIFIED, Frame.NORMAL}); + examineStates(null, new int[] {Frame.ICONIFIED, Frame.MAXIMIZED_BOTH, Frame.NORMAL}); + + + MaximizedToIconified.pass(); + + }//End init() + + + + /***************************************************** + * Standard Test Machinery Section + * DO NOT modify anything in this section -- it's a + * standard chunk of code which has all of the + * synchronisation necessary for the test harness. + * By keeping it the same in all tests, it is easier + * to read and understand someone else's test, as + * well as insuring that all tests behave correctly + * with the test harness. + * There is a section following this for test- + * classes + ******************************************************/ + private static boolean theTestPassed = false; + private static boolean testGeneratedInterrupt = false; + private static String failureMessage = ""; + + private static Thread mainThread = null; + + private static int sleepTime = 300000; + + // Not sure about what happens if multiple of this test are + // instantiated in the same VM. Being static (and using + // static vars), it aint gonna work. Not worrying about + // it for now. + public static void main( String args[] ) throws InterruptedException + { + mainThread = Thread.currentThread(); + try + { + init(); + } + catch( TestPassedException e ) + { + //The test passed, so just return from main and harness will + // interepret this return as a pass + return; + } + //At this point, neither test pass nor test fail has been + // called -- either would have thrown an exception and ended the + // test, so we know we have multiple threads. + + //Test involves other threads, so sleep and wait for them to + // called pass() or fail() + try + { + Thread.sleep( sleepTime ); + //Timed out, so fail the test + throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); + } + catch (InterruptedException e) + { + //The test harness may have interrupted the test. If so, rethrow the exception + // so that the harness gets it and deals with it. + if( ! testGeneratedInterrupt ) throw e; + + //reset flag in case hit this code more than once for some reason (just safety) + testGeneratedInterrupt = false; + + if ( theTestPassed == false ) + { + throw new RuntimeException( failureMessage ); + } + } + + }//main + + public static synchronized void setTimeoutTo( int seconds ) + { + sleepTime = seconds * 1000; + } + + public static synchronized void pass() + { + Sysout.println( "The test passed." ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //first check if this is executing in main thread + if ( mainThread == Thread.currentThread() ) + { + //Still in the main thread, so set the flag just for kicks, + // and throw a test passed exception which will be caught + // and end the test. + theTestPassed = true; + throw new TestPassedException(); + } + theTestPassed = true; + testGeneratedInterrupt = true; + mainThread.interrupt(); + }//pass() + + public static synchronized void fail() + { + //test writer didn't specify why test failed, so give generic + fail( "it just plain failed! :-)" ); + } + + public static synchronized void fail( String whyFailed ) + { + Sysout.println( "The test failed: " + whyFailed ); + Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); + //check if this called from main thread + if ( mainThread == Thread.currentThread() ) + { + //If main thread, fail now 'cause not sleeping + throw new RuntimeException( whyFailed ); + } + theTestPassed = false; + testGeneratedInterrupt = true; + failureMessage = whyFailed; + mainThread.interrupt(); + }//fail() + +}// class MaximizedToIconified + +//This exception is used to exit from any level of call nesting +// when it's determined that the test has passed, and immediately +// end the test. +class TestPassedException extends RuntimeException +{ +} + +//*********** End Standard Test Machinery Section ********** + + +//************ Begin classes defined for the test **************** + +// if want to make listeners, here is the recommended place for them, then instantiate +// them in init() + +/* Example of a class which may be written as part of a test +class NewClass implements anInterface + { + static int newVar = 0; + + public void eventDispatched(AWTEvent e) + { + //Counting events to see if we get enough + eventCount++; + + if( eventCount == 20 ) + { + //got enough events, so pass + + MaximizedToIconified.pass(); + } + else if( tries == 20 ) + { + //tried too many times without getting enough events so fail + + MaximizedToIconified.fail(); + } + + }// eventDispatched() + + }// NewClass class + +*/ + + +//************** End classes defined for the test ******************* + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + System.out.println(messageIn); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class + + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/Multiscreen/WPanelPeerPerf/WPanelPeerPerf.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/Multiscreen/WPanelPeerPerf/WPanelPeerPerf.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,178 @@ +/* + * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + @test @(#)WPanelPeerPerf.java 1.4 07/06/19 + @bug 5085626 + @summary Exponential performance regression in AWT components (multiple mon) + @run main WPanelPeerPerf +*/ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +/** + * This test must be run on a multi-screen system. + * This test works by moving a Frame back and forth between the screens a few + * times. When the bug is active, the first move will overwhelm the EDT with + * recursive display change calls. The test fails if it takes too long to + * service the setLocation() calls and send componentMoved() events. + */ +public class WPanelPeerPerf { + + private static final int NESTED_PANELS = 25; + private static final int ITERATIONS_PER_SCREEN = 3; + private static final int MAX_WAIT_PER_SCREEN = 2500; + private static final int PAUSE_BETWEEN_MOVES = 500; + + + private static Object showLock = new Object(); + + private static Counter instance = null; + public static Counter getCounter() { + if (instance == null) { + instance = new Counter(); + } + return instance; + } + + private static class Counter { + int counter; + Counter() { counter = 0; } + } + + // This one is very slow! + public static void testAWT() { + // fail if only on one screen + int numScreens = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length; + if (numScreens < 2) { + System.err.println("Test must be run on a multiscreen system"); + return; + } + final Frame frame = new Frame("AWT WPanelPeerPerf"); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent ev) { + System.exit(0); + } + public void windowOpened(WindowEvent e) { + synchronized(showLock) { + showLock.notify(); + } + } + }); + frame.setLayout(new BorderLayout()); + Label label = new Label("Hello world"); + frame.add(label, BorderLayout.NORTH); + Panel panel = new Panel(new BorderLayout()); + Panel currentPanel = panel; + for (int i = 0; i < NESTED_PANELS; i++) { + Panel newPanel = new Panel(new BorderLayout()); + currentPanel.add(newPanel, BorderLayout.CENTER); + currentPanel = newPanel; + } + currentPanel.add(new Label("WPanelPeerPerf")); + frame.add(panel, BorderLayout.CENTER); + Button btn = new Button("OK"); + frame.add(btn, BorderLayout.SOUTH); + frame.pack(); + + frame.addComponentListener(new ComponentAdapter() { + public void componentMoved(ComponentEvent e) { + System.out.println("Frame moved: "); + Counter ctr = getCounter(); + synchronized(ctr) { + ctr.counter++; + ctr.notify(); + } + } + }); + synchronized(showLock) { + try { + frame.setVisible(true); + showLock.wait(); + } + catch (InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("Problem with showLock"); + } + } + runTest(frame); + } + + public static void runTest(Frame theFrame) { + System.out.println("Running test"); + GraphicsDevice[] devs = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); + Point[] points = new Point[devs.length]; + + for (int i = 0; i < points.length; i++) { + Rectangle bounds = devs[i].getDefaultConfiguration().getBounds(); + points[i] = new Point(bounds.x + (bounds.width / 2), + bounds.y + (bounds.height / 2)); + System.out.println("Added point:" + points[i]); + } + + final Frame localFrame = theFrame; + + for (int n = 0; n < ITERATIONS_PER_SCREEN; n++) { + for (int i = 0; i < points.length; i++) { + final Point contextPoint = points[i]; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + localFrame.setLocation(contextPoint); + } + }); + try { + Thread.sleep(PAUSE_BETWEEN_MOVES); + } + catch (InterruptedException e) { + System.out.println("Interrupted during iteration"); + } + } + } + Counter ctr = getCounter(); + synchronized(ctr) { + try { + if (ctr.counter < ITERATIONS_PER_SCREEN * devs.length) { + // If test hasn't finished, wait for maximum time + // If we get interrupted, test fails + ctr.wait((long)(ITERATIONS_PER_SCREEN * MAX_WAIT_PER_SCREEN * devs.length)); + System.out.println("after wait"); + if (ctr.counter < ITERATIONS_PER_SCREEN * devs.length) { + throw new RuntimeException("Waited too long for all the componentMoved()s"); + } + } + } + catch(InterruptedException e) { + e.printStackTrace(); + throw new RuntimeException("Wait interrupted - ???"); + } + System.out.println("Counter reads: " + ctr.counter); + } + + } + public static void main(String[] args) { + testAWT(); + } +} + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.html Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,24 @@ + + + + WindowGCChangeTest + + + +

WindowGCChangeTest
Bug ID: 4868278 Problem with Action button tooltips with some multiple monitor configurations

+ +

This is an AUTOMATIC test, simply wait for completion

+ + + + + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/awt/Multiscreen/WindowGCChangeTest/WindowGCChangeTest.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,161 @@ +/* + * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + test @(#)WindowGCChangeTest.java 1.6 07/06/19 + @bug 4868278 + @summary Tests that GraphicsConfig for invisible (peerless) window is + updated after showing the window + @author artem.ananiev, area=awt.multiscreen + @library ../../regtesthelpers + @build Util + @run applet WindowGCChangeTest.html +*/ + +import java.applet.Applet; + +import java.awt.*; +import java.awt.event.*; + +import test.java.awt.regtesthelpers.Util; + +public class WindowGCChangeTest extends Applet +{ + public void init() + { + } + + public void start() + { + Robot robot = null; + try + { + robot = new Robot(); + } + catch (Exception z) + { + z.printStackTrace(System.err); + throw new RuntimeException("Test FAILED: couldn't create Robot instance", z); + } + + setSize(200, 200); + setVisible(true); + validate(); + Util.waitForIdle(robot); + + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] gds = ge.getScreenDevices(); + // check 2-screens systems only + if (gds.length != 2) + { + return; + } + + int defGDNo = 0; + int nondefGDNo = 0; + boolean isVirtualScreen = false; + GraphicsDevice defgd = ge.getDefaultScreenDevice(); + for (int i = 0; i < gds.length; i++) + { + Rectangle r = gds[i].getDefaultConfiguration().getBounds(); + if ((r.x != 0) || (r.y != 0)) + { + isVirtualScreen = true; + } + if (gds[i] == defgd) + { + defGDNo = i; + } + else + { + nondefGDNo = i; + } + } + + // doesn't test separate screens + if (!isVirtualScreen) + { + return; + } + + GraphicsDevice defGD = gds[defGDNo]; + GraphicsDevice nondefGD = gds[nondefGDNo]; + + final GraphicsConfiguration defGC = defGD.getDefaultConfiguration(); + final GraphicsConfiguration nondefGC = nondefGD.getDefaultConfiguration(); + + final Frame f = new Frame(defGC); + f.setBounds(nondefGC.getBounds().x + 100, nondefGC.getBounds().y + 100, 100, 100); + f.addWindowListener(new WindowAdapter() + { + public void windowActivated(WindowEvent ev) + { + GraphicsConfiguration gcf = f.getGraphicsConfiguration(); + if (gcf != nondefGC) + { + throw new RuntimeException("Test FAILED: graphics config is not updated"); + } + f.dispose(); + } + }); + f.setVisible(true); + Util.waitForIdle(robot); + + // paranoia - change def to nondef and vice versa + final Frame g = new Frame(nondefGC); + g.setBounds(defGC.getBounds().x + 100, defGC.getBounds().y + 100, 100, 100); + g.addWindowListener(new WindowAdapter() + { + public void windowActivated(WindowEvent ev) + { + GraphicsConfiguration gcg = g.getGraphicsConfiguration(); + if (gcg != defGC) + { + throw new RuntimeException("Test FAILED: graphics config is not updated"); + } + g.dispose(); + } + }); + g.setVisible(true); + Util.waitForIdle(robot); + + // test fullscreen changes + final Frame h = new Frame(defGC); + h.setBounds(defGC.getBounds().x + 100, defGC.getBounds().y + 100, 100, 100); + h.addWindowListener(new WindowAdapter() + { + public void windowActivated(WindowEvent ev) + { + GraphicsConfiguration gch = h.getGraphicsConfiguration(); + if (gch != nondefGC) + { + throw new RuntimeException("Test FAILED: graphics config is not updated"); + } + h.dispose(); + } + }); + h.setUndecorated(true); + nondefGD.setFullScreenWindow(h); + Util.waitForIdle(robot); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/lang/ProcessBuilder/Basic.java --- a/j2se/test/java/lang/ProcessBuilder/Basic.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/lang/ProcessBuilder/Basic.java Thu Jul 05 23:47:33 2007 +0000 @@ -22,10 +22,10 @@ */ /* - * @test 1.15 07/05/05 + * @test 1.16 07/06/12 * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 - * 6464154 + * 6464154 6523983 * @summary Basic tests for Process and Environment Variable code * @run main/othervm Basic * @author Martin Buchholz @@ -144,14 +144,14 @@ } private static final Runtime runtime = Runtime.getRuntime(); - + private static final String[] winEnvCommand = {"cmd.exe", "/c", "set"}; private static String winEnvFilter(String env) { return env.replaceAll("\r", "") .replaceAll("(?m)^(?:COMSPEC|PROMPT|PATHEXT)=.*\n",""); } - + private static String unixEnvProg() { return new File("/usr/bin/env").canExecute() ? "/usr/bin/env" : "/bin/env"; @@ -245,6 +245,12 @@ return sb.toString(); } + static void print4095(OutputStream s) throws Throwable { + byte[] bytes = new byte[4095]; + Arrays.fill(bytes, (byte) '!'); + s.write(bytes); // Might hang! + } + public static class JavaChild { public static void main(String args[]) throws Throwable { String action = args[0]; @@ -259,6 +265,9 @@ } else if (action.equals("pwd")) { printUTF8(new File(System.getProperty("user.dir")) .getCanonicalPath()); + } else if (action.equals("print4095")) { + print4095(System.out); + System.exit(5); } else if (action.equals("OutErr")) { // You might think the system streams would be // buffered, and in fact they are implemented using @@ -593,7 +602,7 @@ if (Unix.is()) System.out.println("This appears to be a Unix system."); if (UnicodeOS.is()) - System.out.println("This appears to be a Unicpde-based OS."); + System.out.println("This appears to be a Unicode-based OS."); //---------------------------------------------------------------- // Basic tests for setting, replacing and deleting envvars @@ -1244,6 +1253,19 @@ } catch (Throwable t) { unexpected(t); } //---------------------------------------------------------------- + // This would deadlock, if not for the fact that + // interprocess pipe buffers are at least 4096 bytes. + //---------------------------------------------------------------- + try { + List childArgs = new ArrayList(javaChildArgs); + childArgs.add("print4095"); + Process p = new ProcessBuilder(childArgs).start(); + print4095(p.getOutputStream()); // Might hang! + p.waitFor(); // Might hang! + equal(p.exitValue(), 5); + } catch (Throwable t) { unexpected(t); } + + //---------------------------------------------------------------- // Attempt to start process with insufficient permissions fails. //---------------------------------------------------------------- try { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/lang/ThreadGroup/SetMaxPriority.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/lang/ThreadGroup/SetMaxPriority.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,69 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test @(#)SetMaxPriority.java 1.1 07/06/06 + * @bug 4708197 6497629 + * @summary Test for max priority setting that matches spec + * @author Pete Soper + */ + +public class SetMaxPriority { + + public static void main(String args[]) throws Exception { + ThreadGroup tg = new ThreadGroup("foo"); + ThreadGroup ptg = tg.getParent(); + int currentMaxPriority = tg.getMaxPriority(); + int halfMaxPriority = ptg.getMaxPriority() / 2; + if (halfMaxPriority - Thread.MIN_PRIORITY < 2) { + throw new RuntimeException("SetMaxPriority test no longer valid: starting parent max priority too close to Thread.MIN_PRIORITY"); + } + tg.setMaxPriority(halfMaxPriority - 2); + currentMaxPriority = tg.getMaxPriority(); + if (currentMaxPriority != halfMaxPriority - 2) { + throw new RuntimeException("SetMaxPriority failed: max priority not changed"); + } + + // This will fail if bug 6497629 is present because the min tests is + // being made with the (just lowered) max instead of the parent max, + // preventing the priority from being moved back up. + tg.setMaxPriority(currentMaxPriority + 1); + int newMaxPriority = tg.getMaxPriority(); + if (newMaxPriority != currentMaxPriority + 1) { + throw new RuntimeException("SetMaxPriority failed: defect 6497629 present"); + } + + // Confirm that max priorities out of range on both ends have no + // effect. + for (int badPriority : new int[] {Thread.MIN_PRIORITY - 1, + Thread.MAX_PRIORITY + 1}) { + int oldPriority = tg.getMaxPriority(); + tg.setMaxPriority(badPriority); + if (oldPriority != tg.getMaxPriority()) + throw new RuntimeException( + "setMaxPriority bad arg not ignored as specified"); + } + + System.out.println("SetMaxPriority passed"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/lang/ref/SoftReference/Pin.java --- a/j2se/test/java/lang/ref/SoftReference/Pin.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/lang/ref/SoftReference/Pin.java Thu Jul 05 23:47:33 2007 +0000 @@ -21,7 +21,7 @@ * have any questions. */ -/* @test 1.6 07/06/21 +/* @test 1.6 07/07/05 * @bug 4076287 * @summary Invoking get on a SoftReference shouldn't pin the referent * @run main/othervm -ms16m -mx16m Pin diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java/net/MyDatagramSocketImplFactory.java --- a/j2se/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java/net/MyDatagramSocketImplFactory.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/java/net/MyDatagramSocketImplFactory.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,12 @@ public class MyDatagramSocketImplFactory implements DatagramSocketImplFactory { public DatagramSocketImpl createDatagramSocketImpl() { - return new PlainDatagramSocketImpl(); + try { + return DefaultDatagramSocketImplFactory.createDatagramSocketImpl(false); + } catch (SocketException se) { + assert false; + } + + return null; } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/AllocateDirectInit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/AllocateDirectInit.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 4490253 6535542 + * @summary Verify that newly allocated direct buffers are initialized. + */ + +import java.nio.ByteBuffer; + +public class AllocateDirectInit { + public static void main(String [] args){ + for (int i = 0; i < 1024; i++) { + ByteBuffer bb = ByteBuffer.allocateDirect(1024); +// printByteBuffer(bb); + for (bb.position(0); bb.position() < bb.limit(); ) { + if ((bb.get() & 0xff) != 0) + throw new RuntimeException("uninitialized buffer, position = " + + bb.position()); + } + } + } + + private static void printByteBuffer(ByteBuffer bb) { + System.out.print("byte ["); + for (bb.position(0); bb.position() < bb.limit(); ) + System.out.print(" " + Integer.toHexString(bb.get() & 0xff)); + System.out.println(" ]"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/Basic-X.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/Basic-X.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +#warn This file is preprocessed before being compiled + +import java.nio.*; + + +public class Basic$Type$ + extends Basic +{ + + private static void relGet($Type$Buffer b) { + int n = b.capacity(); + $type$ v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)(($type$)ic(i))); + b.rewind(); + } + + private static void relGet($Type$Buffer b, int start) { + int n = b.remaining(); + $type$ v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)(($type$)ic(i))); + b.rewind(); + } + + private static void absGet($Type$Buffer b) { + int n = b.capacity(); + $type$ v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)(($type$)ic(i))); + b.rewind(); + } + + private static void bulkGet($Type$Buffer b) { + int n = b.capacity(); + $type$[] a = new $type$[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)(($type$)ic(i))); + } + + private static void relPut($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(($type$)ic(i)); + b.flip(); + } + + private static void absPut($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, ($type$)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + $type$[] a = new $type$[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = ($type$)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + $Type$Buffer c = $Type$Buffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put(($type$)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset($Type$Buffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + +#if[byte] +#else[byte] + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + $Type$Buffer direct1 = ByteBuffer.allocateDirect(cap).as$Type$Buffer(); + $Type$Buffer nondirect1 = ByteBuffer.allocate(cap).as$Type$Buffer(); + direct1.put(nondirect1); + + $Type$Buffer direct2 = ByteBuffer.allocateDirect(cap).as$Type$Buffer(); + $Type$Buffer nondirect2 = ByteBuffer.allocate(cap).as$Type$Buffer(); + nondirect2.put(direct2); + + $Type$Buffer direct3 = ByteBuffer.allocateDirect(cap).as$Type$Buffer(); + $Type$Buffer direct4 = ByteBuffer.allocateDirect(cap).as$Type$Buffer(); + direct3.put(direct4); + + $Type$Buffer nondirect3 = ByteBuffer.allocate(cap).as$Type$Buffer(); + $Type$Buffer nondirect4 = ByteBuffer.allocate(cap).as$Type$Buffer(); + nondirect3.put(nondirect4); + } +#end[byte] + +#if[char] + + private static void bulkPutString($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + StringBuffer sb = new StringBuffer(n + 7); + sb.append("1234567"); + for (int i = 0; i < n; i++) + sb.append((char)ic(i)); + b.put(sb.toString(), 7, 7 + n); + b.flip(); + } + +#end[char] + + private static void checkSlice($Type$Buffer b, $Type$Buffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + +#if[byte] + + private static void checkBytes(ByteBuffer b, byte[] bs) { + int n = bs.length; + int p = b.position(); + byte v; + if (b.order() == ByteOrder.BIG_ENDIAN) { + for (int i = 0; i < n; i++) + ck(b, b.get(), bs[i]); + } else { + for (int i = n - 1; i >= 0; i--) + ck(b, b.get(), bs[i]); + } + b.position(p); + } + + private static void testViews(int level, ByteBuffer b, boolean direct) { + + ShortBuffer sb = b.asShortBuffer(); + BasicShort.test(level, sb, direct); + checkBytes(b, new byte[] { 0, (byte)ic(0) }); + + CharBuffer cb = b.asCharBuffer(); + BasicChar.test(level, cb, direct); + checkBytes(b, new byte[] { 0, (byte)ic(0) }); + + IntBuffer ib = b.asIntBuffer(); + BasicInt.test(level, ib, direct); + checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) }); + + LongBuffer lb = b.asLongBuffer(); + BasicLong.test(level, lb, direct); + checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) }); + + FloatBuffer fb = b.asFloatBuffer(); + BasicFloat.test(level, fb, direct); + checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 }); + + DoubleBuffer db = b.asDoubleBuffer(); + BasicDouble.test(level, db, direct); + checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 }); + + } + + private static void testHet(int level, ByteBuffer b) { + + int p = b.position(); + b.limit(b.capacity()); + show(level, b); + out.print(" put:"); + + b.putChar((char)1); + b.putChar((char)Character.MAX_VALUE); + out.print(" char"); + + b.putShort((short)1); + b.putShort((short)Short.MAX_VALUE); + out.print(" short"); + + b.putInt(1); + b.putInt(Integer.MAX_VALUE); + out.print(" int"); + + b.putLong((long)1); + b.putLong((long)Long.MAX_VALUE); + out.print(" long"); + + b.putFloat((float)1); + b.putFloat((float)Float.MIN_VALUE); + b.putFloat((float)Float.MAX_VALUE); + out.print(" float"); + + b.putDouble((double)1); + b.putDouble((double)Double.MIN_VALUE); + b.putDouble((double)Double.MAX_VALUE); + out.print(" double"); + + out.println(); + b.limit(b.position()); + b.position(p); + show(level, b); + out.print(" get:"); + + ck(b, b.getChar(), 1); + ck(b, b.getChar(), Character.MAX_VALUE); + out.print(" char"); + + ck(b, b.getShort(), 1); + ck(b, b.getShort(), Short.MAX_VALUE); + out.print(" short"); + + ck(b, b.getInt(), 1); + ck(b, b.getInt(), Integer.MAX_VALUE); + out.print(" int"); + + ck(b, b.getLong(), 1); + ck(b, b.getLong(), Long.MAX_VALUE); + out.print(" long"); + + ck(b, (long)b.getFloat(), 1); + ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE); + ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE); + out.print(" float"); + + ck(b, (long)b.getDouble(), 1); + ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE); + ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE); + out.print(" double"); + + out.println(); + + } + +#end[byte] + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch($type$ [] t, Class ex, Runnable thunk) { + tryCatch($Type$Buffer.wrap(t), ex, thunk); + } + + public static void test(int level, final $Type$Buffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + +#if[char] + + bulkPutString(b); + relGet(b); + b.position(1); + b.limit(7); + ck(b, b.toString().equals("bcdefg")); + + // CharSequence ops + + b.position(2); + ck(b, b.charAt(1), 'd'); + CharBuffer c = (CharBuffer)b.subSequence(1, 4); + ck(b, b.subSequence(1, 4).toString().equals("def")); + + // 4938424 + b.position(4); + ck(b, b.charAt(1), 'f'); + ck(b, b.subSequence(1, 3).toString().equals("fg")); + +#end[char] + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put(($type$)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), ($type$)42); + }}); + + // Values + + b.clear(); + b.put(($type$)0); + b.put(($type$)-1); + b.put(($type$)1); + b.put($Fulltype$.MAX_VALUE); + b.put($Fulltype$.MIN_VALUE); +#if[float] + b.put(-Float.MAX_VALUE); + b.put(-Float.MIN_VALUE); + b.put(Float.NEGATIVE_INFINITY); + b.put(Float.POSITIVE_INFINITY); + b.put(Float.NaN); + b.put(0.91697687f); // Changes value if incorrectly swapped +#end[float] +#if[double] + b.put(-Double.MAX_VALUE); + b.put(-Double.MIN_VALUE); + b.put(Double.NEGATIVE_INFINITY); + b.put(Double.POSITIVE_INFINITY); + b.put(Double.NaN); + b.put(0.5121609353879392); // Changes value if incorrectly swapped +#end[double] + + $type$ v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), ($type$)-1); + ck(b, b.get(), 1); + ck(b, b.get(), $Fulltype$.MAX_VALUE); + ck(b, b.get(), $Fulltype$.MIN_VALUE); + +#if[float] + ck(b, b.get(), -Float.MAX_VALUE); + ck(b, b.get(), -Float.MIN_VALUE); + ck(b, b.get(), Float.NEGATIVE_INFINITY); + ck(b, b.get(), Float.POSITIVE_INFINITY); + if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN)) + fail(b, (long)Float.NaN, (long)v); + ck(b, b.get(), 0.91697687f); +#end[float] +#if[double] + ck(b, b.get(), -Double.MAX_VALUE); + ck(b, b.get(), -Double.MIN_VALUE); + ck(b, b.get(), Double.NEGATIVE_INFINITY); + ck(b, b.get(), Double.POSITIVE_INFINITY); + if (Double.doubleToRawLongBits(v = b.get()) + != Double.doubleToRawLongBits(Double.NaN)) + fail(b, (long)Double.NaN, (long)v); + ck(b, b.get(), 0.5121609353879392); +#end[double] + + + // Comparison + b.rewind(); + $Type$Buffer b2 = $Type$Buffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + $type$ x = b.get(i); + $type$ y = b2.get(i); + if (x != y +#if[double] + || Double.compare(x, y) != 0 +#end[double] +#if[float] + || Float.compare(x, y) != 0 +#end[float] + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put(($type$)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, ($type$)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + $Type$Buffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + $Type$Buffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + +#if[byte] + + // Views + + b.clear(); + b.order(ByteOrder.BIG_ENDIAN); + testViews(level + 1, b, direct); + + for (int i = 1; i <= 9; i++) { + b.position(i); + show(level + 1, b); + testViews(level + 2, b, direct); + } + + b.position(0); + b.order(ByteOrder.LITTLE_ENDIAN); + testViews(level + 1, b, direct); + + // Heterogeneous accessors + + b.order(ByteOrder.BIG_ENDIAN); + for (int i = 0; i <= 9; i++) { + b.position(i); + testHet(level + 1, b); + } + b.order(ByteOrder.LITTLE_ENDIAN); + b.position(3); + testHet(level + 1, b); + +#end[byte] + + // Read-only views + + b.rewind(); + final $Type$Buffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + +#if[byte] + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putChar((char)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putChar(0, (char)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putShort((short)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putShort(0, (short)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putInt(1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putInt(0, 1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putLong((long)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putLong(0, (long)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putFloat((float)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putFloat(0, (float)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putDouble((double)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putDouble(0, (double)1); + }}); + +#end[byte] + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + +#if[byte] + // For byte buffers, test both the direct and non-direct cases + $Type$Buffer ob + = (b.isDirect() + ? $Type$Buffer.allocate(rb.capacity()) + : $Type$Buffer.allocateDirect(rb.capacity())); + rb.rewind(); + ob.put(rb); +#end[byte] + + relPut(b); // Required by testViews + + } + +#if[char] + + private static void testStr() { + final String s = "abcdefghijklm"; + int start = 3; + int end = 9; + final CharBuffer b = CharBuffer.wrap(s, start, end); + show(0, b); + ck(b, b.toString().equals(s.substring(start, end))); + ck(b, b.toString().equals("defghi")); + ck(b, b.isReadOnly()); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + b.put('x'); + }}); + ck(b, start, b.position()); + ck(b, end, b.limit()); + ck(b, s.length(), b.capacity()); + + // The index, relative to the position, must be non-negative and + // smaller than remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.charAt(-1); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.charAt(b.remaining()); + }}); + + // The index must be non-negative and less than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + // The start must be non-negative and no larger than remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(-1, b.remaining()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(b.remaining() + 1, b.remaining()); + }}); + + // The end must be no smaller than start and no larger than + // remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(2, 1); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(0, b.remaining() + 1); + }}); + + // The offset must be non-negative and no larger than . + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(s, -1, s.length()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(s, s.length() + 1, s.length()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(s, 1, 0); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(s, 0, s.length() + 1); + }}); + } + +#end[char] + + public static void test(final $type$ [] ba) { + int offset = 47; + int length = 900; + final $Type$Buffer b = $Type$Buffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(($type$ []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + $Type$Buffer.wrap(($type$ []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + $Type$Buffer.allocate(-1); + }}); +#if[byte] + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + $Type$Buffer.allocateDirect(-1); + }}); +#end[byte] + } + + public static void test() { + testAllocate(); + test(0, $Type$Buffer.allocate(7 * 1024), false); + test(0, $Type$Buffer.wrap(new $type$[7 * 1024], 0, 7 * 1024), false); + test(new $type$[1024]); +#if[byte] + $Type$Buffer b = $Type$Buffer.allocateDirect(7 * 1024); + for (b.position(0); b.position() < b.limit(); ) + ck(b, b.get(), 0); + test(0, b, true); +#end[byte] +#if[char] + testStr(); +#end[char] + + callReset($Type$Buffer.allocate(10)); + +#if[byte] +#else[byte] + putBuffer(); +#end[byte] + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/Basic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/Basic.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @summary Unit test for buffers + * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725 + * 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529 + * 6221101 6234263 6535542 + * @author Mark Reinhold + */ + + +import java.io.PrintStream; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; + + +public class Basic { + + static PrintStream out = System.err; + + static long ic(int i) { + int j = i % 54; + return j + 'a' + ((j > 26) ? 128 : 0); + } + + static String toString(Buffer b) { + return (b.getClass().getName() + + "[pos=" + b.position() + + " lim=" + b.limit() + + " cap=" + b.capacity() + + "]"); + } + + static void show(int level, Buffer b) { + for (int i = 0; i < level; i++) + out.print(" "); + out.println(toString(b) + " " + Integer.toHexString(b.hashCode())); + } + + static void fail(String s) { + throw new RuntimeException(s); + } + + static void fail(String s, Buffer b) { + throw new RuntimeException(s + ": " + toString(b)); + } + + static void fail(String s, Buffer b, Buffer b2) { + throw new RuntimeException(s + ": " + + toString(b) + ", " + toString(b2)); + } + + static void fail(Buffer b, + String expected, char expectedChar, + String got, char gotChar) + { + if (b instanceof ByteBuffer) { + ByteBuffer bb = (ByteBuffer)b; + int n = Math.min(16, bb.limit()); + for (int i = 0; i < n; i++) + out.print(" " + Integer.toHexString(bb.get(i) & 0xff)); + out.println(); + } + if (b instanceof CharBuffer) { + CharBuffer bb = (CharBuffer)b; + int n = Math.min(16, bb.limit()); + for (int i = 0; i < n; i++) + out.print(" " + Integer.toHexString(bb.get(i) & 0xffff)); + out.println(); + } + throw new RuntimeException(toString(b) + + ": Expected '" + expectedChar + "'=0x" + + expected + + ", got '" + gotChar + "'=0x" + + got); + } + + static void fail(Buffer b, long expected, long got) { + fail(b, + Long.toHexString(expected), (char)expected, + Long.toHexString(got), (char)got); + } + + static void ck(Buffer b, boolean cond) { + if (!cond) + fail("Condition failed", b); + } + + static void ck(Buffer b, long got, long expected) { + if (expected != got) + fail(b, expected, got); + } + + static void ck(Buffer b, float got, float expected) { + if (expected != got) + fail(b, + Float.toString(expected), (char)expected, + Float.toString(got), (char)got); + } + + static void ck(Buffer b, double got, double expected) { + if (expected != got) + fail(b, + Double.toString(expected), (char)expected, + Double.toString(got), (char)got); + } + + public static void main(String[] args) { + BasicByte.test(); + BasicChar.test(); + BasicShort.test(); + BasicInt.test(); + BasicLong.test(); + BasicFloat.test(); + BasicDouble.test(); + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicByte.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicByte.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicByte + extends Basic +{ + + private static void relGet(ByteBuffer b) { + int n = b.capacity(); + byte v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((byte)ic(i))); + b.rewind(); + } + + private static void relGet(ByteBuffer b, int start) { + int n = b.remaining(); + byte v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((byte)ic(i))); + b.rewind(); + } + + private static void absGet(ByteBuffer b) { + int n = b.capacity(); + byte v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((byte)ic(i))); + b.rewind(); + } + + private static void bulkGet(ByteBuffer b) { + int n = b.capacity(); + byte[] a = new byte[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((byte)ic(i))); + } + + private static void relPut(ByteBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((byte)ic(i)); + b.flip(); + } + + private static void absPut(ByteBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (byte)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(ByteBuffer b) { + int n = b.capacity(); + b.clear(); + byte[] a = new byte[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (byte)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(ByteBuffer b) { + int n = b.capacity(); + b.clear(); + ByteBuffer c = ByteBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((byte)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(ByteBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void checkSlice(ByteBuffer b, ByteBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + private static void checkBytes(ByteBuffer b, byte[] bs) { + int n = bs.length; + int p = b.position(); + byte v; + if (b.order() == ByteOrder.BIG_ENDIAN) { + for (int i = 0; i < n; i++) + ck(b, b.get(), bs[i]); + } else { + for (int i = n - 1; i >= 0; i--) + ck(b, b.get(), bs[i]); + } + b.position(p); + } + + private static void testViews(int level, ByteBuffer b, boolean direct) { + + ShortBuffer sb = b.asShortBuffer(); + BasicShort.test(level, sb, direct); + checkBytes(b, new byte[] { 0, (byte)ic(0) }); + + CharBuffer cb = b.asCharBuffer(); + BasicChar.test(level, cb, direct); + checkBytes(b, new byte[] { 0, (byte)ic(0) }); + + IntBuffer ib = b.asIntBuffer(); + BasicInt.test(level, ib, direct); + checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) }); + + LongBuffer lb = b.asLongBuffer(); + BasicLong.test(level, lb, direct); + checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) }); + + FloatBuffer fb = b.asFloatBuffer(); + BasicFloat.test(level, fb, direct); + checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 }); + + DoubleBuffer db = b.asDoubleBuffer(); + BasicDouble.test(level, db, direct); + checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 }); + + } + + private static void testHet(int level, ByteBuffer b) { + + int p = b.position(); + b.limit(b.capacity()); + show(level, b); + out.print(" put:"); + + b.putChar((char)1); + b.putChar((char)Character.MAX_VALUE); + out.print(" char"); + + b.putShort((short)1); + b.putShort((short)Short.MAX_VALUE); + out.print(" short"); + + b.putInt(1); + b.putInt(Integer.MAX_VALUE); + out.print(" int"); + + b.putLong((long)1); + b.putLong((long)Long.MAX_VALUE); + out.print(" long"); + + b.putFloat((float)1); + b.putFloat((float)Float.MIN_VALUE); + b.putFloat((float)Float.MAX_VALUE); + out.print(" float"); + + b.putDouble((double)1); + b.putDouble((double)Double.MIN_VALUE); + b.putDouble((double)Double.MAX_VALUE); + out.print(" double"); + + out.println(); + b.limit(b.position()); + b.position(p); + show(level, b); + out.print(" get:"); + + ck(b, b.getChar(), 1); + ck(b, b.getChar(), Character.MAX_VALUE); + out.print(" char"); + + ck(b, b.getShort(), 1); + ck(b, b.getShort(), Short.MAX_VALUE); + out.print(" short"); + + ck(b, b.getInt(), 1); + ck(b, b.getInt(), Integer.MAX_VALUE); + out.print(" int"); + + ck(b, b.getLong(), 1); + ck(b, b.getLong(), Long.MAX_VALUE); + out.print(" long"); + + ck(b, (long)b.getFloat(), 1); + ck(b, (long)b.getFloat(), (long)Float.MIN_VALUE); + ck(b, (long)b.getFloat(), (long)Float.MAX_VALUE); + out.print(" float"); + + ck(b, (long)b.getDouble(), 1); + ck(b, (long)b.getDouble(), (long)Double.MIN_VALUE); + ck(b, (long)b.getDouble(), (long)Double.MAX_VALUE); + out.print(" double"); + + out.println(); + + } + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(byte [] t, Class ex, Runnable thunk) { + tryCatch(ByteBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final ByteBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((byte)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (byte)42); + }}); + + // Values + + b.clear(); + b.put((byte)0); + b.put((byte)-1); + b.put((byte)1); + b.put(Byte.MAX_VALUE); + b.put(Byte.MIN_VALUE); + + + + + + + + + + + + + + + + + + byte v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (byte)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Byte.MAX_VALUE); + ck(b, b.get(), Byte.MIN_VALUE); + + + + + + + + + + + + + + + + + + + + + + + // Comparison + b.rewind(); + ByteBuffer b2 = ByteBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + byte x = b.get(i); + byte y = b2.get(i); + if (x != y + + + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((byte)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (byte)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + ByteBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + ByteBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + // Views + + b.clear(); + b.order(ByteOrder.BIG_ENDIAN); + testViews(level + 1, b, direct); + + for (int i = 1; i <= 9; i++) { + b.position(i); + show(level + 1, b); + testViews(level + 2, b, direct); + } + + b.position(0); + b.order(ByteOrder.LITTLE_ENDIAN); + testViews(level + 1, b, direct); + + // Heterogeneous accessors + + b.order(ByteOrder.BIG_ENDIAN); + for (int i = 0; i <= 9; i++) { + b.position(i); + testHet(level + 1, b); + } + b.order(ByteOrder.LITTLE_ENDIAN); + b.position(3); + testHet(level + 1, b); + + + + // Read-only views + + b.rewind(); + final ByteBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putChar((char)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putChar(0, (char)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putShort((short)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putShort(0, (short)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putInt(1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putInt(0, 1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putLong((long)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putLong(0, (long)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putFloat((float)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putFloat(0, (float)1); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putDouble((double)1); + }}); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.putDouble(0, (double)1); + }}); + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + // For byte buffers, test both the direct and non-direct cases + ByteBuffer ob + = (b.isDirect() + ? ByteBuffer.allocate(rb.capacity()) + : ByteBuffer.allocateDirect(rb.capacity())); + rb.rewind(); + ob.put(rb); + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final byte [] ba) { + int offset = 47; + int length = 900; + final ByteBuffer b = ByteBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ByteBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ByteBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ByteBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ByteBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + ByteBuffer.wrap((byte []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + ByteBuffer.wrap((byte []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + ByteBuffer.allocate(-1); + }}); + + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + ByteBuffer.allocateDirect(-1); + }}); + + } + + public static void test() { + testAllocate(); + test(0, ByteBuffer.allocate(7 * 1024), false); + test(0, ByteBuffer.wrap(new byte[7 * 1024], 0, 7 * 1024), false); + test(new byte[1024]); + + ByteBuffer b = ByteBuffer.allocateDirect(7 * 1024); + for (b.position(0); b.position() < b.limit(); ) + ck(b, b.get(), 0); + test(0, b, true); + + + + + + callReset(ByteBuffer.allocate(10)); + + + + + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicChar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicChar.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicChar + extends Basic +{ + + private static void relGet(CharBuffer b) { + int n = b.capacity(); + char v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((char)ic(i))); + b.rewind(); + } + + private static void relGet(CharBuffer b, int start) { + int n = b.remaining(); + char v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((char)ic(i))); + b.rewind(); + } + + private static void absGet(CharBuffer b) { + int n = b.capacity(); + char v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((char)ic(i))); + b.rewind(); + } + + private static void bulkGet(CharBuffer b) { + int n = b.capacity(); + char[] a = new char[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((char)ic(i))); + } + + private static void relPut(CharBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((char)ic(i)); + b.flip(); + } + + private static void absPut(CharBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (char)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(CharBuffer b) { + int n = b.capacity(); + b.clear(); + char[] a = new char[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (char)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(CharBuffer b) { + int n = b.capacity(); + b.clear(); + CharBuffer c = CharBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((char)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(CharBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + CharBuffer direct1 = ByteBuffer.allocateDirect(cap).asCharBuffer(); + CharBuffer nondirect1 = ByteBuffer.allocate(cap).asCharBuffer(); + direct1.put(nondirect1); + + CharBuffer direct2 = ByteBuffer.allocateDirect(cap).asCharBuffer(); + CharBuffer nondirect2 = ByteBuffer.allocate(cap).asCharBuffer(); + nondirect2.put(direct2); + + CharBuffer direct3 = ByteBuffer.allocateDirect(cap).asCharBuffer(); + CharBuffer direct4 = ByteBuffer.allocateDirect(cap).asCharBuffer(); + direct3.put(direct4); + + CharBuffer nondirect3 = ByteBuffer.allocate(cap).asCharBuffer(); + CharBuffer nondirect4 = ByteBuffer.allocate(cap).asCharBuffer(); + nondirect3.put(nondirect4); + } + + + + + private static void bulkPutString(CharBuffer b) { + int n = b.capacity(); + b.clear(); + StringBuffer sb = new StringBuffer(n + 7); + sb.append("1234567"); + for (int i = 0; i < n; i++) + sb.append((char)ic(i)); + b.put(sb.toString(), 7, 7 + n); + b.flip(); + } + + + + private static void checkSlice(CharBuffer b, CharBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(char [] t, Class ex, Runnable thunk) { + tryCatch(CharBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final CharBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + bulkPutString(b); + relGet(b); + b.position(1); + b.limit(7); + ck(b, b.toString().equals("bcdefg")); + + // CharSequence ops + + b.position(2); + ck(b, b.charAt(1), 'd'); + CharBuffer c = (CharBuffer)b.subSequence(1, 4); + ck(b, b.subSequence(1, 4).toString().equals("def")); + + // 4938424 + b.position(4); + ck(b, b.charAt(1), 'f'); + ck(b, b.subSequence(1, 3).toString().equals("fg")); + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((char)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (char)42); + }}); + + // Values + + b.clear(); + b.put((char)0); + b.put((char)-1); + b.put((char)1); + b.put(Character.MAX_VALUE); + b.put(Character.MIN_VALUE); + + + + + + + + + + + + + + + + + + char v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (char)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Character.MAX_VALUE); + ck(b, b.get(), Character.MIN_VALUE); + + + + + + + + + + + + + + + + + + + + + + + // Comparison + b.rewind(); + CharBuffer b2 = CharBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + char x = b.get(i); + char y = b2.get(i); + if (x != y + + + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((char)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (char)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + CharBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + CharBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final CharBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + private static void testStr() { + final String s = "abcdefghijklm"; + int start = 3; + int end = 9; + final CharBuffer b = CharBuffer.wrap(s, start, end); + show(0, b); + ck(b, b.toString().equals(s.substring(start, end))); + ck(b, b.toString().equals("defghi")); + ck(b, b.isReadOnly()); + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + b.put('x'); + }}); + ck(b, start, b.position()); + ck(b, end, b.limit()); + ck(b, s.length(), b.capacity()); + + // The index, relative to the position, must be non-negative and + // smaller than remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.charAt(-1); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.charAt(b.remaining()); + }}); + + // The index must be non-negative and less than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + // The start must be non-negative and no larger than remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(-1, b.remaining()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(b.remaining() + 1, b.remaining()); + }}); + + // The end must be no smaller than start and no larger than + // remaining(). + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(2, 1); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.subSequence(0, b.remaining() + 1); + }}); + + // The offset must be non-negative and no larger than . + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(s, -1, s.length()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(s, s.length() + 1, s.length()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(s, 1, 0); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(s, 0, s.length() + 1); + }}); + } + + + + public static void test(final char [] ba) { + int offset = 47; + int length = 900; + final CharBuffer b = CharBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + CharBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + CharBuffer.wrap((char []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + CharBuffer.wrap((char []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + CharBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, CharBuffer.allocate(7 * 1024), false); + test(0, CharBuffer.wrap(new char[7 * 1024], 0, 7 * 1024), false); + test(new char[1024]); + + + + + + + + testStr(); + + + callReset(CharBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicDouble.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicDouble.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicDouble + extends Basic +{ + + private static void relGet(DoubleBuffer b) { + int n = b.capacity(); + double v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((double)ic(i))); + b.rewind(); + } + + private static void relGet(DoubleBuffer b, int start) { + int n = b.remaining(); + double v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((double)ic(i))); + b.rewind(); + } + + private static void absGet(DoubleBuffer b) { + int n = b.capacity(); + double v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((double)ic(i))); + b.rewind(); + } + + private static void bulkGet(DoubleBuffer b) { + int n = b.capacity(); + double[] a = new double[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((double)ic(i))); + } + + private static void relPut(DoubleBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((double)ic(i)); + b.flip(); + } + + private static void absPut(DoubleBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (double)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(DoubleBuffer b) { + int n = b.capacity(); + b.clear(); + double[] a = new double[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (double)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(DoubleBuffer b) { + int n = b.capacity(); + b.clear(); + DoubleBuffer c = DoubleBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((double)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(DoubleBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + DoubleBuffer direct1 = ByteBuffer.allocateDirect(cap).asDoubleBuffer(); + DoubleBuffer nondirect1 = ByteBuffer.allocate(cap).asDoubleBuffer(); + direct1.put(nondirect1); + + DoubleBuffer direct2 = ByteBuffer.allocateDirect(cap).asDoubleBuffer(); + DoubleBuffer nondirect2 = ByteBuffer.allocate(cap).asDoubleBuffer(); + nondirect2.put(direct2); + + DoubleBuffer direct3 = ByteBuffer.allocateDirect(cap).asDoubleBuffer(); + DoubleBuffer direct4 = ByteBuffer.allocateDirect(cap).asDoubleBuffer(); + direct3.put(direct4); + + DoubleBuffer nondirect3 = ByteBuffer.allocate(cap).asDoubleBuffer(); + DoubleBuffer nondirect4 = ByteBuffer.allocate(cap).asDoubleBuffer(); + nondirect3.put(nondirect4); + } + + + + + + + + + + + + + + + + + + private static void checkSlice(DoubleBuffer b, DoubleBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(double [] t, Class ex, Runnable thunk) { + tryCatch(DoubleBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final DoubleBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((double)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (double)42); + }}); + + // Values + + b.clear(); + b.put((double)0); + b.put((double)-1); + b.put((double)1); + b.put(Double.MAX_VALUE); + b.put(Double.MIN_VALUE); + + + + + + + + + + b.put(-Double.MAX_VALUE); + b.put(-Double.MIN_VALUE); + b.put(Double.NEGATIVE_INFINITY); + b.put(Double.POSITIVE_INFINITY); + b.put(Double.NaN); + b.put(0.5121609353879392); // Changes value if incorrectly swapped + + + double v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (double)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Double.MAX_VALUE); + ck(b, b.get(), Double.MIN_VALUE); + + + + + + + + + + + + ck(b, b.get(), -Double.MAX_VALUE); + ck(b, b.get(), -Double.MIN_VALUE); + ck(b, b.get(), Double.NEGATIVE_INFINITY); + ck(b, b.get(), Double.POSITIVE_INFINITY); + if (Double.doubleToRawLongBits(v = b.get()) + != Double.doubleToRawLongBits(Double.NaN)) + fail(b, (long)Double.NaN, (long)v); + ck(b, b.get(), 0.5121609353879392); + + + + // Comparison + b.rewind(); + DoubleBuffer b2 = DoubleBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + double x = b.get(i); + double y = b2.get(i); + if (x != y + + || Double.compare(x, y) != 0 + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((double)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (double)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + DoubleBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + DoubleBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final DoubleBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final double [] ba) { + int offset = 47; + int length = 900; + final DoubleBuffer b = DoubleBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap((double []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + DoubleBuffer.wrap((double []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + DoubleBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, DoubleBuffer.allocate(7 * 1024), false); + test(0, DoubleBuffer.wrap(new double[7 * 1024], 0, 7 * 1024), false); + test(new double[1024]); + + + + + + + + + + + callReset(DoubleBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicFloat.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicFloat.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicFloat + extends Basic +{ + + private static void relGet(FloatBuffer b) { + int n = b.capacity(); + float v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((float)ic(i))); + b.rewind(); + } + + private static void relGet(FloatBuffer b, int start) { + int n = b.remaining(); + float v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((float)ic(i))); + b.rewind(); + } + + private static void absGet(FloatBuffer b) { + int n = b.capacity(); + float v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((float)ic(i))); + b.rewind(); + } + + private static void bulkGet(FloatBuffer b) { + int n = b.capacity(); + float[] a = new float[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((float)ic(i))); + } + + private static void relPut(FloatBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((float)ic(i)); + b.flip(); + } + + private static void absPut(FloatBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (float)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(FloatBuffer b) { + int n = b.capacity(); + b.clear(); + float[] a = new float[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (float)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(FloatBuffer b) { + int n = b.capacity(); + b.clear(); + FloatBuffer c = FloatBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((float)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(FloatBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + FloatBuffer direct1 = ByteBuffer.allocateDirect(cap).asFloatBuffer(); + FloatBuffer nondirect1 = ByteBuffer.allocate(cap).asFloatBuffer(); + direct1.put(nondirect1); + + FloatBuffer direct2 = ByteBuffer.allocateDirect(cap).asFloatBuffer(); + FloatBuffer nondirect2 = ByteBuffer.allocate(cap).asFloatBuffer(); + nondirect2.put(direct2); + + FloatBuffer direct3 = ByteBuffer.allocateDirect(cap).asFloatBuffer(); + FloatBuffer direct4 = ByteBuffer.allocateDirect(cap).asFloatBuffer(); + direct3.put(direct4); + + FloatBuffer nondirect3 = ByteBuffer.allocate(cap).asFloatBuffer(); + FloatBuffer nondirect4 = ByteBuffer.allocate(cap).asFloatBuffer(); + nondirect3.put(nondirect4); + } + + + + + + + + + + + + + + + + + + private static void checkSlice(FloatBuffer b, FloatBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(float [] t, Class ex, Runnable thunk) { + tryCatch(FloatBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final FloatBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((float)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (float)42); + }}); + + // Values + + b.clear(); + b.put((float)0); + b.put((float)-1); + b.put((float)1); + b.put(Float.MAX_VALUE); + b.put(Float.MIN_VALUE); + + b.put(-Float.MAX_VALUE); + b.put(-Float.MIN_VALUE); + b.put(Float.NEGATIVE_INFINITY); + b.put(Float.POSITIVE_INFINITY); + b.put(Float.NaN); + b.put(0.91697687f); // Changes value if incorrectly swapped + + + + + + + + + + + float v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (float)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Float.MAX_VALUE); + ck(b, b.get(), Float.MIN_VALUE); + + + ck(b, b.get(), -Float.MAX_VALUE); + ck(b, b.get(), -Float.MIN_VALUE); + ck(b, b.get(), Float.NEGATIVE_INFINITY); + ck(b, b.get(), Float.POSITIVE_INFINITY); + if (Float.floatToRawIntBits(v = b.get()) != Float.floatToRawIntBits(Float.NaN)) + fail(b, (long)Float.NaN, (long)v); + ck(b, b.get(), 0.91697687f); + + + + + + + + + + + + + + // Comparison + b.rewind(); + FloatBuffer b2 = FloatBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + float x = b.get(i); + float y = b2.get(i); + if (x != y + + + + + || Float.compare(x, y) != 0 + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((float)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (float)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + FloatBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + FloatBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final FloatBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final float [] ba) { + int offset = 47; + int length = 900; + final FloatBuffer b = FloatBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + FloatBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + FloatBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + FloatBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + FloatBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + FloatBuffer.wrap((float []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + FloatBuffer.wrap((float []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + FloatBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, FloatBuffer.allocate(7 * 1024), false); + test(0, FloatBuffer.wrap(new float[7 * 1024], 0, 7 * 1024), false); + test(new float[1024]); + + + + + + + + + + + callReset(FloatBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicInt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicInt.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicInt + extends Basic +{ + + private static void relGet(IntBuffer b) { + int n = b.capacity(); + int v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((int)ic(i))); + b.rewind(); + } + + private static void relGet(IntBuffer b, int start) { + int n = b.remaining(); + int v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((int)ic(i))); + b.rewind(); + } + + private static void absGet(IntBuffer b) { + int n = b.capacity(); + int v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((int)ic(i))); + b.rewind(); + } + + private static void bulkGet(IntBuffer b) { + int n = b.capacity(); + int[] a = new int[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((int)ic(i))); + } + + private static void relPut(IntBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((int)ic(i)); + b.flip(); + } + + private static void absPut(IntBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (int)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(IntBuffer b) { + int n = b.capacity(); + b.clear(); + int[] a = new int[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (int)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(IntBuffer b) { + int n = b.capacity(); + b.clear(); + IntBuffer c = IntBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((int)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(IntBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + IntBuffer direct1 = ByteBuffer.allocateDirect(cap).asIntBuffer(); + IntBuffer nondirect1 = ByteBuffer.allocate(cap).asIntBuffer(); + direct1.put(nondirect1); + + IntBuffer direct2 = ByteBuffer.allocateDirect(cap).asIntBuffer(); + IntBuffer nondirect2 = ByteBuffer.allocate(cap).asIntBuffer(); + nondirect2.put(direct2); + + IntBuffer direct3 = ByteBuffer.allocateDirect(cap).asIntBuffer(); + IntBuffer direct4 = ByteBuffer.allocateDirect(cap).asIntBuffer(); + direct3.put(direct4); + + IntBuffer nondirect3 = ByteBuffer.allocate(cap).asIntBuffer(); + IntBuffer nondirect4 = ByteBuffer.allocate(cap).asIntBuffer(); + nondirect3.put(nondirect4); + } + + + + + + + + + + + + + + + + + + private static void checkSlice(IntBuffer b, IntBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(int [] t, Class ex, Runnable thunk) { + tryCatch(IntBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final IntBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((int)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (int)42); + }}); + + // Values + + b.clear(); + b.put((int)0); + b.put((int)-1); + b.put((int)1); + b.put(Integer.MAX_VALUE); + b.put(Integer.MIN_VALUE); + + + + + + + + + + + + + + + + + + int v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (int)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Integer.MAX_VALUE); + ck(b, b.get(), Integer.MIN_VALUE); + + + + + + + + + + + + + + + + + + + + + + + // Comparison + b.rewind(); + IntBuffer b2 = IntBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + int x = b.get(i); + int y = b2.get(i); + if (x != y + + + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((int)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (int)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + IntBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + IntBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final IntBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final int [] ba) { + int offset = 47; + int length = 900; + final IntBuffer b = IntBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + IntBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + IntBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + IntBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + IntBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + IntBuffer.wrap((int []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + IntBuffer.wrap((int []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + IntBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, IntBuffer.allocate(7 * 1024), false); + test(0, IntBuffer.wrap(new int[7 * 1024], 0, 7 * 1024), false); + test(new int[1024]); + + + + + + + + + + + callReset(IntBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicLong.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicLong.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicLong + extends Basic +{ + + private static void relGet(LongBuffer b) { + int n = b.capacity(); + long v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((long)ic(i))); + b.rewind(); + } + + private static void relGet(LongBuffer b, int start) { + int n = b.remaining(); + long v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((long)ic(i))); + b.rewind(); + } + + private static void absGet(LongBuffer b) { + int n = b.capacity(); + long v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((long)ic(i))); + b.rewind(); + } + + private static void bulkGet(LongBuffer b) { + int n = b.capacity(); + long[] a = new long[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((long)ic(i))); + } + + private static void relPut(LongBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((long)ic(i)); + b.flip(); + } + + private static void absPut(LongBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (long)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(LongBuffer b) { + int n = b.capacity(); + b.clear(); + long[] a = new long[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (long)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(LongBuffer b) { + int n = b.capacity(); + b.clear(); + LongBuffer c = LongBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((long)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(LongBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + LongBuffer direct1 = ByteBuffer.allocateDirect(cap).asLongBuffer(); + LongBuffer nondirect1 = ByteBuffer.allocate(cap).asLongBuffer(); + direct1.put(nondirect1); + + LongBuffer direct2 = ByteBuffer.allocateDirect(cap).asLongBuffer(); + LongBuffer nondirect2 = ByteBuffer.allocate(cap).asLongBuffer(); + nondirect2.put(direct2); + + LongBuffer direct3 = ByteBuffer.allocateDirect(cap).asLongBuffer(); + LongBuffer direct4 = ByteBuffer.allocateDirect(cap).asLongBuffer(); + direct3.put(direct4); + + LongBuffer nondirect3 = ByteBuffer.allocate(cap).asLongBuffer(); + LongBuffer nondirect4 = ByteBuffer.allocate(cap).asLongBuffer(); + nondirect3.put(nondirect4); + } + + + + + + + + + + + + + + + + + + private static void checkSlice(LongBuffer b, LongBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(long [] t, Class ex, Runnable thunk) { + tryCatch(LongBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final LongBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((long)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (long)42); + }}); + + // Values + + b.clear(); + b.put((long)0); + b.put((long)-1); + b.put((long)1); + b.put(Long.MAX_VALUE); + b.put(Long.MIN_VALUE); + + + + + + + + + + + + + + + + + + long v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (long)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Long.MAX_VALUE); + ck(b, b.get(), Long.MIN_VALUE); + + + + + + + + + + + + + + + + + + + + + + + // Comparison + b.rewind(); + LongBuffer b2 = LongBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + long x = b.get(i); + long y = b2.get(i); + if (x != y + + + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((long)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (long)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + LongBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + LongBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final LongBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final long [] ba) { + int offset = 47; + int length = 900; + final LongBuffer b = LongBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + LongBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + LongBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + LongBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + LongBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + LongBuffer.wrap((long []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + LongBuffer.wrap((long []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + LongBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, LongBuffer.allocate(7 * 1024), false); + test(0, LongBuffer.wrap(new long[7 * 1024], 0, 7 * 1024), false); + test(new long[1024]); + + + + + + + + + + + callReset(LongBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/BasicShort.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/BasicShort.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,828 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* Type-specific source code for unit test + * + * Regenerate the BasicX classes via genBasic.sh whenever this file changes. + * We check in the generated source files so that the test tree can be used + * independently of the rest of the source tree. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + + +public class BasicShort + extends Basic +{ + + private static void relGet(ShortBuffer b) { + int n = b.capacity(); + short v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((short)ic(i))); + b.rewind(); + } + + private static void relGet(ShortBuffer b, int start) { + int n = b.remaining(); + short v; + for (int i = start; i < n; i++) + ck(b, (long)b.get(), (long)((short)ic(i))); + b.rewind(); + } + + private static void absGet(ShortBuffer b) { + int n = b.capacity(); + short v; + for (int i = 0; i < n; i++) + ck(b, (long)b.get(), (long)((short)ic(i))); + b.rewind(); + } + + private static void bulkGet(ShortBuffer b) { + int n = b.capacity(); + short[] a = new short[n + 7]; + b.get(a, 7, n); + for (int i = 0; i < n; i++) + ck(b, (long)a[i + 7], (long)((short)ic(i))); + } + + private static void relPut(ShortBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put((short)ic(i)); + b.flip(); + } + + private static void absPut(ShortBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (short)ic(i)); + b.limit(n); + b.position(0); + } + + private static void bulkPutArray(ShortBuffer b) { + int n = b.capacity(); + b.clear(); + short[] a = new short[n + 7]; + for (int i = 0; i < n; i++) + a[i + 7] = (short)ic(i); + b.put(a, 7, n); + b.flip(); + } + + private static void bulkPutBuffer(ShortBuffer b) { + int n = b.capacity(); + b.clear(); + ShortBuffer c = ShortBuffer.allocate(n + 7); + c.position(7); + for (int i = 0; i < n; i++) + c.put((short)ic(i)); + c.flip(); + c.position(7); + b.put(c); + b.flip(); + } + + //6231529 + private static void callReset(ShortBuffer b) { + b.position(0); + b.mark(); + + b.duplicate().reset(); + b.asReadOnlyBuffer().reset(); + } + + + + // 6221101-6234263 + + private static void putBuffer() { + final int cap = 10; + + ShortBuffer direct1 = ByteBuffer.allocateDirect(cap).asShortBuffer(); + ShortBuffer nondirect1 = ByteBuffer.allocate(cap).asShortBuffer(); + direct1.put(nondirect1); + + ShortBuffer direct2 = ByteBuffer.allocateDirect(cap).asShortBuffer(); + ShortBuffer nondirect2 = ByteBuffer.allocate(cap).asShortBuffer(); + nondirect2.put(direct2); + + ShortBuffer direct3 = ByteBuffer.allocateDirect(cap).asShortBuffer(); + ShortBuffer direct4 = ByteBuffer.allocateDirect(cap).asShortBuffer(); + direct3.put(direct4); + + ShortBuffer nondirect3 = ByteBuffer.allocate(cap).asShortBuffer(); + ShortBuffer nondirect4 = ByteBuffer.allocate(cap).asShortBuffer(); + nondirect3.put(nondirect4); + } + + + + + + + + + + + + + + + + + + private static void checkSlice(ShortBuffer b, ShortBuffer slice) { + ck(slice, 0, slice.position()); + ck(slice, b.remaining(), slice.limit()); + ck(slice, b.remaining(), slice.capacity()); + if (b.isDirect() != slice.isDirect()) + fail("Lost direction", slice); + if (b.isReadOnly() != slice.isReadOnly()) + fail("Lost read-only", slice); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + private static void tryCatch(Buffer b, Class ex, Runnable thunk) { + boolean caught = false; + try { + thunk.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) + caught = true; + } + if (!caught) + fail(ex.getName() + " not thrown", b); + } + + private static void tryCatch(short [] t, Class ex, Runnable thunk) { + tryCatch(ShortBuffer.wrap(t), ex, thunk); + } + + public static void test(int level, final ShortBuffer b, boolean direct) { + + show(level, b); + + if (direct != b.isDirect()) + fail("Wrong direction", b); + + // Gets and puts + + relPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + absPut(b); + relGet(b); + absGet(b); + bulkGet(b); + + bulkPutArray(b); + relGet(b); + + bulkPutBuffer(b); + relGet(b); + + + + + + + + + + + + + + + + + + + + + + + + // Compact + + relPut(b); + b.position(13); + b.compact(); + b.flip(); + relGet(b, 13); + + // Exceptions + + boolean caught = false; + relPut(b); + b.limit(b.capacity() / 2); + b.position(b.limit()); + + tryCatch(b, BufferUnderflowException.class, new Runnable() { + public void run() { + b.get(); + }}); + + tryCatch(b, BufferOverflowException.class, new Runnable() { + public void run() { + b.put((short)42); + }}); + + // The index must be non-negative and lesss than the buffer's limit. + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(b.limit()); + }}); + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.get(-1); + }}); + + tryCatch(b, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + b.put(b.limit(), (short)42); + }}); + + // Values + + b.clear(); + b.put((short)0); + b.put((short)-1); + b.put((short)1); + b.put(Short.MAX_VALUE); + b.put(Short.MIN_VALUE); + + + + + + + + + + + + + + + + + + short v; + b.flip(); + ck(b, b.get(), 0); + ck(b, b.get(), (short)-1); + ck(b, b.get(), 1); + ck(b, b.get(), Short.MAX_VALUE); + ck(b, b.get(), Short.MIN_VALUE); + + + + + + + + + + + + + + + + + + + + + + + // Comparison + b.rewind(); + ShortBuffer b2 = ShortBuffer.allocate(b.capacity()); + b2.put(b); + b2.flip(); + b.position(2); + b2.position(2); + if (!b.equals(b2)) { + for (int i = 2; i < b.limit(); i++) { + short x = b.get(i); + short y = b2.get(i); + if (x != y + + + + + + + ) + out.println("[" + i + "] " + x + " != " + y); + } + fail("Identical buffers not equal", b, b2); + } + if (b.compareTo(b2) != 0) + fail("Comparison to identical buffer != 0", b, b2); + + b.limit(b.limit() + 1); + b.position(b.limit() - 1); + b.put((short)99); + b.rewind(); + b2.rewind(); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to shorter buffer <= 0", b, b2); + b.limit(b.limit() - 1); + + b.put(2, (short)42); + if (b.equals(b2)) + fail("Non-identical buffers equal", b, b2); + if (b.compareTo(b2) <= 0) + fail("Comparison to lesser buffer <= 0", b, b2); + + // Sub, dup + + relPut(b); + relGet(b.duplicate()); + b.position(13); + relGet(b.duplicate(), 13); + relGet(b.duplicate().slice(), 13); + relGet(b.slice(), 13); + relGet(b.slice().duplicate(), 13); + + // Slice + + b.position(5); + ShortBuffer sb = b.slice(); + checkSlice(b, sb); + b.position(0); + ShortBuffer sb2 = sb.slice(); + checkSlice(sb, sb2); + + if (!sb.equals(sb2)) + fail("Sliced slices do not match", sb, sb2); + if ((sb.hasArray()) && (sb.arrayOffset() != sb2.arrayOffset())) + fail("Array offsets do not match: " + + sb.arrayOffset() + " != " + sb2.arrayOffset(), sb, sb2); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // Read-only views + + b.rewind(); + final ShortBuffer rb = b.asReadOnlyBuffer(); + if (!b.equals(rb)) + fail("Buffer not equal to read-only view", b, rb); + show(level + 1, rb); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + relPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + absPut(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutArray(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + bulkPutBuffer(rb); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.compact(); + }}); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (rb.getClass().getName().startsWith("java.nio.Heap")) { + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.array(); + }}); + + tryCatch(b, ReadOnlyBufferException.class, new Runnable() { + public void run() { + rb.arrayOffset(); + }}); + + if (rb.hasArray()) + fail("Read-only heap buffer's backing array is accessible", + rb); + + } + + // Bulk puts from read-only buffers + + b.clear(); + rb.rewind(); + b.put(rb); + + + + + + + + + + + + relPut(b); // Required by testViews + + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + public static void test(final short [] ba) { + int offset = 47; + int length = 900; + final ShortBuffer b = ShortBuffer.wrap(ba, offset, length); + show(0, b); + ck(b, b.capacity(), ba.length); + ck(b, b.position(), offset); + ck(b, b.limit(), offset + length); + + // The offset must be non-negative and no larger than . + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ShortBuffer.wrap(ba, -1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ShortBuffer.wrap(ba, ba.length + 1, ba.length); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ShortBuffer.wrap(ba, 0, -1); + }}); + tryCatch(ba, IndexOutOfBoundsException.class, new Runnable() { + public void run() { + ShortBuffer.wrap(ba, 0, ba.length + 1); + }}); + + // A NullPointerException will be thrown if the array is null. + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + ShortBuffer.wrap((short []) null, 0, 5); + }}); + tryCatch(ba, NullPointerException.class, new Runnable() { + public void run() { + ShortBuffer.wrap((short []) null); + }}); + } + + private static void testAllocate() { + // An IllegalArgumentException will be thrown for negative capacities. + tryCatch((Buffer) null, IllegalArgumentException.class, new Runnable() { + public void run() { + ShortBuffer.allocate(-1); + }}); + + + + + + + } + + public static void test() { + testAllocate(); + test(0, ShortBuffer.allocate(7 * 1024), false); + test(0, ShortBuffer.wrap(new short[7 * 1024], 0, 7 * 1024), false); + test(new short[1024]); + + + + + + + + + + + callReset(ShortBuffer.allocate(10)); + + + + putBuffer(); + + } + +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirect-X-Memory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirect-X-Memory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#warn This file is preprocessed before being compiled + +import java.nio.*; + +public class CopyDirect$Type$Memory + extends CopyDirectMemory +{ + private static void init($Type$Buffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, ($type$)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init($type$ [] a) { + for (int i = 0; i < a.length; i++) + a[i] = ($type$)ic(i + 1); + } + + public static void test() { +#if[byte] + ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024); +#else[byte] + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + $Type$Buffer b = bb.as$Type$Buffer(); +#end[byte] + init(b); + $type$ [] a = new $type$[b.capacity()]; + init(a); + + // copyFrom$Type$Array (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), ($type$)ic(i + 1)); + + // copyTo$Type$Array (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectByteMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectByteMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectByteMemory + extends CopyDirectMemory +{ + private static void init(ByteBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (byte)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(byte [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (byte)ic(i + 1); + } + + public static void test() { + + ByteBuffer b = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + + + + + init(b); + byte [] a = new byte[b.capacity()]; + init(a); + + // copyFromByteArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (byte)ic(i + 1)); + + // copyToByteArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectCharMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectCharMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectCharMemory + extends CopyDirectMemory +{ + private static void init(CharBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (char)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(char [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (char)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + CharBuffer b = bb.asCharBuffer(); + + init(b); + char [] a = new char[b.capacity()]; + init(a); + + // copyFromCharArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (char)ic(i + 1)); + + // copyToCharArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectDoubleMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectDoubleMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectDoubleMemory + extends CopyDirectMemory +{ + private static void init(DoubleBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (double)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(double [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (double)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + DoubleBuffer b = bb.asDoubleBuffer(); + + init(b); + double [] a = new double[b.capacity()]; + init(a); + + // copyFromDoubleArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (double)ic(i + 1)); + + // copyToDoubleArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectFloatMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectFloatMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectFloatMemory + extends CopyDirectMemory +{ + private static void init(FloatBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (float)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(float [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (float)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + FloatBuffer b = bb.asFloatBuffer(); + + init(b); + float [] a = new float[b.capacity()]; + init(a); + + // copyFromFloatArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (float)ic(i + 1)); + + // copyToFloatArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectIntMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectIntMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectIntMemory + extends CopyDirectMemory +{ + private static void init(IntBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (int)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(int [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (int)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + IntBuffer b = bb.asIntBuffer(); + + init(b); + int [] a = new int[b.capacity()]; + init(a); + + // copyFromIntArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (int)ic(i + 1)); + + // copyToIntArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectLongMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectLongMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectLongMemory + extends CopyDirectMemory +{ + private static void init(LongBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (long)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(long [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (long)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + LongBuffer b = bb.asLongBuffer(); + + init(b); + long [] a = new long[b.capacity()]; + init(a); + + // copyFromLongArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (long)ic(i + 1)); + + // copyToLongArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @summary Test view buffer bulk operations for large buffers. + * @bug 4463011 + * + * @build Basic + * @run main CopyDirectMemory + */ + +import java.nio.*; + +public class CopyDirectMemory + extends Basic +{ + public static void main(String [] args) { + CopyDirectByteMemory.test(); + CopyDirectCharMemory.test(); + CopyDirectShortMemory.test(); + CopyDirectIntMemory.test(); + CopyDirectLongMemory.test(); + CopyDirectFloatMemory.test(); + CopyDirectDoubleMemory.test(); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/CopyDirectShortMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/CopyDirectShortMemory.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +// -- This file was mechanically generated: Do not edit! -- // + +import java.nio.*; + +public class CopyDirectShortMemory + extends CopyDirectMemory +{ + private static void init(ShortBuffer b) { + int n = b.capacity(); + b.clear(); + for (int i = 0; i < n; i++) + b.put(i, (short)ic(i)); + b.limit(n); + b.position(0); + } + + private static void init(short [] a) { + for (int i = 0; i < a.length; i++) + a[i] = (short)ic(i + 1); + } + + public static void test() { + + + + ByteBuffer bb = ByteBuffer.allocateDirect(1024 * 1024 + 1024); + ShortBuffer b = bb.asShortBuffer(); + + init(b); + short [] a = new short[b.capacity()]; + init(a); + + // copyFromShortArray (a -> b) + b.put(a); + for (int i = 0; i < a.length; i++) + ck(b, b.get(i), (short)ic(i + 1)); + + // copyToShortArray (b -> a) + init(b); + init(a); + b.get(a); + for (int i = 0; i < a.length; i++) + if (a[i] != b.get(i)) + fail("Copy failed at " + i + ": '" + + a[i] + "' != '" + b.get(i) + "'"); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/genBasic.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/genBasic.sh Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,38 @@ +#! /bin/sh + +# +# Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +SPP='sh ../../../../make/java/nio/spp.sh' + +gen() { + $SPP -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 Basic$2.java +} + +gen byte Byte Byte +gen char Char Character +gen short Short Short +gen int Int Integer +gen long Long Long +gen float Float Float +gen double Double Double diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/nio/Buffer/genCopyDirectMemory.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/nio/Buffer/genCopyDirectMemory.sh Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,39 @@ +#! /bin/sh + +# +# Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +SPP='sh ../../../../make/java/nio/spp.sh' + +gen() { + $SPP -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3CopyDirect$2Memory.java +} + +gen byte Byte Byte +gen char Char Character +gen short Short Short +gen int Int Integer +gen long Long Long +gen float Float Float +gen double Double Double + diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/security/Security/signedfirst/Dyn.sh --- a/j2se/test/java/security/Security/signedfirst/Dyn.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/security/Security/signedfirst/Dyn.sh Thu Jul 05 23:47:33 2007 +0000 @@ -21,7 +21,7 @@ # have any questions. # -# @test 1.7 07/06/21 +# @test 1.7 07/07/05 # @bug 4504355 # @summary problems if signed crypto provider is the most preferred provider # diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/security/Security/signedfirst/Static.sh --- a/j2se/test/java/security/Security/signedfirst/Static.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/security/Security/signedfirst/Static.sh Thu Jul 05 23:47:33 2007 +0000 @@ -21,7 +21,7 @@ # have any questions. # -# @test 1.8 07/06/21 +# @test 1.8 07/07/05 # @bug 4504355 4744260 # @summary problems if signed crypto provider is the most preferred provider # diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/ArrayList/Bug6533203.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/ArrayList/Bug6533203.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.1 07/06/11 + * @bug 6533203 + * @summary AbstractList.ListItr.add might corrupt iterator state if enclosing add throws + */ + +import java.util.*; + +@SuppressWarnings({"serial","unchecked"}) +public class Bug6533203 { + void test(String[] args) throws Throwable { + final List superstitious = new ArrayList() { + public void add(int index, Integer i) { + if (i == 13) throw new Error("unlucky"); + else super.add(index, i); }}; + final ListIterator it = superstitious.listIterator(0); + equal(it.nextIndex(), 0); + THROWS(Error.class, new F(){void f(){it.add(13);}}); + equal(it.nextIndex(), 0); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.out.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new Bug6533203().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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 class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/ArrayList/IteratorMicroBenchmark.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/ArrayList/IteratorMicroBenchmark.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This is not a regression test, but a micro-benchmark. + * Be patient; this runs for half an hour! + * + * I have run this as follows: + * + * for f in -client -server; do mergeBench dolphin . jr -dsa -da $f IteratorMicroBenchmark.java; done + * + * @version 1.1 07/06/11 + * @author Martin Buchholz + */ + +import java.util.*; +import java.util.concurrent.*; +import java.util.regex.Pattern; + +public class IteratorMicroBenchmark { + abstract static class Job { + private final String name; + public Job(String name) { this.name = name; } + public String name() { return name; } + public abstract void work() throws Throwable; + } + + private static void collectAllGarbage() { + final java.util.concurrent.CountDownLatch drained + = new java.util.concurrent.CountDownLatch(1); + try { + System.gc(); // enqueue finalizable objects + new Object() { protected void finalize() { + drained.countDown(); }}; + System.gc(); // enqueue detector + drained.await(); // wait for finalizer queue to drain + System.gc(); // cleanup finalized objects + } catch (InterruptedException e) { throw new Error(e); } + } + + /** + * Runs each job for long enough that all the runtime compilers + * have had plenty of time to warm up, i.e. get around to + * compiling everything worth compiling. + * Returns array of average times per job per run. + */ + private static long[] time0(Job ... jobs) throws Throwable { + final long warmupNanos = 10L * 1000L * 1000L * 1000L; + long[] nanoss = new long[jobs.length]; + for (int i = 0; i < jobs.length; i++) { + collectAllGarbage(); + long t0 = System.nanoTime(); + long t; + int j = 0; + do { jobs[i].work(); j++; } + while ((t = System.nanoTime() - t0) < warmupNanos); + nanoss[i] = t/j; + } + return nanoss; + } + + private static void time(Job ... jobs) throws Throwable { + + long[] warmup = time0(jobs); // Warm up run + long[] nanoss = time0(jobs); // Real timing run + long[] milliss = new long[jobs.length]; + double[] ratios = new double[jobs.length]; + + final String nameHeader = "Method"; + final String millisHeader = "Millis"; + final String ratioHeader = "Ratio"; + + int nameWidth = nameHeader.length(); + int millisWidth = millisHeader.length(); + int ratioWidth = ratioHeader.length(); + + for (int i = 0; i < jobs.length; i++) { + nameWidth = Math.max(nameWidth, jobs[i].name().length()); + + milliss[i] = nanoss[i]/(1000L * 1000L); + millisWidth = Math.max(millisWidth, + String.format("%d", milliss[i]).length()); + + ratios[i] = (double) nanoss[i] / (double) nanoss[0]; + ratioWidth = Math.max(ratioWidth, + String.format("%.3f", ratios[i]).length()); + } + + String format = String.format("%%-%ds %%%dd %%%d.3f%%n", + nameWidth, millisWidth, ratioWidth); + String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n", + nameWidth, millisWidth, ratioWidth); + System.out.printf(headerFormat, "Method", "Millis", "Ratio"); + + // Print out absolute and relative times, calibrated against first job + for (int i = 0; i < jobs.length; i++) + System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]); + } + + private static String keywordValue(String[] args, String keyword) { + for (String arg : args) + if (arg.startsWith(keyword)) + return arg.substring(keyword.length() + 1); + return null; + } + + private static int intArg(String[] args, String keyword, int defaultValue) { + String val = keywordValue(args, keyword); + return val == null ? defaultValue : Integer.parseInt(val); + } + + private static Pattern patternArg(String[] args, String keyword) { + String val = keywordValue(args, keyword); + return val == null ? null : Pattern.compile(val); + } + + private static Job[] filter(Pattern filter, Job[] jobs) { + if (filter == null) return jobs; + Job[] newJobs = new Job[jobs.length]; + int n = 0; + for (Job job : jobs) + if (filter.matcher(job.name()).find()) + newJobs[n++] = job; + // Arrays.copyOf not available in JDK 5 + Job[] ret = new Job[n]; + System.arraycopy(newJobs, 0, ret, 0, n); + return ret; + } + + private static void deoptimize(int sum) { + if (sum == 42) + System.out.println("the answer"); + } + + private static List asSubList(List list) { + return list.subList(0, list.size()); + } + + private static Iterable backwards(final List list) { + return new Iterable() { + public Iterator iterator() { + return new Iterator() { + final ListIterator it = list.listIterator(list.size()); + public boolean hasNext() { return it.hasPrevious(); } + public T next() { return it.previous(); } + public void remove() { it.remove(); }};}}; + } + + /** + * Usage: [iterations=N] [size=N] [filter=REGEXP] + */ + public static void main(String[] args) throws Throwable { + final int iterations = intArg(args, "iterations", 100000); + final int size = intArg(args, "size", 1000); + final Pattern filter = patternArg(args, "filter"); + + final ConcurrentSkipListMap m + = new ConcurrentSkipListMap(); + final Vector v = new Vector(size); + final ArrayList al = new ArrayList(size); + + // Populate collections with random data + final Random rnd = new Random(); + for (int i = 0; i < size; i++) { + m.put(rnd.nextInt(size), rnd.nextInt(size)); + v.add(rnd.nextInt(size)); + } + al.addAll(v); + + // Also test "short" collections + final int shortSize = 5; + final Vector sv = new Vector(v.subList(0, shortSize)); + final ArrayList sal = new ArrayList(sv); + + // Checks for correctness *and* prevents loop optimizations + class Check { + private int sum; + public void sum(int sum) { + if (this.sum == 0) + this.sum = sum; + if (this.sum != sum) + throw new AssertionError("Sum mismatch"); + } + } + final Check check = new Check(); + final Check shortCheck = new Check(); + + Job[] jobs = { +// new Job("Vector iterate desugared") { +// public void work() throws Throwable { +// for (int i = 0; i < iterations; i++) { +// int sum = 0; +// for (Iterator it = v.iterator(); it.hasNext();) +// sum += it.next(); +// check.sum(sum);}}}, + new Job("array loop") { + public void work() throws Throwable { + Integer[] a = al.toArray(new Integer[0]); + for (int i = 0; i < iterations; i++) { + int sum = 0; + int size = a.length; + for (int j = 0; j < size; ++j) + sum += a[j]; + check.sum(sum);}}}, + new Job("Vector get loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + int size = v.size(); + for (int j = 0; j < size; ++j) + sum += v.get(j); + check.sum(sum);}}}, + new Job("Vector iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : v) + sum += n; + check.sum(sum);}}}, + new Job("Vector descending listIterator loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + ListIterator it = v.listIterator(al.size()); + while (it.hasPrevious()) + sum += it.previous(); + check.sum(sum);}}}, + new Job("Vector Enumeration loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + Enumeration it = v.elements(); + while (it.hasMoreElements()) + sum += it.nextElement(); + check.sum(sum);}}}, + new Job("Vector subList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : asSubList(v)) + sum += n; + check.sum(sum);}}}, + new Job("Vector subList subList subList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : asSubList(asSubList(asSubList(v)))) + sum += n; + check.sum(sum);}}}, + new Job("Vector backwards wrapper ListIterator for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : backwards(v)) + sum += n; + check.sum(sum);}}}, + new Job("Vector backwards wrapper subList ListIterator for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : backwards(asSubList(v))) + sum += n; + check.sum(sum);}}}, +// new Job("Vector iterate for loop invokeinterface") { +// public void work() throws Throwable { +// final List l = v; +// for (int i = 0; i < iterations; i++) { +// int sum = 0; +// for (Integer n : l) +// sum += n; +// check.sum(sum);}}}, +// new Job("Vector subList iterate for loop invokeinterface") { +// public void work() throws Throwable { +// final List l = v; +// for (int i = 0; i < iterations; i++) { +// int sum = 0; +// for (Integer n : asSubList(l)) +// sum += n; +// check.sum(sum);}}}, + new Job("Short Vector get loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + int size = sv.size(); + for (int j = 0; j < size; ++j) + sum += sv.get(j); + shortCheck.sum(sum);}}}, + new Job("Short Vector iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + for (Integer n : sv) + sum += n; + shortCheck.sum(sum);}}}, + new Job("Short Vector sublist iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + for (Integer n : asSubList(sv)) + sum += n; + shortCheck.sum(sum);}}}, + new Job("ArrayList get loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + int size = al.size(); + for (int j = 0; j < size; ++j) + sum += al.get(j); + check.sum(sum);}}}, + new Job("ArrayList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : al) + sum += n; + check.sum(sum);}}}, + new Job("ArrayList descending listIterator loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + ListIterator it = al.listIterator(al.size()); + while (it.hasPrevious()) + sum += it.previous(); + check.sum(sum);}}}, + new Job("ArrayList listIterator loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + ListIterator it = al.listIterator(); + while (it.hasNext()) + sum += it.next(); + check.sum(sum);}}}, + new Job("ArrayList subList get loop") { + public void work() throws Throwable { + List sl = asSubList(al); + for (int i = 0; i < iterations; i++) { + int sum = 0; + int size = sl.size(); + for (int j = 0; j < size; ++j) + sum += sl.get(j); + check.sum(sum);}}}, + new Job("ArrayList subList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : asSubList(al)) + sum += n; + check.sum(sum);}}}, + new Job("ArrayList subList subList subList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : asSubList(asSubList(asSubList(al)))) + sum += n; + check.sum(sum);}}}, + new Job("ArrayList backwards wrapper ListIterator for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : backwards(al)) + sum += n; + check.sum(sum);}}}, + new Job("ArrayList backwards wrapper subList ListIterator for loop") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Integer n : backwards(asSubList(al))) + sum += n; + check.sum(sum);}}}, +// new Job("ArrayList iterate desugared") { +// public void work() throws Throwable { +// for (int i = 0; i < iterations; i++) { +// int sum = 0; +// for (Iterator it = al.iterator(); it.hasNext();) +// sum += it.next(); +// check.sum(sum);}}}, + new Job("Short ArrayList get loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + int size = sal.size(); + for (int j = 0; j < size; ++j) + sum += sal.get(j); + shortCheck.sum(sum);}}}, + new Job("Short ArrayList iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + for (Integer n : sal) + sum += n; + shortCheck.sum(sum);}}}, + new Job("Short ArrayList sublist iterate for loop") { + public void work() throws Throwable { + for (int i = 0; i < (iterations * size / shortSize); i++) { + int sum = 0; + for (Integer n : asSubList(sal)) + sum += n; + shortCheck.sum(sum);}}}, + new Job("Vector ArrayList alternating iteration") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + Iterator it1 = v.iterator(); + Iterator it2 = al.iterator(); + while (it1.hasNext()) + sum += it1.next() + it2.next(); + check.sum(sum/2);}}}, + new Job("Vector ArrayList alternating invokeVirtual iteration") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + List> its + = new ArrayList>(2); + its.add(v.iterator()); + its.add(al.iterator()); + for (int k = 0; its.get(k).hasNext(); k = (k == 0) ? 1 : 0) + sum += its.get(k).next(); + check.sum(sum/2);}}}, + new Job("ConcurrentSkipListMap entrySet iterate") { + public void work() throws Throwable { + for (int i = 0; i < iterations; i++) { + int sum = 0; + for (Map.Entry e : m.entrySet()) + sum += e.getKey(); + deoptimize(sum);}}} + }; + + time(filter(filter, jobs)); + } +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/ArrayList/RangeCheckMicroBenchmark.java --- a/j2se/test/java/util/ArrayList/RangeCheckMicroBenchmark.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/ArrayList/RangeCheckMicroBenchmark.java Thu Jul 05 23:47:33 2007 +0000 @@ -26,13 +26,15 @@ * * I have run this as follows: * - * repeat 5 for f in -client -server; do mergeBench dolphin outline jr -dsa -da $f RangeCheckMicroBenchmark.java; done + * repeat 5 for f in -client -server; do mergeBench dolphin . jr -dsa -da $f RangeCheckMicroBenchmark.java; done * - * @version 1.4 07/05/05 + * @version 1.5 07/06/11 * @author Martin Buchholz */ import java.util.*; +import java.util.regex.Pattern; +import java.util.concurrent.CountDownLatch; public class RangeCheckMicroBenchmark { abstract static class Job { @@ -43,10 +45,14 @@ } private static void collectAllGarbage() { + final CountDownLatch drained = new CountDownLatch(1); try { - for (int i = 0; i < 2; i++) { - System.gc(); System.runFinalization(); Thread.sleep(10); - } + System.gc(); // enqueue finalizable objects + new Object() { protected void finalize() { + drained.countDown(); }}; + System.gc(); // enqueue detector + drained.await(); // wait for finalizer queue to drain + System.gc(); // cleanup finalized objects } catch (InterruptedException e) { throw new Error(e); } } @@ -75,38 +81,68 @@ long[] warmup = time0(jobs); // Warm up run long[] nanoss = time0(jobs); // Real timing run + long[] milliss = new long[jobs.length]; + double[] ratios = new double[jobs.length]; - final String nameHeader = "Method"; - int nameWidth = nameHeader.length(); - for (Job job : jobs) - nameWidth = Math.max(nameWidth, job.name().length()); - + final String nameHeader = "Method"; final String millisHeader = "Millis"; - int millisWidth = millisHeader.length(); - for (long nanos : nanoss) - millisWidth = - Math.max(millisWidth, - String.format("%d", nanos/(1000L * 1000L)).length()); + final String ratioHeader = "Ratio"; + + int nameWidth = nameHeader.length(); + int millisWidth = millisHeader.length(); + int ratioWidth = ratioHeader.length(); + + for (int i = 0; i < jobs.length; i++) { + nameWidth = Math.max(nameWidth, jobs[i].name().length()); - final String ratioHeader = "Ratio"; - int ratioWidth = ratioHeader.length(); + milliss[i] = nanoss[i]/(1000L * 1000L); + millisWidth = Math.max(millisWidth, + String.format("%d", milliss[i]).length()); - String format = String.format("%%-%ds %%%dd %%.3f%%n", - nameWidth, millisWidth); - String headerFormat = String.format("%%-%ds %%-%ds %%-%ds%%n", + ratios[i] = (double) nanoss[i] / (double) nanoss[0]; + ratioWidth = Math.max(ratioWidth, + String.format("%.3f", ratios[i]).length()); + } + + String format = String.format("%%-%ds %%%dd %%%d.3f%%n", + nameWidth, millisWidth, ratioWidth); + String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n", nameWidth, millisWidth, ratioWidth); System.out.printf(headerFormat, "Method", "Millis", "Ratio"); // Print out absolute and relative times, calibrated against first job - for (int i = 0; i < jobs.length; i++) { - long millis = nanoss[i]/(1000L * 1000L); - double ratio = (double)nanoss[i] / (double)nanoss[0]; - System.out.printf(format, jobs[i].name(), millis, ratio); - } + for (int i = 0; i < jobs.length; i++) + System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]); + } + + private static String keywordValue(String[] args, String keyword) { + for (String arg : args) + if (arg.startsWith(keyword)) + return arg.substring(keyword.length() + 1); + return null; + } + + private static int intArg(String[] args, String keyword, int defaultValue) { + String val = keywordValue(args, keyword); + return val == null ? defaultValue : Integer.parseInt(val); } - private static int intArg(String[] args, int i, int defaultValue) { - return args.length > i ? Integer.parseInt(args[i]) : defaultValue; + private static Pattern patternArg(String[] args, String keyword) { + String val = keywordValue(args, keyword); + return val == null ? null : Pattern.compile(val); + } + + private static Job[] filter(Pattern filter, Job[] jobs) { + if (filter == null) return jobs; + Job[] newJobs = new Job[jobs.length]; + int n = 0; + for (Job job : jobs) + if (filter.matcher(job.name()).find()) + newJobs[n++] = job; + // Arrays.copyOf not available in JDK 5 + Job[] ret = new Job[n]; + System.arraycopy(newJobs, 0, ret, 0, n); + return ret; } private static void deoptimize(ArrayList list) { @@ -115,15 +151,20 @@ throw new Error(); } + /** + * Usage: [iterations=N] [size=N] [filter=REGEXP] + */ public static void main(String[] args) throws Throwable { - final int iterations = intArg(args, 0, 30000); - final int size = intArg(args, 1, 1000); + final int iterations = intArg(args, "iterations", 30000); + final int size = intArg(args, "size", 1000); + final Pattern filter = patternArg(args, "filter"); + final ArrayList list = new ArrayList(); final Random rnd = new Random(); for (int i = 0; i < size; i++) list.add(rnd.nextInt()); - time( + final Job[] jobs = { new Job("get") { void work() { for (int i = 0; i < iterations; i++) { for (int k = 0; k < size; k++) @@ -152,7 +193,42 @@ list.remove(size); } } + deoptimize(list);}}, + new Job("subList get") { void work() { + List sublist = list.subList(0, list.size()); + for (int i = 0; i < iterations; i++) { + for (int k = 0; k < size; k++) + if (sublist.get(k) == 42) + throw new Error(); + } + deoptimize(list);}}, + new Job("subList set") { void work() { + List sublist = list.subList(0, list.size()); + Integer[] xs = sublist.toArray(new Integer[size]); + for (int i = 0; i < iterations; i++) { + for (int k = 0; k < size; k++) + sublist.set(k, xs[k]); + } + deoptimize(list);}}, + new Job("subList get/set") { void work() { + List sublist = list.subList(0, list.size()); + for (int i = 0; i < iterations; i++) { + for (int k = 0; k < size; k++) + sublist.set(k, sublist.get(size - k - 1)); + } + deoptimize(list);}}, + new Job("subList add/remove at end") { void work() { + List sublist = list.subList(0, list.size()); + Integer x = rnd.nextInt(); + for (int i = 0; i < iterations; i++) { + for (int k = 0; k < size - 1; k++) { + sublist.add(size, x); + sublist.remove(size); + } + } deoptimize(list);}} - ); + }; + + time(filter(filter, jobs)); } } diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Collections/T6433170.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/Collections/T6433170.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.1 07/06/12 + * @bug 6433170 + * @summary CheckedCollection.addAll should be all-or-nothing + */ + +import java.util.*; +import static java.util.Collections.*; + +@SuppressWarnings("unchecked") +public class T6433170 { + private void checkEmpty(Collection x) { + check(x.isEmpty()); + check(x.size() == 0); + check(x.toArray().length == 0); + } + + void test(String[] args) throws Throwable { + test(checkedList( + checkedList(new ArrayList(), String.class), + Object.class)); + test(checkedSet( + checkedSet(new HashSet(), String.class), + Object.class)); + test(checkedCollection( + checkedCollection(new Vector(), String.class), + Object.class)); + } + + void test(final Collection checked) { + checkEmpty(checked); + final List mixedList = Arrays.asList("1", 2, "3"); + THROWS(ClassCastException.class, + new F(){void f(){ checked.addAll(mixedList); }}); + checkEmpty(checked); + } + + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new T6433170().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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 class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/Basic-X.java --- a/j2se/test/java/util/Formatter/Basic-X.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/Basic-X.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; +#if[double] import sun.misc.FpUtils; import sun.misc.DoubleConsts; +#end[double] import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -484,6 +488,7 @@ $type$ oneToSeven = ($type$) 1234567; test("%d", "1234567", oneToSeven); test("%,d", "1,234,567", oneToSeven); + test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", oneToSeven); test("%,d", "-1,234,567", negate(oneToSeven)); test("%(d", "1234567", oneToSeven); test("%(d", "(1234567)", negate(oneToSeven)); @@ -627,6 +632,7 @@ test("%d", "null", (Object)null); test("%d", "1234567", new BigInteger("1234567", 10)); test("%,d", "1,234,567", new BigInteger("1234567", 10)); + test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", new BigInteger("1234567", 10)); test("%,d", "-1,234,567", new BigInteger("-1234567", 10)); test("%(d", "1234567", new BigInteger("1234567", 10)); test("%(d", "(1234567)", new BigInteger("-1234567", 10)); @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -880,6 +888,7 @@ test("%.3f", "-3141.593", mult(pi, -1000.0)); test("%,.2f", "3,141.59", mult(pi, 1000.0)); + test(Locale.FRANCE, "%,.2f", "3\u00a0141,59", mult(pi, 1000.0)); test("%,.2f", "-3,141.59", mult(pi, -1000.0)); test("%(.2f", "3141.59", mult(pi, 1000.0)); test("%(.2f", "(3141.59)", mult(pi, -1000.0)); @@ -891,6 +900,7 @@ test("%.3f", "3141592.654", mult(pi, 1000000.0)); test("%.3f", "-3141592.654", mult(pi, -1000000.0)); test("%,.4f", "3,141,592.6536", mult(pi, 1000000.0)); + test(Locale.FRANCE, "%,.4f", "3\u00a0141\u00a0592,6536", mult(pi, 1000000.0)); test("%,.4f", "-3,141,592.6536", mult(pi, -1000000.0)); test("%(.4f", "3141592.6536", mult(pi, 1000000.0)); test("%(.4f", "(3141592.6536)", mult(pi, -1000000.0)); @@ -903,6 +913,7 @@ // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -975,6 +986,7 @@ #if[BigDecimal] test("%.3g", "1.40e+149", piToThe300); test("%.3g", "-1.40e+149", piToThe300.negate()); + test(Locale.FRANCE, "%.3g", "-1,40e+149", piToThe300.negate()); test("%.3g", "1.00e-100", recip(ten.pow(100))); test("%.3g", "-1.00e-100", negate(recip(ten.pow(100)))); @@ -1033,6 +1045,7 @@ // %a test("%a", "null", (Object)null); test("%.11a", "0x0.00000000000p0", 0.0); + test(Locale.FRANCE, "%.11a", "0x0.00000000000p0", 0.0); // no localization test("%.1a", "0x0.0p0", 0.0); test("%.11a", "-0x0.00000000000p0", -0.0); test("%.1a", "-0x0.0p0", -0.0); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/Basic.java --- a/j2se/test/java/util/Formatter/Basic.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/Basic.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,11 @@ * have any questions. */ -/* @test @(#)Basic.java 1.12 07/05/05 +/* @test * @summary Unit test for formatter * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937 - * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 6344623 - * 6369500 + * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 + * 6344623 6369500 6534606 * * @run shell/timeout=240 Basic.sh */ diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicBigDecimal.java --- a/j2se/test/java/util/Formatter/BasicBigDecimal.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicBigDecimal.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -687,6 +691,8 @@ + + BigDecimal one = BigDecimal.ONE; BigDecimal ten = BigDecimal.TEN; BigDecimal pi = new BigDecimal(Math.PI); @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -888,9 +896,11 @@ + test("%.3f", "3141592.654", mult(pi, 1000000.0)); test("%.3f", "-3141592.654", mult(pi, -1000000.0)); test("%,.4f", "3,141,592.6536", mult(pi, 1000000.0)); + test(Locale.FRANCE, "%,.4f", "3\u00a0141\u00a0592,6536", mult(pi, 1000000.0)); test("%,.4f", "-3,141,592.6536", mult(pi, -1000000.0)); test("%(.4f", "3141592.6536", mult(pi, 1000000.0)); test("%(.4f", "(3141592.6536)", mult(pi, -1000000.0)); @@ -903,6 +913,7 @@ // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -975,6 +986,7 @@ test("%.3g", "1.40e+149", piToThe300); test("%.3g", "-1.40e+149", piToThe300.negate()); + test(Locale.FRANCE, "%.3g", "-1,40e+149", piToThe300.negate()); test("%.3g", "1.00e-100", recip(ten.pow(100))); test("%.3g", "-1.00e-100", negate(recip(ten.pow(100)))); @@ -1080,6 +1092,7 @@ + // boundaries diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicBigInteger.java --- a/j2se/test/java/util/Formatter/BasicBigInteger.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicBigInteger.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -620,6 +624,7 @@ + tryCatch("%f", IllegalFormatConversionException.class, new BigInteger("1")); @@ -627,6 +632,7 @@ test("%d", "null", (Object)null); test("%d", "1234567", new BigInteger("1234567", 10)); test("%,d", "1,234,567", new BigInteger("1234567", 10)); + test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", new BigInteger("1234567", 10)); test("%,d", "-1,234,567", new BigInteger("-1234567", 10)); test("%(d", "1234567", new BigInteger("1234567", 10)); test("%(d", "(1234567)", new BigInteger("-1234567", 10)); @@ -1298,6 +1304,13 @@ + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicBoolean.java --- a/j2se/test/java/util/Formatter/BasicBoolean.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicBoolean.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicBooleanObject.java --- a/j2se/test/java/util/Formatter/BasicBooleanObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicBooleanObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicByte.java --- a/j2se/test/java/util/Formatter/BasicByte.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicByte.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicByteObject.java --- a/j2se/test/java/util/Formatter/BasicByteObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicByteObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicCalendar.java --- a/j2se/test/java/util/Formatter/BasicCalendar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicCalendar.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicChar.java --- a/j2se/test/java/util/Formatter/BasicChar.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicChar.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicCharObject.java --- a/j2se/test/java/util/Formatter/BasicCharObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicCharObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicDate.java --- a/j2se/test/java/util/Formatter/BasicDate.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicDate.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -1298,6 +1302,15 @@ + + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicDouble.java --- a/j2se/test/java/util/Formatter/BasicDouble.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicDouble.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,9 +35,11 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; + import sun.misc.FpUtils; import sun.misc.DoubleConsts; + import static java.util.Calendar.*; public class BasicDouble extends Basic { @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -712,6 +716,8 @@ + + double one = 1.0; double ten = 10.0; double pi = Math.PI; @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -888,9 +896,11 @@ + test("%.3f", "3141592.654", mult(pi, 1000000.0)); test("%.3f", "-3141592.654", mult(pi, -1000000.0)); test("%,.4f", "3,141,592.6536", mult(pi, 1000000.0)); + test(Locale.FRANCE, "%,.4f", "3\u00a0141\u00a0592,6536", mult(pi, 1000000.0)); test("%,.4f", "-3,141,592.6536", mult(pi, -1000000.0)); test("%(.4f", "3141592.6536", mult(pi, 1000000.0)); test("%(.4f", "(3141592.6536)", mult(pi, -1000000.0)); @@ -903,6 +913,7 @@ // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -1005,6 +1016,7 @@ + test("%.3g", "10.0", ten); test("%.3g", "1.00", one); test("%10.3g", " 1.00", one); @@ -1033,6 +1045,7 @@ // %a test("%a", "null", (Object)null); test("%.11a", "0x0.00000000000p0", 0.0); + test(Locale.FRANCE, "%.11a", "0x0.00000000000p0", 0.0); // no localization test("%.1a", "0x0.0p0", 0.0); test("%.11a", "-0x0.00000000000p0", -0.0); test("%.1a", "-0x0.0p0", -0.0); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicDoubleObject.java --- a/j2se/test/java/util/Formatter/BasicDoubleObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicDoubleObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -720,6 +724,8 @@ + + Double one = new Double(1.0); Double ten = new Double(10.0); Double pi = new Double(Math.PI); @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -888,9 +896,11 @@ + test("%.3f", "3141592.654", mult(pi, 1000000.0)); test("%.3f", "-3141592.654", mult(pi, -1000000.0)); test("%,.4f", "3,141,592.6536", mult(pi, 1000000.0)); + test(Locale.FRANCE, "%,.4f", "3\u00a0141\u00a0592,6536", mult(pi, 1000000.0)); test("%,.4f", "-3,141,592.6536", mult(pi, -1000000.0)); test("%(.4f", "3141592.6536", mult(pi, 1000000.0)); test("%(.4f", "(3141592.6536)", mult(pi, -1000000.0)); @@ -903,6 +913,7 @@ // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -1005,6 +1016,7 @@ + test("%.3g", "10.0", ten); test("%.3g", "1.00", one); test("%10.3g", " 1.00", one); @@ -1080,6 +1092,7 @@ + // boundaries diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicFloat.java --- a/j2se/test/java/util/Formatter/BasicFloat.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicFloat.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -696,6 +700,8 @@ + + float one = 1.0f; float ten = 10.0f; float pi = (float) Math.PI; @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -880,6 +888,7 @@ test("%.3f", "-3141.593", mult(pi, -1000.0)); test("%,.2f", "3,141.59", mult(pi, 1000.0)); + test(Locale.FRANCE, "%,.2f", "3\u00a0141,59", mult(pi, 1000.0)); test("%,.2f", "-3,141.59", mult(pi, -1000.0)); test("%(.2f", "3141.59", mult(pi, 1000.0)); test("%(.2f", "(3141.59)", mult(pi, -1000.0)); @@ -900,9 +909,11 @@ + // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -1005,6 +1016,7 @@ + test("%.3g", "10.0", ten); test("%.3g", "1.00", one); test("%10.3g", " 1.00", one); @@ -1080,6 +1092,7 @@ + // boundaries // NaN diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicFloatObject.java --- a/j2se/test/java/util/Formatter/BasicFloatObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicFloatObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -704,6 +708,8 @@ + + Float one = new Float(1.0f); Float ten = new Float(10.0f); Float pi = new Float(Math.PI); @@ -736,6 +742,7 @@ // %e test("%e", "null", (Object)null); test("%e", "3.141593e+00", pi); + test(Locale.FRANCE, "%e", "3,141593e+00", pi); test("%.0e", "1e+01", ten); test("%#.0e", "1.e+01", ten); test("%E", "3.141593E+00", pi); @@ -817,6 +824,7 @@ // %f test("%f", "null", (Object)null); test("%f", "3.141593", pi); + test(Locale.FRANCE, "%f", "3,141593", pi); test("%10.3f", " 3.142", pi); test("%10.3f", " -3.142", negate(pi)); test("%010.3f", "000003.142", pi); @@ -900,9 +908,12 @@ + + // %g test("%g", "null", (Object)null); test("%g", "3.14159", pi); + test(Locale.FRANCE, "%g", "3,14159", pi); test("%.0g", "1e+01", ten); test("%G", "3.14159", pi); test("%10.3g", " 3.14", pi); @@ -1005,6 +1016,7 @@ + test("%.3g", "10.0", ten); test("%.3g", "1.00", one); test("%10.3g", " 1.00", one); @@ -1080,6 +1092,7 @@ + // boundaries diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicInt.java --- a/j2se/test/java/util/Formatter/BasicInt.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicInt.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -484,6 +488,7 @@ int oneToSeven = (int) 1234567; test("%d", "1234567", oneToSeven); test("%,d", "1,234,567", oneToSeven); + test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", oneToSeven); test("%,d", "-1,234,567", negate(oneToSeven)); test("%(d", "1234567", oneToSeven); test("%(d", "(1234567)", negate(oneToSeven)); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicIntObject.java --- a/j2se/test/java/util/Formatter/BasicIntObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicIntObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicLong.java --- a/j2se/test/java/util/Formatter/BasicLong.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicLong.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -484,6 +488,7 @@ long oneToSeven = (long) 1234567; test("%d", "1234567", oneToSeven); test("%,d", "1,234,567", oneToSeven); + test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", oneToSeven); test("%,d", "-1,234,567", negate(oneToSeven)); test("%(d", "1234567", oneToSeven); test("%(d", "(1234567)", negate(oneToSeven)); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicLongObject.java --- a/j2se/test/java/util/Formatter/BasicLongObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicLongObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicShort.java --- a/j2se/test/java/util/Formatter/BasicShort.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicShort.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/BasicShortObject.java --- a/j2se/test/java/util/Formatter/BasicShortObject.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/BasicShortObject.java Thu Jul 05 23:47:33 2007 +0000 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,10 @@ import java.math.BigInteger; import java.text.DateFormatSymbols; import java.util.*; -import sun.misc.FpUtils; -import sun.misc.DoubleConsts; + + + + import static java.util.Calendar.*; @@ -330,7 +332,9 @@ // %b test("%b", "true", true); + test(Locale.FRANCE, "%b", "true", true); test("%b", "false", false); + test(Locale.FRANCE, "%b", "false", false); test("%B", "TRUE", true); test("%B", "FALSE", false); test("%b", "true", Boolean.TRUE); @@ -499,6 +503,7 @@ + tryCatch("%#d", FormatFlagsConversionMismatchException.class); tryCatch("%D", UnknownFormatConversionException.class); tryCatch("%0d", MissingFormatWidthException.class); @@ -1298,6 +1303,14 @@ + + + + + + + + // %t test("%tA", "null", (Object)null); test("%TA", "NULL", (Object)null); diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/Formatter/genBasic.sh --- a/j2se/test/java/util/Formatter/genBasic.sh Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/java/util/Formatter/genBasic.sh Thu Jul 05 23:47:33 2007 +0000 @@ -23,8 +23,6 @@ # have any questions. # -# @(#)genBasic.sh 1.4 07/05/05 - SPP='sh ../../../../make/java/nio/spp.sh' gen() { diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/List/LockStep.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/List/LockStep.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.1 07/06/11 + * @bug 6359979 + * @summary Compare List implementations for identical behavior + * @author Martin Buchholz + */ + +import java.io.*; +import java.util.*; +import java.util.concurrent.*; +import static java.util.Collections.*; + +@SuppressWarnings("unchecked") +public class LockStep { + final int DEFAULT_SIZE = 5; + int size; // Running time is O(size**2) + + int intArg(String[] args, int i, int defaultValue) { + return args.length > i ? Integer.parseInt(args[i]) : defaultValue; + } + + boolean maybe(int n) { return rnd.nextInt(n) == 0; } + + void test(String[] args) { + size = intArg(args, 0, DEFAULT_SIZE); + + lockSteps(new ArrayList(), + new LinkedList(), + new Vector()); + } + + void equalLists(List... lists) { + for (List list : lists) + equalLists(list, lists[0]); + } + + void equalLists(List x, List y) { + equal(x, y); + equal(y, x); + equal(x.size(), y.size()); + equal(x.isEmpty(), y.isEmpty()); + equal(x.hashCode(), y.hashCode()); + equal(x.toString(), y.toString()); + equal(x.toArray(), y.toArray()); + } + + void lockSteps(List... lists) { + for (int i = 0; i < lists.length; i++) + if (maybe(4)) lists[i] = serialClone(lists[i]); + for (final List list : lists) + testEmptyList(list); + for (int i = 0; i < size; i++) { + ListFrobber adder = randomAdder(); + for (final List list : lists) { + adder.frob(list); + equal(list.size(), i+1); + } + equalLists(lists); + } + { + final ListFrobber adder = randomAdder(); + final ListFrobber remover = randomRemover(); + for (final List list : lists) { + + THROWS(ConcurrentModificationException.class, + new F(){void f(){ + Iterator it = list.iterator(); + adder.frob(list); + it.next();}}, + new F(){void f(){ + Iterator it = asSubList(list).iterator(); + remover.frob(list); + it.next();}}, + new F(){void f(){ + Iterator it = asSubList(asSubList(list)).iterator(); + adder.frob(list); + it.next();}}, + new F(){void f(){ + List subList = asSubList(list); + remover.frob(list); + subList.get(0);}}, + new F(){void f(){ + List sl = asSubList(list); + List ssl = asSubList(sl); + adder.frob(sl); + ssl.get(0);}}, + new F(){void f(){ + List sl = asSubList(list); + List ssl = asSubList(sl); + remover.frob(sl); + ssl.get(0);}}); + } + } + + for (final List l : lists) { + final List sl = asSubList(l); + final List ssl = asSubList(sl); + ssl.add(0, 42); + equal(ssl.get(0), 42); + equal(sl.get(0), 42); + equal(l.get(0), 42); + final int s = l.size(); + final int rndIndex = rnd.nextInt(l.size()); + THROWS(IndexOutOfBoundsException.class, + new F(){void f(){l.subList(rndIndex, rndIndex).get(0);}}, + new F(){void f(){l.subList(s/2, s).get(s/2 + 1);}}, + new F(){void f(){l.subList(s/2, s).get(-1);}} + ); + THROWS(IllegalArgumentException.class, + new F(){void f(){ l.subList(1, 0);}}, + new F(){void f(){ sl.subList(1, 0);}}, + new F(){void f(){ssl.subList(1, 0);}}); + } + + equalLists(lists); + + for (final List list : lists) { + equalLists(list, asSubList(list)); + equalLists(list, asSubList(asSubList(list))); + } + for (final List list : lists) + System.out.println(list); + + for (int i = lists[0].size(); i > 0; i--) { + ListFrobber remover = randomRemover(); + for (final List list : lists) + remover.frob(list); + equalLists(lists); + } + } + + List asSubList(List list) { + return list.subList(0, list.size()); + } + + void testEmptyCollection(Collection c) { + check(c.isEmpty()); + equal(c.size(), 0); + equal(c.toString(),"[]"); + equal(c.toArray().length, 0); + equal(c.toArray(new Object[0]).length, 0); + + Object[] a = new Object[1]; a[0] = Boolean.TRUE; + equal(c.toArray(a), a); + equal(a[0], null); + } + + void testEmptyList(List list) { + testEmptyCollection(list); + equal(list.hashCode(), 1); + equal(list, Collections.emptyList()); + } + + final Random rnd = new Random(); + + abstract class ListFrobber { abstract void frob(List l); } + + ListFrobber randomAdder() { + final Integer e = rnd.nextInt(1024); + final int subListCount = rnd.nextInt(3); + final boolean atBeginning = rnd.nextBoolean(); + final boolean useIterator = rnd.nextBoolean(); + final boolean simpleIterator = rnd.nextBoolean(); + return new ListFrobber() {void frob(List l) { + final int s = l.size(); + List ll = l; + for (int i = 0; i < subListCount; i++) + ll = asSubList(ll); + if (! useIterator) { + if (atBeginning) { + switch (rnd.nextInt(3)) { + case 0: ll.add(0, e); break; + case 1: ll.subList(0, rnd.nextInt(s+1)).add(0, e); break; + case 2: ll.subList(0, rnd.nextInt(s+1)).subList(0,0).add(0,e); break; + default: throw new Error(); + } + } else { + switch (rnd.nextInt(3)) { + case 0: check(ll.add(e)); break; + case 1: ll.subList(s/2, s).add(s - s/2, e); break; + case 2: ll.subList(s, s).subList(0, 0).add(0, e); break; + default: throw new Error(); + } + } + } else { + if (atBeginning) { + ListIterator it = ll.listIterator(); + equal(it.nextIndex(), 0); + check(! it.hasPrevious()); + it.add(e); + equal(it.previousIndex(), 0); + equal(it.nextIndex(), 1); + check(it.hasPrevious()); + } else { + final int siz = ll.size(); + ListIterator it = ll.listIterator(siz); + equal(it.previousIndex(), siz-1); + check(! it.hasNext()); + it.add(e); + equal(it.previousIndex(), siz); + equal(it.nextIndex(), siz+1); + check(! it.hasNext()); + check(it.hasPrevious()); + } + }}}; + } + + ListFrobber randomRemover() { + final int position = rnd.nextInt(3); + final int subListCount = rnd.nextInt(3); + return new ListFrobber() {void frob(List l) { + final int s = l.size(); + List ll = l; + for (int i = 0; i < subListCount; i++) + ll = asSubList(ll); + switch (position) { + case 0: // beginning + switch (rnd.nextInt(3)) { + case 0: ll.remove(0); break; + case 1: { + final Iterator it = ll.iterator(); + check(it.hasNext()); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + it.next(); + it.remove(); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + break;} + case 2: { + final ListIterator it = ll.listIterator(); + check(it.hasNext()); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + it.next(); + it.remove(); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + break;} + default: throw new Error(); + } + break; + case 1: // midpoint + switch (rnd.nextInt(3)) { + case 0: ll.remove(s/2); break; + case 1: { + final ListIterator it = ll.listIterator(s/2); + it.next(); + it.remove(); + break; + } + case 2: { + final ListIterator it = ll.listIterator(s/2+1); + it.previous(); + it.remove(); + break; + } + default: throw new Error(); + } + break; + case 2: // end + switch (rnd.nextInt(3)) { + case 0: ll.remove(s-1); break; + case 1: ll.subList(s-1, s).clear(); break; + case 2: + final ListIterator it = ll.listIterator(s); + check(! it.hasNext()); + check(it.hasPrevious()); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + it.previous(); + equal(it.nextIndex(), s-1); + check(it.hasNext()); + it.remove(); + equal(it.nextIndex(), s-1); + check(! it.hasNext()); + THROWS(IllegalStateException.class, + new F(){void f(){it.remove();}}); + break; + default: throw new Error(); + } + break; + default: throw new Error(); + }}}; + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + void equal(T[] x, T[] y) {check(Arrays.equals(x,y));} + public static void main(String[] args) throws Throwable { + new LockStep().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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 class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F 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(); + new ObjectOutputStream(baos).writeObject(obj); + return baos.toByteArray(); + } catch (IOException e) { throw new RuntimeException(e); }} + static Object readObject(byte[] bytes) + throws IOException, ClassNotFoundException { + InputStream is = new ByteArrayInputStream(bytes); + return new ObjectInputStream(is).readObject();} + @SuppressWarnings("unchecked") + static T serialClone(T obj) { + try { return (T) readObject(serializedForm(obj)); } + catch (Exception e) { throw new RuntimeException(e); }} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/concurrent/Executors/PrivilegedCallables.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/concurrent/Executors/PrivilegedCallables.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.2 07/06/22 + * @bug 6552961 6558429 + * @summary Test privilegedCallable, privilegedCallableUsingCurrentClassLoader + * @run main/othervm PrivilegedCallables + * @author Martin Buchholz + */ + +import java.util.concurrent.*; +import java.util.*; +import java.security.*; +import static java.util.concurrent.Executors.*; + +public class PrivilegedCallables { + Callable real; + + final Callable realCaller = new Callable() { + public Integer call() throws Exception { + return real.call(); }}; + + final Random rnd = new Random(); + + @SuppressWarnings("serial") Throwable[] throwables = { + new Exception() {}, + new RuntimeException() {}, + new Error() {} + }; + Throwable randomThrowable() { + return throwables[rnd.nextInt(throwables.length)]; + } + + //---------------------------------------------------------------- + // A Policy class designed to make permissions fiddling very easy. + //---------------------------------------------------------------- + static class Policy extends java.security.Policy { + private Permissions perms; + + public void setPermissions(Permission...permissions) { + perms = new Permissions(); + for (Permission permission : permissions) + perms.add(permission); + } + + public Policy() { setPermissions(/* Nothing */); } + + public PermissionCollection getPermissions(CodeSource cs) { + return perms; + } + + public PermissionCollection getPermissions(ProtectionDomain pd) { + return perms; + } + + public boolean implies(ProtectionDomain pd, Permission p) { + return perms.implies(p); + } + + public void refresh() {} + } + + void test(String[] args) { + testPrivileged(); + + final Policy policy = new Policy(); + Policy.setPolicy(policy); + policy.setPermissions(new RuntimePermission("getClassLoader"), + new RuntimePermission("setContextClassLoader"), + new RuntimePermission("stopThread")); + System.setSecurityManager(new SecurityManager()); + + testPrivileged(); + + policy.setPermissions(/* Nothing */); + + THROWS(AccessControlException.class, + new F() {void f(){ privilegedCallableUsingCurrentClassLoader(realCaller); }}, + new F() {void f(){ privilegedThreadFactory(); }}); + + policy.setPermissions(new RuntimePermission("setSecurityManager")); + System.setSecurityManager(null); + } + + void testPrivileged() { + try { test(privilegedCallable(realCaller)); } + catch (Throwable t) { unexpected(t); } + + try { test(privilegedCallableUsingCurrentClassLoader(realCaller)); } + catch (Throwable t) { unexpected(t); } + + try { privilegedThreadFactory(); } + catch (Throwable t) { unexpected(t); } + } + + void test(final Callable c) throws Throwable { + for (int i = 0; i < 20; i++) + if (rnd.nextBoolean()) { + final Throwable t = randomThrowable(); + real = new Callable() { + @SuppressWarnings("deprecation") + public Integer call() throws Exception { + Thread.currentThread().stop(t); + return null; }}; + try { + c.call(); + fail("Expected exception not thrown"); + } catch (Throwable tt) { check(t == tt); } + } else { + final int n = rnd.nextInt(); + real = new Callable() { + public Integer call() { return n; }}; + equal(c.call(), n); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new PrivilegedCallables().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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 class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/concurrent/FutureTask/Throw.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/concurrent/FutureTask/Throw.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,141 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.1 07/05/28 + * @bug 6415572 + * @summary Check exceptional behavior in run and done methods + */ + +import java.util.concurrent.*; + +public class Throw { + + @SuppressWarnings("deprecation") + static void THROW(final Throwable t) { + if (t != null) + Thread.currentThread().stop(t); + } + + Callable thrower(final Throwable t) { + return new Callable() { public Void call() { + THROW(t); return null; }}; + } + + @SuppressWarnings("serial") + private static class DoneError extends Error {} + + @SuppressWarnings("serial") + private static class DoneException extends RuntimeException {} + + static class MyFutureTask extends FutureTask { + MyFutureTask(Callable task) { super(task); } + public boolean runAndReset() { return super.runAndReset(); } + } + + MyFutureTask checkTask(final MyFutureTask task) { + check(! task.isCancelled()); + check(! task.isDone()); + return task; + } + + MyFutureTask taskFor(final Throwable callableThrowable, + final Throwable doneThrowable) { + return checkTask( + new MyFutureTask(thrower(callableThrowable)) { + protected void done() { THROW(doneThrowable); }}); + } + + void test(String[] args) throws Throwable { + final Throwable[] callableThrowables = { + null, new Exception(), new Error(), new RuntimeException() }; + final Throwable[] doneThrowables = { + new DoneError(), new DoneException() }; + for (final Throwable c : callableThrowables) { + for (final Throwable d : doneThrowables) { + THROWS(d.getClass(), + new F(){void f(){ + taskFor(c, d).cancel(false);}}, + new F(){void f(){ + taskFor(c, d).run();}}); + if (c != null) + THROWS(d.getClass(), + new F(){void f(){ + taskFor(c, d).runAndReset();}}); + } + + try { + final MyFutureTask task = taskFor(c, null); + check(task.cancel(false)); + THROWS(CancellationException.class, + new F(){void f() throws Throwable { task.get(); }}); + } catch (Throwable t) { unexpected(t); } + + if (c != null) { + final MyFutureTask task = taskFor(c, null); + task.run(); + try { + task.get(); + fail("Expected ExecutionException"); + } catch (ExecutionException ee) { + equal(c.getClass(), ee.getCause().getClass()); + } catch (Throwable t) { unexpected(t); } + } + + if (c != null) { + final MyFutureTask task = taskFor(c, null); + task.runAndReset(); + try { + task.get(); + fail("Expected ExecutionException"); + } catch (ExecutionException ee) { + check(c.getClass().isInstance(ee.getCause())); + } catch (Throwable t) { unexpected(t); } + } + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new Throw().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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 class F {abstract void f() throws Throwable;} + void THROWS(Class k, F... fs) { + for (F f : fs) + try {f.f(); fail("Expected " + k.getName() + " not thrown");} + catch (Throwable t) { + if (k.isAssignableFrom(t.getClass())) pass(); + else unexpected(t);}} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/java/util/concurrent/ScheduledThreadPoolExecutor/DecorateTask.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/java/util/concurrent/ScheduledThreadPoolExecutor/DecorateTask.java Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test 1.1 07/05/28 + * @bug 6560953 + * @summary Test ScheduledThreadPoolExecutor.decorateTask + */ + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +public class DecorateTask { + Runnable countDownTask(final CountDownLatch latch) { + return new Runnable() { public void run() { + latch.countDown(); + if (latch.getCount() <= 0) + throw new RuntimeException("done"); + }};} + + void test(String[] args) throws Throwable { + final int jobs = 100; + final AtomicInteger decoratorCount = new AtomicInteger(0); + final ScheduledThreadPoolExecutor pool = + new ScheduledThreadPoolExecutor(10) { + protected RunnableScheduledFuture decorateTask( + final Runnable runnable, + final RunnableScheduledFuture task) { + return new RunnableScheduledFuture() { + public void run() { + decoratorCount.incrementAndGet(); + task.run(); + } + public boolean isPeriodic() { + return task.isPeriodic(); + } + public boolean cancel(boolean mayInterruptIfRunning) { + return task.cancel(mayInterruptIfRunning); + } + public boolean isCancelled() { + return task.isCancelled(); + } + public boolean isDone() { + return task.isDone(); + } + public V get() + throws InterruptedException, ExecutionException { + return task.get(); + } + public V get(long timeout, TimeUnit unit) + throws InterruptedException, ExecutionException, TimeoutException { + return task.get(timeout, unit); + } + public long getDelay(TimeUnit unit) { + return task.getDelay(unit); + } + public int compareTo(Delayed o) { + return task.compareTo(o); + }};}}; + final CountDownLatch latch1 = new CountDownLatch(jobs); + final CountDownLatch latch2 = new CountDownLatch(jobs); + pool.scheduleAtFixedRate(countDownTask(latch1), 0L, 1L, TimeUnit.NANOSECONDS); + pool.scheduleWithFixedDelay(countDownTask(latch2), 0L, 1L, TimeUnit.NANOSECONDS); + latch1.await(); + latch2.await(); + pool.shutdown(); + pool.awaitTermination(1L, TimeUnit.MINUTES); + equal(decoratorCount.get(), 2 * jobs); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new DecorateTask().instanceMain(args);} + void instanceMain(String[] args) throws Throwable { + try {test(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");} +} diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/ImplementationVersion/ImplVersionCommand.java --- a/j2se/test/javax/management/ImplementationVersion/ImplVersionCommand.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/ImplementationVersion/ImplVersionCommand.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file ImplVersionCommand.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.6 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import javax.management.MBeanServer; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/ImplementationVersion/ImplVersionReader.java --- a/j2se/test/javax/management/ImplementationVersion/ImplVersionReader.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/ImplementationVersion/ImplVersionReader.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file ImplVersionReader.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.4 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import java.io.BufferedReader; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/monitor/MBeanServerBuilderImpl.java --- a/j2se/test/javax/management/monitor/MBeanServerBuilderImpl.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/monitor/MBeanServerBuilderImpl.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file MBeanServerBuilderImpl.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.4 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import javax.management.MBeanServer; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java --- a/j2se/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/monitor/MBeanServerForwarderInvocationHandler.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file MBeanServerForwarderInvocationHandler.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.4 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import java.lang.reflect.InvocationHandler; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/remote/mandatory/version/ImplVersionCommand.java --- a/j2se/test/javax/management/remote/mandatory/version/ImplVersionCommand.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/remote/mandatory/version/ImplVersionCommand.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file ImplVersionCommand.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.4 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import javax.management.remote.rmi.RMIJRMPServerImpl; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/management/remote/mandatory/version/ImplVersionReader.java --- a/j2se/test/javax/management/remote/mandatory/version/ImplVersionReader.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/management/remote/mandatory/version/ImplVersionReader.java Thu Jul 05 23:47:33 2007 +0000 @@ -25,7 +25,7 @@ * @(#)file ImplVersionReader.java * @(#)author Sun Microsystems, Inc. * @(#)version 1.4 - * @(#)date 07/06/21 + * @(#)date 07/07/05 */ import java.io.BufferedReader; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java --- a/j2se/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Thu Jul 05 23:47:33 2007 +0000 @@ -22,14 +22,19 @@ */ /** - * @test 1.4 07/05/05 - * @bug 6436919 + * @test 1.5 07/06/18 + * @bug 6436919 6460930 * @summary check that XML Signatures can be generated and validated with * SecurityManager enabled and default policy * @author Sean Mullan */ +import java.io.*; +import java.net.*; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.Policy; +import java.security.URIParameter; +import java.util.ArrayList; import java.util.Collections; import javax.xml.crypto.dsig.*; import javax.xml.crypto.dsig.dom.DOMSignContext; @@ -41,13 +46,62 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -public class XMLDSigWithSecMgr { +public class XMLDSigWithSecMgr implements Runnable { + + private XMLSignatureFactory fac; + private DigestMethod sha1; + private CanonicalizationMethod withoutComments; + private DocumentBuilder db; - public static void main(String[] args) throws Exception { + private ServerSocket ss; + private void setup() throws Exception { + ss = new ServerSocket(0); + Thread thr = new Thread(this); + thr.start(); + + fac = XMLSignatureFactory.getInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); - DocumentBuilder db = dbf.newDocumentBuilder(); + db = dbf.newDocumentBuilder(); + sha1 = fac.newDigestMethod(DigestMethod.SHA1, null); + withoutComments = fac.newCanonicalizationMethod + (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null); + } + + public void run() { + try { + + for (int i=0; i<2; i++) { + Socket s = ss.accept(); + s.setTcpNoDelay(true); + + PrintStream out = new PrintStream( + new BufferedOutputStream( + s.getOutputStream() )); + + out.print("HTTP/1.1 200 OK\r\n"); + out.print("Content-Length: 11\r\n"); + out.print("Content-Type: text/plain\r\n"); + out.print("\r\n"); + out.print("l;ajfdjafd\n"); + out.flush(); + + // don't close the connection immediately as otherwise + // the http headers may not have been received and the + // http client will re-connect. + Thread.currentThread().sleep(2000); + + s.close(); + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + XMLDSigWithSecMgr() throws Exception { + setup(); Document doc = db.newDocument(); Element envelope = doc.createElementNS ("http://example.org/envelope", "Envelope"); @@ -58,23 +112,26 @@ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); KeyPair kp = kpg.genKeyPair(); - //XXX make sure we don't accidentally pick up user policy + // the policy only grants this test SocketPermission to accept, resolve + // and connect to localhost so that it can dereference 2nd reference + URI policyURI = + new File(System.getProperty("test.src", "."), "policy").toURI(); + Policy.setPolicy + (Policy.getInstance("JavaPolicy", new URIParameter(policyURI))); System.setSecurityManager(new SecurityManager()); try { // generate a signature with SecurityManager enabled - XMLSignatureFactory fac = XMLSignatureFactory.getInstance(); - Reference ref = fac.newReference - ("", fac.newDigestMethod(DigestMethod.SHA1, null), + ArrayList refs = new ArrayList(); + refs.add(fac.newReference + ("", sha1, Collections.singletonList (fac.newTransform(Transform.ENVELOPED, - (TransformParameterSpec) null)), null, null); - SignedInfo si = fac.newSignedInfo( - fac.newCanonicalizationMethod - (CanonicalizationMethod.INCLUSIVE, - (C14NMethodParameterSpec) null), - fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), - Collections.singletonList(ref)); + (TransformParameterSpec) null)), null, null)); + refs.add(fac.newReference("http://localhost:" + ss.getLocalPort() + + "/anything.txt", sha1)); + SignedInfo si = fac.newSignedInfo(withoutComments, + fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null), refs); XMLSignature sig = fac.newXMLSignature(si, null); DOMSignContext dsc = new DOMSignContext(kp.getPrivate(), envelope); sig.sign(dsc); @@ -90,6 +147,10 @@ } catch (SecurityException se) { throw new Exception("XMLDSigWithSecMgr FAILED", se); } + ss.close(); + } + + public static void main(String[] args) throws Exception { + new XMLDSigWithSecMgr(); } } - diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/javax/xml/crypto/dsig/SecurityManager/policy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/j2se/test/javax/xml/crypto/dsig/SecurityManager/policy Thu Jul 05 23:47:33 2007 +0000 @@ -0,0 +1,3 @@ +grant { + permission java.net.SocketPermission "localhost", "accept,connect,resolve"; +}; diff -r 16f2b6c91171 -r 64ed597c0ad3 j2se/test/sun/net/www/http/ChunkedInputStream/test.txt --- a/j2se/test/sun/net/www/http/ChunkedInputStream/test.txt Fri Jun 22 00:46:43 2007 +0000 +++ b/j2se/test/sun/net/www/http/ChunkedInputStream/test.txt Thu Jul 05 23:47:33 2007 +0000 @@ -1,2 +1,2 @@ -Fo`kMsMr*sth,dr2oD]eg<N\U4KGXn2VQ,&'!;AW&I["@nZQJWPG$PpAl;1AZ@R:DZ4;<,C-&1H7ZAjAq7LN`NV[,YDa^JKW_!oW6>=tA9q;%*^5$1[C24!O=7p0LB8c6EQ:bpii++fSJsNl3$mN#K[2eL#%d>c<39pV55VfO? t5a5 >+g-X9Yc=es5sI-ts)A9R5TqE?/<M.C8Zl ^n"s`BDQp*W@oVW;]I'.h/b1:4!=.W%/01LcYF7=Um1(.GNWiH:Kp?Ch12Bg[5M`,TTE5TN\pba^I;oM2Z*KqR@#RqN\;Cb99`H0d5^K*=fJ<]%Sd>i1hpA>313bbb#MCtA</sM^aXko^.Z7+VJ+(EYJgJ;j*\%5@13(Wd^;PcjC44A  I$8,VM>Eg2T*ancMc.8]W(7%'g.#VpQC!2AZ(0oW12mIhnJ-G]D;Q6OF(eon*,UL_H'UE 4Y? 1?_,2ia$K^X?R hhS3!R5BC,T>@#rs1 gF*lPf8,*cCi:nAaE%*,qP_ofK]hZ@>cQ?A;,EH7fU]GR2p25#UA$.oE5/ETshg=9Vk_;RC#<^nK?)PKL(YCWdtBChB*T>[%;/@Rq[Alea)>Ib^QrKHG2KcbE0mD&/'eS*tX&\8+U,Q#Zm_`8?%In$FLme]D% ()6TEs4q.E.\S$= 7iO_5W?K\UA2:WSgk?-p@=SQU#E/1!4.@--8IW]kLr"j;$TCUr,R,s7OlD-(o#dlEef9VK?'53Xq]/3-s!3B?ZOk&d'a*X1TRs$(?O`DTmX3mPX,>=,![AO/gEO^,W^00>Aq\)M=a3:U`AVleR6-Y[4qdj1Nl,gEDi']t&><6n0#)'Z0Ci.pZY$d1A4E?FrX9Blka%LHWMd ilA@#'i'db3# ]+Mf4VRQn6'nXg#E)I(8<5I&(lT5Y$1s.5[0tYd]IbLkgGlt%?^MHq!k!h'FP18>%"oqn+V?WXAK,6JP\KYb5jIJZAG 7F"0a'"A"g<61lB:'^;idCr*82Z>MEOCeHqH^Se6;OgKSWR]"Kji7'1:VI)AC"nA7mhWM*okf"4,G7hm:c6B&$3CM.8fIbb[kPX',j^&K6"IoHXPQgY>@E=HE0-$10tpQ mXol_g,-rmo11C4F3b8t;@JINZ.t#TT7eG.+CjQ&NN)IqI3hE6EF'h)!f6spqV,fm4`Hirb'7+pr8Y,NqR^eF_23mt@C3@MGAHm0d;3rY&+tsK(BK30:V]"gTpI=$ms8j*+qddro#A(Y64/i!F2PA3<9/WQX?l6QV^V&)m!C]F$@ 468?JD8p``2c.;]3mkp)Bl'X2PpYSi+[t<UF\X)=EGfr K?A/;Dgq)qD4.4c)7Y&PKg>Es^%2h ,)YbjfMA5:dYE'1)rb]]/j1?:Iq37N8f.>+UQ "f5qFFYloKPQ`I#0ZFLrgQ1WQ\:)L-6\$Q1UDgI!d,_#),YE90K^EY0*0saQnl48<1`(@3L%LshoA?:5Gd0,6/b0!pIibT2UW9c()EH0.+>aoE%`]e[:.A!9^rMan?\peDIlNkjaJiX-=gYcFoXXbTYD8+Sp8US^t0cBf3@I?<7&f 2%n9!]t9rF_flN_U)74!ghb.I!'D4n5dim##5j:?GPH_3Q;gB$j'qNk[H,%n6dc0aBl&>PN-X3J.[pNK 2S'oEm_dsA1&+b`$3h32%m)"QNiJIWX9%*49_)I&ARkIm:gM(Vh!$bI1iSC/;/efNr_`sWbT'>T;fNIJ<%NW0%A)]npAdI>\KaA[.G-8An8&VN6)A$o4,@31\];&k4*=*?pasKksN1=1l-ISJEY/_`=U]j[Td-9;(OFh(IHp70H!2kN/9to//b/_ar&/Xe9CmaqX:`X,S\^A+AQes./s'F:2ZMY :m H+3XS)l35Y]AicKV"G?4XERT;gD?+)S.0?,8X=414C$hD`@?3"Sc/s>A[bFPR^]CnN8ml`[pD$q%M,aSCC$b$#D!JN=;^9VLl>P$8s).J7tC!^LQ,c4dPAoU,M7NmQk=90>$=:&_J;s?Y$/#I^h_`%2K$[^S[7f=Oa21sm+aM=G89g8RD:KQ)pRKLf'/>$ciA'Lr7+X'%1D+6hDh@8G#+B:/_"EaEc)VPU$kLC32rR-?HCm_QlA2Qlf[@n^K'OC7CDEFI]`;C5.EQ$V0,V.<E#;<.J8PiYa`M$FYCP[8$3Dif8K'RSc@r@MF XRPUqE?nmRhVE4D<^[%5D(^.>V.t4OQ_mqq37`53H)8rAGPldR>'1DEec?"2IGY,ane;V7C:K/__[:&<dboAG@@WqJZ:3<^.ffSXTgT(X./0T_"B06!]fejtX+?"dGC#nSP\JUSFU'mS22bI#WAp\83A2T(Mah,S`@56_B\r2.1Q9=f(-6K6YZ#Gf\;o,  7.cIAMP_(5X2O("&7fr`;lO2!5=W,8`9`s/6N!+6+A!PJfWK\A< XSr6gdpo=eE!e1jqMR"ptea0A+i[Qf<Y ,)YtQ4qA7e+#E6pcFs\c^_-Q(Y3DN39tKGiOML4ZJ/]jY*6K("f?j]d5Q`"(!a6^EnhMXs-4(YR2'J@A!hV_VYI.'P,/ct:aiY%I5X*@<Xt!%`[GkeOtZa[( XBpK2#?$1UiL2i!?t8SDQ]UBEW@5SN:$qlSg'CJ>p4G44h[U)U*4s.C'ieWRf:.VF]R(Q.iRPRAi0HUFmR8GAtnR1D&03T):Hpn+RlJa>:[U<*83'R8Fr%W$]?l)KANM[Ttj gKAfib:.oo,D?jMTW<3DIFMR\io*NBBA$.9'8A6g#(FsamZsV[>Ml`Y&<W"Tq)i8'ROHA9<4@#a56nIM,ME'>LJ18>52+]9pLqoAIWG##HMS2`^SX$'N0dP/)7*DVh;<llE__mo^GAHFXh+,nhg[,\S`oWd!dH+iUA)Cg@qlT jQ?8()W2`0RA9_i Y;!EBdA$_[IX'ERYmL[MkeMnHN0 R"8Nhn7>%)Hh\ e7F@VP61nAQm%^$@;fs\@mrNC5=Or32)c[O6G3#OrFN>k;m0oPe/]0!.i=5Qp+Is@bJ<-cLh_.Ia91f6M+7l;+\mH7V$Ai"4mAp-#Y(jDKCL:4Vr!h#k8R"*n88`WB?N)/o9KG\8A]PmSnj,=q=h!%(X+*%Z_/ApSK0`.L;*%@G22NlmG='pP%,JBl$WZ:AS)rlaK/^(J+B^6fW*E C37[ae^A]L@g$;/Ho)o)1:W6q>GbC42!!oDY5#cMQmK3-<)(m#=s%&K37[:CU-hm->V"/AM\ 2BfkNtlILl`fPWRG^+d_9rcNQFckrMM.!3jP2V<b(:QZiAo6XdK KD5-f95M&=Y$'1hV=]F?b6E"^W.I2<7kgnUQlj;YQ'W8NFe?Pc%[Z^BEnel*gUJ:gp`7lGRfg5_YboSY$].O r)#c8_"RFR#WEt(dQCYF8h;ngfPe^Ero9^bWGha"p"J]+f.<>A`G s^Xs9s%I&aF3k(BC@WZ"J9-425-K3884cC_#0Z2 >%o&UIrn.]!F8I#*Th=17cHo>^;_8dB:>NMm'XX<sZM8$3UsY(sJ-An`L0_.!/GhED.&$37=>@beT#@YdX3DFir7"Q'tVgC2$3="Ke9<0Z/i"]":tD-/nfkbdT_X/f)ka]=.l!c?IXTW,9!34IK/'*,/.8OA`8aoXCBI)SGDZdi3b?a`%bI;nNAAfg5KXSC8NdCa(!E:T*fIo2V)8Q;j q<42ACAa.4[Y@<OX&G&JJ[bW[3;Akj&&e!.;;=)abrA2*`5TQlbpi!?P,f_eV#Tt G!rd bi-Rf'-p%U@V7Q\/I?J+mR0m/p6VW4g26;7BUGfQscTe-Af]R9Z!B&f@3T2^G+NfGDgHPP!J,Qi5oCC\$B@I3Eg/6D3&MOfs$K9V),ESse*!h_BL_h-mA_19@P&s3i_0iHT+8#"? A)te`srfDN:Qjr =9Q5@m&S8U*eG`k+UC@Op]SVZp7bRqca5TaQ@_g,K"O>Mk8Tkh6K%[TeG=k1P'^k4`43Kp'N+A3+'>e M>-a!M@QEPf>BY.M^D#@!8RAn&" lZp*=gJD#>l.44)c8kJ0EjKn@q4]@Y"mKH\t@=Q!ISeN@[A=q`kl;K32M1r$LV+mb_ni\;IE,6>d$t)B ABH]7&-OK7"('Usf4U>;ZrgSANg+q7P8tFk0)r%3<-aN*%`ZUL-142$\*VD79cs,gWm0n+DS7bcA,c14[CZQn]kb/-$nM,K;F";E%4X[R#GGdpX"!h`j=A9_%pt4mZ]LJoOMh#$*nX57JktJ5HI?#ne/qIMd:?F9:q*_UG%ILCdH>fQ\f#>Y7OP(+"C'HD9a&F`'6ir+QkiB`,/EAT'IaBH$'gIAGL>;RtSL"1gO>XeX.L 1SZ+A]31S4W9T>4EJSpPk<4#("#CaOV>>iGftc7?5[?(T^qc:kl2I'#.t^6,`H4W!DfMI9oGt$p0>5f.Z>JO`^Be%q=/\eg]7MaOY:2_,]-,b!A;;_OR A5P.n%Z7YLIe^)1_$N$?&>oA6$59qS8"@VbD8bV:ON"!]`jC@4n:6eDT)3E=(orMJr+U/U-E%h*J> ]QinJS"Z`-9QP2rBF?g#8m PlBDJg^)p'Y4bRk OZ\`0<"p0#`FqLDRa_Md",AR>_7tqgAI6q>F\ rUP2h6P5Lf!WmaGeslT$$:km:"^b98>B@[58%Vk8o[4,3`i-j`:lG Jp3Z@RD+o"K;Oo`cgPBOm:XS[SO/hl\%V"K%rXTaOdA?!`KL0[jil< IE9'PaXf@/tA#eT'SBZ]es'ljk^/f?i^b`k`CeqsgEah1N^_qKFOQ:V,nH;?rWTWAh8@J)AJ-fdM.Ub'>9`Ht>[4A\. HEF2YA9)_X3L^H[B`)dO UYDPi]b&C`-AD`ettad@A#nG>L4c\Wcp"a%d1Bt4"atAn_#%3>VCJq$l$>O^!?$WB17E,NMQI9hqOM,Kl#0QC)5_M%B2E"K7Dt9XK[s@_HW( Xp8-1+,k\hs [i?3?4XCQ9R@I1c,D4?]8FU17BbSEg^J]H'(3&Hist50)n$_k1ZX=$.[:O6R_rL`V#&"GPi(Zk4\Tk?UAZ@,gt)S#c&n/KSYnFGZjs^cACm;+eP6F^)MAGhoqV4`@1%UMmfNba+"& 0sY!5$N>XYCnoO9^FI6'Y >U,i^S$3>sW3#itq3RnU@rgE1^8\UTrjTcUHbl$CFC%)UY[P:8'M'a6^1O4Y!kgi@n8:%j^P-cslBH*r,-Q"Psn4bKbHHAUVLl%F_fB\P<sD$^O&VU,5Xf';b#cibEC64s c(Wl+T+UE&N,[r6Z`Nk>h*jme`BI1EhITO9_gA%]A"i<37)\jY=sD8sYN^9XFA/Ml<+seGea<.6D^$UC[=X-4`tk@fIXG]%M_h:kVC\&C#1j,`E;2[CP_;_,SHb+MHJ][=@?Z\J[!ciZMSC=8T_P^+7+4 #0aMJB#M7+J9Y(TrprMRVhqp%6n6ph[#A1N=8i>Md4<b+GoT'>mPMB$b#AdB5bdamqKn6.so 1O2dscP,`V1#sAjYn-$).Ao3moshGH`Y^-a>1T?/^VeV aR(MfbU*_)lDiE%8OlO?pr$ZfBJj5#^-GX'h(lCVdm<9)q".PI$+*5j!p_'3#>\Il_VpFG6Zjia`Dtp+IWhr@EH#]l0o\`js?_);^=90%PE(m]hA-Vm/r)\W9ENd*Edn+NM,G^,U/n;tA^+RQIGfiB9s5o6`RjM[ALmTXqNm@Z:O<6NTbU`)NOr.a:gm^b_XYn-Va0`;P? RCFlYsq/5Pr%$G?r^AZAE&/d*X7AYM\AC,Mes7G -Hb0B\BfX6kcUaJ_5[W1+lp6<;T$WU=C&\hg6A^NeR%bIWE6ZjlN\:k&Kb+<V9boOA3We'Pp+PkF'h5^NrL(PC&SIg%Y$%fDpJA1Ol[+q!_>B7A6N4>?q&C-pLlqE@c)j/Ml\i'J'\/N4((UnMeLVG-?rc?_4]>TAn6!eU_:tUA?OYrAJ[:n>nrn>tOl]L,L3tb%q1"TKD_Ggo :+r<+/L<-QrHM<=)i1La%Yj*#]#`akcXI$cXUbL:=!nNd4$]flE;,Y4(i51saE!5.n97EkgA`IQUb$1s_<[*SpA1j/,IYK=$^.'*J;^U1Aa:r\*[5'BfPm5i\R:Y5N7XT*fJ;m"f<-*_ ePoqPlR7d4nX0[ZP'7CSd8!faj)#/6e[R+!^]L[R:N:TNV!(Kr]OV]a`% 'I-L hGX.orUtGE^39%Nio,O9MZ;+bHD?BJDBPVAk'SV%5rFKf"?[RX`W\t+Dp$)0NZ_IgY*9I"+GSj3NL[k%HI-fm9A]*9\;\>CTdiC02j0G04t_2C)XN&a6!NCi&_[W*E+K*."oe6R:Oj2/4rU6PtGm9X]s>ho)^1<44a0AT%ELqE/-UKgS#AB$kVBmie4$1Y`0JHGlRa#Xc:]60EN9KE:of(H;ElD[-b]C6hOqKdd#&8/Ct2<^WG->k1N._J]6)TUC2mWRXrPD"Y8'_,rqThCrN+A_oEMMkM5-rY2:3Xl1 @J)D=WVEo)paNT7\MYaD^:\WF6(/m:-oEQ98:]mn#U2rTqm7W07fcC6V&pFWgZ!A^-Ri>AAY?!!sY[:h8OB'o6t?3_]rM4^IfRmA$'mPB<X2,@j62V_BkPrr/6H*4NiF23S%(,EO!Q %$RLjP5X& dHpAUB h>9RjB34sA:CJ(R;lN6,kj1<ao`E3p[LNKFk4a!+V_Rh;;O>&;)P/*^g?AAiJ`@*k?1A%p<4%9L2R:C!fReCA[f#T1C6sYjI_D/H`IV@*N6LX'`m>\qeb %'3.)%;s#s!6/B#8dd`5di,iDPHo7MQ$AV=J+V0:(\<8fZa%E@Z7)"ZlWG4;b.0*S,<"K9#CihF83rBU(&mA&5EDV,'WJ=3NXeAW3@.j2/:!+an"I%3q(9(kqZgY9h]q,VK&![P9;J=D07JI_\6+/:21[RBq#4%?Fci'2V,<%6krSb@]jEo:YMGB7P87$W;76_U"nHlgO2 o>'[KdHeIl+n@'5[+Bd.^:\Jt&\Ap\RO2Fn5C&`omaZk:sGJj&_SIO0P-Cd;G3#j(I.Z=NCqc 2%(:[0hN1FV89i'a+ed49r,f\kNa@_KE*@ZZP\GFNRNQ;"+ghd]$LgM%3U05!U-$#I2.6 GM.Cq7P&WDYj$qd`V_755b9$K7,9(Sf=6>@J9pbr+RAf>A74AV_E>Fg]^+-0UtQi_m3+rkfFFEr'<%iHE/4B7N'sRWoRIc*U_qfZ(pFqp,^'0-ja;tcTHL5:+gJPb_qrZl.X(/0TeXTVZ"4AR/'lPAsqA<$@Ej%/0XV$:][.2mhWZ]lgQ?eD8q:t>_himc#`.>6[$mMSG)7CZBZ\e!QI7U=HDoP,3)B5C7Ulm`8l&?97]9bV$) c*11'-:+% f_[-8hncgs>Na[J (jUgspZ80?Ia_'AV;n/VQ0I`\QC$>`:PG6t >1!Z%s\a(FNgB;;HbsFWlOV93M8[Ut%f/AT2]4a@fo=&HiQ$Kkle-FYl a@C8F)*S;lU"VkdR9\LfU/TT!@.L'+ZhI,!?G3A!#@-h)^!B?)c>:O8cA4gUgeE#kH'\>E:`Rn#i!@2,*)H+HVeRB,cATD8U;RsNOXr*M;O+NTMJGe6$J,BI9'cg'=ei>U`gN41oN#SSV`o[8aOLPjsb0pL^G#MnmAgsb=(`-0T)4mP2A43]F!Uh\hA*V6 9#@Za_'IE2Ai;qk$JQY5>o;L)\]:h7Z)^G7#b'r-KqtTi'dWAC^g,"^i)abIli*HV@7rW#;[H.^HAVDU0)J:8sn2XK+LR._$[Vr,4Eb/7LT^MBL3gcWI7E?sZRn0YPA.\N%UqZT"H:5"Ha +4&mLinhZ%SHpLCjG@EpaTt]I+&VgLL6s%+epH56Rq<iMh6LE_Js\!*V6EAJ4"tQerAf'c/]icOeFc]>qJahlBP61.6Zn1e:I5 r78,#,F /3<;SFor=OJLpMlGrc$]/91SAq6(c[(Fle]DE#!/r\CdaCl)$0R$4B-4bm4dX ]0#T,5#9#(`J,Aj?&_%EcpA7_aQJCpFA*F[0r;.q*f0>3$$!_'tRVnR?Q$Q"0XT9?Tq+c_9!_^8eph%AR25K>)6T%F01e/>&b2f]l+nAgmQg8kHb psX3`)5MpE1O.Q!"DT'`;7A-tWqW@P20f$$T/a>PebHtn1!qZT'&JHqr[&'* =52"&7dpe?g.$o%-kKF7q,O0.i?lc698?&86,"NdI3_=M]nkAfAt(7"*tEfQ=-K#II_0q:N.0:K]80%4=JdT[F0n":o%VE& 7;;]E)'rAS_Nc-$P\NppVegCjTY>\lcF!%a:rq;9ndd'A:RY&IhG`p5>>Hj^/Wpn)7-f6$8A)=>0+* 7$4o63)&!i-YA,0;t\MkD(AgZah_<[k0o"0]af<(rDd%XfeBU#W/^QS!LTO[PV+8,jY_N*bApB[$!`-QWWA#H->hAJRlr$UQN(hAmmN\m!Y3R?nY'"`Rr4e))Ys@rQ6(FW9+m(8<6%1roR(^ERjQ>Aoab3a1MR=_]O/h4Irsl=W5+T3ZFSn`X0+r#O*iHD?bGj?I7m8IpjrFoa5J\97IJE66Ob[-4N_o,d-KP#PmqB;G=fXB8#]1AL7.HQoXm-[$A\\CQb)f*TfEH1Q()dJ?f&qZlmRo;a%-LnqtW3e&5PgT5d;Has=F2_VI@'FrHm,WN?2 *"=U `K'P$PchrWcdt L92Kj4;kTH=#?H"cf<@iiXjA_QN^rj4qLV";XPD9j:bV01]`34N1\%DX/Ff@#XBI/Lo#c QCoJ\IZ$g(1KG2#(:XDi8A.P"d,A_68DjmdT!hT<G[=Z0H@%j]'jQbkp"q)+)g_:[AYDW,K'LPY:rM4t>.V&m?$9OAM3$5kn+,%0o>W\pIXT`^5!6<K>k%@p]Ybdg-7nI"A9V]]2SWb!JA!k)D#W8R2B'ALHClX$++inHhl,8AXH!U j.7%W"Z6tNSf7STULk#,b=c2Y`\M8=j>!LA\i$qn8!`$El*4qXlSbfb3!aDY?2R%[1R5Ah"'$$j?8pp1qtA'Jl$%CW/KX#QcL%9a)['lmKB/(.BG]:TpH6$]M$P3\E,H=El.).V_g'G(SKG/>Z +7Sg  PKXjE]t+.WS^o8?G+9(9o@9@1c?LgS<$&?)tbb^'g(er+C2@fq_->mnAkE5cCn*<>AI/KAoGo>9TcH+h`Wd? FbbjTld6Hm+oYiT&XBq+Tb/Yf9BTIB^Ch`AZldmX'?0WT. @VSl&XcW:#(FW^.IAG(a&UF98DfaUc5>!o9$?$41o7OMdQN 'CCF=3n9,H-GV1:C2fre*/DfeAAgS<E.bQ^&4b7:#ChiO0/(Hq\S%DaH#T+7lYsIUS\"[Q60MRkTZpC29Uam&%?)2LniR"^$@&4Hta5=hQXj*M_EC.4DGJ0,V:>Cp#^OM0Us`WMg\KO4)#5VeCjJY-3Nn8Z+dM8HLr;&bU#`l<.J:+WdI9TALi7"Z.An&t-&SVX`XOY)D:7Cd+Ddfr!Y-0&jr9ie)OCg-)sqid!Q,>ghj*.<4]]ft=rY!g>i%M`] kX-bg;:*`c :*FpCB="6Cp?Ksn1E-$6*nP"]JM1==QSeI5@A"1AJ/Z_F%\AC')E3ZqSM3L2.IfClYbSGOb?aeeqJU!UH_2PI2IVoJ6q7pYVa71dJ%G/foptEZbhC#'i^4tPXI0= KDT Y-TRaHabpCCf="Bi`+t-V#dP>j"+FJN/KL',;Gpj3Q5Vfn6i?8El?H4p'?A"h)A'K%Sm^r%a7-\YgE9pLcSV!=?p%(7TIdC,UJ?]b+L0LJ3PEHeXZTr].8CR?b;,t4!C'>Z&UEGNT$PlIQW6DSsF;WeM2&o=mUA>cAhf-i$qW*KB I)9.1Ae%^ICbAe2h7.Z]$UQ!@G,pCLD1J>:A#U>hg/fathk5@GnFm"/:HW)V\+\*c)m2Jk8DoKPOBc7]fSih46G/\rq0&rm#,G3J;E-*rDh sS= *C%f.NATZooQ.modqS#(%dHm;?a4d&b!XWgOmKTf"q9I -2%%q,8R4,J#$5gBfZTYMm,tq2SA+ifSo/r[#P]T^7eX0(.?F6`%@`NXKL=PX\?XR7=GQRsCYK 0Q\S/ZOS`W`[9W)X7V_(iTHfR:`>AF:g>b LA3A@>8dj3,0ned.C9%JHBg&lDPd9#)n\@9&p)jY]=s!9 :qp)mJ3#7,;-Nm`e9lY@:m]"The#>be)i8Ahq]g 7#C_o&cdPH13j;Sp$)0sqL`Z.WA8[L%sSPF@E-(\S\9Y(fRCOm4p#A+/.-O(a11A$tQm_(R)NjCW(2f_' ofHL0$??.r'tB.`X]ZTY-740RoY&iN5STW5I Y>I!rPHtYX"Y/ ]m]QInX!&K`NQRU)A>OG5&En."WC4<;4;\=BB.gia@?>Y0'ASF+mY*2#Lb[9B#JZ%RhJ<>fc!Ae*daYAO6gYGjGl-!/h69M)#jlf86;rhHb)i)DV\@*_9T:__^KQ^l @<85s9 M6]?eA!#Cps.,Y$ e-f$32>G2bhqZA!B1LIA6@arX(5L&:e!eg0X=_bWcP-%",09!bEk^C&Y!irAW36XKqV6/MbI)Ak![%,TPZ/AKX0]*\WPq";OP*pa)Ki!,)$\1N-X$@M$b!8<;O`$8OZh_`N0mh_cs1/7&k3=["]tI-OGV.oYk Y2+.riBdRQ7k\d8GFpG/PVm.]tlq>RU!J_h'fVdeSAbW[^.iXN!f#;cO[m]U9NstB?Y`+Ab(IDE;'P.!Z\N@8!HZ>d>(@m"p(lS4/XIEKNZ5h:\YL>SWGK#]2OP.q;][.s$84/9FJeN')"(&q42g3SKpVUbifkn,mpIT- @XaW8j?_3AJT:Voh==X>+ ?1)iFM(aWV4]1_hI,\Slc#pWkThsicBRV[AhADB9KKPUJ`KL$eSSPC/['K8(hb?AE3^sJ7;;oEH6A8j$#1`AQXq]ps9,Ap08AYc/MO]IfN[.]7tD;U%6lh8;XH`s+'p4diRJ%oF_4b)cOH8 /J=sS"0kOl)4^H.]mP3:cCoJ8V1hl+)+2d7W Dt$0'FNfB&5PlW9$M]DJE_D:(;N(?$o&d,qGsnX ;1dOdm0c.Rl^Ct/GiDTs&^SYV.PW$"J@8 b,>I-<Gm&@`:[p6h-V:)e7A-96;h8:[364n4pA5C8I3WTj%5k)'[,&4>:#.aEXL8niGh;KrT F$=M/DjA'3s5/9@r1hqn@+HYf""RWe9Afnlh*\tg\T$X6dE9C#q[\0\:dFf4!-]NS4`VIJhs6-=6e2lT5cCT"24i5G$]2n^Bb$3$,R6:ZKjn@n.A;.MEscbH4 DdA?j8O`!mM#7p (Mb(4\qBrt!VG>>(BIRK#@Z:0AcaHk=6AL-/"R+&S!c-BagoA8,om0\!GWbeO<.R":,J>2aU0%PFdYd004$69J5;\tLU!5Ym$k)$!cm%OR%btd4g`bla;Q&(f`X3:4DeNTAmo=m*:p1]Al3O5H8,'4G6c-h3;7n>Fq/)Q'@lk!K[k0:eKGq8'^Hbjj*^%?XnWb)/soo."AmJq]dI[KZDV&75oA*F:"*VWY1d`DAUtYXFESlLQ:A9c_qNT^NYs.-:rZkgJ".PD:)-#CMDPjY3^/mi\s+r67s[c@V=;W6e*^PJO9`@2fPXRojZ9Z%1+:OLf?fGi)YF]!H %Bcbh!X*+F!)/)#Eg+Z;c*f^&2;tm2;slJSP2a+& \W;9)_LH`"+S$tAU MQ+dCr^ $1(AY!.b-2ce%n.dInA;#Vipko"dmU?'\qoV[ngS)K[\IhNC`)f:On)g3&qdb!?cQ&r,.UoSd%9KA8O!L([*H.!:j;cE7V65ae>>K)=('.65D3G;+]qYa4Nd;5l+PW ACE1@pAZ!9fj`ksP&cNdARrG dHjaQ5oVOYpEt>,V3SV /T)`t (A(e3UG*B:$*U%1qF'.Y&@4m;$i R!&GXLANqSP^N1$/D5SG9AP@nCAr=gHZ8G\FWrDbm\'IM:n4b!oXSa#UmqGQ(=UD*99GH#2FAcmitH0)]lAfKB;T<fbN'_q=TPt.AbP]s=6gRTsAZ#aJ&+`[3'.,nkmM(M)>S5Q$tR],lh]mC$AP;D@ULc0jXAAT>pBH_EDkoO7H2_oUJ!P@01V94VqMXTS"fUAS.Vq8W7*8jMn9>mJBQE0?C@1KW>E7_AGr\BQ+q/kpCe2B@)'1.3pE0P9NbKC$`5X^'*+[69n.gQDdk!6N`c(r5CV8O[#$Yh Ur$&Z?,6iif)l0lTtGi%Iq;+L3_U>Y#*78dKr,BH6An2gR5bcap^l)Y3!c&>n<VT:7o<)r>.ee4 aE5AcSdA>MPOSQK\#=r&1"0_S^@0*e--@bKC&1Nc"P;&2Z:GGifAL6]:t%t"Y$9O#GW]?-?>OCNKs A@-ekH0m`@*!+J>,/WJ9]kt5tQC6j+V'VG<.77h*g&)+G9nKA#5TAW\ti)&M3$k/7W?A%\=P*&&L]kY&rKk!kjTUl,N6R7-cPUHak5odkeHZH9A3V/]e/;fYF-<pP^Vka]?L%Wt!> 'JSsn/16VA/c,(-q T)"`=2JkBj^:aT8sTp_+2o%N:b%QTZ\gnq"t4D_1B<2AXOUM;O4*Ak@I\ENSP'eanE/Y^fL4TOAcV4an>(*-1fPMHG=)$j4j8tKb`59DFSA+QR?.;n<(j:3sr33Q-o]b5;j^l<-Ua&+5%1?7smY;jbUM/7"Zf70BdK@GnRNi%\2A+%S1J/`?(NH8JFjLeJ Z9$Mq986!Pn6H8E=Eg=k)e]>^Ad=?#rpK+J^5QQsb)oT1ch=rtJrj.c+XK;Mk_e_dc ^YG[aWPCZd!n,D+1F=_O\K:LU3"G'rFViOQO`B+PP`%XRnoQg9V:YCrJjl'rh5"HeFCLg:B.Ic7r:&F($UKC>8#C"lGT*p!A\3'_A*'.InVC1n8Z@F<O&B45YQ%bA*n<&r7.WlfF@>O;Iq7_7tWk:q")I#=4mK(56h45X,q,9s.lG#mPRAAfs2l/8MBX_na39RX1B$7LKc'&?bV/'g' k_D5I67WP!W/a'l%;ZWeAH"f7AQ;OA"^*oPXQ%;8;iU46BOD>lJO;8k,[Z1W`N'Bk^0Q_7P<#K%b*cpHlEFaJMNaHL>>J(p@9OVAOb8]Djdf+69iccX jG1Q9kqd*.,"lmC3"mYNY35[,2A=oIg#`S8OJ#be %49a81hN,bj1J-ZB9MYg,p*,1gKDe=>lr'+(fb:U#_eKBV(:H8\eY-Zs4bW5CLo:PZ]&V ]tV5`';2A@r:h;k(62p]F.ga5.r%EH)=f=AlBO-d;9*;n-=Ztn1@/-,7Nm%3t"^-?+sTCNYq)pZ[R#%BRe&5EM98USIRnH]R,Ij[aJ5#GcDL1P2'U%1U4B-0pLMZ:],^f*a)tYI6->6F]]rp*Fi! h2_=EaBn5D)(F?1amaLA4)UZ)\;;4B8F8PAa#XA\=$>RK>aPcH's.cHKk9o9Yc*7CO;(m<DreX]hQ>1f5^ZpkRf`5#?(],]V@j"JEi_U&+ec^F9L+o6S`$P;g':4%8ZIGG_$22bNQ589\KG%;CdqrRWd"f"GcNj&-$QNs2'2=j6AojYZakT>_KbC4HIT4.^o=ES8*5JZ1<(!\Fs8!r;!:!@U[/oA*I:AeFUE.UE$^[dbN6./B(o+&Khj";/-h7U]"6pb4W:3Gd^'+82&iV6L$oar/'MR?Wo,W"@YY&)#&_<%eETG(I??e'7cRH$>%H&b/BCF"pt+97)2YnSV3Mc#`m#smn^Y9jpKoO=e9j+fnJ+/V]Fq?:kpU(tq8hX\Zl2#ppK'X.Xa2UdC95c)8D?q!AQmHL.qh+?a.PN;ZHUmo&jm]dEnA] fin@9St "5i+L-4s,$sW Kt^;[K.q2QQO`?!m\?:*]-j;5\Te*TYd[R*#XE?R%JJRX*gELE/ZOMoP'"i-U[8We5H5qOj30C-lI1\#MAo36hPt.caONtgNM,:8aFnFomY<fHcg[Hl8P AV!IbYROa,4^dDX__$F5)S)b2e+73K [4#q_+mrX?'YC]N2RB0U(S&QQ hOgA,AZ0`qb3V'n35LNK?FZT]%o7_G4B)+dH!WFj;?`(OA0p<tr_D)-h+-XQ:Q9,UH[4R3M Xc7#T:Fe&#h<:H23V*WWo046t0IM*G9$@%ALWR2C?ADqS3e>4(g]IO/H0$Sc3nH@nd0n)lG;+$%`nilmb*S[gZE0_`Rm/T>RR%">8C$4 be`Y$@Bj$^Sdf4OY_N+C;K8]fi!4g3cF<58F-dat-XT:DkVSopo4.^ZhsjV/eX7AEPS2FVgB$'&Xh=VSM$Ik07PPW6ZO':)3Uf7)dOK8jh_f3?H(Jr=J.LgWnT1_eA=M1e,6f!4%<&&A2&DON;?=N_kWlt\Kag$9 26W#;7 crF(` K+M`V"PfX,K%Ul_d@0i!KWfX*OGp4i=EUbSAqBrLALs%[A.^,l0Al?QEaj(amk)]FBXCiYK--?0U(pfC?q!+_=@mSLkXrK'J*gge)^B-a6n'9Hs)75QM5+cQ_[B^[je,\&h0,L2:n3+V:eA6RKlQnAh^: #7oU(C74=K*?8a@iMN 6)?Y2imWkj)jL3t=2lo%-A%Gmm6AGXq_4!Ebb6`hLDF-N:dPU-j=o@5]'ibipCDlZg8,*CGk`A71c00>eW@`lpcN++U?e,n3\;Y#a($_>;^HrjD$XkV&[F,SB1n7gSqmnJZ[Id1g^sl*\E]lIB^ROG<^fcY4L[M^]n*O[R3GnNg9P/XAAM=16F,A^VM3/HLLO3#gZ!31(_R8kt:X2EhY\#6)+[`Q$B#C"A7-qpb/JiZ$eMFkn^MD ,TL4B?tXT&-c,/po271,` L:QjqT/q!K'EqA 6n#[#UY9n`TOWqC)=[A!8`QY#;#:fLP\"n+9hd&@S8&98>gA1=@,sIE$B1.F\m[c2-092XJD<`_R109#40(RH4j$j'(^%l%LaG[tiNdNZd*L1\p&tAXEZ$g?Z02SLek*3eor_IN&2ML+)kQAg3r8Y'\^UIW-h=C1`3]Rm:6]k..&0H*fa8l.nU@9a"kZS0BW6]KU9Y(_gF#p kT*6NY\(LoI+>=7e":1nOl4V"$!IZZY,B8hj6fhZ7>HA^rt'%q(_IeAAN#$#"8MFmA2qMckc cP)2Nn9;YF3LqeBr;(\kgkAfI0eR*@.h`&A+`ESKeNB"7q;S,6E/B'U'\'1FYW[5,sBM+KgV1A\l(q.oU7(!F0!T:g&.X(<$bD-DS]3Cr[2U?^/0_g%5=6=#cQt:]hj1O7-*[drWco:"b>R!sa"'8k_dU;QMV?:lSAcFDAaK\bO':MoAp_lAh`-" EqBL/@I)1Q -:'/=tR0A#;9N?(II?^7"Wr8-.@_*/KdAbk=Kb?6/5k /l5J:::)1cNJBbV/bC%Gf<"1r>kprV$Fat17n#07s,X$5"q5'M'%q%f6Y%r'\tr>+\UpOrS;&:N*0&?rVlQp*q:9LhNVteW"%&_0nP]CVWeWYb[mIOkkDfKdF9END]C>(/EUcC3'KtX3)- l^9"AmN>%a7htW0sKW>ko+-1p0A2NPU8ZpPV[sI'QOYe4+[F%aIY!jA `E?h[:=BrTgJ4p^1d7sAitnEHsfm)?\MJ1WA/Zim*4V-B3o'kMrct@h.>*OB-/7YG=)EW.tj!CpSYMa>CdEqFI@`1G#apQ/J4LV_VFO/PS]ZRV;s84(hSM.n8(`6LX.,jiGkF5,*UkI$H> /@ArY_7EOm)/2;6=EjTI&*#\e'#*2*>k.3T'0C*o0^#OHh[&"W6Eo2A]5GB6S,?"m$ER:Pi?aY4pH?Z; A,m!K+sF/-oB >-Xh?WQ'TI)L'mBJWWF>%mY!F&X8ZZ0)q2UfsSqZ[X:d0[4EWb!S7I(,FN3F)LdFX^3:`EhCO=U9>5.6\R;PF;)`^3M4EI/A b]Re\,*TD!C[T"iYIj^+l.tUG<0&ID.JdLFEF,lrZogh-JT-;a?2`HS7"eQ+Ng&icHUr[3kn'?nNUVD /b@7[cRe(U6BA?jmq>ToSn @6G03!ngRd&*ZKo'Ue,Ll)_2'- h1 98UTlo@LX@i7hgRUb\trHlfc\epd$Dd'=6=tm#:U]S;d(`ABONL L6q,6lVID;;TVbZb3oT?#!cjhA#S9'J =Iie<3KV%eXg9ST cf%hT!aZIG74l-^bP>18WA:NRE,1VQ>8n_d`II+&4Ume@SeS Q`+>dmTNhhU+8=+gc/Unj=\LBal9)>-cT7]Nh_,!'&2Oa;O_!p:NEnWnKsUke-I@`1=nB)N>[)qs_)>E2r3B@c%N0R7PVUEf['eeAnFZtesX'+o>$5Y<"i?6&_Fj*iY\Rr]5)>7/E\e?mp^dUAn]C3?#T'`oEe&3R5g7t[U21bj#^2t?>HAVAb)D]gf2B,esZ"shAWS=WN)5P.p+TZGN3\KAkAmHN2DbS[V@R1fS`Ti50@R0>UdFAK1)Zi*-J0D7j"/FE0RKgkB;0iln2Vh\<@,l5r]`W?D2+"Bt/6X 0L>3\066f+6tYoOA`?=e&r+4_C(F?pZZ_h]2V0&2bBhp(=3Q,]EGTePc&Co;lFKHts'mB>=OgZJ5rFRoEQ6$W?]j$BT@RHgO*82+a[@NRqTPYs:Ks+^NG+2"2jF(5!\ kq?M9_GhBC&']rj'Qj)AhgNs#OnOQBXPO!o0&=nZ!i%DX?:cOY,2Y8#2IALK1>:R^N+o6hfqpU f[O%m6lQ%_I0=>bgAG'%\7(4Tm+LtH]Q(f[KYjRnf`W0-B'*LL- s90UE*\Ks5< =BWFKc485lcUBk(R%gULHnT^KAPiWSR6 ?35O?dmV- ]mH45?&LV=EsoB]%)!*$'edIP"HG+V/A::SkJdA1k+@K%D:IB_ENml)0&r$NS`[IdK@Tg>Jq5]_0*/Q-KIb IWTFA!SDl%\-:M7ni6Aj9j[^!L?`ZS^T47j`e`*lc!hK=rb;UG! #CL$5c(3iTti:(pCpR34`];*shFF]-d>MAn59AF1a_E2>SbWX_0to6Q'":44aKk4,_OWN'WE+p9GES&eVmA!ZAWe;*qsL/ l"?l1kg2d9<5jgb5\#OmVf3WH4:$$ad*b>=G)U/n7dEeC([U<@`qL2iOVk(Dib2-K:K?Y*r+^A^,72qI)JQ>.VE SfW`"Qrg1`cJ!oAKC>O @CpG-A0t@M*]8=":inR=\NnGXpC1+]3lQO]i?5P-WsB0t^VOrZ8kQAhM+-/3'N7[h^&Rg#A%K\^9XV4Rl gZWEKgPEG;$^iRChYtWGPlp<8#\6OVm7h`lDL-V11E[4QN:,kH"\o(<)7`=*@tKW]66kb^#jiLt*/%]!)A1(Vt]%e;K0FREkVrC,XQJA'Foj:?I&Zb>^Z+4D4"A9)%`=J nAEL+q\'\F$kAP627_qJekh$gb:_FDj/*fM#1<(;qNmOX/:T&7B?EMGQ@QAs.O*o2ld' jcoHpC:/'!;`CX*#, 0M[`0HB[A5#]4&jDdoo' tf6e",o(9HXr,bVrfLCL0Aa.bjVFXVF5P>b%R(lpHU*'3XDQQWq-8MECG"t"'dj!OM[_N,FfE40OCHd6Z!'M&6f!PZ0t+@\2#)&%Pk45Vf#O#be?9I.6DkcS%rV/\^Te((c*l7+cDmMaFCFhGD$Lh\ID5;V0a7iRqdV)<],d-e>q<E[ (Zg7.D!\4EJ4[U(b@(AhmE`_OS9G&&pdj" q3PHR$me3_LRA`G[9poS)*7?L"2_qe3HXV^[%rTArKEAa:S-aOS](?hsJW_/7R\[+%;pe*kZC<@(q`<8!`&7#4.OoJfbpo3ig@50+m*eR53JRhqrU=H3GH@^KM2%<`pA;<7dUD]9FE$tYmlj:4&)lWpjoXje\L;nHsWBi%7Z8@%W2M>]WatN3e&Ya$P?d1_j+a6i$FGQe [Ho%f;j#Qt=QGoBobQN?lP1[f>fL:)H^SC9A[ ;\(Q=WAm6cp29%SZhY@(8TsDkq=l3_I,h(g?%q73K`h6-55Nigo3:!<3c4d]&(M/RC4(eIiBKW,oI1d4!(<;B >+HZ0)e.bs' II6_7LN#)q0a(AMn+>q59C$8oU0La]iI)[H9,gNXL4&:BUAfcT@[h'dlY4tBR90i9=:_bb?\QZ673eo0Ea?JZDAFnHn/UH6]C0 /t-;)e78-B$@6G%OBSL1a.\&FQb-+OUZWrW&1ecmcSTKW#ZdeT1+ApR'5DMSQ, 9Am& )+ e<2W.Wa?CO"X_l"lQ/Q<*[.hDltZ^6JjC[PiL2814O$?j/QC&AnOGmtW_ b]KA( 9LO*7FOICC/7dr)pPH!B?r[;`^d[\V2,^08jK/C[M3k,V78XZ@LoJf\HmZAko6>rTepb]iPgEQ!;4.c$ClmhP9 1T=6&0GBA*(Un49P<=BR:p2#p&bO!H74&n`98`_,VkA6]t dGYqeN"grDXBFk;-"dNOARN[5-%).(_NSa/RE::QKJnZG%f"PP=6#l'D'I48qT\;))GTV2K1E51o"_6-RH;:$cTB5"48AR<+U*>A7N?5J+iEFl=h2p+f6]h.fH!E0CtSO7t;SK_/h/-^ndjRX4$rfi7Onn#B$CE="L=nLG[]3HB=/ph65]@7dB7P#"MTBSV[P-60h'#NLG=klt'MR8q=d)fN])[O_`Ia-7BMX%eFAkcF6JT8MYV!)/cL3[cj3VnH$ &O"iJ_g2HosF.@ To@V7OK2"LsYYcAs5>M+d:Z1XW*e%Gm*K>tcI$W6Q:;KCW8U@LOlgU_)VE bAQRh6)apl,gr3^#@NbAij\=Sg_"teo$a WNJ s\q8+r@pKXeJ*sh/T'M=L+QaNK!gdrAe+n+FWDCZ"d73O&/!Sn/0.[9[> *,%SA'G#Dns-Q(RBA`aO7ehjH)t4Y>ad%^:]&QOX[M[-RS5W3846J>)6])AO>s&GdJcAMo[mJfU<>YkGoI%14nSCT:feac2KYL[-! Hm.Y7Q=:(&B9'$OVjb=d*e?S5Zdm'Ar!qIRLG soR`^Z:ee +eAt.Y.FKE>i*h$BGo)I4L)L;A(P!-]ofO(X1\m,kn4&;6HQO>TAD--L"8+>W$6m'Yod9bg_4 (a%XKa;;A)@t<"XXDf7j(g6/+W`o$%[@-c;ZRqq,9bkhLBa&X@(>sY^DS2fB`Aq]pm'8iB!RsL`MeG$atMf'^$hk"i[r`s^LS>(WP-?,oPj_BMIs_1gA$qsn?'oA1Z4Jf0BFg8n.[sf@=gm]33!6m8_IK6',"ZM[M>)ejl/M5S`7NlJr(^!dDiF[.n U%6S]nseSC8=_2>bcCgcoW!sAbgRfL!kgj%81")9\EUQiobP%Cd`[S%t/WV[A`T+_WFrsRlPS]gK0G?)-l)i*_X"4J,[Vl8mQb= 9Y(a^=%lViQp(feU]A`:-MU`^2tA#_mKUjSE*h,pKKl^n\bg5LBF6AiUAt tY,8kJ; B:*CQk]!fn4<&*&JQh^]rJ`k'j?PUQbR*dHaYWN`IqI5d'*L%2HmA?=HK>g73Ih#/Xke3&c^@O\rHG&A1&F!VPW^2'H.[9WD[;=#!Wk267l\ggd@B3(CnV"@!^C*Cm!@8dg6pIAiaVY`omHsisq:(]e_iW)(,.3 '_Y;bm&qQXO[_c2L*>=U)U@@V6QWjlsCA_(^TWdoAjC-6.^kp/8PVmW2pMq]*<[rB(-bHH34$OB\;86lq!,hgU*m&"",6e6`dNO<;S',0jLdrW/-I\P1IJV##$>:TEl=B"$WHA0]k*cVFE+#j,%ZID]KSV=&2S=<XD\h!tWF-.maP>L(qS-;P%%"9'*IqA5:E(-H-^IJo4-*9o]ogIIqd^G[U"P(ngM;AYL)a\+on0"$+A,iYLYIb]Ok8_fBRloV?h^>i?A;VM,5F5!O;mI)Dp(7"H4E+C8$M,K=ZHM3iaT?t;s*\4tZ*f-!dB\9UqF>siVD8lFn_eNf,5In:nD#h.;fF#M\P=*J,DKKM\,pq1^`=90Q!e=,@LU-4PFS(IJm/J$0mrDUEDlDZ/<>SUO"MSWAb 3ER:/YH*ab4%E-KC g>8dCgZT2$7/5Q?8)&MqjOj34>%m-^a8GG*P_fF?dA5rhNmWU`@XTe,O;S)EF%,0Aj@T#8(1A%1:!?bI?U_mGggnQe\\1 1cTr:Wbbg\b 4RGo#7Tm]\@0EaI]:G>4:2CR+IQdHmOsFBgo2;1g6@jt1pC'GAaa>/HM16?i(+/9=h'-[]OL4Q0&eTGc8GP:A'>O:1-$#.AdI0Bh9aALq^#XbS:^>me<*kQ*H&g\+oAO*#U;L=M;?#!"b[^K*?iL+1seV,e4]M?p3A(=L3ee/?D#p#)2ffq\lXn;"b N]1#GMBaGDTEk:[r(4ZF$j50M\K5W6NIMrpMI;E5X@I:nZH/sA8 3)#,l,1J`/8f/gJKP[h%Z5\"ir_WiH; Gi.-dF4UA+#(`EgB$!\CiV2nfHi8bde#CNHNg20q>KZh[O)2T2+'cUU'#L>iBnDJG]`*"i>:Ua<\bJcA,b&*i3Ct02M))Q$$3LAH90I7TA-$1SWpR3JmHQ<)ki([726n)#$LJV,] k[ZnXs")+P1EUfF--*kAWRgp(e%h^Asmq_EWK[CS,AN5U 'bgNLlUYn]A/FkZ]F9KU6OtVFV$>M*1!/q2pKO]8#:Q4'9BA@6#N/UWi@^,Bsq!R32;%Za_A-;;q+5&R4?8endVAd#"[O-?b$`E**Fk "Pl@d?3>T!taRl5"Q=GW"IE2?;81%s_b-n7jH!"VH[-Y8`^?[#8kBfN)oKgJ8?k8lA#0V]i'[dc'tcNEbaV9XT_85*(<5S_W!m^l;h`Z$`U;\rVKW:V8RA-ctGH7O9roE6;F0D*$C-(n&Do^tXcL3=$%@K3&An&/?/iFaHn6&7'X0!G0o5ng*#fHsl*_BQT`N$fgYGUC.Le]JG@NV!fAS0"WEGApT!R/^)#D]m`H'O*kPd?&kkAPrR\(3?X2lX1D'"*Q+,A!:&N_W,l!H_'PZIDVD:X%1j40E[>c#3l,j,.JdXlY&NsLrL!Xff8R;6#%K2R(p%O$rB")9tr3-FJd7EYgTS A(\!dgX4Vq_'_<0FJ%8V_0U>)jDSpRJU0K79LT2(C2*?NnnAIF9a\&AI['B$EkH,Tt8:JRd7bJ1BW6 imLcO27=Y)o%j4C/6;%[gAZ$k#`cWCil0[:sbU)Z9`f46@>X/\>MO)3kLnmtL^/4Q=^9a@N/n^D4sZi)R\]0\4Q9YE4VG,@d:V?\ jrTm)Ra).W^YAq]-=@8(kKhc7O_^CUdZ$3ZlC-ZAP0"s=^\Q7':=+X^r%*," OZQ M, l%oH2X7Z-1;/p,f%i!'Qg90ll9cE.]6)=J-71ClLUS*D?Phg.t,`^g6c`q#O/NtWP1dHAWYFIJL/;ZbrMd6Nl=UDrs:\9D?#YHFK\ BUhIJD#A`faf6"1X3g:bkS?4a 5dY`"A6Z]+jeU1QMhcQ6]@,e"3)oU<Ql59VhPq IO$3[=&)j] 6e!fY+9$Z;C)%p+csgdnAl;Ote]k !n9/`Wc`,9QV4F&Yq ?[pE_lG*nmem<mTPP'.2a2Q+6.BY0dmi-U$%.Jrt37@07jAjF/'6$!#taa;Z_f0[)2l"8L8Z(-+5*2s!PB9Z4K+dUcX@PA olt(IN]T3[r*q2O( gV,8 \5 pQAUq`ln#KObIiH$)Cm=\BaQ-[+WAEL@:j@A$niZoQp*\fOtI0/peWG0>OL?Z`B?s@i_?J9<$23sGI OA.(ZQ6hotT-KjOi4ai.T*27jrJ!jg$3WWE87=8\kBD`%53Pibf[jBAnKP)\XD*6Md-nrH Lk'o-Bmk6SO-l=d(Wj"Amp!VC ,iOF8IgAb7_0*XW3o`/eXiVN3q2k@p=+sSiPVs7$1hR4b@MA-'Oo_9\hcJV7AA#it^L&S$GV(m1FWq38)d\CY-Bq)\ZaHDdA%"5-IJ\=S(-)^BHEJm>Nt'fdfi-`6%+o(qa2o;j$$AN\K=I$'FEap4D6p8,#L-8%-oUFbgAWiG[nD.g5p<%0FM:ef*AtRh5jJE=N2'fciPam'd#\@*R>?2Kr3Yn'RA)($i%$,/eo_p!8^#<[%1Q\7p!i5eR9dr9jkE#NfPej$kW,&Ar3N;4ab-a-7a,qtrcArL^+7<6@aO_ph;C`j$TeL^UhfA-BjjQD>Xk]nEKF.?:ASU8\$A!@r+XLUlr?[a,@dfC_fN810! D!KYBtmVs5+#U"I0q_F^A2nfF0RE>t&P,`0V7._ajj^<>Q?tl^!#$O:tRlmHd!BejK]aqUCaJm0[Vjh/*iQ>D,-;S]XY$Pn2@3lh1(:AnX,,`4?'Z0 J)_` -Wr5?\r2PV_bA:h2HL'/?A1($g0?SG!"=:N+,8"hqI9VYfN4Y3?bS<;[p\3/qK:D80G$EUb]tgDU['[O)7Ht$c.7WT,dep*%&Ta_R,XT=n4G4M!/A.04d/>Y8'Z=Cm=,A'a!=bhRADYk9?sqics9TMQL_1?7:O6E:/^de,TXZ3A?enI)&@ir5U*9;HYV/nn$F"oJ#@a'%*,m6sHScVQFj/Hff/Nr ZP<'V6FaDYH4<8&i7ZTs/+FDH>2F,BP&BAM`9`$NTRCi7j*,a\S!>O?4rCV4]N1_$p>]E2eg aJ&sA^,T;n38Rj>U9,`mY@_kIsY[fbd%XmmD@p7A6^01L1XcG`&t+ISC\L^,7GYI>)'Z +t2.DPsGO!hae9L0Bt*U6D4g.edlmm;g(;=:h5:@d3k?@^!mnT%cjRpQPE8r8BA-70K6PS,#8mFp!^_lDl@kYfL#XtMEG]fe;d%%5:(>Q dF`cZ/\eA)^l.`3dPAi6(4VAf7jWV#6jfVD3.-7,$aT\ICYnB#et H#1SLfA?KNg6lPl`.0bdRp?Y!rl(JUm_?X)l>$/_!5]r.]f?M/B+HiL7Mf8P;A@iV:]'NX=K8]_^$, <4< qPK[gag.V7WHF@&ZKq01-"8g3E?]VK2ZLpmLgehF%SfQ"YM]W?FRJ4.V/G:jGpe\bjt^io$r<30]HJ"2n7H8Q\"o.=BsfZ\=+o)@B>S5.f]]Q'K4^bP3Tj0(q&)eP>

6LjYG/,CVt3*DgB`+_q'9lK'-Tb+s)T27FJ[YR$Ot^!(W$beC?m[DgRN548N&LZ:/?sXs!F4]gFV*DnRMB`g8_X+a7qa^QAVgj.q0!rb/]OCp01ToFb%]qAHj,YTY2:PrfsO@?ajC$P(KShC T<[^'gO?!f#B]].HBS`3X#p"':.l^7m^,J1843Mah@-qe*)t0ZG2l3FI*f]EU8CldM29$WUD<2m-&'B;kGU\$gsib7(8d2@&-r b=Q1Uo^rGFmaO5?iK+A,A7">b#Z6GpJk-"*^VNlaY> qTlfc5K:mCT4t!Jk&1Y<*CU$'d5qL">s#F4@%W&+,[e&G(s3%Bdil_&+d=m#oR/j%1CBn,`;\:Xr-` &9a#/A`5`^e%V-iR4X+N;Tl?fAKpYV%kWL2P)'<tB?j2QS-4Hol\:8@&N[^?aG>eB=4P0)#T+B,Ll@Gr'XZ!^g7iF liLoAG#MX*kLKX:'A#.EP-b$ZDpdgQhP5A61n:&B r_=$g-4AR(IsV*9CbiWH7Gs+mA+o^sQ?4(p"B @?:B!'*kpj@'^:73Y[[P.WoRKeOm%066gH'6B558DqDXp6tOQSsD"c?6;"h,msOpSBYjLq(QAJZD;=Dgg@Nbl/ d_$0:fM==X2\=m"j][d/Z7K1[3aGS$p 0.6ED74l;g"3;7*C'c*7U8NpCZTr$^9FZ7AWf.EA<X==C-+F<:$oMa=k `=-7fS!_qfOJciIZE18f_e64JQU/lCF9Q`"1^qX=6iE)Pk@s=OPT) X&<$!i7Z%]alK'D Dl#VCl,h_c"I:^IPNUWi$dGM8@sSr@&%B'XcqA_@1a6eMZ,)ABFo< $hp]9!R_@1daHGd@)*KXpgHq2b6FV7>O1&aYi/!mVUmC1Ya`` ].M=JYJAX#q9F'k-#:.YAn!foVE7lb9AbBTX$LlFRR&Qj"%UdbQ(2CIQ"6W$NF4P\-e,<OsZa<.P#_aH&SXJd^G+rpNtIl-4#AFM1&m,Ja$GNfoh=e>CRGR;G72S1&rFhlAOQH#85[.Q0<_FNk+F\iUYK'Kg+,cYkkO!Ad6S\<9`n`*AL:MH*-NMo %1AQIYZB"lPft9$q.4K7$fiQfW@05*2M0Q,gaBYj4]Al#1EPUWAs)pd3/fM&;3C*le=YZF'sQ!pS7Tk1+hGA2b`A'cs*&&!#V2;*;Jd\7a@S/R$8mgLpcdf](QGWYAAF;O":QIe()+[::3&Xms,6G#7s04PXnp8T-Dor6bAZQ.i2VIC!BCm&,D5j!LJ?/+M*i_8t+s6:!pb^;qM#f:)k4&!rfLUQ/-GcDq9%?$qtNFe#4:"*"IQPBZc]61@(fT!7/.T7 -Vn $2>%%,jjIb,M$`L-82!q1&?%W0qpDCFWg@U18f*%::H%sRL#n/t.r!gg/?VeM"DHH6AI;+%a)h(ilYcP4B(lrq?$s3RpED3%\:o!((N)]]FrJrRO)"A)2i)t&LQh-l]WbUX=iP>l[Tf6MOoM7"f(:hfim0*@?Jio3=If%"H96(<8;7(M;/Zr!t?,=K"[aD:+6ak;,?&:;;me?f'7PGmT(B\`YmFqTaK7 :]4\Ap7$R:^?Xh0qGB$qQnjGaNR1]"Y9T4Z% T@pte3Q/??@4*p\^73Kr=s*FGJ5e!#/m33Arrl1]/1g6)jSIG:ah@9/aRR]To-!toL!hb0%I"1mJqi[H7@fT8+N:)"gCDr2\<AW`3q!)#6klf']q)P WODh:JMo!-AMX &s9ZA%:raO$)=,Sa[sBp*\`U.^^?J5nj3Z5Z*O>\Z)r([G.%e.QJ(DTm(TR(F\V^WqMk,^c$P=0^/noT/AncjC,c4>r5OrQOU#M6,e2U0YcW;*1$P"ZM/1Cbl0?dQ^\A6@3:Z+-^nph]2 2tc#>6&Z@6[*B7]fGA[cU&)Sk0UgUe.FFA,'Xd`6epPmXfSsT )-iT>MAi:\a5+gl/.pP@DE%'St*+r;51hk6,/4TCUejW %7e$D4pQKGFW"r=h=a8^s.hp!?.6lI_:h]fD:i5=@m"3>^XHa\R9KU?;Vs@_%3-3>$H4L">8ljV"O:4Wje3#D<b2:2(,`RX*qj_Bm_%sOoN/dqZ?,,N3`Y2NOt2.dW8U\?OLiMXHe R/m3QtI%f)qNU@U;sfUb*HQBKJXl?p*)lf[K"UWl@BeAHi/q=[hF-*`:JtCM)I7XD:,3%tZD(LV`d_>e@@>"LTS]ShI:!WRml\NG#cMosHE@t<1Z]"@JENC&=M7gW5t=D7Z'.KtN#r?fF/a[r-B20%J-,A&5A6N#K?;9k5Yg!:b=)Q,4jXh@>h$@g$GX"sH8]Wk$\qB"0*&3q,dE/a9g>*d^V8Rbrs&J[??YH"c9<@QAkj..T/nnaaPdQ ]s.-#&m/+,U0FA/lA[$O7;lW].`r;](S62JFttJS_!I')O4fZ\4AlMm:7d1'f@2ZE-O*Xjfho)O)/:*.aQeFAA,hiAFjV0mLH@tK5 '\F%m;g?AM]]&p%A7S&^ab7^5^%P^t?GKiYJ`"aBmcX7Z\Q_KN\oYJ%F[G'>Xre>-"9R\O\_J*Yh&0([Aq0OZ%c&RYCWJW[,.KEo;8/oUC2PRM6-\sAqF?TXll'2^$TlX2OdR*W7PX0$CmK:J\MD#C*O:^b!*+rm6/ 6HUi^hB8%AmmS=cPT>9e;EMLUrFY6rAL`Ni]UQetHfeE-9bo`Z>!]C;$k\mtSE!ndgq@2pL@ i`m`fk#OGRcTeUgCB.'b^>sm s:Ib(j`%Q#. 5T\IldJfhF^kdIAZ,*,;8dnT7Abkag,]"-nL$nb]JCWR9L$n85 [f3'd(WTmHGr>$XeM4p&fd+1bTqE_jfn% kMPkXk- (Q7V,m*VYdCEZQrda(r1>$A>;@a\/)=joY+?"$%AQs?J_0p4Q<Ihck5UXW>:([Wdq#;/>MKeH4kI@m30otpY[5jAI*4g'\f0qiJ5f6V-OmQ`B^LL@AIK$or:nOHa.N`;KEh*cQSNYD.8h9H%HAn#`=[Wk(?H)?[>6=LYJIbm"QDW-4c+ES6WKS^P.?Y^>1\O6Y44l5WdA;.=;(ZB";qm%i`^;mS?$6Crjg;;qR(Af\1ID\QE;cT^Bl:> `_ij_8>cK[Ut,)DhKX$NVGXl0RG`GKH+I/H'Mn#r?Y"67Pm+'3M7&FL\DFWN#qGIhK$N1>X\23%N#@ c4i$s,^>tNSrY&Oq@#N?*R%D$.!:QU^6B>pA^.Xd[i/Je+e+AKb>-=H(8jMiD2BWi%(72F>()`Te^1;b@]nKGrX1c!PjC"@q0f^\Ra;9r-CVIT2.XLQ\GK`/oQQZ<'WnA?@>P#*3INmY$R0N3-pAO"lRsDlts!8i0NAmC?lS"A>rdil+R?%WAg?/jT@L@@? ,3)P.J(*Ps6FHQ^lM<)J`B-K%Cr=fPLptLA'c?r.\Ji36@Tnmfb*"@gh_j*mN2EhM[]55neP1'#J[4fb!!j6eA!/jA]C]7]>mii%m=o/Y>,q^LSS9GUn$l@jn?`t98@ns`IbS:>mI^smC%qm&)ms:S1c?Laq4U:YlM[>bH.t7!14F d?pH[HPBtA%9E%7m]AK4-?q'r+eL b\ZZW%j@#BpRI#UhR:FNFBY,0 MX)UD.@V&bcVAB!`\Eq %Q74!Eg7O%CDk'-fK9/49\5_ bP*M6qTENeA[A5e[MDmk7Ncj,l]a&\T>WVPZ,>WJiK'_pS(i@HR":0-T0nI\pY_5f7\9]I(!&otDqY-MRSX+th4gU)pG0KRJ)V!VGpTDiU!:9MilXlsO9K?O.#Vt("0Rcq%UaAoM'l;E!a[Lko%C3qUa2/fgC%Ako9!#8Cs!X"!fOk*(.s12S9tn`,SFBF9#n%UVYKTo=+FR#@C"r`%rH1U*o.?Ee^YH `WRM-kSJg-80T8+$ofi&gJ.0SQbUcAm=pY63?SmfL.ZL:/rA RH`-&OtN:T$-4Iq@O.r$++jHcbd^kKr33*?KYbt,'e9\GBAJ2;sq-+]r$@St)O ,H_EFUaBX1MbN*f/1W\hjrDLK"R#ia?P(-an& <7g/@11^/Jf9%]6Pj[1)6o$i.Fc#q"5+gm-3HPQ9gbLp7FOlY[j12JE)[>Zl!Eo!F#.nSdm!s(;$VL2#W`P:.^L$0"c)/'G,H"H=08o_%^Q7J`4>Z17cX q9dWhZL:IFn5H@U,.-1;q%U)%cqFXQf^=[h5p*3C6_>OVcsm<$t#-(/g4o9 >U/T>>Le@?7D(P`R`Z)?+N`S+**I#1X5AA3IJEUa";l$>_G^4 G`\5ID8L$31/]a0V[qg+grWO*^sPAga>D6[hG,jX^W^:"!D'2WRQH+XA-AS+jOhS2nR@3b3ghn[,MH@sZQHis+d%A)=7$>IRVg+.r9.TT*ZSkmfMTg!':t7QUgk`b=(HD8ON?gf nOjj2^SPXoCV=HF_[P]cjPs,bH`r4]:2)7M[L*st%2Hlf&eq@ih+Fsop I(EV&oU.%";\0`@(;)V>2Oq3WQoh$F3:E6ai-spi^T$kjc+`rD!cWK($?kGN%?T(*]h?eO+T_E=)8B5ioL6W7<9)-r1cgW.XVf2Y3R[>+0]KiC8Bh>,C!$HAmQ1_8>2UTo._a[[qchmRnN2A^`BcgckQW]r(._m\g_gGt0C`e$GJ.r-^B"?75&4q*)2CE^$F!f.;M.]>LN7P]_(^:2DLhTWH,:)A7c2sJTbDF*e%K*OL]<9"O:tWeV%]V=h)>r3!]l"pb3;\&!Zk*iUn;"A&'Wnl!=ghSC608;A@;mj8!GgAUm&W./c$F+AkA1J-P*ma>Qoqbn\;2<1Hbp;/,V^(G'c%J!8WF76%+/='$FK)!Dt>Eg""2/4m"ok<#`,Y5pdE'$&>-K#1FnB@76/(D#(pp))6aN#*;)ro'7Eea6qGsg"6qln-An'9;TgLrhd;:d9#["e@<#'AY6PeE6DnRL+jL)A7jA.qGMNN)s,_\.6EjDZ?.W*.#S,9Nq-_Y+57LNA;qZrB+4"aOr4lAbLcEA:Md5qQ.QrTlnsYJ\TH';5^F\EZD`<$8sKonrr$J&2DZ@I%Ad:FF0I)g`13t,rgm.Y8nA[.T!+k;kjd.#Ps<2JCCb$ksm0732;Bp*XjA5F"2G-e3$rrAbc0sG0HbS$N)>L-Up?fbkQSjG9mr$f.,nZCYJ.o[S&YER?3 AV4&1-6#LKt7+C") \\@`B^Y:#i5gT0`(\E*Y!(.H%c9h1HkNC(>sV3XPgi$%.@YApoiOIm/=!4@,]9Y?p-5fN-f4@i.AIYK^QVgA0gI`W&*rI?X=Y?^/98'gIYnqVg[CkH>c-XL-/h]JSU_Wl^#C5I9GII;?YteE`t4M?f6'!T k]rUol25g1I^2k0/q6UXhV16b15[cqs]P=n];5plS6BZpITMN,$I4bm0aF'b:Tpmc^JL0/eg=Il\&:T 0JndFH$n%CUH6dCAa/+$SSGl?t/2YqPIooLf^_&/UtoL[WN/\,qn`TD\/k/-b$(!+2 TI[O@*1@h;scTFUIXHrN(+);jLZ9&oe'lo7eWcX8/ '6SQ3W4@bGC/N01^_Xh8b#Xi3rt^X1Co5OS]JrGQC!&V[bR\?++e@B:Kj:<\"#tDm*&?8bIY%;V1K,#E??rQEmr29fO!a1,hgIU)]U_6/X`6n)5rok"AXA`6,g;'p30]t$l!@.8M'XYZgAV4H%N\a1eG$Sg W!Q`WD!ga(r/tXFa3WA9mm5LMT"Xid&T.q.Q+VOrj#.(@.!hEYB*Ncq-et0bK+D1W_T2_Z-'r;d+df+7dNfC!To#[$RL3J[]\:3Ns+>?4J:Z4-if`L86=TD=M4ot8!7Q"N\+%\@`a5[0`DjbRiT/G2IkOpKZ`?)T8]a[ELKqFogA2P1ZGJd`(hA&A*':c8HM#3eE.sRcb#F&,r[B3$Q7lZ&IW%T[h;>R;qV04CHjhKr8/O8IAn;h>M:5(((d1J5?qAS']+."p[kK<n)a6A:t-08^X:TejmZp1E+%;Lg%lnDsAMt;)cqgRs.^1_W\YG>A:QH+1@H;\otrctFi96"EQF_m6E@W)S(oUA`pKfM@Y*o]Q3K5iCR.gec%4XOTf8e)<J+7=\<2Uo#IR!m::-% @%$;A:eqS)t( @RDj=GbAYn]%$H*;Ubhkm8eh\1fbKl4('*`05i1m"3%KGUS_G*0 _k,kTJ6X=?A\Y4Wdl]iTonCL:t)L.ptEB?Ab+:F?dRY[H=37M.JrRl"YAjj_T$dLtbc0Tkk4hRXTaAlFt/HcQ7HINZn;Qo?\P92q`si7W]WQtlC^`EN :akD;RZHn1-+WTX,h'0Z_s+<#2+_.4["s"tac_C-WhgA*gA4RGnO,2L&E8$Mf[mRiOj^!_Ec#cq_\TEH(>QsBk^J+A0rPl2=Q%1L+4j+TdUJ6)B!0IcqMfR&o`]Gsi@AgLV,-Kr-5l,*I9(==KW0CW-?Q"-WrnqM6"[%]NcPfP]nOkckft\Rj.?A;FbTC^MfgBhD- #;&rM$( ^b#)Y@;HJ#@2g@0pBj6PiOlX%A6A7R2hZPZk(8HfP+b1GB38&F=FO+%L+j +d:J#l\rl`nAbDEtdT/8@#s>l>f,t!.$L-XjP&Nf6Tqc h4eIsWcAEd:'E;:#6Js6sVS]eB9s)q`L,-1iNKq$F0[XXIE [#[mlZ5Rc06dfB>A:% nb[n;8kKDBN[HnaPpI;=+F*5n`Ttsr0^_&@ YOA:$[^t[#A=_QQ;VfHT=4Ir8\&" f#?QW>OiSEhrk @shHirk>9/berZoY>3bH*PtUN>nTp`Xs7[2hAJO[H,bbROhY:RFqsVN+WtV^Ai*Z_8P_D_j?f!4[X0GJk<6O&A5'/SCO;:P+1DDH;n2O1O AADT8l,d3-=Ar*V>*IFR6.jc8CN+]s*bZMR)d,iH#P33Bq1ABaQWr<>R*;-@jT><98-^5CnO>p8]-G))41BD$7M,-hCAc'.Gs_DRC!gk>HSIHHER,+0afJ#(%9jJ`@QF%L1V;GfpAM:`;<1@Of(UC$P@(2TSLo-g)M05)F&*b7Y9o5A(OP5R%WL8rJd9Wbc0L.enUZ1F&[;ac7"!K,,NW*5]>>,X[>%@Ei37q,ro5LRs$#eLU1j&YVO\@A%b^MK._QBm;4Z2.3X$U6RZ*eOA7$bPkMd37aQEma`YiOa*QU;G6KR3X*q1G0K-Q=m1Ok#lE/gI5$A+-of5>a4\^%)$)=4-stY;Cr/]T3AHqY*,W\_K5-U/'.I6@C_A$M%G<8FD X0-s%l.>p5c7/)89RL>$-P>gtP]!YoWh?LMM!Eqtg?a,o0mMrYkjrf8?\\N)A]k#5&@8-%)RlN-3-!R;P70oq_KlO;CAAP<3JOr^sV:24rt=(q= $oQ(1+l%AK55\P9?t;BKMV>5dFHb,iG#<>#X_DMQoEZ+H;WXd;G=0+ Ze&@M\A5C=B:r=1ULSDD]tHq$b2sYXAc#':I5 D"YR0=LWXee[s"f4O &-l4@8t^qL7l4UWlQ:5Opq%*_'b]j4Ik^_kH+K5(@Of_fhWAs`_D^2o]]=':KsmcPn99VoGCtCKP\73;K?l>O3gF-Ns`_O^l*e3h(FY=Ddt#M?Rhg^@`o>-OSSO&(G0Xa :Zk')4ATV0/&##cWpG(AWj ?*kd5sqG/9.H]e%GKb*bi'Yg>K2bEcb6;fR'j=Pg1rnSL<!.=h.H2QJl\M_qD,J6g^6>fT)a?@3pMXLprO>^Uo4`ba_"i#tt'CAP*NP'Xt6tan_SpOq/Hs/N3V/PR9Y.>h(#njXVjDNmDSLEJtA$\V@C[>fcWN>3(Y9/(\,]Vf; 2p(b@$72V; )\$s*HdfHp@j>DLD%N@gf?:_8[RU/O"Q[1jALA"[='/OAA)-i=@'636!el8[YdW/V(-d3>T;S2Oc\PR3QZ+7YGG6#d$ mS`#CnW9iANsQEoRP3ZU2q(@/AGF$8MWB:bObcRSOR'/;6iOD@iWh_M=/Q;fQ@^ P*ipN=7GDGqTC],@t(@%+1_LjGq"%HbLc9/IJ@Zl8sBP`Mc8C0\m5:s4Mj"gZ&Y3LhKI7+`m#(@r-R59\/I\$0$X!e p7W>""D(/k8OIt#3s;/0*7bYoik[F]4"6@,2'" WP@c5?l' J?J[TFE*d-oOSOTVGq:a%giE%Flg.bE626m-2i1h06BnFJULW#!20?:C(7D^9E0%hrZE&H^Ve4#j-W68M\.!SdPG<,UA;M)Q -$[7gT;j,N\08e"\,;`6X4<^2AAbe0HZ`Jl]\8tN1P]-HI7pV:Q6DD7$k(pQZY7#OP-G %3co4:Bj.A`A5_iJrljh"J><-ZK^Gm.b3[QcPripbVm/EU0Fj:Dq$D`/*hJ\*8F8)'&O>YHQn6MSkmMdT^gd-NqPt m=$6iY6M7;l!l4CB>Rq2N=O;YSUi&bA8>)R9A&KJJ,A\sBCm< "'#!!I[*Vm;a4Nh2^f10r!.p:LjdF77_rg@V*XU%!t+`#/elU\2\lk.@Uf>0tR8$?qQJ_:kWKJpe['.iiP'G/,Z-L8pFOqo`KHFDsWdbG0n5aiC?><Ha\cmVls(RBdo[KpER8%FWZ)gJ(4GKPZ7;6h\daAa?j$AA>`bVT_&"A+H\hW2"p!4E6CrV$*#N9.LL:5tM.KT#i;\bJdqR]B94)i0;I9)/;_5_SR"G4T/Uq?_3WmY*Yq%6K^dt:d59p`jeK A7Z^U=OOjHR2FeG0OT>S=mT-A#'Yc7s s,@_p"Cb#T>.jI/9:8;cS5=jsSXE5H?(.VlG3CVaNG(*CBam!?S5B-Oen)\\p>"\/!i)ka$m0i,8S6no/o-glcW&PAcA![7-A3DVSAA9js5H_.%CH=XT83\Yq^+er tWe,P:FIFHiE=1K&;&5+@jj&N!]%i\Fq0sD;9cR ZO0P$4:?VT.;hFi_??dcI"pDeF4U.(BS>`oqn]VA:TksLA\OW18p^FJhqX,/F&MDPFm1GfAd_sUVC2P DUC rMl@APAG9J8+r*(JjR;!7Ddh:nN#'BH7"Apd,iKd(&LW^Q*A'W5$=/H)Mn\2a'h]OXO["oUSI"$;c]YhdsU82dWk'L.ic o"Wk+<:X"N)e_DdrW1_OL0#ap []DiN\JjPe"lRaZM8r4+ag'7=*4tNbea=?;2HK)6%?tD982!sdEd*VDh,gqGpD=$j;q\mq]c=r@ .\Zo+Gj"FWL(@/4[T%TQ@=!b*! )TK$!Ih8)i&iP1HbDk!G@s5A;RAKR+JPgi\Y1jK1l&5^50S?LMPUI]rfD&^6>LAf5[7MmdRNp?/!:!`3@ @m=/9C3*c'&=Jlb8^?o:`YhO-5GrBbqW0S_*:D6G'AcGjrds#LI!^7&RT9A>"[=bOJN`4oW7f^p`S^J[<(iA^7.$q0Ad9s=6-AcK4r?h`EXp9(`g59GJjHSm%LIU+)O` +05ZHsoZN=h`'"FOc:T;@_7CPD-TWFg/7UUAQl^&,_)IAt(7^3g?X"1']/&b>FMD5p%bgqDHd'+a`\*88*$BeHJt K jm.: VL)cF_=R<IK^\8Pa-)mPR,n3bNE["S8>^<&hV'B <.p0\F'E;Ze?3+C/g@2-^LPA%-Wt%Mn?%PoB[r:=U48X49Tl7jDQ-WC!LC:%#5l[3b]>e0TDkC/Kqs->A2$7HgDU\Ob=*= a(%j89@-bhMa9GMka%/')S`S0@2kgA9MS!rtX65JBEmS?h7WqqkJToGc@S^qK7S0Mi.@^WI'Lf1NZ(%hA^))K*%mlBs7VE9M tNi@9SNk4F1ah3?<`WWX!^:b("rKN1`qT&[))Pa%h#?\O?s<IT_`'M'^tB9+grJ3'/<]d&Z]O.n1A WUBlaE-n-2TDK1h+)ig8g[K <]]R4(#9fM)C<]\HCZ1YdaJjX?+K2#mGha3>2#YYOVBE#jcI7CHR__T9Qd?/Gm5[tRf8tW8U'id fS@_5?".$I9)1Ve?9J/?hL:rHa>f<>qAn`Ug?i^R=2IOYq> Q-WJa_S&]S*=VhPS`-%pWptKBhe.?IMc/G3B/#m9lI?p8e>FFpt]bT6hP,(b6o6=''.p&rYZ]niT?L(JV.1*I#qm$qGU+@1a@cLdC+IF"Af(l1J6PA(O?[RbhZIp0IFooE-%j...DOF&]^l 7J;6pC2CJ,dd[#W1cA'0Xl!nH:a24**!%kF6\S[cp!PhCgTLWWPsr9lV.r_:HUD"PWti<@6R_W)LCkM<kp0cnA> `fcTl.;1+rhbXX5^=(Ke@^b')g,WcdX]c'j)@KIc\Ng'-G1@[:J%MJ0E<*&"f3MT*$fVTQ4=:5l#pAIm+ns-,:R(0q,.ibo*21jq`5Mn5"UXX_n/J<cg6c7j82V\$H1!mlYnj7M0AA[8X#)=UG+;Qm5G=`5g4*;j6q#q/hiOATs`oLIBa.p7][34AJe_r/q,N(CUMO4Seg%:(9s:FqBnHLm;Sp^HNf%fAs6/DL@GS,=F2<lY+b+4r."IEdri4J3-e$?ZCl-W c`+sdl8-'."@;dIr>l0H53.1=>IWA?Ac3_th=HtF?p-i^VFsC]c)4E!>+AQN@@\?IH*tN:NBt$^Ab=?jj;lm;Cl[>DV.MJjpeXd19lD4k28tCO)^Zm7kZ'bOjG-Jnd"A">-m;hHB@g)p8ZW.j4k^0/k7DRD=Yn0=-PD#]%5kU@eK.\H;H59XF[(hm]qV"R@"iOA1M"]MQR5, 'c2=Ph.2sbD+HmOZAp?_c]5mOg]OM;1:$_QkaS$csUnd/)e2iN4>IN9UAJ(J 0Md^]/dB3N8"^q.j'bfCjOSs-!rCKYUj#;_o$54D,Lq3H0MB?ZCI*C6.%P>ng>EW#9h("sMP8(B4l;!oe4)'&&,Vbd;P-%VH8&q:=/e_(4#4/:nNho\*6BbMqG6)56F>gpEgZK!nEWS,T?r>,ApAKD9E lr/1E_Tk5o#XUdGYft`5194^WV[Q@;jA)Za1NOQ-a"5;LZ'YB!6RfA#sZVIf(\6B\irp/KYVa[N*8m8O(MK9+JD=m;iF4VF@`7?mhKA>bdE50AVVJ6Xt_#pgZ7,U"B#=]*?mrF3MAYRfA"- N7ZDanqj(hK3T``#mfi,0 0tGA(LbPL0k0DWJ8XS82,b+*YF;#;_&6-&Q]tFMafcfC/\r_QIdc kd0.o#^clX.E=3'B]78%oRLUbCd8Cdit^GnMsE#pR:=qV0% skgZGnOK:scEd30<*f'dem[/$!B!jSRZah// SC29rRbrk"!A.i%[!Zlg:&O6%iWnM9 8^e)K$` .G-."W,QN2rnGm(V'LEF*IUT1pmH=iC$@jp!D@&C!nDr>5FOj^N!5%Q<(jF@5<1N7^scFZ"ZpkQ=UKL`QqZH&"6Cp'(Q,H8ooqZc.\WEl1 a<GHjI%;4#!Of%KUc\T2o ,))^fP#[OhPE$(3N.hBU(Op0'?$1*B7"I)R^IA\8_G<*j6h>UR`><5 Y^l,ld/f28MJXjV&$I&T>$9g c[K"d\mc7OV#Z*Y$M?`Q(QY\,_\/@r5H \McYaaR#CV=JK(A*.LI_aRAArY?AjK+R= Pn%t'3dX&ZJ-YA9p(q')@2F:GVe9V+7j.]pdMrT QF1V:$*`@.?atU6Yi;0+;oNA_'Va0A38-sf6#YZn_J3WIfF Fsh(TE64S5-=Z/L)#J7S.Hg_oYN_e--jU2oaK=peMh`Q[$D)dI5q3tA7VDD+,?iG=f*bs])J/8;qOam0mcO$FXp4jQqN!iMM'KIE:l+He=U[8o/9/sLtd[c3oJ%:Z5hVVZ"dO1$;idosNDg,(A'F!NfeY^O!akMYg*SM??f73PL6.lfHY`r_I]-`V;.\A9j8h0*Y73ZUQkqo!Io%i*+hO.G@,/d_%'FO9dP@^D"l&Qe*-[$!^=X)tKAH$:TAK4KQ"MFTAk818%GnKgdSG]J4p\8K2ZN".1om'PN+i5)lI1lhK8ik#m3jVY'W(+!%_n*W@.KUQ+Tq0-JE -7G#gd:ARilZh9/>]0,_:kTKm!F_oHrV8Y<*]D4'tSieR&AOkf_?J'/o:qPdReU)LmpB j?;In4k?[tAOi+DZ_7&<2GMK76BM`qMUc#1#^Xi%(H1J^OkS;a/^ANh8e.=-"J.f0\P$,h"s/,sW"Oser6QcaCK[D<^:pbTZB_$q;0FT//eqJj-%KFO37,%`6kg6B%`]M?"8cte0V\*W#&WL9:5a+,-(h8`;;D*I@:ZoS%9(oJoYfGoSgUJN,N15"(I/G?G$G.t#nspAmaV4KoAIEQbi-\4R?t>Aq6kVE>3X"XFVNn;<:;]r%'p_N[pjjeJ]^W :(&NdMqg"(!'F*PoO^!\f2q!S]\Thf+s;9AI_3-SA@k>p/[Ah'WtN7=#f-+k(+p5]e\^jQB6-rDWMAb,+K0d=WmR.><:Xsg(fR\tMOkh!5'L5@BsTsGMd4A+[ZSZIp%/$aPAAc*A>I"h?d:^? G)snhb2eNC[(J8=I-e.nb2lLLQ#TVNLli@WnK`PXVI]M[ki^r0Se4?W_&9M%)\]r/0lcJD[Rl4rI2qG(_]^1,`_RJ#YA&Y3JI,eHKKG@p2##LQX.89hjBo!t_,MC;;I!TWAp>!sjf.^,+sZ=Hr%N2o+cSk.9lg1d!]4#MX6(]ReFA=!%"gqCc-MW,8#C;c=th*btBtJap]K\^+lV?\>[;Ap8<&RsH8cH`#VS^J]?gIJ5lo'9Z,GC@f,AT(>^dS2StQ+mNQm0e`6\_:)?/Wr?,_^'ea6XtD2fY3$hTp?eTdaG<+,!fsOW1-^B^4:8d++a'ra]JQkMO9V#V2@U_YWLW0L)OSU is?CXFt'5KA:p3ZY/Og!=ImOhfIR4@Ebg3AAXGh-Xkr>!!?CbmA;M$=]<'C[W.i=B+s4"RG.)DcBm(Q7PB#I2MiaYs?\VeitrGO4@U"ZWW+>5V8/C#.hP(`P.9,&S,8[6IO?BUO.oU[*OAmm("Z=4_) RX>'AjKETf+?Jt`28%7n%dnU3bRc0=>PnWVZ0_j+/a5&kI$G_=Nk"nAPVWhe0PV*tIZD&*-^]gpV0E1P4A]i,DH8j*@-@=W9'B2DTA\Q23k$K./AVc':YSZ?%dQ9[d!i58q!6$qP*J-.i5JAj1[1J_`lK\6pIhQ`;pA0'"XDL0#0oV;N[mZ)e$qTtNRZb4AGH$S(J9=ACXY)jG%^ggr@%IsTQkk:ThT`@^qJ8[]qPj8$.lmTp,H<71TW@ASeAY:q.[0mZ5N,sA;VkN=6?j$E`[SPR 3n*:ND1c1-L1KU'-WPH6QA+/E_bph'83j;eG**giUl6ASo[]7m2[^T8G6jUUd@prbCrAOVlgIU[9_chGe;^X@ T.a:+&tptA0%5-p#@#$>r5T27#jKEjFHtS15pplmSM\mO`"FsN)d2jm9KKme *OTa="`gABf'/O=2@,e19XR&<8p:1L&U,(@DBYcCGOIeD7ajB<-fbp'\V>q7n>o8fBkERO\?Q4ie#pFb eSs)QTR[pd1`-YS=Jk/9Y**^`p#YPQENmk6UU-"]E'ZP?^,L5SlthTnc2_lKd_>imUpXBVDmRbd5r2-O?G8;6=,.$CRMUdZ9RVs'oPB *U9T*&Hkf^]Rn#VHLZqlh/JJ&Y`At `hPB&TR"an*#.J0E26`+CW=[s;^?%gebsV+[^`EUZ'aFMS!NjmBc cAG=VO+]+M[1rgR-?5lOMiXm^@0X1"7j_=A& Je2mMh_>M'mat?$)l[S'YjOsH]l ek+Ls5l8 cP,=`MW@m UoEYnV^MD/A>4mN=4?S/Jf3*>f%V)B@(;A$Bf^IkcLAq-T(f]i`7i6Xf:%=0U>X[+'(ac:l7o#[Pp;;`&D+CLq:U"/k<";m/K[E/L"23TMi(bf2L6A0'D3*B1 U.-]Z3FHJ/#@9'V5A;Tah)q8)4]JBp+%7>nmhS?e79@Iq/C*J_5r@9_ZdsVc5Y/k`BkgialL8::XP*%V[cg^&Aoje_/c[ms_4\N3`Xt^(KCneo>^ogjDh,=^/RP'-=q(!%[B54UpT,ic%K+RcrXP9sKD(0/m%>ZA:s==@cAdm`aT]JIC63Q0209[%MM;9:d.`tnKqFhg,3(YO4]4 =@&[?%6VWTA+K=A%`S/[jRA/rCA3#BBhAdn D8p'l/W+tiilb;=^'\GRM(8b"I.[?*VF,+%1"_#J8mL7EYJ#1T%Y3G?K^57Xmk(TQ/&Ajl6^mhsR0CB12Q@$(tBiE0YB)Uk;A@'tJYCab76t1Q9Ta*0f!AdV!5!3%;K!b<,N&mO%TdK 4bOOfn;m`I_/:nHcOq]Uc:3ljjJQop8strF,cY'Z?ME[`ps[+adMHJ2A:?)ffMG@OHf6*,W(kDNM:P&#"f=)e3h%4^]f=0T]1+bapD=A60M&l'b^4HU\la-I-j<`A_"/V#h6r)_Ti8b)KG.K>6ECdLQL;d`VeFI`8=)`Qh0ejFQjJckrf,><6bBmIUJ+rZ MAs)AJ'*[qSIC_e=K*1P0G.nW_A]c%)H*HR.-.g-oO7C N+Ie%aZ]_fDW]:S.9TZcXq3*ih*a)U6k)iqoXs\"*dp#U&eM%A6mVd2[bp&`r$'^UEi&jSsWU,OjYX4r9$AG*r^Db71Ul1M9m8g6+s) CaaTI`9#b)U1AOY3ALhtA#q\_+]PE2TiW'6aZD\HdkD)/Up.d++A%I^#fGKAW]>CtGt@A.Qj%UKZZHNnXer;a(&?Bq,]W*ot]P9e%iZ@]lXcdPU(h#TA7HGT.E8R(h;EB9JT15I]q)XtH'h[0IjLYE=/RFFlcVS)&GK"[Ag`+GcdI?tTD,_XG..XfWAl)gT)7dOFFs3jC#ctjk"2lpNM!Ui0$5H@ja;XZXDT\FMh-m ^D%AIc;N5A.j%o%"a>#'h:kjq-Al`V\]Ih H>:F1hd,tSoPac]sc\'j:4\Zfo<-%foa.F%XN@]ZYm+SIFi3f2)prdB/c$U1)["WitMkFS5N?=b.\XXf4D@[A\\jpg8iNkRCch?pB@R3$:G!X'O%-B!HRanglMWA#5eaF2;a 2TCs_>cEXqFAo7-<l$ ?4krlJ/q]K\Y)j_$AdU"3'P`AblRql9t06f8(bRC&*:[#E5c6cnNWAQgS7aSnn1X7rNM<c-tV+Hpd`MN$R!AL": =LdPZ[D5mg=%sD"TdL)m;AaQ7P_-9A2s[.'TnY'6"C6aFL!a"G][8>&Z0U1iOHNSG BShrT+_I.=P0:S]oA[]6&,W.`4_+#j5G7Qk+67og`SA8X5RB1)K9WG\go0C_ao<m$^:m[JAA4RiVWn_V`c/am _]F#-;K^ HV\QBI4UD()0+e>N-2sI8bQ*>P_NM#%ie,fA31lW[sYn)Z-r#>4lA[C@Spt9bG0YQt_;1$V%O\-Srhr6H?jM\GX"KX!CpVK,)Z)Sa/YB6&^i4TpU\FNZUgPQ#`l5jnK]-.A*l<](I1T)M mQ[TM\;AdEF-n'*f[o&=$SD`oD#*7Kg#R?0'N=FomX:N"m$rM H*_2X1o,RRolm1@Pe05A)X[3Asq<ig!'gbhLPd`1t_,eA^O9R] jl+a=jlE$g+k<"$lm]FUTi`RPZ?3BUU8A.F0lelo#drgnH2oJ -dd6*>n$r0RHNDAfC`JoA!e*.E]NQWh.O8CAM_Yk%s0aaP22;=30;9p`,liM"tl\@(q9K\<%V!ifKFoh0>QWs)RDAA=Ra\o]GE"3"T[2iC$PL_ M, TFR<0G%iR[j=4EJLZ:iHnSsAGCQF;-gd"'f^PI3s!WP[gbp\p2Kg],fl(NBF,k;l[bE'27W%cKWL(J,8RH^PLqi5d[&W%Y5iU.IH5\6PfP"-2htG-L#W8b^"J%'XB6nV:Yk7'bE`sp[^i"l@kZ@\*T0jnA4(]_pf=R^SYRG+EFQe[V&iW3OMp!VRghd)Je+^<VM5=f^)qNs3.KDRBCM#6gJL?:(e1@M\U.&R2AJtbdNO&9 [\-T"p$+PLQ$Bco QOiA;o;N'HA`eAV+654S[o4[>]AjcN/g'VJHS9Ltn7b7*kF5\\`rkP@ChHLh"]W8!;V8C)&^%qLE?Mq88IHbJ-eA$;+qOaB@4kCGY;O=d8\.oRU%s[]O?\D\0JO98 L`imB\!#rHo0]i+02k9"4#)5:% A&9Q:,;sDZk0[o(GVlI*T-W[-G#J+-@r!,AF3NG6OhUcK-hXd(##J85GUGZp0Zi"9_Pj4^e])>UC3I8T+Hol=BE ([Y24p[<]CUcnR-,G=hO3WH`WDo]5;`=EGi3^d7aj#G.r2kEP6S];>ab[<d%03jh2X1\'!2D'sl/*+oZ8;&\"VXrI);dL\(c?1; Qp]/?g?:.b8%J!N`31"B>Or&U"dHHk-+.`=27f%IT+#r:$0SfoeZ%p7[4RG!3GTUmO/JVKYm=5aC$WQ!X^@"9li>0s2qj)2G,AZ6%F&N#lHlaA (B5r5U5*TX\LJGd1!hOV`]YpD)_>[i*T,(*_oi*"b6a-am,)Y"nK:-T#Eq"-l>R9TSU310G8h?gm$[7DgXt4B2i7fB+IEWi`Hi<^lRseL7U>f@*+N_hAsH)J>f?[B$(-,E*58/44`l%/9]6c,Kj)TfCDaNAROGXnlUaN=WIt_!Y9b5@@?@57K-68'\0[`cnBG.YRD@coGCTG*&ChORm*2%a"<'0s7TKC!hp_`.A2Vi,d*)Zd Iq6QK^KSO9[n`[soc&tHMWD`s=K]1h ?BbJ?pH.n>A%CIWKNsboRXU"/p%Ma"iVi`mA V'R)b^e^Ge!iqH`dqTs@a6\7EA(lWKVHW^,,2o5@moD^Q4\GN9YPjq7K4e`AadDQL-R]3/b89]MJ9jf7*2#m>=*RW&Dg1`A)dAjA`^&]^,OV.iYWHliSEStGtBgt71qQY86*KcG453U//XH5:'^R0<[=9h(IsMdA)$%L(R'mAW5BRHkMP\5dm.:"J?0]+b+=Eta#\XFb9VpAZU6;?1S^VLWq$\!V=./:2\+lnHEC=.oMSj/E72a7[kE1ZM$ h;m1=lfT#32?VZoCDnK?EAA*MJ%MGB_l\<&/P:3%Me(rQ3N&'@,b@>KGk`4D^h)Fl$DmI>L:J>^1"MYHK.o^!_]!qj(Z[=!'3S._MeE1GdPrI#i^#jGq4"h\DZ,?i?jdXMcI\MtsT1:(PG8#?DM?Zse)Gi1OC1W:d`69"akP7!>:PcQc64aGhpcnC/A+d/nn@fQsG3D@9+i"GP?G9[f.3W!RACAqVrdn!k/VWJSfoh;f5C!H:a,M@n\7_]oT *>nDGh*r@N?2;9"6cV0-.e4](:FDEas<%>X fle&l=!C,q;6dNIU`;?C#[p9*d+'LN_aX;a.e2PGRkcVPFIk3X*q qM`"jRY?>#E]"-`YLK[C:QTa/,8p=1J7_rZl7XX-\rlM0;$HGfZSt;_Pd/DPlGJ+E*aaO!X['htANedI)<'j+s!KKh@q #VO!HT3m\SF$Bt36o@0tc-ZYFs?VnN2)D,?Nf^['h4m#0;OLSfOA/dcHiX#L8b4dnDs-nV_btDU6gJ+[C%Q!&9kL^.Xh?JrO7jiCTc^3d@;\$,t,+JQOjjf^FUj+*m+*A4]??RgFBWlA]bs/CcX49ejPb08lN]h)>=g_C9`9sY'g+e3;A7At.1j@>4gM^Tk0S]E=;r1Q*p)8ira/O:I+9/_QiRc.\R<,PDD_lGKK4ff**n2A@HK=&?4IUAk2-S-[E E`JepsjP*B-$@`KaMlrHo]6i-PBP]%i]$/FKR=$>-Nj9,m.RmT8H&h.Y5o,Y4)8.MPWLmnRC$A.D0pd>3C_sB(-p%7orENVmP6Q2kd*SPg?M+GB-RBH0'JU%NVt-qg%>-A-Xk'!V2sEXF*"<2[:htt#e L*[AMYK3B$ .lH-Pk85-mqpcW.2o$jlf9>%UCd%E2(O6)#kR1,1K6OPDV1[2$&)bJeFc/R@(2Vr5Ko==WmK80+s(4>Il.0SE XX= )-[W"=@BNT//C4EGCWVSGo5/iZKJ@$A2:5Z:02L1eR-1Fdh[ljahX"+-XaD&c2`=eod1g"_l_mIK,kVP!.1^7J3\YR%G0Qjr9N/]hgAdC3@bE$hb`$[A:f+Bp1rYU6TH0!KcnRN4( r9 ][nqNnS[brTD(`CEkeoLoKAZ-Bn227d-k/%$i?aU2kD`I!Cjg& 'H-/o"E'7bdaY1gL6bpAefnAqJabJZfnQ"^G@%SV)S.4 t>>rrdNp7f5?Rb@EmA6_q@(%OCd^_]SDsbgf+C488AFd%Kn@dmQ9D\8P9dW\^/+g-;_?fDr) qb#AY+T"R^]JkF-n8IP7o:;Q7W=4s&A8?IKrn0U9URPPf0Mj7^q'AL^<(D0:UsbP>HO>&N6@J1`s,&^j/Gi@^#i+YjnEf>G&!)dohal(\&Y^d\Z0_+LC$c6OFV>iPn9WCd`?eM:-Ahk[#"daffELAi^sAqbgKAf9q-+=^V#4:WJa#fI5rFrU'BM:a?b-&_-j&[T;,0KH,!:poUkAORn6L-U9VsCX9r<25r9g\hltAV79W%b'k2WC"'E6H*:EA A!V1`PnSba\kVrr'AVShRN[''U60+%2)kll<+f8+MefEDtmsXgB^;_O5A6cG5j8GpWVs#bGp(;;[oNB9tD,/D3[pcJ.@+@=n\F*l!CHa%KW@(&@0>=(W%mOj+"?og>4b;3Yl]ocT0Nr'C_o< P':8(\3.Lcs9NB8*WPk,3.[_29,Wpt `+h%:0\]?>$5s56aeiS;7;tHIgZ`5j_WONE,e`gJPR^88K+b VMQ jWI%]mc)3]1tOt5\/?;TM`=$D# d"#pfLjUn"Ns=:RX?gObQa2a[i2g&<^(jG.ZQ]>rJcqWpPjlA#EYif^<&.pAl\3=H05lr.=K'@dWb@AWZD .""MQ7dsXcE^g0t9(:TYUlHjY>DB6DgGP>'9[$](VBh&a 0t&@Uf1B9Bq4ef$]sPI'S'"=ef&b\/j'HAM"s1tPkh-^'GV4j"f5sAl%WCp[Y)9HJWC]@VNTf:o+'5_L5 =R[Y50##nJhCEX 4(!G#<9A?oi$pq`Pl&`lPWVAMrBDYaVam"L70VbSbACEAi-;]WP )>Rp4ep.3Ap&QF2Q[C!LI6WM4a*f)62!>29VZ6NG]7F)M'%H@Mjoq#H^+.XZtnV'Fp4H#Cp?055[?AK3LIt#_if_"9msn[+Z V##)Vq\/_>kM%I.,h=WA4[f+Ds:SVRAoHdn!o:CS;ejT"?@k-Qj*2!#eXpm>9RN&JS$Vn6kq%iOQ-g%Cof=`\A']IGVV%0O O7"qqeBtJ)Ula4Mm*86#QQ\TmkR/!J2G'?6e`)6RVq5%*ItWq)P:5pC#X!:K^# 3 E-"eF@s5X9=$AZgJ>>YfZ.iq_C1t^JgZ.4D0]^88G[gsRo+=^/8d3e/(lr ?n4_4EL&%VX Sr$$S]@@d3SfX:\!>FphR;%P$R;TX>\$q=%mafk\@Z(C]/UZnI9R"P%@0U^_pf`opkp8.>?ZE/c&FVqlGBdYsj*S!Dq^8!K1?%mR:g:PCNqagL8hS"T(l[ ^<\J&9ZN%Q!AtVKS;DDkbboAKT'nkBqa!Q90#LJR;..-te=aabVt@40KFBr8h/T`Zr"A-P\1`84Xq\fCl:USe'(eR>dblk.#l^YIH,*rbK4(Ws,:?Gp@d#W0_+.,2aiK5trRDn`KO(+4kemO.lJ?g^bOsWG%D^P5NP*$nf7kFG@%0W]MlP*3.$TO^l 9;i'p#OMAKdl/rKO+jU3F!JBFdg!qXAl,&sR<'o]*p7V[A\k[YNQDr@"oct>!h8eIH.QU5'6L]Vpe*-0XUhJ,5aAkK:6]UlBLMtm5--at 3PA/YT@^D9!E;%cUR(ec5*-SHVfBA]86_b$]gT@ FOG!kf!mUmpI5A\lH,^sN- \%?.W&ReT]TN*jJ;3!Z7GWRW'[\]=Sf%A\GK$6,s#'Hr_ME8DKc,HiE*H@0f*_TC(8^'qCZrbh#.`50hC]9A!oK-Ie?]f^gZD)'sC\JEmKPK]1&6U:A<A=HOlI)9?$ErSj8$\)6.14Xla@eN,lj5+Y;g@A,=V\l7$h&BI];RMK6(__^n\[Z6rLKo`oO\q-p/$q%AqSEB-X"A=:AlDR1lKCHVl.Cgn`4?5C2iS>&g)d"GQDg4PJ,1.ADoP36IMsso$*m!@4"Geh>QM@e]Xd-I"C)D=`:$5An$4sle" +\s/k".M#dG 3T/,,LipcSZYU%c_T&O_/HrO+U,IA.$a+=U GBt4BgpPB`!Fj6< &#:5M<??Qr .T[`"[Ag"O^2!9 DWIQp_/7B.t6+aA/W9DZ($JcYDAf+Ne@iLs\;P`/>C'e0o,0](Clf:Dfg@-F"`ig:*Fr%>HIQ#V/?,t5H4B<Qs^A[l%88+d<$'aMa5Cm.fD9:A=LAHbpA3^M%5=rcnMAA$pCANJ0qYil1jG,8IPA/4.,b/JX#nhUbM%Ynn6S1]*=`pO^q_dlCh7ledKj1HfCU8$"sA=<\K=qKAfEX5+*?liR$rUBh"W`p8m(**5--fCj?,18QS"?h5^iaMZZI'V_qC#JPCr.`&0Q=n8LmNemp1Z32eBO;EACRQWaIaj0(]8dalOb@!NV2!tkfsC?+)\'f783/-1Yn4lV7c*A2Al9*8:;(^JSd#W69%p$jqQKJs8L,fAaCLsOPT5=;+2Sq%VmEA<1h#6J-KpU$0A-aA: $a'NV]oQkk^(f?eAnQV&tVO&a9p)A2Vf.ata,FqU]$KsTf']49JId2t'R"j7jO^$A;?9:0HiEii(OrTP'Wc_G#2W[Z^L2AieEf%=k&&-a0f..E8?2gh7=S^-JY'KkHm;ABpb1&)@lZ!eQ*!QXs0.qnTHkkO/Vi?pGje3%^0`EVcan>G`Xi XZ>kheR`oFNGZ'#pRA4:^2)Y).tsO%g\YYK#n/sA2gO*?MZLNpFXVcY@R;S:X3;9hHgF"N_JDmYCE,=lPY+"&qkIgr@t!!d?I5bMd^Jg2 IVIA=FRRat.b16dEc7l-V\7^Om3 LQd0I,tsa@fG\sOMF%P-K56+\82XDJ445em!")a.*49s@>W6`j)>]E$[5h+b`-ji*Q! gCZ01k%VIBlCt']*a&1 MUSJ4H+AH(BYE&B$7JT/TLbqtY9%K,r)Bt>XRsk[l]^9G?4p&N2.5J)4#k''Mq(1/FnAeCZrKqWASh/Te^'+p>)O\4rL[hY)F-Y+X,,@"#J2m:a@\Wp-]VbfRRl^$tA\!)('E-KC*[K27;KbY#$*l")_lb'NtU:GX%n=[BX`.$6RN5[["/$pA^,H5/*/;WF/H.D'As+N+/6.YYhfjX-a1Cq&?6I48OVR*"tDZ=#p\&cDnbnP6Qe\tN6C_Wt2f@ATsR8]9[0#s*IUI>gA^be#nKI`4fl-]%0qXQ_VM1Q=bY1hn*,3UIBIMOF 3@QLV' )F>H>lfHZs[P[B#bRK_f&d-5_d)Lj\*Z\Q+aI#U)]D9TN'&!pG=<8KScpJ'WjU?^5&-EaU$aU5AK)E5eCIO[TKt[&WPomg8`m=S5j9lUKB$`i GK5+qcW/>$FKQ:_rTG6K,#%PWP qM4f'E^ r;<_\Ja4/2Bo%a:f>)Z`X?)]0.V-<-=fkPIe$tRoPdI1M;;d0&1W5T$^dWVn!CX&]b8@:_AbB1c_V+,_:NtkthMM6m#Lh/PR?VEqb&lrCXFC`O!6+`Ce^5Z$s83MeK2`Ho_.jo\25P7ghe3XQb.3bfF&+?#sGeBp,?"*KNh\1XUqdn>j?V*Jm87r%U+ZCAgeF>\(9SPU@GI<<,C_j$QjT>J3k +9`RcbX bL!&*U5Il$PjL&^W>:$=FcVZ'qg-8VGg17-o1"B:B@iI$$'h:F$5#We1rS,^onIE?S/@%_gc2oC_ AG-MnMZ b[i ,-#BG_Z/jh0;ebCkqCQef8UO"$M1cW O"Li;97/9?Z1bH8MaXEi;3aAC4-2dLtfU@_=>R:[Plg8NkJF<4,dXk\WOq)tSP=T^)b#G+18Emjt.eHFst,G`]Xa(GBJ=5;"/>;/=&* +'/3`Ag kI-[i*Z/T2#ZK'>7PaVO,kW[20(nU+(BqGB@AaZ<4:YdG6jUAXB0CVteK!7Tn0Ai&rq_J4>O>siC:?#FqO6n,NY\_;SElXKtLD7WQ+*/J_Q19*]D"H(nP4,IA)p(M\X`or6MdT?RU5d-Mg8ZU)FIn4Jn4A-AF[mQ`f.a`;j[AgZL>3$<:jcnWk/!+Jajgf<F!&Ap:Hl \PE$KX,Jd,bnNr<$>:;p3reF6!Y!$f`&68$COR <["a*O2dkf]hWRNjKkl2K/Ts+m=@TjE2%^/R8ST4?+*cSY`M-+`dNhd+Yn3d9GV_lTP/3#^LKM!h-j#0A-QJ98d8(DL]Zjm?',U=+O5e_$8E)ikIY\Fbc[PLVco8:NYq/dIE`bYm)0@7Y+[DtHrlTd[B?.TYG02neN7s=fF#HrcdSe#B'R\a(X%hKTUN>-Gl]VnX-i)cVVI4'TRSP-X3Y<7,K[KAqoOIWbhWD18$\*^h P]LL4s7*KdbJcX5HSOLjEJ:DY&SA,nZ]\\b&^r41nPIoQ(83k<:K^]oW940AVfHYIb`GW2,C.G9X*tPI;G+RrZ^c65Ar0lp3Ah8Pc2CAgZr=9DBe8X8JmT;7*%Hkb9tWg;Za)Lj(VUX.>9/XbC>GrRHqtJMLA,,Sc7X:<,SPAVF]iC?=7CX3(;Vq es8I8Yjb[(mkYc%"+j!hTkP_c+_K9"KLjHo_2)$^;:;G;B@`!$Q6(W0G Ajb%tsAI'YWIFM;gE2;05=$db5GT#s4i9)bp//Q*GT?EknHAdeND;ABONA]*fV&3'-.@ae oWH0dCS[?5DK!gqA-b)I7!6-&ND<'@i ``I/YqMqY-6d$QCGOR-IiDk93Mbrcrl4K9/mK*5MP>AQZ/m6_EEti,m"A3X [fY0f"(g'ZQgE+@-OBg]=U CN"=?1m5\=&h0C2G3t-a.Zs5i-PaF1;QnAAZHeio-9sq9\UJ6Gj =W^(rnNgok]mS>Fl3Nb##)6#&DVWKP=+U3CWfV ;?<?<+cZSpd-+3V6o"!j]p53_b3KQUP0G;72`'5_ipWF59>/k\S*EjnOe,Ep=WhR9ABBiWS-%?F.6NQq>n#6k<*H`8U^B88+:-<(^=T,5qAp.OW%i5ncXA'[#2@72_tArB3s?'6=^faQ[ak/XQ*bqmJQ`C6SLM'E8i^Cl`bp!c^f,_5=t)o;\G*0(U/"m:)1qC+JUdt02caN)oS(WtK$=pB/A%qC6:Y`Y4E[UK5KTG47mePiqFRacGX9,ps\M1sK%@r@S,9fV((ond[)ZL8@.PR_o+2U"J[IADF 3!5sF9>UJIpQn830RX2VfpQ@Nomt_h]R0#pa?lXDjhQ/ZqWjnC2T-5bNF 0E'L#-.t+bNE!:U_W/4Vr?Up<\Kj&/K.p@Zh%PAtdXJNA@F Yp4D55m\p]-[/G2PUo5>haQq/^^Yhl*Tn?Fad=jp,=Xrd_eN&0?8G`n%8X_Eq98n8O$hY=\M,[@n$b32JEBA(9=-AcX'H3BX3\Xs0U'9m\EVs[(4)&$9AkXc:(]HX.dL"Kq_mb^2O"nJ_A/EbFNXT9"pqsZ!FCDZ5sg%jm2fIf2A:_A23WTjS^?P5ei0iq)a/#:jV8C7-r;SP>M\c_coqI`W3ripm6No[M0W+jtcAZsPS+)BdFVh>#lZ7De 'ora7XVAS@cAC?CCs35JjCXb9'!AJ-D#2U;MO](q] ?jhTskl#V9O-gZL6!ad&b95Qs-UG5hNWd%a%C5B;Sq;;"A'P^0mJ]F`SfkP2aQ_-@BpC@TBV#DdfO7asSY'!De! ]IT$lSo-c;qS"Vle^I:k(Oc+Y4DD jQrFXATEUlm-3&3Za]Fg<05T&^!YLcL%<))1A&>1N.YT/D+):#!go-,+31P"MC;k0Y'p.<;CoJGo+a@4("!pX=?Y"$0E1Y"%UAZo2_]&KiNjH@*PKmTY@7I$_a)$1cP;OVU>I/$tG3RJ02Hq`X^c\_EMCX8Z4#q,'HF/B&KiY"IQ&p+$@:i )1)3/D"*m=2MHX\CX;mQ+]((C]`%$A*c.L+37:A!@A\66Fih9VRW5dQD?1'"t;fq3.lrYB@R>7Mc>mpp>g_DZ$Y P@VE)Kr.WAjScRpf:d+af_S39#79BfE00ct?DraP:=\l3hNQ9H9>3_Aq!lD^-ta3GZ\W;Aa7l&s`q1?"F\JOpAR&XW!QR\(AB[ X(t34Rf;1X6_%d4-20)=!4!TO8I.&#nl/#.P\CAYeHJr'c$b5EJio^a:e%m4tqZ$3H?%5r)E$$5q98rtU2-QbqXsLmFA`q7AjqOIK&X19N#beR,]q1>^?(Y*8rMhthFT1qsjsTCGFJ6BPpJCVZlWC>hpKt ljt#+1DDZGV@eci,19LnK]j1sA!g>f9G>&rDQVA7m#Y8a6;1q8f:3Gk(VAc8gKXh"f.YXb0(H4mc%#?sCOh#jX!/Qa^c]5@*NsC0.;WIMJ2l W/h2FWr'Vq),Jqd:Zi$:!eDaC'k;qG$1>?Fiq_hSJd."BEJFU!QIQ4TMd%A"5rD-*WAmR_BF;866s-s&Ns'D)fQKWrp%9Vq27(fZrjKA;3"NWDl_]WD+_Ji?lY"D%LRZD*7m+:(0UqS`3WA:;AG=rKUii]qJH[$+Cm2c;?te5#YeIjm@V@(E$U0XQ^-Tq/*V*@hniBiK$M&"3T1]hV3""q@-^7d+D! Ai5D;=k_t]Coa&&4UesRq(3!S5XQB"j`0B`VIhBt&O9q+YUUn1f'1GdoKk"H$&[A:bst\+V%FX1,,]m>k%b!ZY!]mk6Aq0aKQfmbA?`-"@&_si2ig^KnJA2i4)5RR.m[1C?IlAj6X cQl5)OGp`SE>4&=%)ofQ;O9.0r=.pcm)HY*AMC86%"g`2_Ac2n\?AbA^p]!,HKj>g5scI[8cL<f/$?!+5iQVL'_^D6WMXg6fE\ImXTjY2pN.aH-Q0A=/SNO'$F6%#B/;AgcWY%cP?14a`l=2BoFZk<`2R# 9snT;^9-*N3BG"rq q#R;K<`"eb+`<"ie:@sA:89MVQ8N4>2 9\UKt':KMRV7!>j*Hs++aWcJOOSg5'QcFV%E7"_I`k^G:Rj"rH.42PQ1fF00L`f#pJsroLXFr._M2]-J] ]gPaAi#BA7M8iB1e5P-FSl4j!GTk'*U3PnPZ)lQrQ\Z:EUS:9i3G87PB. GMM?=jr]=D4BWeWWtd.Zp$1AbeSIAr-+-GJDZr)g: k4EOKl8g?EMYqAmK0U&N7ogmHC!A,]kGG<>!qThP`+3n7Htdn9$#*WKPDe"Z@7?MH$6AiiS[RMsq+$2f-3:U7N"X"(1I?\="i]1(-JmY%Z/4%)^AMdk/n%=`%Nom@Nd13#(YD`(k0FJrFiI:a.F4#N]U2WcD@rkT!G:^k3t4DC'Rm8C]L`ND$q]WYe[5$m[4H(%CBe7.;,t+ArTW!=lTKmjn!i=_4#BdX(ds1#1Gok3GC;DcO5WF:7@BT7[Cqgo> B04p'1LQYEYR50PSsAE@1hi(*fjocJ@L),e>[3AC:_ )0G))l6p?05M\n178XlA#h^lpG)>\]DS^_D&mULnqgJJ:2^$AVa_lIFh^dkAPo[gt?C'B+H>,1`_gboi-M* 5 30GeG$5B*s:l:O(ZBeUt!.o#'^86\%Vjdb!0tQj5Y,IJ"(qUD(Apj-s3[2I]fM41Wj/#c@?HrT+J=/WlpU\>GUj]so=jIqEV5BA13AD"d#8hl[#^2siAb'[&!F_(fRH&%h@NAm3,>XE4&O4>f6IP\6%nTrb De@EYF,/Wbs3%@p@E$YHQE&Y`Y_D)g2@'/$4]p/Q#N)$XnatM:<:HrPg6&F7doN,Nen+bHtE4lJN&QT9fl^P>W3j&Y&Q!kra_M9[192YW>R`!U^!AS^62KE;=[AVrPK:i^_9] A)mU%SMngF]GZ D-Y+5S@HbHp'X^@*/V@QcU*>iA1dgK e<""`R^YY^):rZ!#9#=ApYQo.EkJ4.*EXcjqmS*:kQD6gYdi$.HBnsCni^5rq+SY\0hC=:t:UH,Ns9+V&k,Wt$DpSF!3HfAM^fI+-A*"9!=G^+hL9R@4XRG3S21VGfZ5a c!(:r+c7iel3(ZAIbQR>L1BsVnn3L :/Blg))[-&h`&IR6YGFCXBKV&G0)@AGTW7QY'$XC0/U<(W&*1R'&Ynk*A8Gnl]3j20ReM1';6T_BK*9h@bB k83;"nq%n]FqqBQp'?QD4>6oSb[4dm.:+@YRTFMABYW3eI.@<D@,'o##hVAP?B*kMl@cY+AshCHMM4UClWn#O4tpgtU1a*"5 cJ_Zt8E9640;C9AkBabe.0nZ%VYBYF8;kl`9^^`aF7Hg''q#]bcXKV#_@pj:)Pla@+ +!6A*no]^?$V8($RlJc]jXWj6]=9M61r*f;btbBT*(N5Fl<[ON+'4#X'hsGeGWpML5&6XAIGWjsRs]B]8'IU#-m$7i-RQ2HA)MqNU?/b_KnsYSD7=8>[d.)*SQs^K/"+n1Qe2B`R/+oK/3Yb@C.1O,>kG9d%=D8A2'aG6Ln-P7nrtoBE_;t$aA#OSj/#dJc=[X9D#^-#i1:\rjR3A*5aZC"2"bQ$otgkEkES\MoU%*H'/i;T:`f(n8:\;"NGRgBQA<.Z@,7a3R=;gZA9MAV6!KOH:=tKWJn)fdoSC=ttJ*N,B5E'_L1?Wdl-M]bGpf@J6'[gRU,Y#edf=T[($O:22\4Mo(Zn1E85:6lg4+"%K3`PtR9*R$tlCJ7FJ,bcbd^T_N/nA!7*QO\0t7JPSrlf:-Tn=q`S7WXG1;7d!N7a5<_6Ul`M_eTE0eZbfb0%E2])7@P3hIDkf\S>#i$Z*[p5>s@ZV9\q=n_O/Y)G;*^S>?/NXM"t$M@t'am*M92] \VEX]^G_XTfDKL4\tA\Ls)J;%:1E%A@8d>&[Am,:Ke\'8kZ$=(+K[s)R]rj2X'!ID"#VO.>Zh?L"0o-=pY^!=BRMA5g#ZK8-/:ab3:mo/F6tL-jb-N)At;%VA["R. _o/Wb#;5C_(NbF1F"G4N(oh`^$18bA8aL`8[>38W#c6t/dcEkQUoZ0+S;LS;G]a\>"QKCsKT4pG6dTVg@kPTZ6F$&*/p[c+n,XeFd6YiaE 'a'n;C@t".Bt*Z?Tb8A`2sErW0CXD:rQ&B?]Ys)+`St-2ikC#DD5$!LORR*jHj^^eWiQV9GF*EYnr.:RT<+^oe^,DR XQbpF\JalQlP2%"%Q9U(?XX&ER:`cSLl9-%78O7Ol3BJ")P![X?J?))$2T+395?;[A5/<4kqm<(tKhPGf*D.O2$-J4t2p%5OFiQ8Y^1#b,5gNYWsb"e/t[`JqnF(*D+5aD2!_"bGEcQe1V+>BARj*J:t*MR3.\WiSNg8BP53,knAVNm3:pD)pAh.JmTnC$A1pZ_$9VOs^[n26PgFb5g2 WWr1^#5TJ)F,2=R%KSp2J!)?Q_b$s9/?lNTAr4kb:/Zq'/%o%K>Kt1$=L5Nroj9_[3;.;+ld=j/a0kq.LE!Nfn?[EN!1@:GsOElhN0=qVR=ik0I<"r/m^ZVk]3.Ee_3;aACWCV<;0thiq]hCj\^3/eC*8Y^$RKh7^lBMQR40A/7P8Ap>4P).gUKPe2XD,f7pAV:aL^d,Un`am8iJ"+o;p7<(VIN"&q#g's^eQ1lj<G?q597IW]g4! F=<7I5A[,H@5GlLT"4dslHt[^Bl=0fT\3sY Bs",^K.Tdcj1H#Mfb\@cb33pkjI<'\dAk(se592g-ja-6Qj^(PgBUL"iSGhm/-rs1eaG2meF%8i7K0besQKi_?L@54>k&LhTHR!F<92ZQDZg0"GKS&9^eE]$7-fad7aLC=2]h.4IT'`XR(_s&#NEptr_h5^>5[2Ff@O[gNZ?\Pe5k/AO?MlfOmHL&jk`ei$r9hArAXg."tEV1+1F^e6WeTS`MjTM4;/SpUt,0&O+V'41Mr%%ZI^t#gk]<]Q[Epr$VD^00[rP5lA'OdjbU;R1FO&*#)e _"N/8KCEOi)QAWFl;47_k<[$PA0RR c)HAB52JL<.+TLp,!2sJ;,UGVk&L#ii!4V\mibWR3Kr6hp5;e0>]d.XHrKMg2*#IWT@6#f$JR>W6U#BnqeJC.iTePg9A?TE>cfs1Ip_N#L$s`X9aJN\Y^,2CTllW%8#r@MdsB^@7&MEfCMpFW0Ze#2!:S0Xm< +S]6lCPk9L%AFM$<.l:V5hF+eXAt]i>%)C8:VA&QY]q]Wg[;@G21#mO*5"3ACRjDO24Iq6pf8e,L_JWU )8_'+&O[Li'IJ#<&(IUnHnhP=7q)kf`2lX4m;fFq0!>)p9k+]a2 c*:'^,>BWlUD^W-63A_O&[X]Zkp\da)r !WRk#[j2H)N^4Ss>k3lVpgiLM&iSe\L4Tt"oO>s=Np)UqfAY/>LPQ[r0L=?5lMWFS03H,XM2J, VN,%O5&2@msR\m<(%sDJDPAT,`BL%sk@a9.sq7*]A;n5iHY^?&ail;J?0**s.^'C].*sAKEn4[D\Qg.gSg>jXFfX!%6AhFBt@mM<^8jOr#Ni6#U:icok"'d!r>k(=E*5sQkX?^<^-4R)X:!a%RCGU83k"P*:eNCCBfLjtA],k&+;oKc D+`slC\c.m8?LVsKJ*2Jc@%FC9Ql1*o%>!2hFqnKD0cUh/Ap(_4a!AYA(gf6?;L0"H0R#AM(Lr6%q@A#qfDo8CaZppKbk:H,UJepP'L" V2pLY@eNG`;m!OQIE!^?RABSLA_pb.FbkNoA%m_'F+;^&AfA@m]<*J?*!$NPKr-=Ze%kRU\gkn^gDsB0_?mk`QFsHcpJt3n;A`.0.5)5Y8NttXQ;]LW G7 b_3,XhdYA0Ak1Go[1j0K!-rC7X+1o;;U<UF+c]GFkWifp/XqsRTQI5PeL_1`b2]?(gs4b2PIBj8H$Yf?mq1fBcB3W8^#d90a2jCkkW&].9Dpt*)&3`=L_`i0UsGc8JEBe[HKqWJ?da9A)*hm%Mg!ajr[tm_V\/PK"A)4?>*9iOWE,C*tkLVZ^U-olaeOWM?hkQ2mFLlOfV5Zqt16o&,C;<p\4sI.a3-1n%"O%;]?@&&Kkb'do] r,Who/hQU<`Jt ^N0?d)pHl2h+,,m3o7\4k/3]4f78Y(=N"JRm0V1U``6Y&rBfgfp?'FG!bIFZ"_GefA#O.b>(LlZbfmbX N0q/c[@WlhTsEsWG&2CO=@@EFWdL0sAsk99o## L;[f4-*IE>7;%X+:A@F(=-U6o>nQ<#./LV7FPb1q!6aROsa[[\@I_F:/<2(7^TAL&8@Zo0ZcR.YO<+'cniABAE'>O:"iq<j/-P-VV8+7JALk;f>^=5NB-'3375YdeL hRCPe7UQXLT*bcA[13a"@.TWjViKS^rVT.L.`-o iS$!Mq?+K,Q1Y %%94)m#8g*i QMdVkn5X*1=`$&8jNs?/isc=b,*SAmYT/^MWA]"@SM(*Je7G;7QtkMfCo416#Pl:.*NkfSc]T5J;)!ff0m&q]`7,nC`bMbpUn\)o7=LTfP-c%mTPhm:?*![U*"5((V?8,FC"$3JL]7n`.>D$AjCl?Y/E%%C,+s7\Ee&Ch]^ m-tmoYADoQX6Vj>df&lXVCc?cSBbdCXEVaI-2;72PVG b$RB*iBT]\O!)tOH&fTbp&LMY bAB$3,m$SO;@Y>&>"SqE=%gLQKq@9A<%'_f6r-9V]`eC,9`!"6cEn:@e*W%tI Oh?Y[j9Hj#"t@.#K5tC<rGR=lk;8)rk]BpIS(8MCRU1c<=oq%&ra-'kPVc(PdFK5,ES"@(_I*)8\"M7q^EeWflUAVCDN\M'MJsTZi+kXPX)43T$.aW)-s<:#o8*Hq0MD1=8B23Sj:>J]qVVVN #A0/A#CMrgb2'slW>-"Wr4Dog[$-j]eo"P=Q-cEVCE.4_/'QR8rT+8=8T2h,A@'N/\NL8[.2K0T\;OS A?(AS&o2:S_TK+b`G:bm:e$N)[G=# ,@;\KF:R$&`D];41=E9aA)c b[Ks+K9l,3r>lZ%LBs`(AciUpF;A*$"^Nt-i,F6d22+Qmrk9@s 37'LPk3-dHad;Efkq$nJnleeLA$YIASX_A2)bq15M'1l@W@=7Y&`bqfWO,.6p/pj2^8/=C._bId'"Td*Slpmo9JY\@Fj7L"(YN!jAON2CAtF`:rDtL9b3JQ7\ZmWZ1LnD9bi,liT0(e HY);_0Re%r1=X(>fl\9`[Pb_.O)3TeSDF`+h@nQfA#3SZa@__C#65Gc]$6J2R(sBFAj)A+VL/"LGY5Par[F^bo!m=sbTY-&aa^;LeRCD=*JNrF0H[p0U1*U@TL=2]O.?iK6,$T<`@/;Gme^Wd$\nN_/b8Ra]pZFeq#g,t?D-V]M5$II3(^b.17rU:(%_I!:.j3M1oooLBP2SW#(V 3I$9CVNU4mdl1JpP&oq>,`mJJiIf5e@\H8i@IcP@8hk3]O,\;43*k4?'q=12)$A6>0DB:7B_el#XZ!U.5C ;/?r:qM]QbO3I&gA%#.RncpfG@UGTU#M) /SH+"r;Z(mJ+M?i]*CcU#dkn"J<4510Z.$YcW=Gs#0N:7"?0X9(C$7,ZITf$-1<(YV)i/8it@m;42Hs1b1JZnMC[t!4YHU] @*!q^3l;bhQ<F&4^(,TTgn]IP:Oo9.=?>sQGolboCh0L3oO\a%,eHENt Qc&R24M$j0Q;C?b^=I5=A.ZA>_j^GY]Ds/D"E(jRf@p%dkE13&O8AY;^Or,!?IYUH%F5k_oCpY#A"FUWrD*R9Gb8iJOi'HAKZ/2:RYhToX!qIIp+`N\Y2K@ e,_3i;9f.LMmEO.Pg\6b$tjF5[sQkd,3XHK&HqVJJZ'tUcnK\gikacet-hQlH&pPAD5TM[ehBh;)LL1[#-O.e@-*DWq?7aeI2;LG%UF;_QL*osn[`TKs^EqZ8oaE'#:p23P7h>HBHd`#R;9&tS(& qKeFHh<$4'tG!TdG[L*-';>+RKU J$aNR2O=E3I'B__9B_\BFolMh"6O\4rPq$f[mXa5'3Tj4I!5t!D1L4dF'rbiUdtFj!(*fhh`L27$# PA-YsF*:&o+7%AoK!"T^<,Jrp"WIr8BAB\mEBeg,&GUT"$k!0(Etj:T=J8W%G"1YGqYD9]P&nkg2-887t@d^XhEJGPa3RAeiAi9,Pqobp+Xi<0)h)BgrOI&YW=R(J^;;_HiX_f]aY_=8@ZQ4-&AKh*RjZB`rL"'rMnZf';Lr+M/E='=$VCmB)O@o6T/I\!Ut]RVCEM>o99`ZHXp]81FIsqa_9ab:+Z5-MK2ob:"c16C [p.IfG",\GPUBAA1JROjW.c,UpK,Dn`'@co6AQfr*G?TN6kgCX^dI]>Tb/H!IUWA`nU@Neb05D0$HQS_I`'Y4!dTl-&:p,+CX^MMj\W@1TC05 icp/=Ce*YVqS+ZHb)Xr*U[2(oN.=CVI[H"!;diAT_Fi!M)L&G1p_lR0NFYj.aB@@_X`sB YX*J9.9'r-`6C%ijb `F]Z6nAL1X/nUas1A%b<C]75JGGe,q",DDncIIX/AM2=,rC6YCZ>M@Ah3Bj]d@ ;"8DcC%orqsAT7)h9\QA=i4A+Ka)6sG,SY6X6qh)h$&*kLL^#&;ei!;()!dVO;>19A\iZajHd;Ihk)I?$orOYU:scq3Tr@<+&$E53g#k@;5WISMGOicsOOq_6n1D_Op4F:7l#&EhbpQO(r6r8aJlJL' d**Nrr/\bfhpI`Q_>q/-3M)!8b<seDU $<4 []6";L]3Og $D5SeY[d/Fam*c1e9g]qA:Yd<>+ZZSF[Y?: d6ri::(sr%,.L,8L;9O'A5cq`KI!$9b0O7A"\:Nc@3LYA"eK3UgBJ/$\j%OI_/D9<;2m.DUr`q4#eleY"&UL!AI:=8'g__)"r#:VN3D1#Y82mEA+Ubb-\g,AaIN&>?POXk#(94`fIfA%eQG!(A(;Z2`mFGs]c\qmY:nXY6#k5"<7bO]>5A?(m?^3PQ^C<>Yd;WUFRs8@D\C9l+ GS9RC/+R2VWe!Q3*X5=_sj!3PDC=A-?"SM_`CG#^.j-E'R:7:MVMW(TL>lO?l=M*4rgI>:052*0b%m[dOD"f AI.3n.MjLTn8K:aDTH@mTqP'qQ.HaB=?6L?b!ma5:"A=3tY5C)VRF'GIdIEa3JCfKWnQQB&^e7BUcZ>Q7?WIP.2dP)Q#T^gd0&AS-0L<&@4\LB6pcW "VsjB@0LPLMr 7qm]ga1--#P3;Wf4FVM;l]I)[Vk_^:IiW+KG>(,SZr8_%Apa0>SUBhAW>VY^3\JA\$$3;RfIph*9P\MbY9llP22N1%o^Y3oU2D#k)*W DCN&1$Y"@TSp+`4c7 ]t0mh(IG"/AXZ,D?i?_-%l.I#g(^#Z3%g'RmB4Us-T`G]:Xo'rE5ZDGl5@,]3crC8_:^HQF6h>'d&!%3['k9O&gFO)r7SEe=_]=6Oe;DaK:XZ%VNm$o%'>;M>q5qH8@DFFXFU^t@O8DQP-J*'"Fj+N4Ur5[?7h6).#+C[:J6I39>Di2CF+] Po"7*"Ih";gA/nhPJ>EP_9"?e*m3*UUAT##9i7eS%T[/m$%Ab, S^!^X+DI!tf?cN9@!t*L[2NWOZPRfc=Ao E$AH=\("8?oe15>dT!B]T<ro+:pAF1`'aH;XMr*$U;)p%9P 'Hkj?04I]Sl;j&$(,S3IC8,\($%XND-+i IPY]DU7s`@PBo?d-bfZ")mOi#$b2J.A3A]Pk<c;`eYeeN7\kR4>RtQRo Fb6G4YJcKB2-i^Nn^t7)dTOdC:/WlkR1IoW)GF^*:=YFA>tV94KRfkYnFApkbb^qLqkc`7 K5m4"$[\RIIYJ-Ys&Qd;P&RmL;fs#2=V1LQtJ[K10n+DYg&ig eYsEbt4EjPP@FsaUjs+^[<i4)Kh$2fe(`b%GqZr_+lgQ>idEMS+7'V)&=nn_m1%=G6ZLP8XTP'rNo>%[Qb4/4seF[&XSB\EVi%!S^SrtiD:ARnB?3As,%L@_OFhm"@:'/=N*A*OMESS2@M1VpaXTd_ISUSkUO@ERQE`SaJm%V0BX$#WAd9Q>_#-]SV'[:N_,_W4/BeP(<,PA+A#lQc+RF![]Xs#_A1Y3Dl_A3,kXp@OXT(i'M>m: +#b9+IMkJ?!94+p`q0Gbrae#sVoTXtlbmSFt(^3P,?jpp#&H/f#9T8m]UJKYT"N?,36RDGgl(5i#j]% # XE>6l$5^?0&kKs&9h#P-G?$q1NMUXc"Y[Re1,K%2RI3D q8?7J6lbG(>jT??)E/F8%MmcChF3Ie1M*d21#"p0Kn0:Hp?8/XRF! $T%-<0f8c&+DV[ZCV#+;a\c'<+^"e`A8+9!<03(F">XTr0,hl-+pZlKA(9a\pCQt:QtMjYYman]4nI]-kD@`kOVZX3o_`Jp#@\q+hJ58LT_8El&d8%.%=o(,!f&"Kca$Q),D<F>BJ)_FNob(/BD5Jp36H;.R-.(fE(^HXHeUbJkN>X(Rb-<o!=P5l,68d'GSP.OGs3O$VL5?a)]XS.5"j!CX'=A2*O.K(3Oe^AU3Q?9Ft0Llm1Q;%"4HM; i,@h':b0Xo/icY,ZV1"W B .c2gXih(2%D(Lapp>V!k1Lth&XdW-Afg$@0'@[bcA52+=at?gA;4W#354d(Un]l`=+^_'P+$pA/4&STiO&>t5#`HJs4V%DTF@j/.6Z&U>'*[da%>TkjrnN3\L.PS>_g#)Gk&fXrqGUJBo+7"oS?U5UeE<n6NGTUJJ3`1O:JKBdYL+oC _`^>'@A;Jo`;r9Tc#)Lep\scM8$--A2C(K?SZlXU0E1M00AJY+?XnhSE7WU?L l!S98_XBA3$ddc"!rtUcTDOe9i;hk1R+`k(?a@K1lmZk5:eSAo*Q&n>Xq`<`I/sg*Lg"=Q_VO0=pgqX1+C^rO-.V& :>rMD^#Mc@-!f--t:KR+ 3mC%[4&nS5!sC`E_W,]A?,5CDSA]i)k0pj`_ne@Fi9GJt6q-d]jJ-jh4PhR(KbmDgL9p:KakJZ8C"?iso4%Ar\5[!Um,i)lgXB6Xl-*U8V.Nm<%7Esb_`?*7tTMqhjqTGh0.3[%6+@dC8W+h(WlR2;27:a6_O$5k3gQ_o(bh*IE0H#E).4b>9bm<%NEI?N#&GDtP6&N>cV3.C"_:O.=!23?!?3LHd5m> NRA)lO3c/d+\1A[QB`C\2U+57OpQEqSc&]@0AX!d,\l: H sm<"j5'(d"[gHX0Y"O#`$hU0mOkh01NWt90&rAen9)NA.io5lq#do>peBfp<>A1BeiI])fe!\R)]1\"OC?0Fc0k 409tn!#qQe&N@*E[FLpPR3HoY,PS,%8A9_iD@Znc! Kp*gIhA*nI"`>;Tsr;g[R`1cmt6"Fj/Pd#gLr!=8XR\:Amg \")eFXG <]JL +Jg@`MOD7a9Xe)C0oZPBE4ikP.QT;AD=3#d^t3sn1il3qM)!2>\c$\12;!jkUftXecD"IYgtr#2tR*Apj$rRT:*-nUY5]T6o*fFNMq#I :.G\ah3sq#`7mT[;2tW;U(Ps(ohs8?SStj13fULZHM2&-[9#/q V\fifI8dq+Bj:NCjEpYa\g<1ef3>cBJ\%8aklFb4V<-A3CW/+L#C(9r+XoaMar ,C:t>6r[KYT3XC#5Sr1oVW=q'/@58a@qD!/X)AA_LrB?Z^V?j=WD)1%eD7=o9)Wti:`O3"]r+>KjIK/K+3+ki11&ciJ4+p>`lA#]p[int1`QTg1/K"d:CmhYG,h&@F3#>h2dZ$kYPIT#Bmq6m4f,seO5R)Xf1Fiq$Dk[kHP74lN>^mapAnWrCiSb4HsUYAYr++\**e-%UVjtfP1S7$K)Y6 0 &;OPXKY]L6Npc>SRHd`?n#A4O3[:tCR4*!;&DQ5c0`lL!])^HsDUJ #&ZO1bXbe1$:q;/Cf:bH57oUE]H%iJ6H8^em60DEeAX6WjXhV0_MiJ]tdAaH<oh,]j+P"R^e0]sJ$AWa?XnK]hGCsYgk,ht]_7])nX2*,+?3eSeA0L^.OUq6&F^[IdF%I#ofm;/J^W#N6N,7(>o-k8\6FSN(a K(6?T($;dRT0Po5\MJOXqg^pVOI[.W<8\3Nb(s9g_-P](("A_3$Ra;b_tSYLb W3RKP!_JV9],P.q!O9>?Z0d^53"Fi+J=bf/0RFnPa]'f"iY-g\QK+ir!K?H&MK6K'Tm:[>+j7P?/>mZ[s9(/$=sU,q787+2bY U#h8<,qnUc6tt3nJ[d372 (WA&*936B1%+9m_]j8m2-Z4OOHppbR-GXQq!s?HhI:JB/4,AO1+b+CtmAAS.In[)=AkLOMbmcD ZP%sqqHrj]F*BeAaso=.5F#BQm7[`h'3l\3Y6&!S2j+pX"]Ma8M; X``jhK(5<%Xm_(DbU^I@1m6qGk0`2hXH5T4Yaa/#m`+cI4UiGc#^Sdf .">A+&!A:gW_MVb-TC/S"c^r;9bbHc6TEtWemNqNn8bbDs9=pGi7A(SoT2d&=Fmo6W!o'haZL>GG`9+DebsocV9q_T_g03?Kl-&'WqE%>sn`4>cA?_@-`p64Z.rVFfH>t:)d#Pe7B>oK&Z1]D^A"A%2`kh#>_[&o/HXjhH2LOC$fW$I1(.?r@VIH2sgDa4o4XM(1VTm4^!Ra6`AD6T;U9d@$;tNR:]4k^ 5l359gf'b"AA&9)^.r!>hA?)]]bW5F>U&Si$ss'7_3,6[`]Acck9AC8Ca\OL3bb@fdQ=VS(G=ieci2BBb_jFq)9L8>o0J)DAL4<]VG'E\a!lI1aEaG-$(3`N 2VrDrQm+!>t_O-X`Ze2 $mI9WQ2T+U;\1P;aAgAHl^Jn.;-@TX2C.T2J\R9A*--2kjc_X&sk8r;^'$AoDON5=bbk6?1,0rpa#+R&?pGAl8f@_])G@lF#N=_ 7cLY[8JYO'k%d[XS$ LdF@lE4Sk%A_AZbP^7lZb62k3p0?XR$q74j`Pgc\Bkdt!3CODA5Et&8@!:A&Z7B4d3q2'ZH.EhAGt;rWYYo_e">WQ#417ATk%'Ro,pS5;`5'&E'\XK>2o&B??IHl,4Uf>95a)qR5F9;Z _AS e-cWA!;?Qc,UiT?iHdY)5rQgD*:"-:* /l./Q%&^b)_`h@37IGR*P)V0Wj0.RIS+t _UMJW)d^S[snLfAocTL(GIB6ts4tr3%Sr6^S&P8:npYaAlVC>n*D``6F)`7-pdG+L:e_e7MnrfSJntJ GQISBRm996%%X?c<l?G1T'A@'Ih!1hp9U*[Rm,Y<@l.:'.i#`S0,nW6hKGn'\):IB#Na@$,5JA,VP5DnErnN_\>tKSm0);?L&`D0E`[;\Rc-9c\ihT/;*9\j'(V"-T@#>lgS$0]^Aj04nKC$<9/D(2K\od'XbO(J5F9PR6=BGFp#3l[p"n30&NEQUe(OkEiJ8%)BAPiK]L"6eM7Q)VO)FE\bYk;*,R %,K$,^#O2eX7#dEKk>]5(Z_p\B_Al`f1HMokqnGU)L8&AWEbl"?495+.`>IO;o0$d32g=b%W=n[>9Bn$iaB=Lr[gP3ZU6;htm_J^EpNtWp;;9cXO56Rro-'13)&C?tq_CX[g'QtQ8fHeQiarjm3ha^q>L@Fd`A'Vc$i!FiSXKDh=*Z4(d6,`.+K>Kq`Np%`.4TZ*d-BAI#/q[Ns+(g(]0s:X,A08)o7ALtHHCOOL&@NqhmikX 8,>=;]!MCea7RC'0sHWnW'L,7E7'+o$A%t2Ff$$a(pZoc5_76#cs76&,b$n,XO;@M"5VRUld*"q7D+s6.kBY]VbTIQAB3PePkO9gIKTSVnZB&0m,AA^?_QRkk*\;:;UiS'6`N:;2.H85:h2ptSR`V24@ H g&F)&@T]A!Z3EdA\L$rnd &D9TN"hCrMls<r^MSD"7SKAN0D#NPe1n<<;e/%fhZHOrV"gLe$1j8Cckl=Ei0\#tpYJ?*pIXc7W,j7r-25<+K`7qh$,Q?DGdpNA7A+PhUiJ'Y9Lnad?8r^;^;t6Did,l4\5%jH[;fPN(0.ReEQfRcidVVY^lX]F:71LYqL;A`m$M*t5(]c5d'A8%"7%!r'mtFDUj.+g&S].*+?7^DXAL[s+/;f-'#&sk&Z*"b\pcchVBdi*7k-Xf\+"-#A-AlbL,NfbcUf6">]^*PmcEOGU4SKjp,1&(]?/.rqk%Jr:UQl3H!X iHpMOr4)0ZB"-0jMqA!>21F/h@%_X$&)Ze_R?_AE$YP6o`,\6&L@tnB#Ja$n,YOF1;e2AZ6;>r9+&IWK5N<3Y'5 GrJcp)ZK>r`TXr%8QWs_m80GnWE[L%geqW7P_6XIq!-'(imGMnKg,ZOUf='#d0[b#&LF%'kK@`;/edX)=pGqsjOnGG:467Vl&r4] SJ%sI%/VQX#K363QfJ,*YGK(1hHf@G4'lTTTL9>>[T%'I3>rAG-:r=GnFE41HgIo=&PT[^BWH]M-!;W=)Ad!.MUs@p#[:>lmd9&^8 ,T_iP9"Tj1ItmHC;-Ib'[r,l?RRV2$V-j[#;h:HK*P8?l+h,$#=t$D,%-Xo)t2#)RZr:>T[i(jlBc)E+>iPIP+6h<Xe\\5FDAX`8@]aGHjX[Uq2k`tb<DZQl3Za%Q39bpPI'RT?O[M(/UAdRsOEqF6A=6#&_G?aeNHYItHQ"Sat2R+jpA`,RB#H9'WVA(45m#,FAR9&*7TK-I$+UgGmA+R9 PC%^hcZpYmO4f%aQe^"a)DC 3@cb"p,>k74KWWML4*3Lq/#6[bn&_GsnLPMI-+cl>[mNdb"nl-$W']\'KaLPNA ml]t^WNOt\W3aS\7]"D5./8lS'5g+Q+hlZ&mm;OK;f"@%s]qkT1n$T6AHtX0FM^en7eIdsKZ<60;(:X88gEg1W@9f&[Y#j!;R_\7K">Y"35C0IXdi0O/$/jm(!l+nmON8=2T8fe&Tpf@YYJi;BrB9Oq&5gDl'j@9F4>/"5J0/Wg;ApWb::fBpp[B'MCUCsKnn#7Uhtp7BqAtS!9f(@Tc\>pYD& Cl&ZY*:5mWKZ3jDVXPZ2( U5KbP]\)#qAK-^NjVd.b#'qk>#F.Gt?ZK@rVt9FgG3mQ;iHIe&m57(h5G9i/8n`:G&HpfXLD:\g:RXg`P)X\k\V-`Bp8Q/[UP0OBCCMHY$i"X61b>q.Y^-7K8ENOXTF%A92nmd>72e FEo(JD?ZNYM80>_iD+1.R^H;pK=AAqLFXnDD>'@oV5,tZ6rpcpAh_F-$A(ljbg-bS>N#i5 j%dT6I_[?_$`a-*)tAjP Pf$e]ak1";1#G/\k)%+c[/3P7\[qQ:\cAE+4M>^;lACMfV$_d hcesHeX`,E7a$_?sIZho7V&49_)a<JT* s9EW8"P_\!"QD)_0\bjUYH!80P)l6:'isq!t4c(Fi6Q>>X9]mhD""gYjf[9K1caC:Va$SPl_KLHR1jo?Snk[R-l$`'aWrA@_Iio^_b!2ZsP^Vg_6Pr`8@>BdRtLp2_G\#iSoJiI^jAj3bm[=T"@Si FfG?o&r(?"gb>% =(jheYkR(BWC_H^Ki=1q-aZ=g*h:Ls! =EMTN[-n2 [MC9*d$s2tn'@0fr%KBG"6k784fZ Dg%OTX0PpR7Kb O5..q`kZ]CmirOg6$*Es#<5VXV,Sd1X*$*oo.&ak3N+g80Uje[H0$l+\1I]*lRi)6=h?T9FOHk+>)JT#a))fl Gd#/"!24O6G:6@PDQm/?4k_n7%[!Ei2Ap@VXmP_Agm9?=F:7WeW $NF\3C0%aI>G.ZNDQLQASrn(hjfH,.Z(kp@:&jI^.?T2rLol<;8o[P5tS#U9%6Z0UJ!dqs?(d7Lnm<'K%_)m6n^,IY;-j'OTCZS`A*j_^b-G'56kcZ'IGa^kNJF6#.=X4Y/VFIG[19(A`"`KjoTcQHfL9Q^0jkRNZK5I>'&YR#g"6.(A3nU?OIcnd+QL[&jN!<!g'`LOUoTWPO3/W^R^`#a]'En5)=N,?D;TmBitXdG0OG!JD=5;HkkOY>AVN];igf.:E*>tRBO:S[*mYjhPCJC)8Qg2$s+0AKeBd4(s1eZ3WD#_bVo'6m.)\&c-?V+f9=&A_j4L?9ZQ:-c'pW74U%r.m#DEH8f6F7H1BLDqa+eIq_cj&T]dr DLjep+oNt93$T10 GXAaL(Dsb(hT&(:FTX,OtVO\9I4#2%boc,0Gh5p(f]'bU$L1[0ZBkF#?ogBjUm2oQH]pTinSN":cD_FaEkA7_M3\*:Q)^WUREFZde1APMp`McO8pe^:-^Y&H9QR,#+n_JO&0Np+9re11>)YM]fYAIkCACaA\3-7fKIFfY7Xp[s\oM)f&*+p)pFXkpjGUalhQsV6iCn2iOBU"?19Ns7.m-_kh<-qI8OlU3m<\r;tM=]]b,/.]'%Lm*Qg1%jGlE4AfWh5TR,:nCU3ob!)XMF@^2%sJdi,@/Am2Pqgsa,nZm;*'%^XK3e9R!96eVbt'2GkO+s,%\F1Vcg^W"s`NR8eM$?&'MA?]^Kj<@nS75,jA-V,`;=V:=p*@L>_Th2>&7TI=,.m;XE3142Z#0$m$8&(!7EC%J<>+$t#-;-"1EVJAW,`AkjOtXb:;IaS#q)lDk6J_DZaJ-P-7?]MO1XrqU4ad)G.lD%aH4m[:`_Tg`5^=Dj_nNSfQ446ffRCc=9#Y.j%AtJ4l:+H2oK`*5;d9mAIl_J5LX$S99sY#TA-=nB*G^m3/#T^"sLOb4Lg6(nGa_'L '7$i;bdDq'j@j5ME_s1BPYWDn!j2Z+MtB8*Q_V#ofZ7Z$?K\)g2Nrm@-6S@C=^tSl)`T$bm2"p3jj8a^UlME$JD1#.XNRk/$,A^g-\nj5@>&!-mhJ*XYNKHps?' jG[*S"lgP$H"CGQT m"hkHk@U)N?"dVp!I(]]0$0;kc:)Fr2DsMXGZLWUFT.s&U@fk4$L5F*j':N&X(DQc.P]p*0ai)'5=^6r4,)%Wi]`O9,L`mPj,pJH)_S*IoN%X\[X'A+RoetZ*q4b<^;2I85HAbh%l5kgAJ8)+,bA1nL!H:8&F';1!V(6D'O;KDE&PhM8oRQViRNV4%Vb@Ab]qpP:Q^i6iqW%/'m&kBK:dd=j58ITNR+CRgI(g1.69cq'B+'+0Y[5[ti=]$0Pe9=7H>s$oZ,6,^iNoNJtg8,SkCjpYOPlSoZ3oP^KF-s1ME@)n?U*KtaWCpCSAFK?C*CGmr4;hCMd3]bLI2%]m*4'aPg%K5He #TLa@#%"_!KItS"4:;9lZEoTOSI6['*(_I^@qFf0+Kc=f3E.`(0hiK&C!jq/-@HQrk&8T*Y4\S!%q"-1H(_:-\nR?O=jKMFfFin0LqO9#prAm#%HHt[4jXK.XFEH?G;""Q0O\5>;jWL;5@c6E;`61Ne?G'T+Xp"-n7pF=#N=@@ri<G^jf oU\UK05 3*>kG,/Ze-3hB==Zs@:OY\AVX=_Y.UotK-X8H;Hk'\U3+dg?Y.W$_Cb=KUbm=j(AYc\CZ%82=JWY53$D2p_qITtj/.1M+:SGC/b'RJF67h7X=gEREg2[Z[9LRM$fRZ2RL4"r!`AYn+jVpPT kPZBHSJUq?AL!fBo`\ ToH1XVtBL0(r50hV['=UCt7Fr%@&e2K^5md;r30nn^'BL?Ra^ZWf&Bo#Xa@_FFUics@m[;tt)P!43p`hR\@O:eYqdAjmY-K7';gQ6Fqp/rKqYn]BsMO.-UaA$)#=-b:di#ZnVaSG:)*]AF]]q3L/0nGU"]2E]MLh-gp4s'QhQ0;oq3WOtNCi:ZQBf,_,"3Q;T&] XFgE'rg*;?MD3`*=N-7$#%nj9sUC%XN%,h#CA71ZAk>q%mKB0mO2n.I]h-1I#+!Y)n,R:rdpBbZ[BHlAV!q2cs+@PSb""Yskj.A81 A.rqFgiB6gJpSc.V3N\Nb&jJYI<(+%QZa7dATpLH'H:F^3FS;YdGY25_U PeoQbr<>J<+Sh(`$P=kcM"0nV\O#%lEcGnrN_=X<pG_^5Rfk@p2UPaY%&Q4>n?XBT13k=qq).!E4BsZ2"pqrGU\;l1r:re`W>b'.nrZL2I_&S3A4OnVW6V\E%14qSG]FQHi?&2);SqGFPZ)q%bn!Os(*`5C^(*>0`8f5.D*9CFf8,C3mMpmdn=5E!X+9Kp8'HHc [%Llr?t-,*RX59hS4_I7gl;;k;%qG4bKscD+RO#go605<^JCZM5pBcdA,oJd'75+Olr=aUe`l>[rL!36J" Boio2$`)Kl-=Mgge*+@Cssq1n:7KE(pZ,2$dY.AK[ D9qAKrjo; ZeU:Xd+q/-KAI&1WaUhsJA4i)R17&_1LViJ!EDpiILQn^sp*1"$s(^+^&]57\5A9G,rI_$&qFSKBff/)WBe!+6ka[k*YaKYG<0RLEA,t:_"g.Y5A5LdTWl"/_UisPLQ:O'Y8-_`.4&gHYIj!1#PfbL7M]g:=hT@M>6%1-t,!2*nXtltI8#X#<)T.L857G*F7JjXq3:n$5q(Ad(8>7J#H=4si+]U5\AAE2PP/h*!cEG?JM0:8_5aC1o1.cI,h'd8B%6BH:E<2"]rrfbOEZ+=q4t$@iU2hF1[AmRg@>t=r);Z 3+Hbd4PcHV*i@Nk_EMD3?Ct0P?d<#A:5W_!F+MG"&kK]4j]-Xd Q31oql;?O7Qa9t@bNSe6A%)hRO12E@VNcsSf407#@?#92KeEU2=b oes)XZnaDg[eh)3PG(*G>DB/:^GsR^-)WK<&BA1K*2i8gd6L"nn2 ,8Z4O5[B22Q0p"r=T .]Mr6AeC[qY?5W)d,72#0:\d]T4LM-2d1)>79[4qAVkE/Z^aSB%hq7@UL)iN!Q1=(-U+2WIBqO_RU\L$rBJ(q9oH53n9kBB5lr[D1*/fie8Q?LB\M^0dIih3Z*^J?)Z11k@,sa:p59]G""sB#2Q;LX@?Y%NBt?t8?p5FZWl_S(g[!U`oD,=A^_]3?8n'FeY(>,kqnsFAN)9nE>;YpIm+#\0lD/:mU0jDZ0+Q8BD+G'oAMtV%EC>FNl6Tn,714bS2_f`X!lJK0JikF#nqYP8DSi&d0+,%+CVq+V4pOd>Se5meYchh2-f4Uksj'3R[m43qh!'/.Z^3j]B$#CJZqjWb+XLUM&-a`^0)b>g2lFt3Ml%Z$g"D(i#H]4FbD E9G+BtjS?8[1ojO:";nU1s';M]F[8DTpiNP7iaPnr(/&1t,EW!f Ige-AD?U8EUET:3YB= &,E@JT;%7^rdl"-1A-@YLU%?sXNo?r8m,A[-H/2nS6#jEPYnV%?8s[ZEKI#;th?Gg`=[r!O=(PIh,TBX(g_14V[jS*oaF=I$]1sbg[.L^U^;gh(YWfco8K*Yo_1m:Y<9XcMf`cd>4B5_)2tP$jja#:\4!Q&4b7GY`NoO5)l:-NSdZ!odhsA<0YX:T`=U,f\%TD&t:"m`> M!V92(Df#!`WYAoBl/A#NLH"XGVXhdmrjc+[)dJ*dXK,\IGLEm)lgX-\MejV&!G=Y:j-ck52qU]f:?rkh:i7?2;1Q-l21cr[\o+JQb/1L2)t5^A(K(9BMK8ZALi4=<=tND"j]nXAgtA(i`T%!"+;A)nFJFVQU)$Mi`Z:1]_AA[aVB@XD>;h9_6WE(l2Gt>I:nBrLcj(nb@GM"7=g=S T\M 6Sqi_o/_)cOr]O:QDt@qk`:jA4tO^+:j#MPV<1kV^;k:)$;)_?,mGqe*AY8#Ago.k. #OY5g:>?g`$qSg+7\>3k:ak*qmj; gdGUiig&5U,BYiB?$QXWArV4Kj*DB,%W\1*9ES^lg^=HB>8qa4%Pol\nnS8*!r`%4Nsqr15g[*Sp[--kpIAq&^Nb91"\Tp_iT^&m='FeOUT&X*ni*rD\0P%LKUetBDK3A0^^EX08qjg+O2Wrc-@U"`M"3R291mG[$7G ;>pnbijT)6F(,$e?88$sX>=(P;!]7e(ht0^MgQ``%7KjDdCmVbV1SLTeWg7PE0g[:e0Q+,4VPfHg+k78Hm^0UO:Ea$>AV\hB0c\#Y3NZiA$i(hPh>PN@s_bKW!W_El%bNg^sA<)b*p66]'!R*Q9(K4'&YfSUHY>`J$0X.Q.m'j _%.LSMKF2 hcael/5(B=mNh&#@7pb'ZLR[41U60[S2L\Fn@eRM_2X+hGYM^-7[G-^h.^4m_d=(m]5DYm[g 9)kF0/=]Dog=hA`@.A!0&'kK'#l.2,T^qBde&[Wq2F.bl@[(-?d-,l>[][34(NmM8*/l,m/fjif[+b'7gn#A!8+H)tiOIfY-VqEbFZ_*d+(Gi3n^cWGP9"I$gpO)Tn\@m848(OA=mL'MLD+#aS^eo.mA0cDK@Ug5O`ig%s&b(t*&?T"O3RE;'g33#cEE.Q>B7Dl"&`\[DF;(RL8R9@%l'e4s$(;7Q3(Wo@Dg 1?GW>,B#9f(48d;E3nkY::p%B?E]4rUIIl/S>_Jm)dkbsPX]I1iedL@/lhDr+!)O_):A4=cK\S.U:*t%V?A3hk!"i-Cgl=KA6Xo:/DJ##(3"Nm(Dh+j>tg;ORJ.t'W;1=k.C5W1sm^T?g%slq,RG37+!"TtcTI$U3UA+B+=O8'F`?mh^5=beG\9,e^69I]@(&%moD-N!12*d]<.7Glqa!*ddYLqWLO5j#$QbW0oJP7XXJCRG,iXOM9&\=[HQ"L_I)^,EpN$[A@0&VdqbX`E[`UiCN%PZABVibPN)U&/l+h_E%h'%!t^k?NKmL9?1i^nB\OT?-_+,`*X4'OH8h%\#],cmg1Mr?M3elTGrA&po0n.XNh9Fk*>h$[(Ol cr-K S,)2mYCtm$HqMh,d(3$Q-Er+=6S\YWS'2tE(6">0]g3D.9*7t O!rO1C-g:JTq5Fa/>MoASLgTj9FA%b*%I\Cj1.jgkX?3n:,#WmA;@EUAEa&bJ$?=5(D.[*4F2ReSk8pq#oOWCW-k$1ks=hN q& (PUA[]iq(elgSlXbZS"I%$iOcin8,_h<*!@@N\raX+JL 0Ln1GTjgIj)d,8ZU#A\<84AiW'@s%#FZ">/ #JaU0hgBgGB0!Qc_RR&rQQh*7 UR3Z9@k-(lDP)XnsEoXt"An-;LA:*4KrF*13/-n;Q&[\U&X'&e97jkU',IY7AoppX5nKZ#s2JS_na@R6ZF2m6pE+%-"$6mt.t5\/:rcnO1B%KC@ r4sr`p0'RoCQ=lfNam6;^?dLp.'3SX;-pZJ?b,kdd;V 1#KB8WX4`Yd?ta$5CGBdo1" P+tR< ^oq-F=0-.J7Kj6)nmq9H>5(BWBc)jG%qIn*INl`TI/np<d'%:lf__o"[jOsqiWUa"1hK+"bA7`"/*+/6%?F$n,^rGfc?.&c\iFICkTtQeBgiR?_9g/G9:N$lKMdnpil^^p==U5)5?7BRiM0l?b78K"H]c%)GF^dR<4\tM"qfhWcKHcJHPH[i7a!>hUP<4<@19*b(^]?:KTZ+P?\/GE`[QMki%nfAV?A6l+(g(t$O`\-2pXCkcU 4p]AY;-+khk6PoZ>lUDbnGJm2``G<h@p$t+39jh;9h+?^4%B=VJ7^'I(_B0^ok/>K!iIe:rE"5UGl1c-;O@Z)ctM#Lft\65Yh<@c#js.!]J"c)jQn\GBaetQ[0WIGn$P(Y6;&:*QW38ffW4DA.Ah?;#-mJ)gi1YT@!fA?7`]Cq>[87HL)rgZ0hYj\<Nm$;h7A)M#PS?$Iq!oSjVCqpaS#WIi(J5=A^c*mX)/#S=%UI-LG!pl -(!pWW2#XiqffEASLdN,(Y*]FR36OZ[EIcY<q%S\?dC-]"I.,bf+rdB)RmB%9I7q8>/q+_t$%+.E7=XB`.PGg7hs7NiZm2`p)PM'D]*e"Y]@-a/7+)DAH[KJ%1?rGgE-G^B1EKj&'CE>-?`mdXs#"\b,P3LmFqOP^d7C:d,4OT2ZpAfBt*^]h"+Q/:8e.3AeW_9;4.fDW@]!!^!tIss`*le='i?_4.F=/L'N3(B[d$aQkA%4%+SF4Jr!AHRTWkLNlr+)_H',e:6sEWnF1YqAiDGt?(5Kgo?&aP/t"ZkJgf6CJ)&ER&^44_dnjZ"> @`1L<3f,*t5Us(Pb>bKLBA[*n:H5MA ;V='WQ@[iBiPFaWcj"C\=/RnlUoJ-HCTgEt>F,l.*f92ArUma2 3m5oT4%N^BS$=$_KW/pP;bL6E1lDUPM6$F8OOcI7I?.d>*E35",<tIg/JU%C/T!sWa4:;ohiZ0,mXUjpC9@b?TJpJO>9\>4R4>^8i=/H@%_*iXi!@Rf\akh(dl+#rsRJG]H)B5"+QEC[1ci,I8f`(QY+>Ws..DmH+/BDV@9PTTA5!?nKhVgAF?['JprQQEC4^@16rgRqELddHHoSl $:X3HCrr Sgi!AOG#TNg&*?r^o*Ms@< Ooi]j28T)^C=II-tdag0=:oQn&>)E-d;+mVrWM*mH1d%m@Jk<*'F$I@KJ>.:25Yh73gOQ!2?:O?2a=/(G#)\X#_rg35abm8rBj8K&OF7$QKH0YCp[D*ROI8F^$\"e[:rFN2J;W0a"-Zqa?;(Z1CU5;OdaHIULE$`^O^m=A5t &Q'\"0U#i\(EL,j)oGOKmU^b>\Td=.mn=9\EcLH`N9&jWAcsOE2!HEkag7:LefbK;MkAA_!h?iAWBN^Di_6R[>0n@[ FHg<_A_-&l:HNP!A_j $"]s`Q'*7dRl'd%F\B&P.%Q?L>q)\]B+ce )qT\KRgNNHQ#o!-e"X/S=(I2bDE3)FV&4:fKY:?&9;nS!RALA>q^\FBY'-4[>lQ,?]#3/8F3.8;J/FG>$0,mJ3dJ&hi$,n]iE5P?Il*"mr3FQ Po-=<)id_X)e/ZF!)qCA:#0Hlh9)R0L$P1O3s(O5XjCK +$QRLM&Lf#\D[tJhQ0g2%.Et.1EhW-I$@8PA7ElQFTX4 @Z+$[0ER'AX.T0A&m[J%F=lqa,sP]_2,KG6J;AN,EpcbjNpAM`HP,F2W%@,X(/9s7A1.haE4Z#FV(Ut ;DHrtNPr;p_V(@9<`YlTF2\`U9Q_82c#!(]T;r0&= kat71d";K$:+LnaWq))=ON$KV:rIda\(@Anf_Z/I:>&-k:i$jn-^O4!j#NfEsGh[#"Vq%5 qn3s3+)b(^.Xd07Qd$dL61bR(%V$D!sAcrh"JG'FK&r,d%[thtZ1Q&MgV 5Aa2n6jV+Mp"?& "i8h+dmKbo@<'k.trdH3P('@$-kJJrI7^.*$"Xl'Z/C#eQ_7@8dEmsQ\L<(8lqhf8OlRSni=T$@'FgGqBD=Xo"m^O8bJANBdn2$78Kd)Tmn.Gm.]f'S4-XCO >b i@K#>bL!a gme-G(e%-kbhB*SGXF(&bkF4M5[B 2ksLC[]j=BIm_C^n5oMk7>mXr><^?YRqJ-88)nH.lYeBA(TlT.Xsf%bM&i[iAqhD2nk#JkbTS.Bm tnE:?h, HONoE?+(+t'q29[5Gg7D*0"EgODHeaD'[O#SDbpNbO%h#Z6&7*0AW3*9%gZMk8C,_#4R*V5Z!5Aa``/PAcpnIc7)q3NakD44nF6.r\P(rB!`cQ#$>PE6rn,Q'jq2Z$.t@clQH/q)K@IjIV?Aa%+.qQ^o`6+`NT-Ac./4;LQ!"HJ&@)]4kS-dVEthjcMWCM[?Uj2l5`!(la4LYpAt120S[F,$+i]MY0q[j!bOcpABT<*A"Ge#%>>">l>J!E=#_#pd73b\J&81(+-=b0;ofqW#DAeENO26b=Bte<=Q:LbC/W4L'NOJi*]kC(<1A<.ne;_k2K'(KA!CN5IYW'_f>XmZ3J5E+YHf>66pe(+W%MeTFtGO2C^kjd;c[td7:f"JErc^WWW9P8X"EGNb`\P!3@kc`]ThN AYGM_6jlqXqj8RaH`BpnJFO2G;^ _A$Q0Ol#6 m4hSdOQJMfg_"j>o5Z$7gnSf%i:A=s5P`M/6*>oZ72@;0\\O\NI!bo0IG`/1l0FW/<@lnX6#\BVl'nb\s.l4/KP60orniFN!MnRO^2`l'KZHHne*0:lA(Ha<*Lq3,M'>&fo5';oqXZl.tbHU-`O(sJrsD\3KA^,LhM!:=YmKqDRCN^&^:L_#H2SUS+n0[(\SE?qGOYE\CV[7UEIkjR)bPsA=$%P:0jo%B67\S>F'D*Y(onLJi''3pJpDW^$Pd4\e='d[lCfj5m"ncOQ;FIGS+"*#kB#*.@ tW\Z&!rZ/116]lhp23o,2?=qpc"]3#8>$/QXtslaYR2e^A%NGOS6?^h"1-9AS%H[/tUH9NF)0cKjLAl?WT85G:_\%28?)cM#J)@i0ajWF8h#f!%9d68&O2;LHS`G5&8hUra(Edco^\Af_fNcgaoXaLH)b Y9DI[]_8B`=F*8"H&*)hD;]5O!DI?]VPR+`VE/.L[QFc._d!kJD;5.;pG^`7\?O(tsh$nn62%X>5h2j B1*\can[?.t5>:OElXG]o]BE2ni.m4GkL,#AM5(=5h'o5P9n sZJ))QU/]T!3ngkVGW2:Y\\=A2A]VQ'$-g]taXA8jY6@8c"He4j4ai [b*5G^>bRXBCo!^f!8c54&.I R!a`b C(<=.`Lhssq:nHF4m8`5BU>Wf(Fq/AnO:BgHbAXd4S@TKWFscj3@(8DA fCt3Ap7Af=]JYGcIC$k[#,%/jE+X8 f7<$!kZpZ'sT53W@@oTiKOi*9Rsr1Y-JI;>BOIqY]S34A:*s-hhkQaL3UCsK7eGVcodIqGB`P6\(M$9>q$OYtD-_`,lF84SFOAWdEcsW8p1fn6\UUoi(3iXNt[M-7'ZDh*ij_rhO3dr_V*E/3[iGGl:G%9 DdO%+[L):QVF%E9oo6_+j_o=@hg9c;nGt;7pWCA5OSEb)beNGrl7Go*:Ab9/La (Vc,CHTp -ed\QeI-L%^$'Vp]YT"Ce[HsM3"7?T#e,8Gj". e06qYPms`_'mp:AIgealhh1Z7$o5sD[o+^XjmC5-kaX]kGZC,0Lo3S!dg56eJ$*G#U+k=. <3Y149a=1@ _Q8R!DPMU^/Z-WKoDM0@!E5@Ja+&)`I]-H$3-@*_tMdI7;A!Do'78BOZ#9RXOGj0Hhq[#^m4&75kF tr&mo6OD,#G (Db4"\e0hJfAj!I#aecb4UEfl>.a9tA'T&O5X]j]I=ia3HB0158N'.%h"6j6Ip/g,nke$",.('-%UQYjCQ'etA(]lGP!Cr0aFO1GBX\F2;Yn?j ?DK"]kVYLb%\1XZab0n:7\mt1sHdf.pUOS_)#B+lat?3L:.T."\JbMJ,EPN^2 6d+31P,TJ:\TMRa6)*]lT6iG=B/W9l1)MmQP+oBH&&"Qcq4Ak+f$jphpbGUc\f[UZ@RXh7[G?O0eGJ AC=[ot6X5ls!ST!+^:`01dKna?8=_V0s#Lro4'bgM52UR1)!ACO4Vf>4'R:r=K-=6Y^j"RFjjL_R ij?@tpa(EQ%n5.B&bCY]];Qr4P;LHZSm2b)M?:0rb!f/C457tRmAq1Sg\=GtkG;saf9Ag[AS*qF:FYp7$rm;;ksPf3Re9egW>eLT_V4L(a<\LAGjmkD1(so:)mCI\4QYXoXN9d_8R>+@& tGbj*f,FC>+F`'\Ep`J1Wcj*3N8#nm;c1=qIi9*#HMbtdkJ!q4Q+k?VIQ(NW&nU]DEA&8pMTVq@6Orq;NQ[h6q=)?AEoHTEcQN?DYD%F8N=7F75UsA=^DL(* Y:odI+^'3"c`OK.;G`c[8;?c2[9bUmA37!/EEfNIQB*A"1#Y"3_._Y/'Ug&C_`&5V'')6[t.4n\<b+X-a[rH8Ci^:E5a3b XkAjD]&HWWVS-8/.pNM/n+-AMj6=1P>+>[qn #=A66c3'"a?_'R\QjPd\-f?c 1ga%M`^3;c+4RUe+8J]Qc^c,Ea6qR:1N_@#i+BgPD^QC4$@[7'<8Xi8^F\gEH7_,mHW?ef.$QcN6:C/?-W:]`RDCKN`d8GV@@R*k=Eh Pj1@94h%n4D#mA8Rt0O<(l7;R4(sg)EZH?!/(iS@WX`.fro5+$Bg07]NU^+S7&3Jik'IOK_ZfeGma;rK#$ZF-iPa5+d2LMWJR504_EW'/!&[&so,'GJ]NJLb2kEp'S87"_VCmXsKc8&pDg399c8Zcqo+(^9VV\-4QE'79ir/;2eI#HTb3i8nXX9po&?=i+75Cg$d8QYB"qAB0RUGUdZjq)EC)99>ednIT+rG2P5>/"l<$^#62@X.OP0<\l&tK2fqSko[-G5+WXG/4i,lt3m7j*gp-Fqg,2;DQAA17Qs\*:UZgH@MD$7.Yg+jAnA,_E$[ZrA(SbGGRn$P[ Pn[$Ak]Kf1tm&e"7\3ZgYWh+Dp4r<`'ha;]^34 ^PTd8$Fd[_r#L*tL2S(O/TG34Te\7Kh%WSk`CocYt@2tI&0YIVoa@#:@iq#5"gL79n$[Y7Esp?b-3Z+QjrVJ1iB&m5p[nZO&j\7BHo@k(,;`>b@A]b)Y:*C*%g/ab=IG/^&W`7eG?"X>\"D':(p2`D>QANkSke_V6MeJ3X4&gB,fes+mGORj3NApg34f0\+L:%JPm\PA=;Gbh^D\;[RM9rV/!pB$qNAA9sno2"bCM\QRA.MZc4&Q`?^OVQ 9'DLP-S,'U3la.pjBK1\g5Z)i>)S33M& T52iAlVo0`A76jFEimi&aafI7>pOU8]_SroKVeW. ,lM]!(:Zf1=V2%@/"ZPF:XF8TXDtAC'&rc%9T':;oLIa<&P(D$MF8KDsKMAGig]UmRaIbOnP?9.Yid]s6::3`e4[H*l0Eg)\At:J#o38<4!>Jb2/QQNE*^9An:I%-bm,)Ar'i?0,So/k-G)S_(M)sh>TqJH:_2T9n^P\A>g)[Q:`L 9X4[k.#X424]_oHPg.faGtb,"!s8\ PqGBae+V9R42d9qQ$#GC?>fTUd8KG!VIAiV$MWr$aMAf>,e<2jfgkB=i@\;CD$Oro^2B=FN M^o+ n8@07?E!`ebB^@BWN1?IR];O_f(sPdLnd]6n;5"7?n>2I[N2L?69OH.>.iZq6&`;^iTaCK !?Ai@S.1%n(A2\$;/fJ!6P0[YL8XT0@:Q:i]C*9E[-S,t=Jqchq:UW[AKFq%A6I1R(F0,'DT3UZe5PbG*?FHaRoBd[MNja0sN@4@X2_T_Sd.^> 8Z]A(dD>(5K54HM5@h"CK:`F/4='/0+bgQKc >Vq]Ff.HK*Xm`Lg+`L7mk%1"32so5Nq2j6W8d%.QnNZP`t5eV, U3Jln$]5^5]^O4lT8@SgbpS"F)7'p?SYAjBSR Q`opb$BV`:"3bt>WM%_CT'(Ap3P>i_ C$rbf47bdK760,a3\&EdC_]d?:\Na$)_5XF;B:_ENnF&Ltd"XEF[&0JfAsID)k!?*21!rI&:Cp?/tkUh>:&:C6KAFqCRQe3h;nNtD$kAqj>4kJ#s@L'YCp-mRRZ[R^p^Z,BUq=6=`9+!)&5AoJEg*rWK]nnb@)'"/S)CsYO-X@5?dq.MF[PWEU5pt5F[]W[M#rZ\Isa%#;KeQ=4t[r%K)mh6b1o04L]N8jlEB-*F8gn5o$TcJ>T#%;1Q',oiXOQIi0Z_lm,Dh]&0e6+I3Qeb9O[YEX)VB*K\_1_t'N;nNc*$I_7'0l-_if0pYIRimXPt?ZGZIs<\>Vl4t]F!X4E&(rEEV<I'1!+9: S$Mg:/*p^'SN,W4_'-mm+F9b[pEa$Di1&jU/,n&I:H`\6"=!Fit"f+W^Z%s:b3-2D5,]aeD5%[a.=F50nZb^Rn$>o6Wp[Ei^=+r*q)(lWCFrUk 40p(TP#ATs//KMZLGDmD3G9nF]A>_E+*bfHq<nB]hO$KUAYS6%B-I:_]CN1PPN );>A.A_-X')92nDI?cj^nTCXE+J]Jo\"$=Q`l-,.blk58Q3N<$X?RQdA5B6=B8pEDR6:KH,ppA=jJa+K@n6^bn$'$O/)Y>J?c$$I-d,#3j^]j80Wt41MWs\?WJE,;COD?4ms,oD.sIRQ9a\!i8t961pg^r4kF)6VXh%&Hl9b)q6K;`hc#H8^n2 )AkTmRhAMi3I"RWbVkaFcN=+%5FYH[*>XUn0/b8XsF!+f^5/0ZfClKWRFbo)M5tjDPecUD2m=''7eSmM/[mLm!r[f?JmZcrkg!Lh[1dUfN?dA@)F.J-9M)3$.Y20n8Zg`3!(UGd(MW(!#5ZTk2.M"2cSaNAOAUktY' nW2%P$'I>U\FeZ [N"$%gr1Uh=[6AGTHBICP3:\*l#_Y0k"Z+i)W#8i_:O a9$IBpl>:i(VYHQb=`r"6 _fW:gmJ[^6*`E921NAIAZO^#7'9Vb?oI&.\S7c%#^#opo9IXehk=\0$T0,G%e9#82k=g$S&G%6N#^S@rDA!+rrf1"bRe%AL (FOT^tDX"( `1?C:Ip4sIW(W%[>5Jh\UWaBn>X."Kn[=A.c7#a"C)<:kfN" 9JLLN_S@aRHtdj<[DVF"f*9?)do<>pD;1kP>]0Vi..`S`,5.>9fq^pL]A0`k3Vs6,]857=RYbq@!UHV7#9\,F6f[O8Rh5,X8b!*h[.&6o?BmZ#9/Z)=[Ff"EK@J`p.i7?7s%BA+n6$I\-VL0agqa7[42#t)+a`/-F(Rs,.6$+6As/EQAETU`7_`*NQJaYlW38t<[FGQ,\S2*q!7mZ]E3a2[gBgS.p=`(O20#3ZfCMTjW);J;1_>6$@ZdU &m[HUg>Q<tgQ_!)k_QE`[%.ZUB9]k>^^db"&rlbj?KDiifhg/ZZ_APqgXga](?jl%0\"OeGm?l*& ",ptA&]q;N[%KIrr&p_YC/BpJt>aANfsB" <=<80jfO3+pc`%iQ[G?YO6eP+]>d?nq"5,^/b+ZacXQa#(/!&"bCEbSqpD'3WPdblq$F-AJi5)2(B3>5`jF[9LDU@hh6=q_?L`R9H3&:TSj,hfhNA*J&%d2[eWol4`ZW^)Y0^!M8UM)Fcq<;610>oIQ6/7GKALd+o.:$:3kqk)Mot^Ne0654ciIqn%h+O@\$V9D+tt.B pB!1fVL;MUGE`s;(<\*ZK3'.?WPO;jH9K[/G&>P$8Z#-&E_i1Q(^(>e+;[-g0PD&.AIlFo?\RFs!T*Z?#W7aB/.+4oOgQd@].*bW:=T.qJ3\j#%5^!N^a `[!tV*dojYTeUId.kI>%?8Q&5Gp#IL'^Tsct/5E\imT>p*oJL KO#5Dr>1.1mRS2eKJ_rZ2_cS+c>rs;kE3a<[K3[T*-%R^`@*W1eL9&_&l#=3NW`+Y^]KVcg]ZqYG,l2Z,j.7,[02J^J]!oeoG-5:U23"5Od,da430\ZNXIHd.rJ*;jUt9d>(t*L^GPkX]ce Ya#NC7c#MGa)!7cN)j5LF%&X0?D@Jn%*/A"NAV$G#mI-+mj)#/^ecY`^!WKfRk[)Krjj1ARmUip]/P#qG4I9H!<]*fVBJ)k*dr3,gI*\'M_bb4C8`ip<-G_ngYq,YmqEj,$oYIi\#NF(>ZsEZ"JWrfdhTGDVP6tSH?`Z";]:gMo_QQYXA7I4Qg?Z#tE>?_t)*t](SE;r;J8cS3EP7.@3p'VJWPL,fHsD%eim[CThlG&SH>eTd-BUo]MC?D=gptat:;":Q(X;YG*5rU7ZHN&[9[!)eRGqnV#8A44nOnh(0Q#+G))c-nQl1Wm/]t4bfpO&A(p)H_8@!A_!rP+0#(8NNa\53QCFI!Irc\#NmmKX;AX:haa'Xl)haG'N+(A@hWfd'QR(Xql,mX!#OA.-?k&Zl)HK5Lmf6&Kp!!dS[fh:rabYhCSl#c#B'F4ZZ-UZ\$5XJDf_X74K]nr>T+"jem!+*`s[Pq'$C$oc'/r=h,'6!O*=3.1m3.SPF4D]jS(X0#&@ZCo)[GG_?`oddGD 7s/7[bL2 fN#KQ:7i:B5(2q$;s=n#^1"c$,5G^6$`V!H?!I%/M.t5n;;?%rph(p0YP/[heg5E,:o3toP@=.OPOPUSnd%RH=7k[O&Pl6c&kYdi^%Yj?"FEl-A>?0isP3KJ*=k$--I5Rr:EOJWo>1bA:n#($pV_7VoIs)GR2[p>C2C\p5A0X]o J?QjNBb$qIeSQL=@62^#QhfA*aYA%f'$XRl5l9gh_G,LRb7a7O1Zg_;r&A$tA\PK&B8sASCYObeOA=(FACKH3!`[DHfpf1\JQnEb_aOk@UbO%?'3-WfSV?b)DIcVD^I;eAU#9`ZH(rp!i.rf0tKF[aO9<,A8#or;^g50XfIG5;t:3<)i"gG9)7CQ5;7MLf>)nr9EY@kSD!Uis*c0/^Y[aIYBlKoX#sQTP4p2+]$ZA1;ZmF%b.aUTSi<"*+@A?G.\6d:EX2%=1PfD'oeF!UtZ^KJ"3JnSh]"s^8M4* ARL^S+oi.Z5-$j`6]%?H"gr;YNAr)-rNT!E6MgGkVN>8`9e#$ c#/`"FR02ME,e2)ber_C8^$#USH:EaV )pi;h=oT aW";R&&9B Q]P@K:!1(A&"G?]L4_c-j3lFVCCqRJo*<$3$!R56l<^*C;)1GBl.">LC2QnRi"AU.,%2o;E9>F.TW4rCOfo/.iH_\Fk'T9b3bR=T06("Y=C>A%7JNc(`.G":j!GCto[aZnDR2LTk1C/,A$%Qna7/lFEjJ-dHFf6c3`2OQkYBi"9m"YZf+,Y%.&o*;H<*=r0- UT^ gp^c8J,5cgsUKleXTH^l?kDPC1 =*l,qpe@n>0enhaI!4A?OR6jb.ja:/ qrO(T;_9iTMME!F/]rOD0`%V.]BpcQfk]Po:)0kN;)d%.W>GCY/gjb,#Ce7'mCOW2FKb3Ea4ZJei%:a@^T`p>D9Q(;I?U;F7(Q!eV.$(O>l_q#olXJ!=B3m_N;0QB4^pjrmRp-4.#=#)Xm382Yi&8jA[-a!(S2Mi6VZ+>Q lFe ^h6P)_N+0nsbb9Yk7R+FI(WZE8\nN-.eT;105'(^QCe_E$J4e\/8ThAI:CU`R'&>HPL/pt(n"Qd\A.5G3r_>th%lS_^sk6H].jfmTNpsJ=",8$"TStbUY#&8Gc-q,Xh4]h.p4YZZ@>hm8^_tZ[@AK_h$Xn>47//PMT@Y!EO=m49=?CO_;(2+nS`3AgXf&][c_"$N&BUpnj+SFhTQ1aCXsZt&WFpNl66A&2V-Qt(&&""=IfljF@"'&]Peg$ik5L%TKo)_^7m=H37bb2(pOX-APf_IlRmiAE#c8*Z4MI.bJ1:``C@pSH):W8CdoSE#mbo9G5c5"b!VC9IZ\6GqgGtAAlS#S#U6"kE@+$`P3YC$n>J52S5t5P\*Vt=Woj.->>WOg`d8:iidhR\F`Th[l?;m<,OAag'DY_DmXi-asq^VA6RW=lpHj*"3;J_dN:(AZ>CBgWC&2tqrf]/*jl%:Y&MtK@?>\Saf.>:cmp(-\n9K>#5DCA$!_+k4kJN'Th]3Qq!dU2Wd!=QlT&n@^eBd#$`/rgc1`IYFjP1KAh7!RG2-%I\t"ECc`n6t5`sCgjHk/rMA5])U\7hMGh<(UAc0RP1M*VaqH9A;2XY.s^s8-KeAH#ipk+5@U*DF4`#+h"*,>3`6[cWB?cGR-TehldI1#E^88TCKd\m7&IQ=?!Tb;DM_$RI/&8;Sc%m: V4o;3[48$>5d0R\Wem;+US0E)+`G<2=]Zb*L$`W0[^dN^N1jQAWEcA$)L1sM 4YIaGB>9,e+4m4C1_[g5[s-S_5#L2f-ZkCFE@J"l?s1(&*":A-X'Ki@B*Z?AFdY5jlk5OaT,I^aTQd^V]iH2P9GY":ph=P4oLi-)3P&[LS3"cA.85a Vfbl5VA`#[(UDKh[fn8+MkV&B?]`6D3o#JZLa9Sfh0kp%Z6>$MMN.!ARk$Q3og AXd"CNCM)&)669T76A'*lB&A".N#Y0gsJ A3sc #/cL"&a[dC;S9$.C8R\[Tg`Rk)nmt @AD6>sk5+6-8V=]F"Y5`Z-^L>(2Q0_ pcig6GKqho0/5dZG>6.U__ S6,!L) sp8eYZ;F`K7GK-]ViPKqkIrhM.AT%3H%eH 'mqa4bh>\.3P)Cis(/;W<%LVXeQlQ5lO'31IB_&Ue0`<AdoC&s#KA;A*1oGdKf268licsVtcpU,5<#jnr*O`Yl_fTAaMrlPDU ;d JH4g1]Hqan Y*"qWsiA[0&h+6EY .D]4&<d$ t5-T:-@/Y6!A]7;@_#k-%]A`VO`h1gDR A!i>e#eCRCSsC8Yg?gRP9rhdg:@g.H!X2Ab RNKBsQ=>mde.t3)7&m#DbLG]qkm1Gr_tAc["br-7-,3#r];%W$ 3m>>K%JgT;,!@t`IH?]R9]CEq*k)At7Q9<@nKbX[8m!:OB)BWP#<_AAO89sON[g=LMBk3](F]A8\RYt[VmMs#,iQ[)eC6JA8r""")gW?Jq#5!AJf7nAa)R,3e2Q?cA`nFp"M^)kO[))qS6lq#%<8%%,N7A`#Lk= >kAaE``=S,r"EQN\3JMMR)bF/8!Wf.O%A'MqIg>EC$s`6%: >3]pHd[`hZ ,,j#dH1>OWPkL6'^HNb).YhY16B5&s:!k_,"&%A:!ZRpNfHVTO3q<\QNAt](F%K,B03a,MYh`k^jreYh&?NCqF_H8\99 tWpjJJZQVqS?p.!-:NrIC7*[7g`dqa.M[W6i#8`I80ie6GGY+FWfAp6Oep^\=#=B#.rA8:X/=d` rP)t43i,s^bKkPBS4G?_Z]Vhb=HA)+7E0M ^V,&^`c'M&kS(r6b#ft(F*@rYg5Zb%4.gih[+,r '_V)d07/8(d7Algo)GEhW>.g#jhJ\`C\Z,Hn7k(41`o:. `9 pHBRGA0q/%<_+43_2)lB9gjFH+OLjVa&:GrqR"$_'m0/GYKA`FPio<Z-#+1qf1/2YLSUW.:L<+ti7k^j(tVY131(Yf !Vm.&^rl"=OR-`hA-jlogkW]M.k?UD-2KlH`fk"Zh,@sOG30,e]#k\4a)47S:%)lhNd2-Olmb,r)hWDW^pq6t3](2('jj8V0oDRe)-r/[mfAHol)'>"R/5U"5;5lW>1RDc5TB7`gR<(%jmgVCl+.dLpmsb-t I^&@.lA(99NA=eL'j[ZS5iQ7(27&-JjCTlHt&<4r;OorA+Qr/1-3=jc'g.*$`Ap>3)O'_M"h6Q2?ghgsPrJXRbA8T._&_)04!0k`ls3/]AH)Iq>s&aGK7fU55GEQLD$J9'W3'.`i2=]F7q)8etEl!B+M5_Yo1bN-B6$79"0KM]CsnY6;cqeiHNdO.9J"BI[;MCo>R!rDX7T;*9[_ \s&=*p7e7>4L'L>knbW(n9K 45(T_G[$_4k3Y^8Yof)550FJ9,^6 #AXiQ/tekn]OA3Q_IG\;nbP^-@!EQP6n!h]`-AV*6Z8kUQ!g&dL"\@C&EP cN/>OB#AdfA["=OW]s::[WLCfiRqa(9;ldB[REY^Ep#//28eMZ4<W%Df*q*D5AM*-*Bc"9?fN67EQT%'6ZfDBlE[KP.^V3ljM3A%=?,>+/-P83Mik2hsGoB.a 4dne AeO7i-mqXo g"LQb)4!G_ [e">4Rg[Yi('P*Km3K\_=1(4IinfR:<Y6adAG eir?6UOAd'Be_bM6""?H;QAN]Y6leN`6TX(I3f$::F/ra@fAjpA63Yc %2\3rJS8b;qsC@]c)UT'd!A:Ak!'\i*P1 25WDDb'D)b^:so`E4l=?8F"lpb2nAp+\eDT21''$m\&l#h\g+%"R0lr8lfk=94PLDH.IoSBf,;]#nK"3kb?Z6RY\s],LZi_"Sd@NAI_$GHNBECT-grSAOcL@WX1,'FDeT2XL8OK;d-,L)lP,3\ngKVG[Riea`tK2rist,D&OfRZFD#p9]8CqpYIPq*n)pUEMW- FEpiW;_(< <6To3Jb?RdV(@1j?r.$#2^>U)#AT]+t?=FcB/aO1h',8peaN!_qE'CM;aLTPF(pF"b'`kk[*G@%bJNKU)=]#?FpeV#28^Ffb,1+mY6<8J4+=$M'!7 =_"1PP12";)Zt*MT!V#B7coB0lRHT]rLXEY+3t"-oq%`gV)1IEs7F?Y,67h%8@6,[H"ihY9+5:sHTNc/qo-esI"_nrmHUZ7Y$!Gi*k[.TFrKaagJ#.ZYc`IZDb@S;$R`T([%\otr(7'-!-8_P/?#1qX4e<^==3L3codji\,sAA\)"NR^]KX38CDA_ZRk9g/*Rgd'dIU'T:UREr*9C]bR^"e)&Y6nC(fr]"=0?QX:6ldPb8)\o\Hm7b`:k_PNBYO(itiV"o./S.s\Q0g(!@%qKX:32LDk^S(t:MBCXA6NN1AsNU7_-)@(He/,ltg[<=IUe6,KP$1APhQDl*O&lpe@2At-@SYUb0%WYt6-,Hg!)>DV3BDO:9I()T/t. dja7JL;Zl3@ )K7@*esQl?.:8Mq"YW@DisKkf@T:jA+<\AaFYJm>1d%;m:('"A0aP`C?>D7 eN>JIfTEIAS1Q@B4kRn\/`4JId3a&'^,\n0XGE*Zonfp$1?rO3LT3Xol:O`46kib+<\F,ilohHRS1?ElmM(#eNE(!'Ip;L3O"t'lr[VhZQkcDO\5*,0d]1PD/( mf bcoCVi2chgQ^I%J1Qa3I+[#k&b;Rd?PUo$Nj_:*[`pPNtob%3Xt!Vm],\`G<"[AAYl0n$k>dQ[o-SNbQ'ZU,<-T" Y8Zp15qL@=Ao[NY2M;rAJYMn)X8p;c7o6*ilL(`mXG:aH3KO oh1=t_*QZ8?L6Mrs^+U9h%O:b^WlA9QiiRi'nZipZ._VbMVI$4rBg(R5pG!DD$bn=2:!*HVUHE(4!TDZO(A$*knR\hoWjk8Gojroa..Sb]Md;t>Ri49_f%8q6(p0i1+7//+5P0Y+lso[="9V?)#\'mBrihJ9`0NG[*'KjpP(*Q9ofL^e3h*kb,B5YJ'M$#^P>&Y135]ci3aD"d&9P,"%5"_YUXpO"F83JU))9PJk=?tp(f0.AO7SO$K>B4AIa8IqNl'OYbY"jA;[7n%Gag_9W+egY.f8(k.h)q%LB@G$:#C1FA2XM0>TkgG$kF5[gPD#m&`je4[-'8PrCC"VL!)sf;7E5Kbh)r,&kJHlgEAS\-`bqlN]0Ya#ka2*Mi;K+@EArBZUIp.E>NBh(j`U<+-ntk>t-QmF`Y,jA*I__nA._k/S"U[ql^[Ctc>e=Rs:/oE7/i(6A8^c[i6'\tlQ.q[#DoBe[ZHk$ Vf1W5e?g2f\6bK*SSYEZboDaLqNrBB8nX(sIU+*Ca+!K:&/f1_`Ym9rMWU.e,r/gpt;_4Pb!\tIW"m)f=T>UrS2+ErcW=!#LbbR3h<Cb(`3n(fOSX2!jTA!i9\K1K)AV]12k!!Hn2@8FoqfBK0)5kisTAbMb:P"^HogtX\4q!OeF^!G,c;boDYB/7$#cXUV,+0W*GjL[3o\#(:a?H'BqipVm1-sDj$=d>niPS#J>3i61;qWL.aVmT!a_qA:%LZNW7(]=F^p^D$$cELa&_e:AACH0D/b'BMaat?hrA+9tsc)66"5OsRr(ckAUFL=TgA_4Da")KA0@)1gp#c1d.P4-n*ng*.XG1f.=\-;(f]\s"sE#sfSX!gY,?]sAjAOs^V_&b4c^?i=?iDjp7p%^[O+jC$Nb@l9CstnbkrQAb?'tRRE!KJ?+TtQ26[&eU3KW(L7`L)O>8E-)GN4H6/X;Pg7A7j,$]&[?KLq1* o[o'mI\iP_m?ECe=AMh)Vd%?os1eQ9#>+Gn8$L%dAkV=N_+Cb2/C9h0j$)i@]VCNeZ;d^A,Q7:Z.?]#DV6q1SsmMT$pqN""p#`5HjbIH2^((E*dOp\UFAZVKkd2S?FM=n&[nHMJ]S2*aA%WFE7(e"tQ!0T()5T]?F[RQ\R?S[Ms8*-G[fP!_J<6MbE&cY=$;1src9GdkKiJ+ZlR3m?M(;Fe:<_D`.;I HI !25$:BS-I<^1SPj)!NEmJccU1`0 >o-S!b7hZc+C(.=k(LI66g-"WP>Kpn^p`EY)T^HB?nA[UW[HMD6&,qcNb;($:gJmLcLa;mR17pA0,I1lBj;sB4U>?t>'_sA 2<7&`HACF9IMJ?HlSCGbng-J[$dG+&ntD26WAINnS$ A]_Eo&;AJdci;W?kUBK JbHDU2=G5Ef#hnf1aTo\AsqX0nBCH'iF)sX*->7G?;;FSkT%]^U\is?>BNWMXGh\in!Ld=b0g6OS,41jpN93[OQa,1.*kNNVYc`IMI?gX_3YZ;ZfF@+o>a^JZn+W6P;UN0U<.WdE4)=s.m6_%4fQD&t9@Q)9>F"O)3*oS An?632I[`68Gm$rdPAKMtHb:dU)R2DX#mmVB3GYt71=dDX.D,kLOnNd"EC9mP%S9Ln0IA&)MMa C@1.a+:"J)A=>LimCYW(1t+9,4h\./VSQHRJt7f4UJFn:HY7bef%/5=-n=;=Ek$o[Q( .:-a,fQG5TE'dntYs7hClXj!)CQ20gEE,3B4^hFrCOL$;id=;lml.kg-]dX0[ZiJ?mZISK"L#H=4T^osPQU(P/T.AA/Nq=oh4%n:m#mKM!D;QsN+1?+E^>iC(5$9-K?;J%^E3m.UIL6WZ>i[bY-sDtO+6_BDXm1tZ@%c<`&b,g 5XVjH+AdPTWB"+sp#^=hX^'NnQ;o;<7-c_>l]%:O@&2ei68IoJO0+h#Sh"'0C)^1=-qb>C)SQm?)ac!5DHA\c4sNW@KQO]c_FBO^B>5B('FV0`?C36-&h=ap6 ;KHkY'28PtoM00:m_!:h5AK8<^)O@&27VPRr>s5L6CFB9ZssE(ZfTdeGPI$T;hX#ksB(D8OY[:7_8oD;` ld8QA#ON4+:oi(Q75g]Uh#'YfDJSR "nVWiP$q'>(R[-=Z8T#WI0rWo&k;0<$\9F]B8O5!baW)45APX0PTd4ST^J[F5moRCC0InB)/t7Qcq'tWL%5tX!]Q)E`fN38\8$hGDg5AA:)e9cU;qGf2AG'2Wfqk!!j.SV2EYn6a'_Ors;=[F^6D5B+M&9Oa3J>E-DAMA#[q4::0jp[l)h,:3Y*IVcb/"pqV(EjehdV:&\X&]'f@ffj4P;)'W Cf;_2-C0Ps_tJ$@*ZeV6)LfY[a2U.m6'VL YFAG-)?-D<`8!bYab.GE&AiTj?*V(hAsHaqNHUN&3_M%(Z3.@NB;%gfi0.aH,XVl8UTlG6gAlcZsgYM\7ZoEb+</?@ekqFW(OB+m&g8AR1BB`NdPmTd8FD?!9*NHZFQ(*Hq5kc,/oJ efAmpWGYtP+QHa#LqN ;bGdUOep`3&Q*:NafN6@+-q)%l=Bh(AjZjaIsF!32;'aP31I';WtBo"_DEk<#?$54O4mOH6YhRTp\oUZ=JTEfDo9*H@I+/A`/H$)PL+EVM 3R4nR1^jOc!_^?`>8KBMT*]QFP4_r9a&M-A/MM%9&Vqm58C;IJPMR&!nXR,\6'D'mFfh(TN+.q#$=k>T?5t9H?$nYX:@=DEFLVkgA:'jM,?dGG!AIKHp"$0!KA%2%!d;(#\TG>ULXZ]'24H?Kq-hK%Ee]18#S$nTE*Q$m;[-:@7GI]r3$#bNg26YaDRCdb1H&G[]@f@&!#%]7o&J:RpN"J:Pt5M:2;Af00/b"F.7!?_r6gHYI-&&l*42`PqXHAO&cK1S q-A.dej%g2r_N6UPcZAj'/Q)iMYQoWA!63at](rR8BrAmc@5 g>XK5U;H8nY)jn;jRV$p.%cAZoJdZb0.U:dba+h,[E\Hhc6PF(h]l*!O-%"kg9[A3pWJT(CXae412[=6,Ahng7YjQ<>VoYsY>;?.56aQBtL,B+c(9:4]43_H(T--b#jp38=3k]5PJZc>mN81oF\,V))#F!FO8pMD:$BI,H2C\n1(U[r.G,2."jbEj4"h*G'5CQg"*o-_,o9Yq1"=MFqm;enNo)2me[s@t.b1,006:h*-7kAL!,dmGB%p3.[dh=meVN/,;r/n^Are4-1`MV4rN$"q,n-M0s[K#J=@/X9JFr0/(gle^TC=,-22CM71id:$F"'M4hWk9mU<\GM13iO&/+F'>'p;UlE'M$X)i2^')8V']\)W8i1h'=]!;D4sMj$7fO0=[r/O;G&@%:E]DJaKDVX0b;LB>1H7\r0+C':R5aq1k_kUef.BhFW40Y1^AN!bM][3j6#88q33ddAoQ5NEQ]ZZ<5A=(/cN(5@UZ&7aZos:0 pdrGQKe+o!!c !I8N0Tq7N*p/S;Hpcp6*<9ZEG+V%;SWHk%eQ7hU908p$nboO:5E'(Gn'BG4)&E/6C?OMF?ZW`(lq7QCfPF89#`\SE-q2]N2nstM`&iN_ '`f6Mq6&8p+*TI/I.!kM2c)Ibp+iC6Ll\!iB+2gP/7b)?rM]IHA0AXAo4"3Vqjr6K>D&\7N]`j92l9[Fol\B:l;QBr17S4dP,X=_US %]LJT$;ap1=F"U%O3,AH@YfgaHMP1RJX(P]JX_A@E85Z9A-MQ7Q4tR_htI@LRLoONhYCn1kpqIj*Zf:>@iD*9p5Ag_-7ea#&Xo,![+3nY>#c&fAjY8qiEjKl"2fC"HU2k5Z?(VE]lc2o&$N].k9o?*/;TZao'g+`[E/gpCbgp+2[B8nDGdtiqU1t)HBNMn4Q'j;b<4k,.V?XIQbon()B8)jnL$)s.JGUo><)]=+#Ha=+dLlZQ[<$Hg/@PD7fAi).d5*Z_F^jk\K`7&9#>W3V'1lE;N!`N-<0-H+R50#A_GJVdB3>@g^XX`4iI3 KU\6*/:BNo^U-YAlY0L`(BS;EY/rHeA^m[]t7^[dMT!-70VfUgS5`W$mH"OL'h5pO2640 nVA[6'rDE6sDJ5;U?[52?Y03-h$jT#6K23$;7pDLR\8g?SNojB!VLtchs`MR-75n.`SZKf? ?+4lTFJ;jE6*$mG4'$K>BSZf/=5c/IK&&Y`MARfqg/E ?[3n+fd&NKKe-HkFVch+[3ojgg?4H [5<=>]Pl 4?Q9Y\4gsUq.AGsHP3G(#^]6nILm;9dR)I\sH2dM3UVKE7l2aTN)7:iKG!$PB>`Er)j7kP:HW[0=Ad@p_(52`>AXOcgkr0aM=UR7!KFs8Q@06JF(.0sSM-*#Q-&+Qp$q=JX3X?O`EC4eAtJ7fP^DFRR>4MT/jnZLqnWafK\VL\!Fcl&j,?;aO@WCJ49e>mJ=]d]hD]qml#mDsM4t'Kj9j@@jWp:kmmoSU=7Vm"A74oA+SAe^JX,K&H_7:^"i^->gKdi-UZSs+Ghl32NZe5$7:^Q7WaiW[8Pr61_KI-e,r ?%4n iag8!+,Jt.A*:COLpr_HK$;_ga[H3E+('^")O6n]N@#:;dl?]09dbH4g^pS60c^9!>RF$PioDhJJb14(oF\AbC&2$JlC(;9g>DniH(`tN'>5aqA#3[mT\9(F&!J5L3?F.RU6M9;'=q eV&>Y1%d]5e9?ZE&7D;>B*-QJSr"O*WF\S=c(qe8#N4FJ!7lCIpn69-3B;W^+6l4&K>;^U-R\@b13VigD%Y.a/c[N?d+4-TRjI,k`m.LfE##>#lt27lgCeL_>(Z\W]$a0Oj-f+t5/rnJc+dj@d4d!H(a3DK9lq7 .mUI$^/HTDL[GncYFbZ& R60(<C7NZV@sA$5>hmHPd5FT5$[BA9A"!n[;#) (n3#5oC#q%f+)65O =tR3\(*dIjm5\)WO)Qn+6,D9'P]A9OO-V^f7Sm:__ $=L7SgZ ./&`hE )#T,R$mE"Io"_VLU4`qjO)fQK=2fS,2!MMY?9]=;1Osa^T rQ.OA]NZ/<@MWrQ4)".Z- o1,XjZK\3EB75DCpL^pl8aiUeI9p1EcH16ZQ(^V>NiA</,$R\&J9m 8I'qh4l>OBKadMKOl*#9nhBa`?_:+I]1@ssK`%AH&JhK>(L03mPfr# J534:BkK8 ^QD"=&),c0%-^WY1ZmWg8Fn422;M+I0UZEA<@-U'&A/`2D=Ni88)t\+F+`l569P/Z`7R.k=ei2;CLTo:'jGb;"SaLdBqBHm=d;O!5Aj MCsU(AKW7US]9e"_9bg,s:??4VZ1-6HirJD"67_)%Fh7MAN\S\BDSbY3rmWT3k39I0329e<2o;0`:W:4RMdp;mN)AC+>@=chL?8+XU6t3`iI<O'jjBo:,RC5pMQOFpY)9c06hS%@<"`N_`>e2hL:Y9)!NU)97V@U(tRck@5i+L,r+iA`9@A=MF%1crm%2(YLX&.ZR6IIFZ$tjZlZm3l&1/[.B6Yl8Ug7V5m$;/ >EB4\>MOL<0%&@d21bOK@_XNFh;H[J^hQN[?9b8(QG7AeG0NmSAE"LC>?P!M_IV@2$WOJt,O#0D1BAF3j80&)Rfn)EbYX'ke4dER48p*VRiW"3'8#]Yc#%bU0bo1)M/n$r\QF13hkF^sh;4KC*^[QoPi]MpQNQJBZqm=Oah2=GJJI^$HcK\d%_e7f$6=mP\;_QtEX/_J-+F'^%4Y%:n06T]R]^Chsh)Y'i_mBZ^ib6^A%aP\sFa[MNb@GCXC/S]<'jB"jG/)^&@@_ADT^bht;?=t":ZOi9b1lJQ':NR@gU%VA0ROb^[Z5 #Qk5%cldRbrb6$j$C7.r8p<Na0r)^4pWN09k)jZ79g*:W"R[\8PGqd2;e]t5M8=)46^I).[CQtVofl@>?.q"pm=Xc" YLPr[:]nh TK-qka^LA5Q=%ktd?W/cK!old>\C1bUIL3LeNoFO7.j+*Al6'MShW0ENADFe7MZM)1['2tK#;aID%gH9oZ6BI:VUATCX2K%(N$=i]]^KJ$tWQMj<="YQc-fMEJo<,rnQd!0LO;CdnqdL1Wc] .n@Ni2psT5BK38n@h'%PW,XRq^gH#A=k7t;4Op\]S,e1+mNgj(:9 IEO0$T&X1G^-CU/RoW_O,F(6rN<6J?SB#GY%;c=B;Glb>mm*&XI@!(]!7>sT7&m_iqo/#QNDkj\p8VTmK@$H;(9CWojQ9@ejK;`nfgOoYbH>E'MQ7MT$;nG7Z'9)^WflKHU@:Y4O;5I\FLUb5t7e:gkN"q(EOdOrehq&r!ROY3j>U;iTK,p1sJ7s1?4jN2-dnArgtpW0D+eC<>efRa_Kh?:aZ8$K1@ABgL_n,kgQ:\n*%tW;#CZ1'c)Bks@W;'5P:hg,iJSFcD$P);k=6mh#A:c/DSOpG9./#iTg57o7rU]Nt,2KN4rW/'!gVA"KgN8U]_irJQUP)7`oU9_NqSfZ2`dhX,ctR6T,gS,S^78>W6hiGW%!rJEdqX)#jsk)6(^M#cAp%@d%o]4dgqLK]5d@jg&pt.dr)`$#$WECm[Pp 4Q #0f]At_hMl('aJCsA2S/M3jiG.a1d@c22R-WIb3DX&S^pK*qs-(.TbG^_/E/F'_=p;U\Ji-hkMS0:O4.&i'a+9MObIlfMF?\Qd=#A$pq;N+bh6j>5;Qh>$5 N!dT&XSAbADW4T)`/;j,t%IK=GA\SP??R/f9!'E%$7mK\tcioalVe2g_FeSCE)qLAstRl;mOLhksfHc>@d&\h&FsjdS/n\d@aDA_PdU-_%fV>3++RG=qc>T:(0&_G+9U;MXYUK\AO?H+s3D!R$OV]mYT#dE#g_RWkM"q(I\AB81n7S%M!VB,O\6)l9[Cl$ F["h6ARRBHh/At4ah]s<"b?4;fL[9GKmc75:A2r\0'CSjY\ ?f@o]pWN)Lo::Y,-#+jtJ`NA7`[8Mkt5T5hqeAf:tkTP[K_,GE%5A'jM>h3J@h%WG5oVsbDHOr5V9V+Kq?iY7-:EQ)8fAS<\s3WlBPJO7O]$o@#L@.bC&hDoW<#!.8j.<deSSBIlfMlFMSV$)=XP]6_r([V2O\ddm C27IL+'0ifqoH"?/,Ji$R`$!_tN4=Z\^BU&!(PKnsrC8W$*hPSh!JZ?:j5e%A/YVOL?[po`CD(-at 4c#FcK-NZ'E.V7+pq,(3OrT$8%E>e37o57[BeTJDYASSD!^;%ob5K)46%67J"l.We*2nFE_+Q[#2o]h7@AKg6QCZO@rFNT=M=,"'fF2inBMKam-B85$AT6$0ARI,"ndV*_nl7"/@ATWWGg:k39m(>t.AWg&?f"3>/Rp/ahL3dtB `2/$5?1bYrhmJLfcMKte`@/n ;s\PnT/el`laD&EK"5+(3,l*jjPWJe(E7Ikt9cJ0%Fc@mm4c3s^AaaV6B,<-O/m`>G+(.&:#aZ#9-4LM," NefR'XeH@nc1AJ?![jD]Ct+iFl[%%TUY_'I:%<*,/&hC@cWUg-2(9>91LXW^WRb6Z1Mpp$-:l[ DQi0AoqIoO`]b[G"Vn:+jA;%kO0-<5Bag=g_$P\tZ\Ufl!4Cii ;QkA\1%*dY(s(sSHDMq=oX*gK?G>A!kST(H.)`!NNb&A>'kY/-)&n'UKd',g+4$qNIQOCHPYBJ7!80Lrt;"M=>5X5G$;DHMNYQrdj!jJjQt1Y!DI?Bq)ZRZH>nCk\c44PAC4^5PLIc\g.285(6$?(c/!0j8:NCC0RiF*k?AT^qQatHh0"d(C1H4W8P>>B:\"^Ui?A\d(YB mOnh*JlA 'VqmWe\0q4-=QqaMbKSI45>A,Z>_#qfRJ#[:c^r\S2+6le^O/TCPFI>HZ8=/G-548sSdom(J?C3[$25 @:Oh<;JJA6)#$H'B+`06\Pr)o%;\`#+FA@:D7CMl8."5'AU5Y0UCNL](BA2b`2 $pHjf\&jS4<0!`nLbYrA eMZnU`,o#Q.[: )3-IZ>^(MUp29?DC.a!)r7#h^d,;D1-coAB:U;=))#Ng!GP/>"]q>9M(1`FW0a#Wr$7"cB$>#E 'eDCTt]3.FS0roi2q]J'B(JtbZp-es2]((SleEpVd4,B@X`=n,LT_b+/I;b?K )<6CS7;lA/*qA"_;J:1O=mrAgeP&JekLD(Z$ffEi5O(E79KWOfd]SG@7@\\NM$^nV_B/US&U7s"kM%G'"K!&?gb:%Kb82?&'"*Dt^bXt>k9E'h,Bl94+.Ns=el@F/FC\1-sA37Aa&<4p,BO5>LLD/c2N@01M\pDte )*nCBEAN]bo):3V r8BdgCl Jq6TUiF[>CJND$=UnJftI5^ApC))lfM#&RX*lFnJ'h5c@/WQ14=GCl'6o=;No2"C"JI/TgW7SViQ/(cjX>M[@.K8?RN([-2HrgS4B.@A^?AP2??N`")AN+U<@;BRAOX5=9<)\F/B!sid \]R4qV(INR$/o\*\m(_8eC3ki.QkkFlPkVSK2?HWAXqMY5*L<Q+V:HU=/[P#l*TEt!fUf5..0q/;ANor()L]\1ZR9YZ!^qaJt4dWt$AoGk?B/@jn?;1LDiLXq:qX8Ip`ciQ>87TOE`ko<3Dr-QBPV >cE<1T([B4^_CgZ,4LZf!bt)t9iVR(1kWXpj3-rrq(aG_SZM&O=-2QU37V@gQn@Sn,/!HqiO-gccspXsa1$%e, ?Vf'5=@/e_,ItO*U2`3mYcqB^eZ+#Adk'>A;.&2osb[=ZEO@^U#:ifJ<;GgZB^o!>D5Gc^/Hq9XH$KVb=A?c%DI294lh+]p[^cDj?&J/CH>p>,l/_1E#i?-YZ-)._(QrZnSc5?KekMbBPs;]SmRbJ=(P-?I!AedL*C@,$dqDm%P&*/*( g*qmb%q!nn8.hs\;nt!UUlXRVsAQAE*#qaO#Y%E)r"LKQNJ@dW"EfX)+\Xf=5.TH3/>dJ?9W tU9s#&CHsFT =c`3DHLNJLkA1cJ"D>aQJh%Z+I=h^rE>d1VW7'aH]]JG6I0YGaA\I4_.$q\b$R:pKB;n)m>%K/0l9LG^(bW1$qiQ\NbYONAA%c. ;:PFQ++0-E5P^s=7^MP8$)rr47`":&$='>ihiFb/>A^7^3UO39<>#]l6N[%B8M$t2jP@%RBeVOYO0l]pOnrFAN&oO:7o Ts,gtoYh7:\1!Bh9)!XOeCHYE%9C8pB10HZh'L-a0$c3AS=r^a67gCNkVht<`c_]f>R4ZAitLW!L;og%CIJ*^T9RsA,q1:c#X`UI`K>kJdN]*A"qD#1.Ua/!FE7e?JEj EGALbU2cdRpPf&=$do/?2),R]p 2D(HtnNsNp-J+k0V;gb6l2;k$e5o:JBCXFf.S)SHs:C/![2kk ,cjJ Kr2,Qt@$$t:-qhO"bnT3e>GFo`K+PbNMO;Rh:fKEF b^T7a@'oJ+a>"^V2Zk)@J`@N^pmAq%QWQN+!+M+bt90mtZE0 `g%qYf,qqqpKg+tr6`aA;Of*\RbV#Frr=&+-pqWsEFAZ/&ToT/sW&kO_7Lt4FL-UA:phLq#DbcirKJ;:J!iUhKdJk`Iq?!8S=dGd(kA8d;klrp4J+:88cXMP*\1)m=,E9k=hd6*I*90X90`?JA1dXAYfX!D16fdaBiI2gA'(;n"cBp4P\XCih-r#GAN3R<%V0<q2I2WtQn8%:*V2D!F@KPQf[A1`^V*qr7U(D%1C0t hd!_.2J4'jr-]MrGV+bo'"EoM:^a3rR^#fm*eQ'T$gA/d'Jp>5c)Ad)p-E(Kqk78CE#O'\:KZ.$GT^d*>)K3MQq&G=R]"2OGEqP%;BH#9<f.r!D^/1tj[ik8tIpRlXq@#7H8R3rJB;AKNR;68#k&"1O)^$.PB0(p]pN$R2i1>-%+i4*lhab2R3M5=b(`WeqJPG@;KkT,dQe)M*WF>&D_N*ib@0E#,[WS(Ne3YPtT -;'m-BQ,jbp'eo[pBjAF>f#h2b+qRd>%^++bN`P]?CNq2Ks$^/XnGO3@G&rEp\_&AX7XH,7!gr@**7'BiS)pERcqFmntb5'[=Z"c/#p:(E@_eZC:p?kPH=o:1p@3)J$\A]q'*C]G*9fa`jeSZgj2laCfVS/+Rgf9=%S_KB[8,l[@`lR"B[o4mBA-dY!UM%Q2c=13AZZ[6fc1["[9g\"=Uq5Dl@d4n^K:'982?V909L0= Y\5AlX1V6$1m'%]"ERYJPnT)Gl#/Fc<]k`/U.[4;cR[b)j#q4q0Qpc=c$eAr-5V+n8(\DNtiJhPis3:@<.F:[`KrKL8W\i,[1].b((pCjbj%LDh0?H$2Z*)J+*Lc`jQZI`Na.k>`PhQHNn2A=OJ@cppcMK00LPg"L@-WWZ5KE#s_ldV&Mtf)3DBA%!#?1I@"`-^E^=!X]4AVDEQT#%;70kd_4V"dKX!j^/UfH'O@[*IHC(b]AZ$ZhLM/X!0/Q]Hj*V%k0mI(Y8$XOn\.qIn5/e)B"I]#/Da6V\'O]QkN_G)[I=8'Y(Z_.RqXB/)[MIAq#n& +nm qtG6g<`OU\iKY/dQE6D5kNJV[rJ=8[(S8T$Ig4eIP_Ff),`&Lp!cC phI)oG57]I6PZ7ciGAcfh87BP]!`AMF;<5TcIYXOemL8En[ag"!hb]T(1\M&7[4C]n<>X,.(bE"Z=([5+>& rentPm#3'4/>U[ mc^#Z6rV*\t$LgGp3$:*IG-1.25FGebgA4U&coE".Ab+j-&ZR+E*e!p)qS>1]'bT-)RC+6/A&ZKX'T\CV2Qr3`E]]iQn[h5&5Ma$"*M*)bf"rb 1=p'I[c>VGXD4BO&O<7Y;W=qbng1bNU[-"<38PdXNhN941Oe,:'opR3b^,0YF\\+f07p3"0lXp,tKtrIL.0e^*.pf'00aE$R#8W]O?4=0QB3LUr?mkX7B(m;)co6E'"<1lQtfQ@5mR0YR*`FFYID+'S0K,Z(nal4ssG[7IS%s^48pi2B,8 (A)KiNFLc6m=&O)5j2 ld*[8=I!/f h4\G#i>h?@8P#VEE76!^E)V!l$DeRMMriK1&8NgVG;f,X^bfZ8;N4$nqP]C^A\%?AmO '$aWQLR^Va,+Zq/p@aiWi?>N[Z"2S+^e]cMRH;7DWNFR1OOaj4sQ^l*]XC`tZV8T>FWeS8N`'`ZmSGbb2eSFN!\>bDh=Mg:S!ks4EOLh&T0[*TN_`kpiT1=?:k_k;Q0I]3Nl])gbh8Qe[+!k4U1g]>XHKo9tgI1bb V:/`FVt5e&D/pg:(d.@+Ti`LPWE+W&/"YVOO`C4kk nOkoUl jY0"< %J9d,%lsY,a]+`A!Qd$WR\n:0DE(XF nG9G?GMXFO9&eBQcA$Ma3]LQ5RBX""7_De@DAoZQNAZJegBWjA36hDcEt.OXm8d*gd_-#0fc(:9*/ N2F9AGikh9'/sc_ISAj:h"s3Lk_'a=a`^3(<`BbZOk["B^_Z[[/,eq4;LT:oHXk;r5;lA( n@cjgaLC2[i)rKZ;OI:EhCnER4k#)1Yoa,+EQ$i6)dSr%2Ba.i3: Z6SA($a!gl$/nC6>X0EE_a72CE`nHL"`ZGU_5SWAA?W! (WXtM9Wj$I8P'8dij.S0aU*$(MBK HLH6'U[tq#JP7->J=na1WgXIWFkjdW;1Y/sUn#bTMqen^`7bA>(^c[!Kn[f7p8AYb(N2%5\FG-L0^5"qMVFfaV;sBVm9oiEHgj8H#OYoUjZMNTL]MqdZ!s]cpa;;lN)0USZ0k+_G!MnioBE=e0hs3r-CTIilr>3q]9?JfI)sNDPA#dp;\3rFdLnA@Vlgp74%r7>Cgf\N4eLYHU?3*\67rK]pP cW23D84fAQO=2,.p#g4RL\<&QdV ^;qPsYans`GF=XZhl-GE%EW5^K=(+(V=OtTqc&:bh48P[RUX/.YKGC]^DA<><6b=Gh2Dq04>^*V370c+O5F&r,CEhV5fK)nMfG)Sr8`i/9K-7fO=b@T+\J+7EJ@6klM`Q4^Yf+e^kXIrNXAGn;/:SJYhcqAr=0shWAs',%1sM.3OZQcJeJI`fO4RV]9g$#h">h=C.AR^)4e&Q&K5,iZ-B(t$:NFV#FF8tY^GHO5n1q#PIMZ_0JrgF[%\I7R\CK5A:-rc-P6fFm:TGqbU_rjs$q+O(I4So>0[ApW!qQ5IQnZ5GHgr=EL-H20@6Bk(AV$0UUF_#f9(6#g":j!Vsn&pX)b477Sif2mg^V1$*D#_.DY@_CmmU-8`$i1,h6^8U.(EtH9<m]5og)eJ!bbP[b!QGEpJkP@:bmPkCONM-(-`U]cXU]gC"%Mj,@f%/]*q*9;UYd9!)=Ne'4Z7rtB]b9pj"dpVkMkA4d>@k<(tQjjl"\gQa7PArYdrTe6r=Fe=T9cYL&@LU6=r5r]hD:o42!1ARde,?dMrkU;`BbNYcA"=KM)hRQ`r\hoQOAA37TNtXr^(6q9@=N9)j6I!8CJJl!pg-_M;tMdSa2sD)B&*c8t/dY0;+=;j)*-03I1n 2I7F1jpOc(ocb%%L/XUj\s$EE2[!<;]8k#])^N+AlXfNZ6/jO^Z2^!R,"s'd:k<[[^ig6Z6W<#(\l5m0+^GHLN:tD`4,k,D:V*HTp8)O_K7DO[>f!AM&]rN'< MOn)D"o@mK?jmgi%FltcD*0.@,-H(e6!!F<5Oa!Q)A4OHKi=2=NDBR6@jDrV&Wj.p`!VSUb0Gh8*Zjh-X[3(Gg3Nl0:'`YMLhApqnB0#aJC$$_67?8k]:lA:+pqsqs/Mm4jBpTGGsKA8RH@k$)kJI<+c^HbkSX0%Q6i%m;?7J(<X\V\G.lX)qP]=#7?7HPMQA>D&q+P0N@9)JKEX!8dCA0b"8TbCZ-4C%L?#,4$UAo`9IPt"K`Sf`b$7?,ne4fS';ok_3l4HIS+7H,JV(5[NqX4TO0KdO_&'"*ZKDtK30&f;;*"3p#]t1@ZYl82b^sjLL,;P)$tJC='b,pm1Cm1CoL1(]URj,HA?_J9;VST47LXYmIq.O^,!54Q4RIsp6QWdbW9CZ0g-5J;Z1i^4bRIk96r.nI.jUBUtc^I![At*:&UE(KjS(/ Jd]I,aAkEn]?QaL!&MV:b0tVF\$_(fq__Uo3W'>*p+6%E,[*>T5hJR^FkJ*$#43+VhrK&&p"?K%S'r";pKQ_1qb8JL_:#Np5>I_Oh%>m3;' $kA]i&P3A)7WUXm*#ZnF7kU 1WcU4+/c,^ -0gAri,BK K=cYV*G9sXa#/#<iK-Y]`m` ^jW GtqIn+LA4/bkSW.9MZ)ZRbNBKV_LN\>$DohPie]e3?rjWX GP.8#A2O5-\7"C,KPlP5Y&U2[KlMQo25q.3EZ/#]X2UYU:gAI"E4Yd2`IY%O<$ptj+Y5]LR'G?P^mRdRd'qh/>A?Dch4Ys!%UG'FYh>6K5g'Wo]c.oGTbGS-?^eAW\3VOP=+T)_WecM?5/9/6e//Jf,$7((V@0/%O_k?8A&H!C(gZA$\lIS=bt.=ZY@%!*`3#1(<:>NNP_$?-H;O/FPOsqr#q?B!C3%4*:JXFlF#cLCIjr`AG:B!d'B:ai=HEr&4cICiI=dGf.F'X;M6n5/S8'LkO6,6SRf"?UQJ 8,8[=tiC(UO]J/AYl0_?+#]rgkV$$.dI 7HGbO;WJ8I^^/ZW:jj+m+ZRir%>jmWXkmbC"Z$[TT\)Y[%)L_O+>NLsS-^\Kr>eStgZ#G A:R:mQ9l024Xb[V]M'lGW-%sjY%:s+b?o?Oqid&TFsJ@HLOL+=1SP31P hSX@eR@61(H7f\W"`mdPf:JlLE\%sVboqP4m\Nq-1j^;jA3521f9X,Aj8 h61c=0G480E30bdNHdj&m!Dp.4OQXj#aaF!H!=VO5-2R)NsdM]o;)bs d/2NC8_'%hG"68'4CP22i5 ID*8>Kok0XF^'mPq6em/"*-0SQU`KfTbIF."oVADl9.i?JbIjp!>4;qd>\/mJ%tM9S^(IBK8CF!'a:/*2^=R&TVHG1AoIgh$;4MMC.sTZ18b@_Zo#F^a'lH%VkRFeh2WYgs>2'$]7o 4)V)"jRBN-OqbfGi5`bUbEG^cc4TB*.I,M<9sX"\hpBYZHZU&@Mp`(t:oi*W:4eUk:j=1q ,E77#5=+>#V]iiI`,A,]$+;aTN]qO^elX5gd1_cZJ&FRjfe50o5YP2'/3.:tN)GPGsWD^3FHn<Po<9t.kFBFP/9mJBM`>qf7Y)jBEs,'lX0J\@FpCNkj$?;b53k3K,1&Op =ktW98o6go'DlS/q$]6qIlD'XPAPmF+52*KkbNsoh;Et'l?WA^MS,cWZp(t5!bSfAhfY-_Q]XtfE,'-9JKs'SPbdC1h*.2MmDb#CcO5ZK4qR hc$;0*<<]G<3F)bo 'As'2@+[.Oi&<\UAp2/fMeA.>A6/$Z"R/ENAd47X+n*=b4Q+FRK00@a(!! leYn1B)b%]n7>`@,nF9q4>7"BE9fLGLt1!X3%,!\R5KBn;AUtn2@2m,"#sBAj`+n(HN2KR7c2Q/&9'N ^XS:_/A'igE2AjG,k@@A^R,I/t:L?DO'U2Prl1NJqr_k&80fZcK>Og<s-&1HYFbg8i:+=@8TC6GL^"HdhZa@D$#-BtK;.,Vo(!keiM:(oDc,3m`!eK8`/jha2Z&Ch5ohpX1bFM8KJ(4*T_*g;DQ#N/SH*GBlsjtIsQ(*>'6c3$J];t3h6CH,g2P/MT7r?t,TKRN9\;OM3RbVC0bhSX_6F5R-M# Tg!EoD%SYW*1Qb)JLI/!MfTZ5""s:8Fmr0*Tp7P$FXqJ#%`#=_Hi91XEeFU(m9+m2hA%ZW4E[?l`=:QW"mdF>Ps03m<9`7jB""<4<6$-`bCsKjMAMPCG2W BC?^;O17GSDg1l'"Pmojqq0\C^,I_\).2+#%I?.kI##'n*@PSh /o:lPp2Z4b7o0EQ'c7%>Xme8V0/+A[A-_n\L\l)=Lt!%c70O[C(7qZ&Xk_@jh'DphP/i7p^g2br/7boPXRH[Eo?l];bY6T&LrD@4Zb mjUf9>\b\PdtDQ :AG\H91r>R(6g6qAb$7DXRdjt&#mdFFjNoXE&]0FU;,LKf.2lK`7In."M0#RCDI4:C;p):5PNIKrL3?oqj=BUQ3;4 AVCAC&1nibS^kES7a0kLA50\3((0f?85.QdN-/k:in<)tFMAkQnN#Aid/G'-+((:Pf*)lh20R&gpeI7U\Yl2k#r3OD%VKs\#i>oggj6J8"N-QlI4:t=+raJWD%Fj [k"AM^O5frFf[K$SI?eH2b,*H<YJZnt5(@Ir6VDUKnPh:9lsHAn C4]AD&Q`"lqil1BAIW+FfiQ[K]K="X'dM&Nb)L*R!A?Yq1C'gS(Y0#U'52,4&f5$">_FN4iT_2W5`Dk;&ib\_qM+VUPX*#<Ftd(f`XXa]BO';.a61BGK(DaU7XWs^d* f)=8R\0C01IdA(>_o:LX2c1!mBV<4l/QA=!gg5c!dX"1f/cJ1P((2,_LkH?hi77HZ0I=A:fO?4 ;$FnW3F6sg?Oof1g'GCA$&]Y)..5U76;%d!Qn+-kp0BTl'km"!0[bL%2]?d_Br;oa(Z>qta.#5A& 7P;BhDR&rW^c(N?H$ZG&eE-b0]m"^:$D&m5aAeh=a_.]970#lT,`a5A]BVThe@Uk)_8 ZpR+H-.YTY3;1>![%_HdMoDPG"s;(hh?NRqHZt"eroGFR9`2OY#VA1#2g>Fn`]<sQ]!,Mh1Z'3Gofp(K(sF(?BUJCHa)%'=L?7gb07T-&X:'n"3`8jh8kaK,]9IG6\/(`5fS$U%Y(qmE"h Vi40&3B5$.\'V/S^Mh$\P#,Z%43m%R()7^iP$oVJV[p@6-t)n&\87=]I^1L\7Xm$T9cp,j7KZNa<98DU:iHc [F!naeI4_E3A15X=K/?&%%JQWN=Hd/_DN];2 a2d0B4+h6($ 2kUAp^im/nP ZYNj/+7+E>\t@9r<sP'k&JX9 h2^2QD0/;go?MKAsS(<&3AQ7?MN=Y(hX9#bLReJ6M*/8L>="H34g#/NK>Ad1 \CmZ'F^F6E`PKDjC)efPUQ&-XD]o?Eo%(9,N3NA#Z[P\rhcrL<84n RsP^.b+KZHk#;\'XYg'knHL3 gJ#doTCiI%XZ@alWl]r/9b_7@0q/TIMA%=L2AbG,3a)lo?H(]!$t&k?)a?b;gpK@tF:H)I5+29Z@Fa8^58D%0DO%(5564 (&RH(!OdYt9-C=.ZJMsfhMR%ZFUc(Y\\5P!gcVp^+5)\]*)N .1<"i-71jr$AY7p7"9T),c)=`S)N*B6:L0U*aW-HDXfsXVf&a<(l/tsMn`;`[l=;f&rbgcDP19ZEZA`M6]Dis-MCIcAO6c+p_Cjkirb!a@hLMC@MqCs2O`]B#rob8S>_U5OXA3pr&39^o:+e9hi 'I3"4N@\J7Xa=lJE3f( #c!T]m0R%].V"YU.*=4nA:rY`)W`4sGkr.ZjqmcYC0gq\QpDs/%Qp5h1>ZaEk$iG4ddArO`raj:VV 0a9Co?8!$SI/:Y'1@hY75]?Ff'^? QFb4lTA.f$Yl90*85i)JDM)1n "UeV\ZcL6WMYrcW7"8A=OK YqMAG+\;q"$Q$C'>(S56?>3A2UgAC#$.EH]?mL2VM;j1kO[A__NaH)etB4AY.nDt0PlpQqVNA`@O>JJG]5joI]sKc[gAJ3GibCf`aceB6$AQO@=hcmn[:%9WVS$?\24 o>I^]qF01Sc18 KGW9[F]`I"A$rA]$6Q?OnpSHiaO5_q'XZfnP:UNHje<=W9eXhr+2qdXobd8)-FRk2OK?\GHPXt\?Wk`3n?d%5iZZ.fCG#MDi_2N&OObPNm(' SW:B8jX`%fFdY+_'f#)B?:*J8sbf$D8f.?<&Hh-37eQOA$E [(Z6"/H`*"%I??Gn<X&q5,@D!$gSMs/ :*&%b7,-&<;A"Bs3CMP]<&$r=Mrl^`$Gg"Pm/521-C>ldl[&$aZ-6gmUAESdC"t`86-WGc'm0cgT?0g.!InTDh,_;?C7!-SC-B f9t$\^.0oSHA94BgE+A2)Ca^"&sN4aY-`fF_N`'8''4mTaq[2kH70 i+EJh<,N:0<@Z`dsBKA/E:$];\j-9O5#`\Y6.'F4+AAI*L >.+Aa"smg1e-;U%U)M/>o^#f3*la>+ E/j!4FcZM(9RbWR0'hE\*-A68[F_G?dIbeH!+cS<,-m6L^8Ffa)]!9>E;kkaW%rds,W+a6mDnhJ2E?DU'f0OBb[Oo&>"-\P2'Rc!Ls I0cE'nArkdfYsfo_`.74[rF` Hi:9a(?&:SprMXm4Z#nC>I4SZ3Zoq3E3207!e`N7pL]?ALII%EcE)UcAsE.W2Hp;H9f.6+, ghLDk,_;h T&AP("mHq/_[9kfk(L0+c_kI+X[b[n.99_:>$f.%.56=4%s9A%%'/"LZ^Q)EZe,i%eJmpGE?Ys+0$FUa@=fjAQl!/Q.CH2_%2AX^<_Y:3SJ]rcrXA$dP).gd([HQlTq=]p7/]!LO9*@=ca0/Z3@0FIMFf_siXZa@9.G&^+ C Fsf!VNRTJV4"sdYt1e`A8fG#/1shHkP&:Bo8g,r^['#Tg?tFsP%J''$2>C)+>P`r)'DP&/J95^P fLEpi4=G3)34qS:,XGEEiEqS$Qj^Zdh7D/7C"8KP&(1=We3^kEtL4TbtU?mk;.VSrCA$8d\08>K*hJib__TmH4e!?G5SN_49jl!&VAO^s"^ PQKL%5)aA [@#,S0O&p]=6,mKq=J,mAB.<#*(_eS ii#NK#p\H>Co*SBDXiV`"%;o^=4VaGiDdCsB$H@\[ FiZ.iALhM>=p0R8UoC&CRV_OUDI5@4>iJ,%'G=Skgt#hMR6H)Ka=91GU[ao9UJH0Ym]S:ZY!d,-1$1"ae].!Ao&h-`/L"ej3YYI.Ge(Qce.Gn*QrSaX7WtSP`PKoVMA;KN3/?YreI$!KB'/mi/ h^$W2`BjDB@9p_JIrqFTq22\`WQH:;")70d"di`KBZOp"<:%U6/-@@T@:KiYlANXit!UJGtk(.t]$C#o+k;:WA&DgiP+TR1r[W2n=KD.9,<_F>i6`85t/+(]s:7J?78q*>>7Q' (Gta[p"f`;AAsNQntj[<HcSFF"iT%Z,P]j/G4lXD3O,ABJ\L3N%PT8_[='i+QhC8A \.X9$Krtr0WPSG`"p8 tU'AJ#e([Gq21Or[em.EB,"-r'+:\t:ZmBb*&( kpA!:63RTsJLbATN`//D$WXRI7,UIpoJ+jDc`<1tVGpW$Pcr#OHRPs6hbZSTU=mkPVLAhL]>@*^q:UJ,G"`'&/)?BB3]4c1p%P,_% +/?^@oPQ1?7o+ppq"@$J+cK4!GY">?J1'-1fA_lNn/[rmG1,_j4oq62Y?^9Q11P0E5'0'3J+tnBlP^]e"0kN3Ekc1WonI9-qsMs@b-.'/AACX:FY190e GgVY!hZ+ Aa7V`Z_k0E865">AW=1Dk^,,nadpT?l,%$1UUUqnh51&M:W,(UFc8Knc0ULMJ`f8h]Pb>T*i_Y$RHG5hsO 7bb gM/A5A'5 5,*;5S82DX%QmA5fgNi/1&P;q]dsNU41[#D2D^Z:M&[;0>b\:7jR*e* _H;m;@09TTsFcjAt-$H?DmP*]l<i`33Lth-ObZ#[_K:E1oBKA\U%ZRW/$HD3JrZ$M-%5!t<7.Z0]pM.75r+4gI;5rS?sXMr`\0Dms:P]2@-S@b7hF\ N\EOW*Djph-em`ak,Re(UkHPWM1`S@_8=pfcP8ZF.\sl9LfGbh6r!*fU Y@Hf?VDaNQ=><7L_aC4oAT*BE50p%_nI),^WUrm>77Ah65?7lQMn<"4@nc]oi3t-A5qp*BD@e'&XCij9#C.FZ6\dt?YRb+^2EJtNkB#o$)'-j*T;Y!\55BHQ"*"fMtP2[jgYr:N!ncG>:B^p=+AK+8_oOY8Gd/%R9]$3`o'aKE34?h>E9q%iIQM-+L46?T]4U7`fUoR!'Wekf._+*ED9<%CIS:^tD+/dd>0^3NWop?Inj>Nj[%&qpVWQ<<'dAhmO\pAECmd2l&?2 mDI:dVSc!3[Z`'!%dlD@8pAKZ8!mkb^^kWP[l.[7\C)Ut\hHaj,H;QPBdpohH]fdK?O.A,EX'5g-6 ZS?]! 3rTg@NE1_r9>p K>[;D9OjYkX&b1g4#fGP? @VHt"HUY@2Iso4nIZM6TA]&Uc]!nEHLj2[@dUd"(f(l!VOgneeni],`S)L:dL!&h2`!,$F,=5MZA4(5*0m%#/'iQY 7D&mN=2VB,19(_Rq]Df+Y!\=HGTK:1J?rkOLae^5`JbE9dah/X,k\]:A2h.Gginn.j+Mb>EXl)Xsb[NNF"Bltp.U=0mq?THM0*nHSblADA&aHj#s#Tf13Jt4@!6NKoK(d5.TLh)9Zneh4)7i=N;Ns?BA5kc"=Hc7gUeX 9spSSBdPO(,JX%a]"Z_fAJ!:"Ds9frG$$lIrib./&@O%f(/`P6E`3T@e?Tgo]rbc*+5IM:H8"GN"j"Ti#37eB@"h44>+B"gCU)eXFRsTHp[V/&a QO:W<^A$_:tU[/0"2>T,YTRNY Sn_@0#m\3"cqBtQXY'?Ial2BW6nhIA\cUc=c B^!d^W9^_-2_/qD&1#nst7C-&W03D>ah.%AU2(Je.AB.e#GZFFZRP_GPM#E dNaY 0VP1D8d.hL-%'UnXRtLI@YE"@q"QSJ5*.1Z&LKison[,3VDs[^MEaS]Sn[35_.]M@DNso)?sOc94@$QJ&533m.$k%T[B?%5:!;D95dCAt"f8(M/,$_8@4Ng[TBACtPE600l;0IMBA`e;JD.6+d_!,C7X[3Ap5S+JkPT-T>@p*HfGgC8G8l$Gt&;j qFHG47U5rP;'A(8RiEp@-"gq85#djA?-M8U8l`BjW*7"o#3'\$dI"Da38TRHP=P=b^Wq0LaaA]%K'8YkcHJZ0>RVokpZ#)k4 $Ta( E*Tc`dt_L%h2PhE.5Al1Qj%)HdAUd@.S4R8'+U'p172,a1$&m'*N+8iMb:A&]JN+-=Ad,"N$NbM?d9GjD's27\E<@s&bG1?me7&qFJjE?g)-^fUf(SoF1K_\W!jN@`lf3h*-Ud%8Ua!AkXGOL%U]+4Ol'!5J)M_!`X0/T1,N^(.SC77FpSiE_rZ^N*g5Ul:XIks/gDdZs70+kKtZ/sdg(l6mE"akc.1'.6) OI%Xoka[%<;iI!q<$n0[X\X)sJ>:.4trHQF,< =UMci)!lr1H'8bAc_m\8W7C0[fP`^sZU0W?$$.%XAB5G<%JTq#0L7OC#F"3Lb#eC?XB6:[2%PM;S+e6!8p[lA*QK7Ci6E)FZNRk'42FmIK"7$A NL!DG0!ih`'L'-@jH*PF0+^e$4336K>LoV!'YRt+!IpKM5o7&]JRKrL qaLj\W`;_NT >)t?;[?')A\^oa518(VaT5ifW7i2_DFA=.XE-R%Y+TWiZAQ_**DS@<6]AtYN3qs=;"t+ni@$pS;*K)6BAta'lcX6kMF2Z:H:].7)+*EOFhSH4S;R7:QU`N>c.S9B*o6^F01lSo\/NX3nd:7>9Nn0! 1Jm7c8X$<5`jQ9,r;qNsognA[a*D2sp5:JlS@D QI+phUn!m(;kKD,2k+b`Wh\M3+1TY(, mAs;!2;NTN.U^ /L2%D^'L[QT2Q[;4OJqK]Ck7E[o2IM7CXBLW*m1?#s$* H"MR[3R:[/.gC\[T!`2h0oWM]*&K)&Z,Kh(JB1&.eHq!N[M[AA$"Ee"IC1\:j7:DPn/h):XZM\OPG)o],.9]NghLT$DA#5Cl+I# V%t[!l9GmT;)8AOiFEXoL^(2'AVZMN#>0;9L?,JF(gifpJ_*pOHQ3o0:dC>aAU=kJnrVq_:;m5r9BJ5Y)df/`3nlE-6e:^i!!7@!b&&cK24pdA]mdr(%hi@YfJD1YJZ(Ddrj08G:J$iR%o\o@4aVPjB0h59$ek;]W)hK1B1-(^=.gD^<1Hgl8LmF9M*e:B5`Zf9!)IH%8(l +VXME\Bb>IRe8JEQ) XNm9A8j5.Doi^+%c&l;N$LXq4]U/fkm$0$;r.q7aX3)I\b[`RhVg\&@]Q.n/>g 70`Ugc7pRQ*LplB&QOro5!!g@8HMZB7@,8RtoC01JED6o5:l_/e'Q(7hal>EiWOh)`KnQh+h?5r912!?'r5'b+(Y,[Q'#='!H\( _`CBR/d;`6AUDN:%d)@n`Ag[,#mPGYWrZ]7?(NRG'Cl9$oCS@^WW8fL#po4`[U7&;&#MQ4l9T.Pr902kA!LQCkkb39/GjZkTm)8VkLZHmj5%UJ#G2ngHtb([`WTN$Q+33HbF]qfKqUmRZ3H$m9l6*G06>+h g^`NWdnW*Cg4kkkteOf*aOTRrN-:\e#%2m^87^1[J9T\#&ASQI9[O6gha2]jqa Id?:@^8]ANc>@*G&.(W!%J0?U\FJIrV&_CKVR))Gs@H=0I4f]-MhcM';9"l;L>dm-)P9fUJU@G*`SE?AVGn>AkA >Ce`Q_-Y`I@AZtkJq!oD\aIZ5H(X;g<O5U]Z\hpOjksfb aKpH>9K2fds^;SA%_J"Eo*"F+F41H,KleCP717"L69Z%5(Ah*j%:q?HH.maa@to2VqoQIm!5CoXk&"Akk>%/['&bP\X']n-A.)q$1OA_9C4AqpW%f`U-PrC< M %6DqGB\_bYLtdAd)L$+4'd+6K/.:ANU.5nk<5$9fSM+,PIESS]a'Fn"=*qg5PO-=bCW7EhL6/1.=hgF.JkE_GPMLs7/2WhW#ZYGLY\Y 'UTr;M7Z[\e:JIEAEjr nisP*ZAD%%X5bLSMC`_0Vg>hbD]l@8Wj,;CX(K&3XT%tFR<>F)'q*#R[bcS7Rke'E>_6IV[g83]4@QT,&,. ^7K>nL=N'[,Ka`2s4gerT?c1>+%+T9E6_""$NjT-]_A:C,\O!N)oLJN+cIh>7M9P;I8f7L:FJ`h[$88Z#".tae"1(Kk12CWL:mUi@[/R^6[Fl?`m89[Q'7MIKRtbVtq?jZOWADLb)5LfY9NDQlo[I'jbtm>1#s;n'F)J\B&X$T!9sH@4@gBL"KZZ3lpNV*pm%E,i]i5PQY]K[8M8A02L]4.P_8!6oBbT1e4U9s+LmG9BX1a1SoTJ!RArs-M+4oHkM kmbd?dm^IE$`>fCid0I^j_FA6VAr11+Grl$h=>6ptU>V.D$-Go<;AF@[>3j)B^`8scNE>>Mn-B>,d"H6>3]6_[`pbI Tli@StiR;]&^BmL(.O&ll 7T:H4n21BRe?`b,Y9@G=BC`3%/f8^#S]K,AJ]Cd>%tA?@JhO+3jjb6mg.[lFKH_N54JI^7n+.R9()PAAj',,kea\.,*heik"i@KE_Wd,=KmhG]")2:_[JOp,G[C]tGs-d=!_7L_pb\'kZf$1I'2"0NlS5XXH\hW0+tL6tIa8gWqDQa6SWil*jk4V31KfU#h!L-(2kYC=6RZSMKj.M&W44@Wikh*,8+A/k=b8h5/*O^Ei T.X=b?\bmFe4p =Y\%/5Ad:(39>AWP#ASmINmgl"gP8&^icBi;B?3,qR,UdC*COaV^0r9^j'J/g1'^k gr`W+8\reRBgta9P,Tao#^njl!.aR"nT:YQMp[+;sLi9m?"h, J.7VpH.?LB&'75J%9JoR&iS@9[rK=UldXCCraQCD_O("f>ahCTF/-Pq,e*QC7HO%sAF9-@XEV5QAft?fZ+]j6If9?D/*Xq,>H]8qjGaZ,4coEai+qPAnrsoL5!OCPl#OQ2Qj9SNTT5r=@-ghrL#+Z?)f9Cn\^+VT4['%"0Apm \ajn%s;She/E2cGUe6S7HifFtC\C'f$Drqhgn6BknpXP`&%lOi=t-aD\j.X/SAW)7AIZG&UWi_(%A! I9pLp8hgsS>;Q;rV5oG9dLDI1=[E9K19`__]/68q4[nWZ+J3Y0X Xop\8bDX.*#el,[HVfpa#`@JL-`dp)[Tk#.:sZG[J>9P$:LU$DZ--9Sk;"PMja,,b+r*i@qMY*07mWpi@@c*@ G'%setr`Oo i$*<)K6UY/`X\3./4W,cg])P.^>ENU4ZbY,p08=b9KW;06emM0r2D]rk7*eq>]UYAQC)68bl4>opCE\@Cia?Yjh'DNB5e!*%JLf=/:.eGj+P4?DC_Om=IFNsJ`Q,R`E9*te+:d6sR8O$k?=rhKA_+]7Z]$]6aNKc[mmE,:FtHn"Z[SU`r.E6a;'n` .6L1QO(!JhXaMIO@+Qsq)'+DD-5?B4d$!Oqb!;,%/c=+I5tW,Oj<^a?%TD:r%f_9U]1t5js[JC>f&O_cV"rIgiJs^,mD?g(;(_GAV)i\M)[#kW''Ur!O*kP57AnnHY7[47,R[&9SbcXW*BVr;=mr8+_U,nUr0I_r^@ br^=pAgHqka3BEOph67]1U#"j3567IZTC*`oGdO21Q3l/V:m7$KdVE;bV28[Z#G.F^&cISNhZ82.emT>oY/^rs.//X=<$%]BB"528)tTn4ETK _5C_IZm;"&."APR@,;=JGk6"o.[?<%Tq4S+9WO,Y:aB#0JLjW0#Sm(\nr`o/sP3Ql%&%j&<>doic^smX8+27 '4\1M h_0q6)99eo^tAm^GH!C'QF`e5r:ns#*bFm7-:1 ](B`E2trob<6e`^FeI\XUA9kMIt0'M5)T_IoX5pN`2C*E#\2AcR-Nsd+ pqo5=;0JsKDQh+'kN'%;"o%:ChHIN$R(KD5)A7Jc[eHBs'!C1>3m(-fGVYj$ZiX/Q7HArA'Mn;8r.W]i6m8/f,>4>XB@MJ!Io(o'T8A@s(?h`KbIGDOkMW_XCee:lL;\#@1I:YO8,p&dMm]#h,*B[o;-E%qUt_O00%l[_BkDt,Wkl8g\6@:S#a302_O>dZ>*>8)Sat@-\/Z)ds3.t6]-a:eLO/0_0tPT-Yen9(*eGfRT@F")SfYnV,$?L>%q,A7NT=/k'oh.kI9f.4kQK S(%_X%`:"%g0/]-iEm&[U\ARk8N+U3bl4(Z]G$9_d'hbSoK#bYreD-cQ"]W1T26F@^WsI QV,cpI.<WPTPiGi0/^_H5W^PSetF:UY-Q4GMPIg:1N-Ol;P#iQo3i4CE.]eYi!b.HPqP8?8rqMK&)%ltAtt7I[2Rc,.F3()Il`)9B[FH0NMiF"imOiBAAQm??^25+I6r6eonS@9&nM5t#5HMGTm&V?EMn(#^6B(X%X_4*o&["iSmAC77R7$h<(k9T(XHbMA7/&C:WHXsLIsj:_JJ*Pjpe$sh@tIp:F*]"#H8KFR=QiEorEFC2VZhO'(\4^C9qNQh,rjGm8[JAmGAC0V@=G;mMLn%Va\ZK>niK0tYo9E7\)kK\U<#6(oX1Ngcf?Mo;dB`lpDI9fVs2>#Hf>LXnq7PtYp[8>:NaCgFI+Z@#As?kokS9%.00\jN"UP+F9*5dQ:ph\)b]Lr*Z:E)bkl q8k1L3mKlc\70&ZNfp7Xq&3]dNg@[T3&/p,id;XI54:&`jOVh]U"Gd4Y"gq5)\n4f!TN!A#lCG:4NV< ,%p`b<-4q\dt^n8b&lpgM+dc/HXAsPgFABAakW!5h38tHVne0prOK@GV+Dh;.A1#;WF5Pb &)A`Has6C#0[TASJW&\8JYpDTHK3_DE1RTlPjRrcm;G&I88C2CrFY'Lf;8c&sr&pBrTSsN-&LTj%\-ct[k^\Ro8JPP% J;Pg]p&8C7`CRLg:cd+T=L*p9VD+'[R$EPM"iniN=s(57WT0eU$K:l,;rATGAKKE39d=`!N-VEA&5[b!MH?;.kKP"XrkJKa-\kZ[SLD5VO,Z+J_lNp@2\HE6^^NO%l%+D0^c9>j6D<\'V;;6[8hd4)2r@\">!pAjXRrKW_:hPT*039!&)D^slWa8AVt35M?6^?8)XTqI*9O9$SGsX!cbr@t!.FSnIGf"_TA(FO)_DGr?Cm"*'hhOkF)C2fiNoDP8YCIkA!l0gOG8bCXsn.F'3=9#(A#r@K@Uq51k=@_,Qmf4;^p7XqnGH=0h#]p](HJ?Xj[>r>?U-4ZH_iR3c;LenPcIF/4\*.ORidj\:Amc]oJ.XFN-<es"F#Q3IA9>aNP")GnN[r.A9qFK;Uc;f<$%X>U+eU]\#pj=Z hqWM:MTq$/&N;eS&<8TLd:&Ab*r$I`^Tjo9Vr=O)->.eWoX67"jKGNfFA%?q-'EK=8g'_3k:PMOEKE66cTU99+#(D PREH#Xer)2ZO_:4H:'/d Hp!I)nqOrglfos*[lJ#rR&]ShTa)$W;ZKenVk`)S[8@?B*'3dHLh$9&h*XmqI]Vk#@AZ"RV8n(tC#LlbRUJ?(hjnf)ZtlUY[ sgHsHKC%1nREJFq+@D.nb4aA!9pS?c$#$-DA*6GQ568LTrtQOT79!lk2d FPo5@"s!WY7q`=s1(Q^S90M#2I/3pHgkr=3IlK% 1r\_'N\1cEU!;668C"1-W-JJErl:VNKbji+2SUDcdH0\3kh>c26a1h#6$8AV3dCAk<5EbS1Z 4`1CE7a7ELnOsLFXTVF9S =N$7b4;a&,7cUY2hr*P]nX06GrASL`<\03eZ*[lG`_k`i);at3041D"Q$`9L]YVZ)Im)IX<\62,DmYMR\HS"t?]o1:NBtH=[:>b#K&Y,$Qa /sl][0 &?pbqX>nU?)1#?jkC0)^$T;OIEGAQ6RT>Z2+')DgKA232na)2586_o1=A>?mBk.9\J@isKbA6//kpEdDbA]pCoK$f!%#?`e;Y-;d[<`&+=XS\&VAoaFZWlAJ#N\)4E=0tMCMKXk$6 Qd<#5@rNCh%7bQeAke(c)Vi0bEG/"8`maPqA!RC6D1 ZH8ME@A_[flBH_CGObF\AAL];j_@Wkf?hM25%P6&fg3/0&ZQYE4(ABStJ'qKG&=YQ"A=esLca`BO5b\!,Cs%U5WTM@Xe@59in0#Wnl2CGU/f(I.nnh8d9nL:.ha],dL%!O&(;Nq5MR]rN:/Z;ga-Rd_JjKB)*`_4T'2AY=IC:d./8@WSU1) [8s3E[W#gm#Y]g4;[r>XD`LY)lAF4[TCgf$-_4' 9MH"I=N+!+g4q:;4m9WI.n/0dm?!6mW,,C==\O0^I"PPLZq2b^J$q?gQG-16IWAdHt5a>4J/_ls R#6\J5$X]o%<%'"3 `A*]=0>+@dhpC!UWb>_+;@E;ka\a h9Y9M"7Z_IET>)L k$dbAaL9]AM>As=oO(Pc-D5@p#<'NM[JQqZT[P=BLtscn*t6C+EYZ_fh0QSCk$LI0(a&`:jtpm6^%=L?8?]\F"P"C](I*(^fSr'$[gatV&o:&k?m^:PMi.f?//`>jOF%`N/ 7-7N>d(R5l"q8=D^C0(-M&tddJCYL:UdMj:pZPmi$_;/0cb7H/1?AlmR(S62#F"e,&CpSQO[m9[-,&dal@DWZ.7+H!;etAsatJpZg,i*okI,S;8Ef`rj$F-N\'%=DM\;$jk (Wg7!2531OQ;Sj$^j^m0jU%(l]j-e$RGirG"po^71[Ie9h+(OLAU9a D4e/HbsAne.d%SN;;goAQ1_`SV 'N*3#kBs 'TfNp`_JsMp$VYrcpIG9C+pV7[j4d,5N^\EK.q1ff!AU9AQ$44B8T6Hg=T-E%"VjgbM%dq d@13`UgbS?#6I$pdl=Qb"p1;A-Q]0Ro]bA "k&5G(8>0`#6)JtrC;_hdrU@CBBrb'%$C=ohkmZ0Q[\1a4A'8l)nA&o0#<TM1aXEGm9.%BqO^dP(H&?q%?'FKQ&Y0g];8,Y-5c"f<1V.t(%#H:;ek!imGA"`(k8+.ak^_CUl(T(eZ@^;sf0!saTpj)5peDp?ZE8?S>n'=3!iZCh-<:f'ZOb0;C&mAF\[7(f7=KfAhpjlM7RT)%=jrK%C&I8J2&E8,+c"mag3"re'""-#rrA?O _0G;KM2gQo`HheqqRGAmAm7"I3r2WYc'eeioojXT"V!hZ3`D\Etrgo-O,VaX8UU_#7GiCgsXV%-PK1(JSm7R'&eN$kQ "#kUArkU4lS_VQ;rVsiQ &@A`csf1E`*+EjNC59F[V\'o0$#Rhbs)><^/Q^/bqL3Z3k. [Umki)clEnQN\. s]S+8ZF0?MBlAqgC\[o7F(1WQ CkHB@F>BU2f2Z>AZ694KkP4q;tkSKaoF\RJcB(+-92"7=6Q_*$'[h>e9W-2,'"E#:D .TqXm'"HeM?]3-jc*(T *QET<^]bb3m-P Y#-\Ql'WL\X5r: H_BjbLsb9a4N"Eb/Em)"hc2XLIKrp.QIXGDL.n*X5A6:Iob=-6k;SAQ_N'>e#C\G?BtOAd%r'H8aX7%5C.5iR.`,Ng0CEKL6_:=UQ7F])d6r(Vo,^O6[I. IJC(Z$kS-sBWMT(mRG*::NS0$Oo!1O<e!7hE:R9hJY6IE?as"^YBI#/Cp'9YGW`V*c>`IO,&)k%lQeG4&oQ*2\aPM8]Fka(/AH508dooZB@\\I\5;iGUNH^;S]NpcJZ>j!EF>NGe<i!2Fr&"T\cMiC@K-h2\g^pTTPl%X3Q#2%t7H/cBGACb/q%>rU>On@+&d"5;;Lt2A=N;$S67l*ZT@Q%7A&t&c[&04&C]e3M;+!:k&ZpA`B!oT$CJ:IJ@Zd>ki/!2_-9/'mki_alD bhQB,nUVA#7dW^8EB8?R[o.T(A5E-?80 DSoTFEi04?%h1h$HL$L-L=nTrHlLAj;q^A;lL1E\XL'p/B5/@9orORMon>Gmd+6B8_r='+MABWfsqL:ipbmcc[lY!A#^f;AS\(\;inAR$^FTn<6%'P3dckS&]nV/q-mpOIgF-6\kriesO&TM;B9hX.[d[>qbd-J[Bmfbd_/j(OVKX83N8Df"4JX^:CH`\fT4,')p$T#0XGfAqY`i]/rm7"PNQ[e6J1OD#LH$QYMMqH1%QL.[tW $etq=r$F=YA^L>DNj4Y.?_C?+2WppMb^:j!.=gl1/:?pBa6#tZltcS)R58;MR09A#p!Rm%RDaTT^"o@-C@*%<;)q%/4.W)nB7^SrWMB3l>$3`UfoUkbgRW>FGK$M7c:gV6G4cWcj(+&BXnc]6Tp+QP%.RW^'-d3Pq! U%l'j26D41c H*(gS3NiQIsa]$Ion p8H3nr*>A^qpl.W[6)\-o+RU]Ydn%s.ON3@Ws`O1*qj/B5AVF4W/-1!ib\(B9@a^gIpW;e96\E*d0'bmpb]\1)22,D(jn1X?ZEglE[U[9;%D^n7Ad_P7)iAXj@tOFI[@4=>>%[g87r8T3+Pt<)4)5Hh>ODI>'?5@APJcV&bXH*AY`#L<4`0ef;N?aC1 P*76q!4M&T3T-/A$njY]p"KSCla\=(UAaWKAi@>iViK+" `]F-EJk2b&_:6OZo9rJ^!tWW/OFNCN<3lF ES=MTpc<kpe1G32)[*p`'At?J> S-AnSDq0'Qf2,.)r5q!MQd03c8g=VCR:)CEe[2HVNg*7p'+Bp3^i#3HjDQ(7i#!!XSAmt 4P-K;,!k9iJ ijHq4k]LZ %KNOA+kAN/^X1fJ"2I,0#<1mlMX59[XUg7ZEm,$GRW\L%LW>Go/qCES.A-0D/fBHd3R("7&n5[Vi;&q)4Rt)js+YEJg^0 &\V9A"KD&8r6t-@=$>! (2aNc:5+I02R3qS9Y n/FBP%$;&T8Tc]_X6p7(;*D)m5<#b Noia*7V>Wha)9/Z2i VW;S"8h=LsYpW;%_.iM3=#g`L][H1rEKIPHVV->?):`8!*Kr2Tl?hq!LQ;\4=rAfL*Aa"RgH1_lR&S?F5HAjP&T0PIg4XLAYRAh [a1Q+lkSA [("*1BWR+$W+i&G9q1][oPdi\' V_1[kqL0K3ID 3h.MCX@V<8Q3PDP4K@=]ob7A)cI*6YOkn\"R=o2@2rXaZ=h&&8SLr'2?8ht `2Ygj?Td,lsoe`b9c8hMpQX&,:o=A``PAX_W;(+4)UmgC.k%k1`?HfBg(.l4%r2 b;s)4q=/kU07;*Z!qJ/3_n$j9"=@p<([2LfI7M`##'[*meTIHG%AZCXWg\6SUo]>aLFk'&#RA5n:oZ,2raU7dIE)l/eo6S<6^EL+tZ*dQ^@m.nr6F`-;sX'@'hOcoT +D)Sgg(\5B/7%-ckN^1gB77WogW&+=4:f"d."r)paXl3>HBFX6XEGjLJ3*ChXJS)k.IXhHZXITitshjDD;mSU43qBRH!,MK$AD-&H 2A"H?q!dj^rZ9= \TYg;[G`SU/@>A`0n;(a@Z/2O>^1=5);qCFnM*3EnN-rSQC ;"+$BK: ?ZjaHJ,FCq>R@cBhXG6\Nf?Yt^99f!pI2e]S1*\p)78"LIY;AY+f5%hU`s:heEq;At/0?^2n\V&=pP5/n`KPVO9UFmNTgdZ[ZgVA`\ILfOfA/$\DXq>@QZ/1AC:73)shS_[o;&%iW<;^2M3=hU'@TOmK>A#)OW`#A:N^@bWOpi@[3st>adqdQF>5]CsdIlI;JrleEc;"dtUI.iPA6A:eTAs$G^oKcUJ?+ct4idA+(`C$H%M?G42c*h(3Fa\7j^#U9(`34N8R1b2qJ_dr6dhKdU62W2L%];]8MN@ipji.6s*fh[Ji@bJ3Agpt_cIBU89Tt('!t)B'J`3/,W?NaYSr92X9t.n=3A.djBQ3Sa0p:@8/oqFPYh(*P42s" 8@:1D\>nE*sn`/"^ATJS3W/?atV?Bo&P8@m1 HK;AS7+K,*FEm#4X9_oqJjXkHg=S^#8RWRp1`!j)k*PY. MmlA&1\r@*t$//AKr8F!R^.bqmse14(AF&Z:Q=o*LSj:>FpFn(erd;IsnaOKAmTMH)9G8G@YFp*(#nh95M.@?iX9,lK"]%r><p<^' T01#ekmY?7leqSFN_a? jA4B'I.VB_K:)P4#;b4#CR*A`cT9q%CUV[_(NYU7LJ%ciL(4P=DW\G]/7)=M31E=Q=._hI1+(Y#4e;EAK9!6qbZX7 9P9YY8q7a\#PeKlAWO5Z5A(1/@r1?J@FA:X5[0+j9I9,#)>26ScaPBl_T8G$RAk4^b*K[F\k653JaN1Snf^lBG1o=[$7<``l1jAI2TsIl-;#.16D%>E(C^t65)0Xm0(CkpN9F'Sg]VPQ`j/D3?$G+?L;)$[Sg$(^80m<].TF&C+h8%[-,ojf;GN8 qWYRg/CPL$qj7b?7h-D24*G1mC?c;"Bq trOD*aHJ+8:4M1'8AA,r2*fK!%&P)[.nQ'af=`W6/0:h9!9W06U2&YW*=m/K2@ANJl&KPS"e:=S$)sYC< _8E*4`=d\]NMLW!R*=5H!@g4rV7F)AtX0!^U CFP4e-:b?0AOmp2+UQh[PYK2H;@\cmW*!QfTraE2BFWQ]\M1jBphT6>_?#8A]'A./9'.[%o8W_KcWtoF:*>W,6PKR`P=$N#*b*R.0.F*gIQhgV`)j3mcLZDpnLK_*&=@)>B'.9sP4DQV%dnb]>=.f+bMq)#kHHUJ^dC7"RiAL@QDLj#r%A#QV)`5.6esha9J7*>-[C#:&N(>\tCV*aB[]$XQ3S@tE<$%^Njd>#n9>.K.0A\j@pEbP:FBAt9qap*"GM$]=Q7 7?kR7l6,)fXV;^^GfoFNL GVS.ni#P\@Me] <&>H5o4(B!g9pUY5o%[o7dnYtg[PlctW`5`T.RprS0CD2m?*/a.?+sHk0BpAtr84RE``9iK"^$i=aMg_e79AMf_p1qGGjY,=@>E+E%5Ft PLFgKN$;bA)XYFNdg[1DPlckss5mfe"A>Sp@R`mL%KDnZ/=HU@ZA&a,N"cA?KOY*(W &UZ+f]Wd6R`;q)bgnJ(m>9D/c"!6(ki;AlB8UGY-?0m6l`l[q@J;.`RF!^^psAIHXr)CMPbDRNJ\dFA`oVG1l&\-?I5QpAQTF+RhF'!#=F\bOh.MsUKUKr;2:Arg'(Snl$W078sP:kPhTiUGL[0Q!I$/!+)1i!@5+/hs9@El2XkddQ&JoX4f]cB>Q9#EfY':^D.I&Mtl.cAR@75]Q\]PbSlsX"G/Z6$NUe.$Q)+gGpF:I2iJ@O1HHEgA,d=ZZ:-jLe0U4QjDtN:pK.CV:d&_^:U(,EGZPF5rA73&L8V\ t E! Vr6\J;*\[NNE8QqA\(m1dQ[6VHT.\?PWq.O:l>"WAm+H^AdIs a_H\2FS*tLBZj=*oi7+Jf!T##@ 'gR\Rgh(GL0^)a\?aZ*53&&t!Z9_h)CCT"]^?XB+>/ZD>e,==9_YQOYZ@=4C%J)n5"t<7mA+s;l\?K%e@pCjq)Y5(QCt>[&L4m3kb&5/7'Kmq^pWUME.pNKcB Rn#b5Ti='Fr;c64M!@Hb:Y/O(=0T]K?8JnVf %(:H<59Vl&6o#ijl&r9SQl(#?Srmt'#?co"JSWBT"7)PanS%Z_=4aSf.:1-Oq>266R>OclW]*4h9_A,j/^V PDEN2e7cnnNn6Wb6qb4E-RXK/DC_nkW5roNrb0k/T_mjK:8)P@[ i^-:L]_?JE.S^im:89(g2?a8F\->fZ\\YqY$79i>p8l."H/EmBP=QL9JX[jB1N@,c,bg0f#=/nPLaQA0'a,oX)C0Q1TQLSYs/$;aGm 7mC&<o!2/ph`YH;ek;#pT7J+RO19@k7D0Xk4K4.sVX_aA3FZfX3(9Pko:q%PY.H:8@^G&pL__G5^![#d?bcRl-kQq+3WtiAr"EMiTTUB@Te@YkR`1W(TfAf8a?dP+aBj:A7C-eKSFcY?KOrl$U==9e:i"gA(?XBcK`Mo,)igG6btA:%C$6shNsn7=[`83AOth^RM*W%*oZ(I)WKae@:K-"Jno\#OaH!"gYq*Z^d@97OX4'%AN+lQWgEd*K,\=L,iV]!AY'o!ba+PXQiaViLAW P@Q$n!V9n;].sM$^o<.[mlHAcK?b*=XcROiNF]eVD9Yb*&iq&TWnlFgb e%1e1+-@ gN*Sb/1q;IZ%mDJM0r>Yo]i\ZA!%:8UF>@CDT-e&t[',Ag5#0GJhM''L'f7tli1A(rPBYUhe5U@\%!;3OdHa%qO4V>!B059/Z.c4-8GCm+=q0A]b;41rQ9W229`FprnZN1o!#.$^#eAp5R(*1K;/\i(I0<_ISZ>.?\^Wekbs]eZERn@5"3)OD=QBrN[krVmA]00HjR(j=.=3.#G&jDT%*%[0QUAh7RGV1=O>a"T/KV)b&B<%JOM?!dkEf-q^/d0Mq-Jnar7HsTWVeZ3j)ONakRK_FJN)[YTUQdsC/$^Elt/blPLHhiW81hWX?19KVeeB()c(piE0CY*HaZ ,dpSJoWHnrkW)BtO<pa?s;M9K`E+1]$-W.s7pCC(&AL Kp$dpX`/Y0@RZ5B[;1Cm"U%*D?.!__E<[s=$XbZhT2iVH@[a4JRDt@*XAh]eXArr4pj?YM2555jKLI`2:&A^ad)s,#0K4mXTpU..-@*FDU@TX.N7>%(h:JBFtYkr!KEG>Gh5KstO#)H7Da@7j!erQ`_6qs3 $8T6D1gP!5H5\`nP-_TCk8CKoDJLNX5-jbnhU`g5:gTf>g#"\QUk=VoSJ4d@NMV)ZYmbP &"rDGK Q7roi.+^XkhrP\VX!m(:-,lEY*bd3B#1$*UY&ans$GBc*:E3=&mZM419#E/mettA@+'=grDQJLY^]GP42R;c?JZ5;;LCnD0a)nRYoftWdk4_c(5#A?M;*D.!O[lT\Mn(2A.$F-H&+P/rg&TXCZILAc9YjBXA'28IZ'!!F6A__mBA?D2CX1:H?hQ^54O\Ba;=F=?rYPk3)4.^c^=OV]b3??]lU%$!*g`YkAa!GRG+UQtS8=)A!Y2='d:;#Fp8B-X3sl'qg+iW.EDU5n3[1"]1\<^4W"oJiE@Ma*CdFJL9`K%-4 'lV:5'G`mj)[]bgA3W)e"3ls`aP%05SDcXSM]d$;-mOc/?H)NV/#j-bl0YG2K?_c(N\5AtW^7mP?b)3;!!$P8\2BRsML.(/,.9t+?d>2(BZCk4AnR?AG*Qfd=c9GAEfXIp9(a3T8Wbg&+A_MN]'p$EeTXB0_4LUB5YiXOsMigM*SY2?Z9+&=gHlk\i7*-M'TP!e,!nb]0i21r6EY@/c,*np&P`( Y4ntisD 'R4DV.h7e'=gchIDed:U?bR9=NO,s\3mm[#O+:8+6?hRRS@*VAL,UH\Y`"DaZcgTFqX<"UYE7F^DrG?A 2l3dZ<46f9*"WB"Cd]$&VAo!JK0=YnoF0QN*ATZ\$16RY(qg]2F5&\,(29'(H'8q!)V_'pI1l(R'm444.QZC,@;7AJmP.< QnYbCkEC]$2,%OIM)'snFB^4T%&X8RMOS+8Z\?J/'8/N\2Gb/<20A1\V0IN$(O.MDh]MhK+,NAN'$KKfUXb(L/A3EWKOk$Af7;ms"Jrs%)H#VL>#^90!42jF?(+btekZPD-_>RH/q[hY%eNS;MAMkAM3[E<2M*6C)HQ>3+I(I^hkgE*;Ai-e7-U53bDR.E?0#f2f4(gm"m%B[2J!3MPZ\DXn33RoBN=>op\XBU(.:g^)g@'<>Qc#9e?Z[55L]jnW_^Z5U/:+@/`c9s\K`)6OZ[go(agP,i+Vpbid'A:N5]Q8q%V@!+/*V%Utd_R?MU1e+;@:*GA/\DQjcO8H])p:4A^,i[:\<-1tj0VXI$->% /5m(OC&";77"BmI[^.8C%_;)AS6+m,;j^hKG0`Nenf!@%oT [Gnf.n'Q1WQ,SMVp\'rI-M!tHce>(+B67J`NiFJi7SP1>j>$)&T#)tF_b;p[ecN,Y?RN!$F!/_>;(>:;GVT\dJU#nO-qXhI],t$V1aD[/]-[2B1%l0i\E$fDCmGK?hnG^p?K_H)\#UCZ)O$C_&JDX$F/_o6UJ%'qg%#r,`1jE)lDL^B;TnsO A'mk5pi/1Mjmc!AET;Cot?F3[1J"-(i*X%eRGp$.nKfVJ=A?h)4B1W&b6=8P."oo,?VWWIo-Y,DZ&DL7]laAWLW)$sI5\NQ5<.eJZ?5(h.L97rDJa4bb&AsH</gZ[5rZ\mWKlQ%R#6rcAbsfH1"Zf322_3l4(cT?q;dB;DrfsK\mtfJ12.^c!hlcFJZY7qY\S$OtHXpPIk^!Q%=5iSD?h@%)<Te#Ad-R%\^Ahe\oF@*'f0 n-\5R:,lm/n5_]iji%d$;!]W06#\Bo@D:o LPPEM@d&JW\n**q&Y:R&E3b0>Aep ]PP*9f"q8-]Y$hA+/bfbe5b-p!"H(6C^P&k&sipE\-"cb],a[B.kh^ ,"A=/]B[)6L7'9B#LjOR ST/]7ID`Y6/n]D^j+[A@V.&UXVnS7.J0Pt)<-[tZqCi#sC2PJ*68,ngP?: D3P<!*)9ta/$=.'q^dIRP.*ec*2/^YdC&JB3Db^e>=g[lEAA"1G5p1`7nr@sDgt8AP7:\dFYSgB\e##sM)kQW=tmI?A)qqFKfGn\F>5cIs 3qM0\fC]KJL?A$.((ij8>";_a2[=Npr[H",#s(=I!a&*)TY]bt8L&bhPq2TK7kGdQQml<[*i]jF9o7$]gK=dd ;>jU%4:(^nqQc/c[>T]iS9sXK_UH+UqrL!lQdM&_S7gr/tbFA^P2"#f[kYh.^Z(U(al5m@TL#Et$`(LO57%Q c^t1&\4dR1F lqANA+o)'@/IetJrJb%b/WR-$8N$A=d38K3[is;Y.#7=Xt)cQA:lX&.&;cdq!si125Nr#GW'f!"@jX#oNts9+25Fa5[jt0VNpBVE27/@4IPk->VGdg$ZOI`c? TP)OFJ8`%nhE@=SflQsXQr!T(@5hPA<AF;mVb@m6<2LKDedE(o@r&F>#F?,,\Xb0c"]!A31L(/7fUf4N!Z,&O7n4YhpK['K>FVE1R+oT'4)YR^,=FMNCUIa_hS=8''%VofLdgT,Ik*DggSD7*X0:C!'`PY]qfrU+76Xl"P?sZKmLAgn*LrcV^#mF=1'LN<6+[.@qTT0;0#N"FIV,F<_s=^`nF$tm"1h.-Q4Ri0*OI2,iJg05>*X"!i#_ctf)lV"?kn=1*0(p_]SU[%U4J2q,LAA,b-h q;BFRs6)kBgp'L/4EAU/kf2+KP_o";?t =44MWelLiom7@UfkO:N"k\Z2,=AhrY$s]'7&A&A;_I8Xc)dMP`-*Db9&U8>YeL<4#-d\eFCM3;YM1;A)8\LL9q1G[fCd*(MUSZk"/LTs42#&YaFl1BFQ*-/)a>>@2X-(;ndjcTGT d`o(p8ESY&Edi;q9?#:qG'"AbAW2$aK/;.UjRU0-@Ih:[$n!c2I?n'^IFArki5)Dc2,'XQTO+5r5L(^N^PP $OQ',ET!pp5dLO-E1kJO9a2=g02OV?Z9DV@a+fASkLjo)aF"JNjgGZ3p^8g5^N:58?,)JK#Zn&4-eGrHXU2Z9OPj]p5$+/Z$-Q3=[Hib%jL6\6L3^G(sAZ;/;$!9MIe!sVY*c-)c9hX ^B8!`V0=CY5XW>FmA>3X+M2KiWJl#nRL/]<<=WG3Y=t;_j2hS?_12 X7O6lAq.%n)&@bbm-%g,e->2ipK49HW VD%@c6'SE/81mAL6?\Z0ig9"l(%-&bA@NPapRAeBosJ*H;eSBq5eNfa7KI\_`FAe?f<*aRKKmm4Y8\mY.E?a\AnRK-'nCM6R4_rZ&7@U".:pJcl[+SNVAp0QVkA.c_<3!+/-KpW#1#gPoTm$-AVaQbMm)+` #cY^(s1(\d3-pG[bQTS#X2e>jSN*6$6& :ZR87O>&7=1C,7q9_`l-f]fln ^b`^CQ^QI5%nAH8=j'Z5MW&BMi(Osr$*22[[js_:%J9Y7FH9^/$>%%L(e:gQR:f0;s24gOi&J%5[[39bQ&f/%CO",Y'QZ>>&g7=ag=@q&9Q*Dfp:7-"6hJ<"7dXNpIT1d;]"s8SV6l?9Ra7b=heU^<4Ackg^FQAVhiU;YdUIB&V_m2#B$/c.`Cf*AK[!*0Q@fBJ#X)cZpt$=pY:_&bJN<mo[hZpDtn>Xf@&01[g+j_Y1bBqBk6tDRZX/\\lmQ&n0E:"@BrsAD#`8MX5d-;EU:ODs.Mkbf m:\"08hIRg^6C=kItD;WM$8[PMNbMJ)K'3#sbH6s>QSlh5o1Z367dNDXCRM4I)N>)SFn!:'E^GN0A@6-6,sETk?Ak8=rA$L_@39h]X%-5JAf,3eeCXHWgo^3VQCD mVqd!Hl\O$15c8dQfHVSnDCSr'0nDAS:Y/Em?DMWqc.hQ2Y*;WAK&CH7F'gWTSho?DTQOj2_!#LEBP=NA,>KX5&>o;_PTQRO>\Y@0gCnerAWa!6D^+KF+YL.Z'b\-"6(F?g\OE;Fs0kDr"1qVA_PHSWXO&;Y+:2mhcGaHsS/G_Z:!'ChZ7I^Z<+:?0.^-@IS@1@? ]: !"$s7!SE?(KJa*CJMmdD,1rRKD5O.6t:j6IddI-! UfW#H33O'YM]hLQY#JT;=5WH@V!nO@BSd-nSJ:8&k"0'S$Qt[-K3,m! RX'daCqMS-dfPHCBe\fEKRoF%ICJQ`NcG'M/SIfQns,7=>U[_4iF(LO(UgQt4h844%[s<n!gW2_aP!mj4\1G"6fA:3./>Y!:&bP/+NL8:4c6+_-F +J_-[E[sV_J^Na&RTj._ 6at+M)2&DF98d.e;]b@4%KA9;F";Ag-"t8>l(-(54VB$\=lFO4[5tqc-,QtinJ*5]D#i14`&C@oSP9n,ma]*SXn3`;)fF6GA(Q_fl"K#gd$T&_Akelq#%h7kO2qN*YPY*o_8'2gXSmE,Y7K?"$7(KF[.C5imgT%87;WI^Tnct1@N\C!+qIT&a!0U"[)).N>,K-rhQ%p`W'RM<.JY@RHepUbb;?-3(a'r\;"hk^d[7Hb-95b(/M/f4"so2f--WAPQ7-C<+!?B0SrE$eb.)m/-`A8+-j44d6]U"\QQdq`^if0mrDqa`P b0B/8cni((k(oTd>Z[]d8k\Glfo25A)^[)Z1pE&^5dN4HG^($FB4BFg%TK1^Y(:,M+>4os9N=d[AJ)qZ!o[J9$F:6/G2f[o[3D?+N@O4:U29OLK,acrJ:B..A%N[o=n3%!U5jleoIPD8Dc)SoT! r^B'a4=+%lp2%(*r"]ATCh^+\[KM@7 h7*9-S(fc_eaUK\AA`U+9P;DQ1HPb@Wc$NX%gOgQ:g2dR>0,e$g;\Y%D.BT_jso>FpDAFI$9I?FUMS1?$iI5enW`ICBJSP^Jmm)pjnB3.%s?-MH[t$612MJ_B'"R X\$aV".J!sEp`q<'>[nbZAbbm$Fl49A?LS%Fd%g;[ggO;FQ-i0B+(CS/-?g*Jm%1PH)gOR?4Q\IogY-JXn8S^Qf0AWZt=HjmS[)Y'CjWrSUA%1&4>o`GA$gUU\LS[kB+,r`/cA-J.KWbjd4]X-*$g P\Al'q-d3q-AfbA@+_7k>AtIJlL$$M4qo21\SQFLo1_V[B;tT>!$^feIPTK)/)V>EYiEJOi`_) ?c7Bk1)XJX#PtR#eAP&T-j2i6.=4tsZm\Ht9XAI+;M@Zj>lh6aA*P^9Ymg(-nB==-!A!JrP@Ujn,c[r*(jRfkdp?C`Ka'\tCX"c-]eWnE2]?!>E.353qKs7+!n 6#@GFonM(-?c#7/U `%=RF:Mq*<"(TX%6m'N##4BN`FCU]KA'IAZIS6Yl^M@.Ac9lM&j+B^nBPM_F8&U9A>4A1\,?]Dm"HjZQoeBS+g@P*r(0$h-(o%_)tF-^\Zaq[G!a!2*+kZEg1FIUQoQ'Is@!O-q6,RDW&L*cfTJMr;Oj@K-m4'q.h.&*g>6UZ=(NAE6(&A`Zt6_.a"'B,/4g6Hfhln\_$VK<9b%sD6DS1ik7n?VoNl2"AkNMRJ(srj,ggIqTJD7qinH'Dr"1T?,?%hclAMI"nj1["LM3$H.A[]_V;R5U&`:]b&6Y#jVf)[s2<3^EFT@'1k[m.sAA^O_^LFL59`KL#`c@_.37hW^3D!7q-d+sH]H"PKBbEGaao'4X0VO*q_]DiJ#ETa`/.\VTG:6;/hY=Wa!&dS'jIhi#gQg53R29DWgDB2mM!@0YmiXSUjT D!&gnKpPXUESfKN#bk#]%`T&M!DV5H#\6\@D`s#Yflk3&2%qXLo/kH-T2+lB3B0d&IsS7IA^oG>>h%GSF V]s/^>I\V7Whb<_U5;P;9SW;iK^'9MkJbf-b>'I^DY% 6/p1lqe$rmpi%@9QBQLOCh9Wa$ABDN&:17**U,7=]j`42D]FA(X='_`0=&J..5R6qj#'X=_SNl&n<0UYriB=h[1YL>bUtqiOrXhb)B t= cb@@148"gmJ<%kTK QA(T9]RnQM5*,[3K/00#\qa(\$r7 pID+>)5j.mCf[oOPbk *Hq]Un-2Neb**1fRf$19k]UK#)%#/icFAV62!V2K=>\f3(@^SAhR6rO9i`c?MtkINO)W)6m9r(H2'PB gFG4,I[Yp0;d1!BqB[S;'L+& pVd.dlcQ*bXk:70KQ;WC< <O4 0[T,\M0h3dL;rW*\m-A%C,B=p:F/QK'WOG47'$)1C*`/I.tc7*``C7q#;%Tf+P&?gn jN,t22cViK-s22LlGpZsFE.Sa;f\QVM!`piM`[X/BOn;b]@p1I3\*D<B#Fof/F:/4Jp5X`4!Ab`/ ra4j:RFrQjYq`!8AA!a;<G*is+]e:%)$;VJEFEEB.A^piDC\,Im^#IfeW(68F8jA%+/Q>s/BgLP1DB$OV`lJ`REf[-Z?cGs;A?ec2WMM)E5QT;A10:]\WaUT)s%-iC%7nSb6>=Qf#!q7Fjj+#Gs X$k(m9qAm;M_4/:AsX$Q_V!L5@1`aisf--I,&;AC[7`2P4,RNPD45@N?C`k!ZR_YRgfWtIfA*6Vok#S+>E@>19/TQVImrkno550EkE"V)c9'Ak:=[$#_,JiSFUg'rJZMD3D'fQUcZsQ+*q/MbR]JtbAA;O?Qf.X,4.#q(WnbNEd7K_@]eeqZ MCJIP0Qjl<5XA#+c(53G+)42KD1'>-#71FPlOpT:)L=gpA>nio"mCS/C>c^t@An]C_m?Kg$/\&fJ3U>TtJCaDf&!+O"S(\&i!0'Og;Tm1Z7t@"jbk[D[oI1qsV4"i@3Rcq&doS$0o-1+U*T:MB!>$E8qA:,s4*UFg]8P*P17W2"*NZWk6$'s2@ `bOp,s1C5>h0fC!gX`X@Q>># BH'>bB$BF%'kd/j/8KKIm7W_`R4Xa49b7+Fqb4O.qc)A`iVW&6%S!,6IE K4o@(lpLEUX96o=SU#cE:J1HKn5VFb3T-kJh!!eI.b-Mfke/EhEm7T0U7h+q7K`Q*]D0X6o$H Y8:Zi`Wsi*VFDtgRdiPY,A<:_M_`^h,YZNG%YhF:_I7*LF3`R.<-.0(o?; F2,A>sW*Ci][t3-=hpVaAQY?Vc`R@$2cY;'8+[,kc"r;fiQI(6[_GF@TU!Qi4NI*?=0/s$VR<_YZIdI.=9@]gakFqn4@on=`"Z"`/G!59#%^lhAi&:c-"Y1oN:dk;isr'Y7FC0`hEAoh6,2` Q-K*``XNoAc(gpA!A=[nB- r/\R;P`(=7j:UB/(W\F!L8+]h/#]*;tW<dP/ai#piqZ0sXqT_(LOb*8.=QQcln\CWLL&)aA)fGi=Q^DN$B 'Z/_^r$O$kW&dU39I"'[E`)$-X$\9 CI04eEc*'n(Pf>C&*A/Z0Y,Vgksst7)T^Rfi9=38]od>kZ\$]h*9cUU,DMlqhdQJ"?h^/;m:@:%ho@6ZU3'gmrAhEq^D2;"=8[O(h>Zm^,jO18*&>tSt4UreJ, +Fk<,;A1Jld[J(W2D"41o[jBL-P_Sg+RI)S6jX1.<>B rd.TsO%nj)X6l3Qd8@W.`WN6F^j+tJg]pdf4=?q@,eZg0&*-ALgS"qb*St>4bhsJcZWA2!A2X"Qb`'Sr@-MVjYLo."C@K*VCFI 7kT1*A_HBA^M1i\j@.^b`NQU\o/c?'Cs6%hCQcD08#J.2$B;aQm nism8,ZKpAgh%.6-UU;le#=CURN+:R,$5oPeg7<.1(okE@\UHV0`\e @4Lto7<1I-jC=PU*/0rX*jjAO>U=7q*/-4\lWG>#KjftF@`/SB_cJ1h9L"as=]ZQ'0N&0Kf`>Okq:oXe*]j'hn;[[dsd*q`5kH8_TkB_4-ESEqgMU7d02[s#OebDd8tBH+jo*MQ s)F$.-UKfl"9+f@4'bd0XsbR^=`NJ*#`.;^E,ftp;/6#AA1(VM\E9m>*4tY pe9V\+Odq+V4VZtYmNShEfd9s<a[$C`3tN%HWU?,p<CPL_@WU#Tnl/nd^ DaR"cW`HAHPW" 0#][5A)`'LTC\)%4Kq"\2p`O,;(n5TVe.JjAtWtt%VBs^<`ZV(m@9W:hSJT#%IA,j5O+pA7Nac7B ]b+__q9>JnP3Kd4,?'R$;$a!;PEoDHOL\GO3R\Z%*^0-7g_cpbSYgI=U%&?Z2JN*"c8+/g4n,MUeG.ACAd41bI%"%1=A->InkNKHVX'AU%LP^@0n4J=Z+:RtgP;#C4#r5!]4kXAh/rtSRk/tah0h#qq6*UTRW)`?9;_&agZ@<J"L(d9&%$&W:rIWCD;q&OH7<8@nC9:@:E[7U/&#.SKi/)1Hp#1CV$[!O:(Gceg60Y!a);BjF:gbLWW3,65%1qEJ Hj;+0)$rN q'#g# UOcf@p,^WAsoi&Y4o(ID6&l5%sAjAq-+,"`JUV/B5HY070!'F3kNWTSb[A9!gNFG9%3-\^*Ieh#e9'_2]DnEg3<:&TeN#WSF'0,llsE+^C,,1'6\LCg/F/68aJrSHjY[BI1'&/`Z08'0YJP9&<=m,jYFBl N'JJ+=t>UYMrtFFj53\c.Ane6QQY,%FtlTt[: _>\P`WVoMnO]E"ne- BL>nM?r_L(.7P,$l <'oV0+_+h.-Yl5hLP_tRUMYJ]#`/5@aW[0;rZ(\DmXN.XR@N&jW8_RL",/`s"4V-[l.VF&DW1%c.<-5p:fY$"bCl3CNM[-9Ji^tngOUdo9WODbYcd)3@r3#hHR'3/K&/DLA\LNkD dM:XDU`=)S3tKgZeTSt^?@Ye&1];%b;NI4qde#_^Q+mSk"caS%p.NAIU/6/Rqq9J/?X_e/^W6"Osj&3QAcf,A)+s$NA7=h2I*O PT7!jOd/(5RU[j/[J+P`2XM2JK+q_f$bGlJVM*B9C@IWNoD-!>Vf$ClFqj;J5\@PX i8T!PLA@M69mfY+$Hj&GV36ko?,P1XL#o#5N]+.>Z&k])W2JOC-,Fe,@o>@H+/];/0kkj+aTqAHmYBfDiW_:I!JApEq<`,oCX2DI3I8ls4ZX/CmRi+_LMX4)`/b+Egj3W<&Yb)-,mq:[$).fYR\230Q6N9J7pJs#g"EQ\:O-#lp)@e`NpB[LHo$_JbNJpt&-5..ct@gm_6)]A8qRtA-P1b7-r3X, V<^OHNB!VLciffttgVP`1XLDJ!Us5H?daa?nspLARhrasnA:iF[PYI4g]5E]6X3EUe5-3AQsMm.*[J#*El(M:SIf])\A@hJ6?U &*Q+sJmVC sE[ n5!WVkb!?+n"Ab00Z8gnQ?i=FC2B%gg5qi;k#Cg>8"2o*6YpO_5p7D4g/c6ESf&'Ao/TpH>WhrpA8U5tO-g#>t?SAgG/-h9<lAL54>gYZ9sAX\Gsc0m$lG^/%%H(gY+E#!.iN6BnR`Sh8;7.-ndY8j2jrnC92f6GmAq""UXsE8-(s+n_3rN&04pj]'"8#TV-W/etb3T;$q=%>Wf1S^CEZVr7q6HV21L`<pg-f\0`ifI`/fmVe6Bl!F!#'UcL 9A`Ltp$=bS7kn3*8cc<+3t6cr@^Rok=*17%(KJ; $0WRPg$7#h'--o22?aWnC29!YPe:b$mhLU\XU0&mp4UM=Wqrs^htO1\>aCI6X99s_9C_09XU>4?E<(Di:\Rr&n*^]DWsZAI[iXr1Nr?j;gfRdO654c*'/k-D-K'k^/)NTL5n!63.>(&`hrYB'/-2c4lkKq]G YijUHe@% bSaa!gbLLK,NANVFKeKsmA^pb0qWgWt6K2iFSc&h..4+l)q.%)F$C!Jg6*ofZt$h'"\Y''*`SRa.ct)R$ P2JRs0'eos&9V5Gh"&eaT&?HG.ZUBDEH*gD&TZQKTY07"i]t1'rY8SCMZK5f`A5pF-n`b)U&J=p8?^>+&SG'sn#.X(=Aqm^6S)KD@8mqG/(5]^Z4LG[kML3$>>rUX7]Tr,kA.s`RNDea#oA)8Vc)F;NL:JSMt_`9FMlVLi[MLLAU;Bhg4qXW6SB-6S+]!pkG&/IZE4.J&p\=b/Z6EN9*!Sd Q,S t3mfRlZ:$Cs6d9f j;BU&&\?Uks_bSLr<Qg6XoeaXK?M(U-TeeB@oFNK_ Y S]tnmL?\SgkPL CKVOdIkl40HVapSC& h8le+Ob"7 J@#(E>.`P`IO(gGW1$&)m,j8)]FGtht?s_B93RKA0!^?f4_G!tET9hS6Q0/33RC$l'-FfdHs)RAH17:IsPSD3Y+L8\e-)W\d`qWrkkoidqt[A6PhNX?Hc,kh!,?,0i#TJAdmoaok['CQ[(*J`8=@FQjRT@NC31hk""_>[IhkY3E/635,_J"A`H_8GP=<.%rl'dpY/(`9Cp&Q=>(t<$fm<6:/a!O ^Y,%1&0 ghC&!F0'A5dqn/LW?7ehD5?>^Q=)ZB]0&lUPjW3B^2S1D&%,c%m*f^ @NT>Be<9O0No`VlQOVYlRV+=.sA_&ll/5n,@@m+RDkB(0Oo-E6$VLZX5kAmnr.I+?h"Yte6A'Ia"8,(=LJWQ_b-#UC%m1I)6AS6$rJ1G$>Y(C;;A77A!C/B2X!Y1$L?Y;go.JT2WpG3O/al,H/Y4TP7\ 5Yf'A&^;(5d"kSGmmD/!7(C<la8B!L#:b!_UHm9,qcc9"DYAQ't=$jhcAQA3"[&tF3\rs;<"hiXI3I(#CMFk0&^73Y9E!aU:m*27;!4AS`,X`K9JgWoa?N>1?a9Tq/!BmS%(+n8iJ#P[C.9\h6>1$O"5mZ?=L>UU7+r7A)g?g;)Dkcf`Acq+bUWt;aeqJe&YNT&U-^MUctE8=P@"M0Fs IZQiji)(!)3I%2:)k&Mef.MfPP2-b!\287:Q O43G%D^9T1e$/B6-_8JZ[ 'JKt&MM9+?&d Bb8IX-'tSaYlD8.=hl*Rck:+T!Y77.9I ib2EtT'^>A1YnIIF(A?QPAL-]4,jJb'g^f@[NRVO\bU)jTfRmX+m0+B+^O)+FDi*4IYq@m:#be*i"F^8N8^f^TJ!?W7$Ho"65r8@s12=X ZgBnWj^XhnL5i],M(#oFKs,YE"=Q<(2.s:0632=M_;Dbeb1Ka3K:I#NQZ)92HD1?O%e]Q"/0iWXY&Q8,7!HJnNs3tY6-($@L%^Hh8EHL(s)tlpa_t;+lW,]"sR;6(AX 08Jb3_VEBs'i%$k."rbc]Y(J"CnC[ES"Z?)`pQH&)P^T#V^J3Uf%:B^:1PbkacUf)p-T8Sc]AF2:j0W:b61-]N1khkK;^T-GD,1Lj`G\S93cH;?;df]meBX"@Q61BW?;N\>HJr@b6Uo`e/FJ+=>Gda\7lQF`2D@pQ\rUg:_M)WfrR-*a(:?\:BnTFNmO3)_*741ZFb9?L\VNWbUQ\ iNOY<'=m[!K4<:N&933(!kAQO+0ZMh>:<^.!BL-^LXM:sPMhE >K<& P$$UKZ3-Er`ZUO'Oc010APmiXmC$YYLmqDOB:&JJGr0p_h`U^2!Zi$O$+qqr:X2QU7>g-j$rBtt$:=st_ST#WiWG]Bh(m#U?86]Ll=[#M)r'K>Y(Yd;*Z@OPnc0O6WBIAWqE%ChqLXP"4XRI6g>d%Oh2c3Sl@FcA+]9TN!1)5Z_4qNR!JW\(*OHor2E9Z YF#ZW3%GOHbker*[$1[)V/l'oNts%P3Yq0hbc_\G:!%42PVKSTEXk)ZL,`sRD1Z>Ht]ioAri/5?oa:%rO%/f\+lI(de*J(!W[Y:,fF+3`T2I12"[ceY`4V&'#Gtn\ H8MPfCF"l*d1/4iHnaFoJHR7tG9rPtsji[AL: pY?'VlW;I"31P ;SQsd6<_88#Vt?#0q-gZ?CY%]D]nan26_$07m[/5'm?0>)^EI@q>a N:g^9DMY!#g%)ZmtXr[T6"[]WH&g#Ds0tq9;WH9RAra!0qPA#0^AM#s_&OM0Arr/Ng0Ym*A"MY`+GmNeHKVI#Bk4& Q:oG-<J@=KXRgr0=A3A^P4BnL>oWQe9t+QN#GW57cYNorf(ETGA(T4P(^CIF;\0s"r.T3QQ$Qn1.mk6a,$m"[6d@91Qrt%s!4.c7(nq[n'"*c0A^I!JoZ^BlUrAA;li[E-fC-F_chc>/IW,/VqFPOM*1+)(f=tmCBeJ`CBc1jAZ<'E"!pa%_Ig`80;/4H ;$'Z%9eJb[?W5NaPtG9T"tfC<=HRJhdRT2GRK5rE#9*>)5kJ8KD,8ap Ap="lA*c##gWa4A-c`if_oLc$L387$c)*TNVJ`'\L?Ok8lsV!A\?;?]46HkkRh,L>aV?"A2I$N60>K.06:4XZDh=6MGRheK(^]]EIID7ocQXN4B5HL4q;QS\>6qp,A3"G"GJCo"Te>5ihQ3`3r<(ctdP&!s)3ET*8&ib:1Ak08U0G`?7rg-AAN7&"lc,r?-6@%T-If4`m`/1Nq>m-Uq\hr\tl=hM:DH@YrM+n`(Qo$h9[[!6AsA7(JCm4J"-D0Lh^=$_OpM##ZRb5-&>iT-,l](anU0gdZA-=&-ag<7)glW=ftg_kRNQ043b%AI=r\!Ab6T&I!QCGQiX+[ADl:?%J,AOm#HF5Y6>/6Ls(U?lmlXW\Di?C6[a-[%$.Gl$&]9#d:#)rk`6Q`HEQ/ZR!dQr_K?;7/]>l*VAf;6-2O"#mFDfes+.%=CPbXX"0s.=C]Zhq%-r$GDC1]fO('PM*K>qB.H?9h8T0pZ.l<9EPlClV&_C:lPmZ*P+Q0\;c]4WdZ%==5Lm/BXMVTH_-d`::Ol*7q1c]A*NNWKM=-/>O@H$a1c@r.=0@;M*FRARei!@a:#O9GAAO%Kds&>ddJLcVT?IT$-AKATC8^MBRmm(GW\SX/WOIPH?1imPf(^!U&2A=(nXd&^(]XQ"AB. =KtFE$A,-8/Rkj^7>cYE,f?Je-AF"l,CA,jS>l`Z?&00JV$_X6262,/n*m+enS@*k1IUG-1f'C9QR2lG,\NcdHf^*N$JZB_#m"4`Sl cpW/6,)5nI;j48=jiE%4X_PFnH:EK"QRW?HZt-L6C#?V6ng iia$VRY>/X,1)C6*aU-mO;Yp"`Kb\oI>?9.0_E3bM8F)%3T:=T 98'L^C2M,'t],;*2d=(AJ?AA7LL>)+cp^F+5)^?Z \@b.#E=m%WTs!3?5A+Il_aA)*(1H>]nC( [o9'5b5%Bc!k.I-(?Ed/Gn8:sl-(Z\LA irQ+LAqelk@EJ!C`:":bpGCT-%Wism20#Nkm0lX@fM1*XR.Xeh4pHSHn=0HUL Vf1_r._85CGRJZhi=Kf=:a7(_(=ARSeai-bX "*&9TZORq.62:6DcMOFA(=NN37F]q1Xd)W(^L<Hp!"DQAgg_XTqP/(0CoEDhR+@Wnc"@2Wtod;\/moOnlSqf`VCehK]cI4%5&=`MN558%B=0E.s&G>5mj<,CZP$KDAr_[0kb7b4K"i#>= "[46g0F/0pPWVpNXUHgOfiV@&b=r* %s2?([p*jG7&re>C\qtb^_Y.Y\KT7GS0@m<0E6766[?_(c)H7JSqT67AQd3&0lUp4.`jiQ'41[,CQe2LU*.,in47K(`d/$C#"qCDHs4?L)rb4,H!]Tn7Wj<;j(f`rI90'$HQL231/4fq3A"cCd]Ob-HH"9`t?89AhYoDV#<\4DWdo0;9PT+9ba;E&.5&(s,,TFOGO."Aq\gn3-r\5#a& FAVPE(-fOUcJ$;*JZmD\b1fZR:'2'dS;fkfEh7B-kqL;FDp#s+[T'tpAb+cMk\819^86`6@'@k'mm!Ci3J1%T; p1TgG1mlKRe:C>H@N&lpR>_2'RG-7')C 35)H0R\88.5lFP0EhdH_FRPRRA/U*7op6c@HrKbo(_6InOgZOL(I"d12 .7';]bcB=PA1\tD^J7q oo$"`"=AW7o5M#PclL?%Y>9P+/+4I^[k<,08C\`o!=?MQdHI]SQm$SGZ%r7LWGZ_]Nm[G1Qi9,Q`Y!bUF5o);(q5rdohKafk-/)pi-Z/i#E/1Fpn&3fXEAl2$gAo%!9@*RDtW/")#H&jF!o$4HZQd(k#bT5]1qaY55B5NX*qAkh;^JAdlUt]tG.%AK6)=G>T0Q[Ld+$M;-U5mE8jc7%!QUiNae55V"1LMVqO%C001oeA9\UGglJ2QP>,]j[F?3bV&_X?N>$ mZY<\Af06H.HP"t\*a8!Vck8PR2io0\9!?[!>#]lZh*i/l(2m3%ZkF513FWEET;5f@?OhF&t6AKbYOn>H2g,$[\F7Do9-]dI!#!!=3MO*])A2L`Ii5)hV]*\n6;L4IDPgo.Rtthd<>HN<$:7@K9:!=\/0t'$CPsc(lF?jXTm*gA_5+X[X)d@EOnQjd8f'+ho-P7 Bo&02Fo>BaU<5jFKWrmm*3=9:M)U6MtbAX9_;cq$8eWP+YZ-VsB7_ZNntt;!HY5o0%NUq"7Kq]D`r<!6"W7$Y2P>Pf"%!@7Bj?nK.t6L%(H(:r eJ@A&)sjLF"OI/f!h#rS%lPRV:i3fhld]%\*;C9PTAJs_+F+! Srnq]BHjI4h;6AA&,7&j];Bdl;]X]Z[;H+.IC.537HVN.ZM1WFfK^o4aZ4#f:.Cp!rK"n+Q8q_@+99&AEILR4EF1*kV#Zi17-M`+#B-%C(I\ 8D`9EkPjJ:t@\;LAc(P6#%em7NMI9HhmZ,]@[#lH.W%&ejsADRKVa!B1o%!RXJa)%98 arX7!r3!f($ZgAp%d:$9;8%Xd$1.a&kZEKbqS1 *TPbtBYQ\fY!Ct\- bBAt'And8N/Z3elFBm*J/J5:qY)A,o@&`f,q\Pp.fCZf\E5JB>&\`2H\1TP4Jj*&IZF`7"h7MgNVV)(Jg[2HC_O)ipS8L[^'K!lp3re'pN*E"$M!GG]_f-Zh!]jMotT(32."?4;=o*"&Kks9sBRc98c=gGCGoP_=EA0R&B4;qAQ>95+4L]mP>%,$(6=@G-GO'* F@l>I-q-RqFB>?8@7<4Hb;(R3Jo[Za_dIN$=I'W*r-/.Rb&.WK*lnL`iVrlYa(GNh62Gt#Z4L^L(o>pkCn"oNI6sF\%0U[tLrdpq,l&NWt4giAdE&08K:ar6nBh&kH+>,5O:EQij+M_[@g5tM%TFAo#^naVFUEX `cEs/Fo-D5i(WNQL:4`WQ/&#LR%%>t 8).'fUYtMl?QI/3KE")l:.7)J0)Rr4p$Ui/?rV_Ui%YfeV9i=lGNb-I$HmR>q3(kdPB`LZf"&*%+"X*O@>nim?@nj+Bdd\a@i7tne0:hfH7WIJ75M*)?FUtYk?GXY/I"GR]gl/th[Liff+Q=hc.U&p]r<7Yrl07:T=\:(A1pltB8%dS#//>7%e;K_""NbN($:BP-i.aC*T?AmY-NM"_oDFrY3-pkL!EkM=ZFes&KC\/+:b?iA-KHX"AESPrS(*A>F'X)+=s/`!pPje] \"(EF'Gc&QT]n`9CM8W?4kraj?*iYB,0[FTt"3#@X(.\VHE;20 m#_da\(c$]3@CS?*s<ld9Dj^AW"k0$htA"BDK`f,/B.Wp=1W)LaA'Okjs)U-m L[n3V@[<%e3-gC!Z)+_f8i9p.'p3 #/940)^4&P1SB#.66iPVn:T7c+/rtgOA-CaV$%8jEc$ 23QX9j<9lC[Y_VJp'1?l"577%U>>(HO?qmi\^\HFeU:R$Ik:^*C@d?Jet.3@`=Ws::id[qSspkk6He;"kGSOpl__Dn@"!&9$IEUQtUM !i:X'G\LDpeEs:h1g4PJ]GmO@d:lkc^t3(D2WFM/l_9L5Z4#,/` F^&1:bXk9C_0jM!bdcd.j.1?s8O9i!Wg_P8=W13AMS+"MEf9j-'Q)^,o$hnsl@)d#e>l&+Qjh%hO=X_ZrARVQlT3N4Y![N`7,h_VXkEnnP`nTt\!\7!R:QTEK+'fSo%)kD0:#ZWe=*FO3Sic]i`F[W1)aY9kRIaS`@1_H<`hA9.#+.W^`V)Yqq2Hn7f:.2;a PZJEKRJAjQUqDYU.`Rm4*LX$Z >r[!R2Y*.ROnXYk?+]JJ`H/K6(G+(l0n/)tHFN%$P,R5_S]B?(AZMH OPbCX$*)T6"YjcMQI^B+; %:@\&+A$KTVB `M+)<@TZ;7$jggJ@b]V*[.jp3;I)$" L**>X+KHgQ*N&PDG6C[Ccs"MN-gl;jPbg)fdR+^_Ds7'`UeMn1,@a9`A:SG]UO]rCqXtQ_C j>AaHtKV,$-cN@D[O`?-A,nU1#!1Zd!R7nb@ZG6+6P''^ZhCNet:lR";8&l=3=6m'p9lA7m=Ht&g,?H"A`ah=qK\O]Kn=US6cJBAt?5Ti)Q8!K.MeNKn`nAU_Dh)=Zo_,R:>sQ+]O+tX&b*Op5*N__mkJdO*-+#n%3pn7?E 0A/pS`V9:VCi+*40;nXU[WBG]t=O2aDBU9(fLUH`AK(TYD( 9JJ/[#Cbm19n'3H,b(Ob:rprqVFfQt; )b&@WZ(tgah#SAJo+W%?6gh6k+*20T;Dh,,XpS36`4"6DX-nB$7lNq&X;b N,f)T?9lbGVFFL$B%9ofD5\5o)CtthNA]CWLAn67h.VS\Qp[7++]s/iZc,ZBJoA1j,C,A#NIBr6&!H>d;F37(A59@btq5./1?S;.F*94=?6@PCIln`M1AaBoge7C18K%JS0m8_D;ZQ?W*4l`1Qa^ [[[^SG U%ZMXP:.4>FpGV('i@fZ`bD8S34<Q';J(")%BkV-jk2c?RljcE$Z"!FlS/( b&k+e+o(3](Mj=jl#is4A&R*Wda-UVGdA;NpS/NCB=3Z_m-+fs2s1C17;qf*]k:*EYe-5)oAS=%"g*_\pXGSAb&doD0.f\SUjKO?13_1+9X[\=KbSM!0B0C 5PtgN( m?%;gP7rG"-Y8,aqtBXne5"_7!*0i/hG&jNV7V5FEGY3TW=L$^O2flhW?7.T1["^Ef+fk=&h!JSi9J_+t226p>8K:`[l^[&%AOI)oI1AIE0A@2mNr*MKAP)W$>l-,.s$614h&b:hW@eWaO+qS7/`)EZk=P)@UtjI)6G^4DiWRB[GpK)=:&YY @ElO5-P+%BV\8;_H=0QV*En\TG%_YM@@7,c@%[3TDLVNi33!2i3-p4UP.$i-653qrVn0&A0F(n5tPm0o.l/SWe%<(9$pSDml_9JgoY)\SQn6:b_>TY&5/9_BmY->iD!@n(W!0\2kS!928^B  Jd%jKS?l+S% GiB$Bk(N74jEcJeHF_ssI[&E3T\R)NE0iqRk^c9>t H3MKKH0FU73U(MU&V\IW\F"A%5";[ri=#A`oPY$=Vo=/%il;!A\*D8_dHL%6S)Kk2IIXBBY]3s9F)H!&$ahAOhS1?18SY.b@WX,.\SJEfbI!78Xg!U5(=N<)iYWOJRQAEIi%s!#CN_[/ 0#aO\7@2jepFrO\^ToBUKf@74VT_rg6/_:kZ2R?,si Ks9_oZFd:A/@\^r'@k^mr'6$KICk,F$;@P]1H[fZrfpWFbg*,f7[Ln$4m.+(;3i:]/A 8#P&fU/\ZI*\O@Y)ai64fi"#_G<@4N2>TDlRMe-o$A&a=l9JWtY:;*5*L.>'rID!qop(R=f0SD*S"0j7Sh!@M@HWkOBb+QHbL["*.#eq3,j;Ri8sGq:#6JRj)Z4?m(WtCZ@DHo>W$<(=mS7*dI :.f$X51B9U`"d'QCCr7s1E_,GfqS)N4Q](>[:4m14*k/'oW&g")9i>F=mZ3YL=">B$=T1O=M4Y@AdaI7\)23KEcM%-B5cQ'$lp]g\1LLm4Do'I[[+[.KSY(hj,[=A'QAHtZGI)iSB8.O-pDH:K6Nqg_AY,aaeWo;9&.Z6!lSP8$WY?%Ucf*l,m=.J>X1(+=ro)$hWSRY<[R*ESAO@kYE,+ZE=B12;UBgB[r.`HektD.RXZfAd=6tMIr0mkAgXrBbm]%hJ$Ia>?]p]>.5>a;8!ZLoc-eC(KB?3(+^o^to+Pgt:LT4Y(A 70sos!rHMEpW@T [=`SA-,jTCB`(HbKgY(!]S=OiPMRDP_kLd_V\?s`^* a,OXlt>i+6Le`,t'^_t[@1,q:dqPA855MEc4&m65\1j3n.+_J0-V 1jej!PM4LYrW],HA]3GAtLF*c%NpR#eAK7W@.CD08 .K-4QeTlr2A\R#P6:t;npdCXPmE;=M)H.Ao2ki.Gk^X7OS?jRr9I4D cg7U]'e69-f-Gj'2(h*.js:I%FpTdhnfDI MNLcQk7B+XY\AQWZ.M;&N)l^W9g*g1)O>cIh(t]l=:g.8MNR[^^HpbAEKhN_VK>=/C]'e@TKAiigaOjofP"UTKJ4?g)N,ro=C:q:<=Sfg4pO#BtfCrk^4*<$M_OI6>\V)"m[8?)=9K.!nH_\@,[J\l&$o4ZS+W_32GH\QKWpRSPo\9ST>,*YIQXj54\O<K@R9ocIYA#a@n!X8+IUq'Dg>aWT+KqQg#rCIpL%:/^A/Zk0!&QMFDtt7ceOoco(0Z9$o:1EV,bq!hT7QjUBK@FRVXA)b#FAG<;c[Ad_&R41&&P<CcTR'taj]EF(fCsFb'/$Of?@1M$!(.'m:Kb`RAXh[X9IHp/ ZG35b.TZjN*!hb(6F+/qUs'@A04ik-#?=YWgjc'Y$)47J*>">oU5nkr'tNTC&bnc,nG*!W5[`8sfC;aF+tTG8t9>1jIf@nOAaEr]DU$chWZ61 )fB4In+i<.]^0af-pJ/C8RlP(ZA`\mP;T4h"c[VMr1X1%fmdpk)4BF9#i&*WbY+A OG;2"V'LML,qI>V4P@U6H\%$lg+D>=B(I?-Q+-$Z&+#mL8f UffC2&RTX"hk7eYXi,55tjFO41th)'T*cSD/\YDiRmJ&4lQD]rrF88apB\qZ[Bs!OX64<PGR$adA:GTfT70q[W*X^<0:S_aiHQsq2%tT3]HYs%IYU'm7Ke\Jiasl258g>L*9lPXApK`SIA49YYMr/D;%*1]8G1j:A#o*MP?N.+=4n=(fW2KLhMD)CQ000_A%XAa^n?a1!ts1sg/V7Cp-:6[fI(YQp*i6AJtf\):mj+)`"[G=P9FVQJ\H"LDYi/<\I#aKdnn3,$eeltPj#iEJYG\(R[*.s&U!KcS).Vm^tr;gA$kc\P\?=+AhU2%V<_Cj/KS0sZ4^QR]pVSZD\:is+:-GUH8i4HIJj7B:tT63-B_m9K>ChXigVt\MN@BUmBDig5A)4?;TjAPpW>6Ab(jdh'\!lF&IH,AN!Wbq E&=ZeNW6:ci%"_Krid<\`No2Vq^]KG>RW'C63MXS1o$(jWI/J>Xp5=N4Ns2S4d33ifOM1!A$&@4VU$1&#-btCrgF""Ge^MR@TD6)Almk!ZgqKC8OgppkZJHl6ZL tR#n,31n]$i-)AO4)LKM?bVV`b[*A.k^R8 9>/ZV+pP(XNi),k(\X F2)T9;*?$9K"-l^#K``8m<@Rd'\LCGqshA9FJs[2Nqiik))Ek.M fgWa[":])lE ^igSa+'4FQ8?O*(DBWH\?8L1qXY(h?k,=i*/=_]l$%d$*cW+5KP87`6RF#c,1r'K6Sg2=&74Yd@7,b`4"95bD(e'UY)YR#kX )A*9.q0sl,j)R^(O'5kP7!jMprGFM*!r5A]BJ'&pkPdeO@Q[B++1KEPLJ0`1MbqoS!GgCZ]-)aDiol)cq@5bkCAn*@8 s-JT!R*mo7PX'&]\A&Cm)F8!1+a!rpK6#dO8;0:gC$?XEb6N.WQTK;cS%KF0*mraSTAP-E[aSVO@7>5$1E##aD5&,aIZTkUE%#9W]C.5@=8(/KHW/t.iDZ]QQ5I=ErFf)HqLV_J)#X&FbIh*QJT[A_Os-/#f!Qgb\!KArLj!UGN#9gl&k3*X3/g;:n`dY-!Y&#RZG8Klc+PSQmQ:e\BMCgJHQ\Oi!jVO!-6g@A3rmb\pVq*B0@5r*ktX\BAdl-L,@@GjBGS7AO^.!jU%icc-^+@!!nTN/E#9)1"m86qQJ$)i2^"e>4*h'&'=kETF-3I(=5c7,bqY5Mc5c,'R!n0hr87*phBM:%t(44jM(!F04pg"-R]DIn@"d`'A4##B;X9d`,R1S%n boGUpSY!4helQV8#69MQRj.(fRJi<;'oIhK&Va@g*eo/k^3O+9tOA)V>;gZ*M!CGYoA^Mek(+p0M7AY9ZY:sS)&7Q+(h+t.NRqX %`1)dh4q$.Ib7s ]SGKn[Q0h]mm+G3IUS@/bq$C%<#2#k9scGN*V$/6gL!Tf@.FF//.r5gBY?9D[#mGbQ+paH4rlVGsXXBqJ-E.ZKeP0AKQX(mPh?W_l.X\I@UKb"rHrQ3n*5nk3L_jA&4`@SkL/4f&,UYsrA1\JU75X `<2QeJ(4,(s*SYAO5<-tNh>V:F^p135lAmDd"#FA2_U@raXOmOqjT&=IdAoa"88UD_5e*=7Yib-q=ier1/b>(\b_?%D)kh(A;A,9Y8ob.WQbi'S@QsRf`%C@%F]qsbq-e&il3-&s/`riH3;+8M7>amMpJXI/XoHAkPKpXJU71$-'?>eo:XbD^N>1J]NBq:Xj9aW8L4"+\f8[r(Nk3AB2Ca3:9M>>(>r3ZP%S7K:Jh5'_)JiQn"2_ff6>#0K/hh2,*,dUbS(UhFeRsr"ZO^p*qM'BW9p8 (/EOjJqM<[pbme&L`2XT/b&$ 4R[GI8.6ReDO#/HEA.2Md]DH0<_YqiF;]mFEX?12oq,NnE5qIV7mM, k+a*)D3SQY9*9!Q?=g[m!mTe:jmq&jAQeCad4Wo^c34ttXHq8Bf&_*11a90K"$Ti7V-LCJ$_\XHOUe9';=>pfk5TFBpgJ.\<BA1RhL6Y7^tP6=3EAG=JlK\e<Mj^a6c-[d=VG/#L-djIrjB._(/KosS>`)$rV#[kDp@M@%)Z`2MQp&=kq-T*-T!`.D7*e*_BM:oA$`O?/,$FB>,^7Rb<`>?QNp0&P?HH\6e\ZW"+]M.N3GfLPSJ,&$UHZQoT3qk<7r'RJD9oFYcY%X*LdK5l\M=VVG%Cd`1V;0AV:/@.GP@&;pMo/%70[36V@UbeR/bqp(aA;/8, h3cYKhm8-!X>`Ak@.=KF/Kn*Lr9A2HBMb+Ma5=6GlaJJ7D)VNsYn>kS+[1W!rF-2=/LV(7ee-LM%)b]Xf@?MknFlJ?6LAbX.H7toG'U*ZhALkX>'`/Z:O7Asj29LgT0&V!+/ABRn=aEK+qI\,oU0sMsfo0e\[YXY]+Spbn67HIJOfCgJR3<43tZC1KnJr=f4fr:.#KRfZ(M=;!k;@HT :/iZ_H.HTPn2VkAnn)s4A1'Y]1iV5#,mI=m`^(4@+(`^%-ia"oh<N:@Nttel]\]Oma*LdIdFt+O6aV/t7MJ0c&8Q%M`attI'R0ij3hasMh]VJj?"Hiq'GR4MWn5aOt-K+DWJ\!\mn[?LXWA?MRs9 ][%Q7+=ZfN>6!%g[_/D&;8!':E1NKG&4))ARR-Ar6=)@Q &&)>/f/=SLQ_#,efRaiKj:*4G.8Lc*>*BkJi#bXoHQr&^=aXB0\-m;?\^F_AF?r5oA\EI`X23a=8RZR3LqN#m,VE5+C,"Lhs*mrmFKG^(4ffII==VkpJ"f)T*qO_ja9,\J"-Qt$"AClXSUTAc/t[-dR/?&fV0E3r-D% ]M;SGmMo>h[H`iA%a@.N\D+eh@*-`Ap##HP&$bIY!-Cm14pK7X@T)^%b'bF7M`F;)Lh!SN9FTG*dY_rT\pK;8A#6lINMYs+JGn9Q`?-oKWN.YfE g^?#n@ZFI8"a9:sc5$tKmD8o-;CRJ92+Y[3cAWNS:Jf9/T1#Y=F-64BiIRiQB3qCbIUXX=p=DA*/j=nrPcOsf`Ja18I7R=_(g5mABgVD3Y&*>JKP')OWdVkC-fRrPcX0KMt2 C`Fol[nRllZriSWs']A=LX<3RPV`?cBfY#-A:#F?Y[$Y$5.@2sW7T?L`$;QH$$VgYkr4B_"eSC[a36dC[ cT%*a(C%<%:X/_R6Fq;YBAgd 9)lUFXg$PtnA,"EQrAq;:Ss+tA"tF3VA^7$\]/!*]2+8/ ,0ES-1??Wq[>_$`;2kf8^lt-fZ>h[#5G>j(BNG.'Xqk]?n$cLOOLhU2F?W%MOLM%JsHp8GJ$VO=3h3P/*fp1)hl]iP"32CFGM@_$,G!`KHh#d0L"5EeSn hj'.3Y06q`#_%Z[%7PZoZ;YgN)b^@&'Ym_,_l_q"#)gK(#6U`k7W,ie/W_)a/Q;r6bl-:@2c]KGGY5WW iKLZe)WWjm 0:;Nm[dF/$%U"f:DoeGgRmY-Lf:tf:a!7_>G!lAB663CedhibAW+PYF-,_"26:NRO@:B8;>dBk?Ej(%NHQ_2:p"5aR#<:N6+]b3J4$31\a`B-,B+)M\0Ramq(XMV>jNKA=Kp%lXbN+E;#EbCHsaX00jg.iAXL:q?\L#1UFRm_%K]h,C%9mo^h*Q,14#^+Z@m8]FqVtFL\BH.m$t8SqGpc?nHLlMJ=@.SCkXhjE5-lqg= BI9Rq8PSf;LmfJTa>jBUaQ,p\,7V]"4jf@dT+,T(r^B#)gk3*FR;'*mq5!2)@N0AK/.`^1tp_p^VZ1,\O3"S]qO9eNQRo`L.eG?/f7Dl.2nZYpd aW8o03SA%ZDLNP3G8*1<6:*hVoJ=TrVa&!t(I+DoLW6h0tkmAnehjg+>UJV ]JTBnm ;hN^l+)S.CG:\j[em6m>;TK5Y%;p=>H.8ZedEk=BN?\\DOG)PP.S-!lT@#&HB9)FOII[CO(e0&JLLJ7V=d(Lr:=dm]p3"SL;'*_O)"6V897cWP$s>Q*I\G*JHZY6/9c[/.!:31'mibAEiEkRa_%]d+?)bna.,ZIf)cfcChc;gFc.e'[)6.eV#/itVK+:Lr0HC3$Z4*oLk%0mYLj3#DU\4qWqNBsNS'_B9d-*09U9),e'>bYi?#&dAl\X(7?0%eRQ:V*hDeI84n"X1a/N,ITr5/N,S2"3Pm,k5]s5gf7WU`NkNrdFd(7P:,)(nPD=jH8c4ksI/<.WUfE=_OF7Up4H>qic<.r05nsEoeXfgB2$ ]MVSj5Hj=GsCs"\hA1>c:9Uj?%[Y=<N6*`QE*L9M4K'k@j!eYC/KDs5AbA/-ATEn5F*tG:KEVSKsbc%TMC"tV]j!LA[8EG*-i^TYY),3hZ1tlKbf\(Y/o66iNjIW-_g."piGg0kT7IlVDo1e$ai'iJ 1k$Z%gJ 3n(ZmD1X]IZYZgHj_"hP-a)N5FCL9c@s[j-9SF-RAeDU)eL0oNT.\nXZpe$,ZHH-:ch:.6:P"cL(09m#L9&g_F)F`kLBfC+n&`MaONb\L8&'XOjW&A5V!9FqPYk1:i9*J@1/=4jA^TCVaLePTrY]2IlGI?SXRiA\0loHkLs?`O\8&?<>3!?SM3AmB)W>oRDU$[2k`7_>Y,a,+C.e":sEb&fTD0EA5.XdX2#ZTM>$X93b37.*$+YrFTorc85839WA[A:7?4>X`VIN3`<5!ZH\h^4pFA^JAln:8Q'HFG`jnAnCRf`8WHPF]]$k[B#1;LHW?)W5IS4@C=O$4E"]4!Cl2GpA ^Cm/tJ *?`6pLMkVdd.iMlo#[/<l\b=JZN$S]G]#Ee&/pd.#16olAklO:s,1e+9d2;SA 'j@VP3BEFcAUh_9Y&Y!cnMsh3>af]Jc#Jn^tn?BefEJ]jMMkWIh`]sha.f+e< 80^_)6 `G0=YPUDm_Efb*\&*S?Op6kBI;Ae!C)-(DFT>2iQk2tOftCQ!M8V(>S=@$RNZ*n=ANm2B1kN#I)PC\G;\aEHjW#XrRo">"YFD(`pU5tf)_T^8SLUZqU#.2C6`#EpJtZ^KL\.(n/&-0WWO&mr`1RAF"&LtQ=`i?5opDmm`Aahli-r,H*1(32^Lc>n<,]]-^]0GRn$l5j_N#hr4;*.e6P?-$+Sm%PU>9as`Ls1-JINC"eFPC%5sATQF#,s`I;SRFCN@:- C?R)b:tX\:iVpK<`0FR`].7k:KmlBjI[,Kq"@QGa*QK.mkd$CnOp$5WW@GqDZnJ>p'E4,/j[_hX"1@)O=A>`-Qb1Re+b'!': $kUB`bgrrJ`&"9V7e/)i,(:I:7j5gh \,&I5>&h/^C0PctX-3s'VAdCB6sO(F."4:OL50H3+o("=n.AU13=OsE-Y$8a0jSp+!3OS0Kn%TY1VjAGI2EcnJ/f,9?RRWUhd^AHAcq=%NF"c_O6\5>lK<IKE"!6G[/=OP!)K]mIYCL_T*U;BmBtV3[1j%_t"OI"c@`#Ib2mim6e*#KG t3Xpsq\MlB>L45A?.jr0B.]XRc(?7?6MB0P1VWEc1n!'/N!75,.=!D>92_FPLHmPDB"qrJ'BK978B3g.6(Nh/-#\"SsokOb>DcfJ^eEa &.ccAH2_bdA"")'I)7Y$3o%@l]RPrAogDj;60"LXpE/VtkjV[%4rYh0NAs\a'_0/Uc(iVb_i%?>[GTP\5@9%iiiB6r91qf0At[t$D-_:5^M_7g?M_ZQX][6OMK8"S,Um8@S[Z3M&;ZYT)N&_LA.=c PAl5A@(\5jB(8O!t% c$s?+Ga?,JjP.,#B_DI8,PPjK+!e"^dqNKdd[jHL'\/_eaPifs[2CiG^nm:.gjV`&qak@BJ0SRVSQhtQQ2[A]?]k)o`lln\^4I>6*SfJ#tc-'aqt7+?h-.Xsn!B*AKV25a'NH,j&YQ[?)@PK8L'PZDPtK>n)+F6^Nnj,ZrfpjWg:H+_*>/6K_]a?#mn^dAa:8tDLa3hi2_bZ@rk?g9%a^s&eW_#k!9Sr(mM0CQ2Ot`qnBfR2Pm`8hq6"g#E9XNF)th%(IH=^FM'bso!)n7Jg3o?\6mQ#jlI0GU5G+#DmC(V;7@(^gs(t\mJ*V&\V\@Ed[b2[[>N^;#SIWj#Af-cF!m,=1Hh$R=VSclKEqnom[0,QV-s%K#!g9G;4o@c^?;D,jRFHaaCUh-L -4\6TX)`\IB4:4(+Adeh9CQf=t0(tO>n;C@Nh__?Fo&Z8]TO:hMf_+B D8?+=PA*bE<M'6@Y!^eS:G`apd(:5)Q>[JP1=Hjn aYs>SRl"ITj4qL)ILm$i\f^Kmg)atqED,]34Mt+IAA,%Y ignFm3&[4rbl6#c9+aW9/R+HSXkAA'.Ij2>1(OJWF24H(SBY^;V1%&Ora?U#(mr]de`@&QJ&(^Zl"9%N"`t_[]E98>c?sGjo#;nd*,kW=>r_Ddt!Q,Q25FgH72eL*fW2f7E+[hihR;bqmDooi9`jiLm)PM-(A:i=D2%P/MB)k@'dTBLX@:EKK4`A0"A)`1LmBr U$ql2)AtCmUsDiAVAWb8""#kV=b65,&CX!H(Da7sdd-<=hHHo03,OLCcC6* \?(_T)47RfWfPYc_eZ&%1lj"0W/?.=J?M%orZT5?9C;#*N S*4l6*R_70:fP>"mlEA-#DPXVdfF>A5JJ*\Lk&!.@CNtQLn74,gN_NK=h'I`RAc'Kt7^AslCRjMGc'j+[,W6$LbUJ0@GLd3FK)]81&P8b]DT;@^7??c:NA]8ptTrR&,/eX)I]MK&'q%TcPe(TaV-er!'3j.iXGAmdG3$GZ&G$')>/AhbOtm2T@hNq\\sfps -L248n$^ALP]ho[@1/.ZZq3IWG!*2WXPs%[S-$**YGC?($A-;.G-NOa>B&)A0_.`Cr'QlM_=>GA(Q%Crtn_6Oi+pj*iq@eX_As'nS U[LJtt4p3Dn6FHIY(1I%D4\>r78crA)E4aD#\hU!][mh3)ME5bCo(OlVLEU35q (fjKUlBq^qCn[%N"WAV_8Tb-EA3IM]4S'-5\phTYY3SFsCn'( F<TWXKhQ&!Q,Nj*!o"],M5_YfG6*EHcZ=P(SiAY%1CZmnIfeA;Fb(hIdH3WA#$?mHK@OFcrF<.pBUQC46T2'?qr5`>l<(cLB=XG#rVjK5P"b9%bJee_/_AL>D_Oa;XZs\ JFHRP"n+.#AY^.$a1p'j+;3@Ho4^)W(C<;J+PfKr'DW(qKn/L^lB@X`8[9\.$#i^,)RCE).`gMXC?p_jh`.d5$Vb4^h\b;Q5LY&&7"BKkn ]$^-`+S9M'=!f:Vh643P-OraoJQnn*@AE3n3%kcMt"dh'CRBK',l@6`?Z)M7_1*3gg)].:Vad("+gft$T3aW]q+3o(d/WcSW:_B2#e@n&mq7N7W09],V[Hio8!6OZ%nP=LjAl"]h1@&T`8XDF-3F,%MD=.Y[j8#Wj6>=8;2nLO`93V8HiB3GYjW4CBdeI<)W(SZ8cm;SCGgC`ZK!$)Z\CM>W!Na/:VK`MA[-YdoS->HZ5Nm+^R[W^NrOI-(c)J6HCC7e'M=-DaNcPf]4r;rTdl\0[>6"\1)kHV,IoaP2\F!PJ2jL1G-4Y?)ML"a:G^^/EkX`>)@_#r$TZJg6;A7YWf+rJ5hec<&FJ@?3%;]GGmB9DmInjAY@^AE24MZ2Sb#(:!ke1J3mU0'q;AM8XHLgrj3<&Z-]l!M%2A5.af>ZRh!qLr)MJn>>0bbDLRR<[hq$8oi'2h.blNaY .N'L/'h[&3*\Onjl/LUoMjA= FQj<2l4[>JGsCM:`Q:#[QL9/U9V>LZrfl%=9OAtLg3.'eLrH75.:Nm,i>Bd7 3n<2-q8p=?`FM"Em6g_ngd*WND4PtcgT)ecQe%d1"8A_(qPr*iW9N#="aBd8N3bKONV* -p[^^h`/C$Oc[b':)#W3>rBBtQ<;giCQ?/kSK'j.gMK8i>6`c^h$6rX>,2t#^r$6Ai)Z8q^=8tr]BdP!WAb*5=[J]Fl $c#Q*JPX\^PnSB8BBSZQ2aTH5qT;:\$en7K737i'C.14gE\/ FK$.`6Ps>k@6+l0G^7fAmgEb\siM4rVF?]2X=Y'(4]O)jBFdVQ#ER0=.BZ,scQ \;l`>Sc3Sej^,YRk+ka%l,eRoANq5+E*$=edWYdJo<#j,8]YIK+t/&6<5.WW2& 6J$i4l[gj.^R&KtPq:+\:AR:cpX4M30_fl77Q*j 196-t9i>PfNLh$/#&+-:tIq__jbj@fj@:.>e?Ysd?=WF`Nf:mSM.0he25-Gbb3s< &Df :$OJ9X%gMm"=`p,(otl8II&M(kn$3M!UI(M\Y'/Cmrl$@AE9 _;cip2JS_e4plaNP)S(9;76Mj]deeSaT.[2b+ZJ1A<oh_/t!XWI\Ac0#@_m^aT6Ng@0Vl3AscN,ib65]4QoCLg58d)g<O87SsN_-eUS6#nccYZrIdO(&&qJQ=J!T^2;9)d+0WXp@E9/n188"eMrV4`Dt06]dY`pX;hE)!PlT(CAa+.MNF3C@CCG<71rkh;PN]Co0VcY%biWbOt]tLB"__IU:L 0? 'CS5ZlWbAlG#$"Y[7rZs=4UiCPKiHQO[ai`Ocl-/R@a?FSFaEJ>%>:qhrPK7O!qS;#EI\,Z(A.nl>r:LY2N47la4e]obrh@0k->>sTFQ6L6T*$AKBJ43DHNtij?HMh r#d.WLOCC"@LPX`-_q1Y3bUHA0<\K^k0nS0O,?f[lM'Y(tBM$2A4Hq-F!3X+,X\"MH?M/6G *NTRg\T[ol5"V+(T@tf=a5'g1(iDWr?9b^D12@6PX1a!C3B.M%PmMNXI:1k9NegL(#9D,T]c;ZhqWj;:[CVs-nflL+A\:7L:1Wk=1e+%4`J9go(4ap9h(trBJaP+3!]LJA-e-lWMp42AfV",>7(5$M58/_UAs'9m$:,J@Uc8jefpVg@PNXiF/b^bV+],1];Um31DAqk"nE"OR)VR/^nN `giO%X 2ZX/S`&rr5\6Wo7ZN3^!SN'nq+P!$7S]H`.(&gAs!?V[6:GptG1Z(Der*Rb]1^D--jX(gPGZ4Le<C&.N2/no ZMP*IcX_A^rOeOC$To5YKg"%r/+-%h%iQ>^0Xl$\dX@I` ]T2h$kFhcQsb/VjV<rF]D$!-Q9BWfQt6V&g s^O,."(KI4h+ARfselg[`Z;WIeV=A1c-jfNF$s6$/3\ek;Jb PHk-X9WpV/"JMT1r4/iV%]"UDg7%f/k#N\!ioc2M;CN1:4!@+XY4d`K*&/Cdjh)KO5@YDm?8l3*2 cnSV2KYg+-S,?NEAF'7o8gE]iVnYNXG9mPb]g [j]1(>!(l1]j5`7E)D.th\X 8?G/dOP.)@)GRSn(EW,,<JAl,,"PthC@,(Ttl3]S+2e&%>.j:)0#[1*kD$]!+[SA8T@jt/^iA,AE@YQ*a/[BPH+HQ5 FSG*S:,BiW@H_MdBK76.<-k75-AR.;6"PD(%0INhS7ePls57q;J1`.aK-E 7_W.mK"[VZlAEPkb7kI45ibQA5LonVs7Ds2_!&;r%G"(!o'FPDT)NAbg/.R7FR[ll.f]#!1eC<@YqiCf1q9YsRA5@`^%EfYcdCjA!Y,6 IK=VOm&sLmA1kkC6eC!*0&e+L"^)pdKQgXAaXk3$mnG(43KDI$Y-pD+h>oC9F`RITFR!D'oX)=OE^eO1IOQ>%Q[5QY9O#ETf!\dc;Z85KXhpALN#4g*.Y q`O5I#XUh*AUb]`R-+TP[@Y+bm6n,N?5`#-hoDn']>A[]Ar?[r6tAA*1;9q/EVV<3*>Br_)kk#n2HP9j.8#c+B8\38($=M+';<6e4SL4"1Nd&.O4eVkT@;8;fMXBrj%bWCr[Qcj110"pWRckp^>qnB.X*cm`S27'f]\0 "l";j(Ah.CA +$R%%6.lk3BPTK;T'aKeY28eQg;2%:bi;5EjP^PlDUZEDQ9 Y%s/'AO?s&+4=&ddn24D&0Z$D>%W#[>&-nAgX;78`-5hj?^GktMm%W=,>KjVV3/a;ik.[@=BoF\+fHtBd3Vc'Rrpm&+PN+sR31AAj@kf*mp[IieK9OqS\=1NgFG5d?/G4`Da&k#!dr3n7jM[NQC>jk8g!5Ie__3"7)/Brqmk1tFUhXKi&q5[9UPdt];$tiMWa'l8mNDZ?Z(SDUH\7N4$F5Wejo]_^J7AngphnD)O7Kk:$;jKVE1\aCRL5aJDW%agA*les"Vk3$0pq?dLfi#2*'S97(Zg5PW*?8m5rjkAhhjd9hk(AS\mB(K?i#AYS)?P[9(bj:jEG' 272%!"*r;tD>"X$/i0A?NJfp`n?dIA9>nb\1TOhZ:2@l1Td?M>H#Q*)>1$@nb[7XhGZKln*7K%,Jb@i4Xl#,_sURb_Q=eU1P()+Xo_N&ON(koKO45`8 3pH_-30HH@K3bSIi7UW*9/%F'SE7I?]<0rmcA43mj*O#s-U$ZeU;pTV[lYbr]$O11l;_(*.D/A-H9)*XrX;7'c[XNmXb+YIgk9[hQHlU]_t'k&V.;qh9+N %A:A*VSRQ\:VL9 I4L.ofoGWqA\90>\-IASNB= 8?W7Ef#hT$s-#@rZH2\ESG2tgon`oM&+9OgEU[T^/B`Kp.lDr(G #r"bOdgjCf?PDPZg.s+5%Gt7lPo"A=L%0cfi`NE)U/&J3^02@-kI\=f0radj/R/4242%X$&pj1`kbhm\F]M2?dnK(T+n'>D75ZC\OI0Ocl0[`2:#: Zd#bWXG[IRSRtj6!r&L/DhcLQ5dl!4n](httJ507Zt)b\=gn2!giPZ0KiI*c8`dpG^`N -6"dl&L2[%\G/gOPPQTp6->6#-SpLM^ aqAR#"])_*BgmV!n7:VU%9`j83E$F[K>JBe )I&4hD"DPo)^nML_nKQem!rJDojCaO7hTLZSUFl=^"al.;AiZ#2;j"ICgk!>#E(7p/%Laonf9;qrK!7&+KeKI[`><'8ml`a=<]TBt>!8Tl#(.JAs*i?NWLL>)'sSpV>2qp0FUhOg'm/@8ojW'&pf-\/hYo#-A83*gclkEZ5/3XSRd`Ae\+7d7fN!8GO(e4\qA&4'N pUR]rnlZn&oWCCiG5q1o_"_@3XMb\IWf$Y"b^G%^,rGY.7/1&&mF0<+cf3jW-WbIS ?'-"B6iS.SL,OrS!+"cGX_DQ\V5[6^7bZEeVP`C#W@;XaC^ oK3gF]9iUS<,:J;r1&U)Af(,LV;`ikl(b+0@#YY2s)%`2Mc#ksHWVjk$t2iM[`Z$%t<PbTEZG@kX4e>4iH*!AlRrpVHE5&)/S:sJ[>U)jXMq)4HmT#o0f;Z*@&%-LB([#m3";cEA"jh"_'#Mqn1,q'Lds ZL`b'A2JOoL+5.aH1i5l$H4+ ;*Nhk*gEl(PA^a;ggATU[8!3$C;JLU2ne9)p<$NV&Ma>W"Ak2rDf28\.($7DnUOGr-n?$K32WYa[Zb^N6%$,I>[>0mN+rn[A#Ph.>M0e@A50.g(%eU-bL\.bSU&imF1^AeY@GC<8qj?Wc"+rls,o%,QLdCk&In%PQnaTG_g!)t@O.7Ak!od5-r-9=<$Y?:5MAW\eD(8R4MK:WP?V6P_OUPoYnCW9@#/>DKr%2q5PPP:?)8L#>.n^C#`C*2k=)Y'\?2A!IDVWa"cHij2C(g#ht8S;9<]Hm@.`$]q#0":;oDCZ^%-ofcAQJp8"eGZg61bW^-U&:t0!9N[caoZ>Ib%,2$.:$;o61TtgB$mUmT:m/K^k/sX\R9[5=fk;#E9+NfC,Q;R3LoOgoDW02QOIOQ`M/TZWXX%7\dLI&fk\n2-;A0>3Ua>+&BpV&LeF8_?QUk7er `+MKIMqT7hh5H%Y'!2ahrI!-XC!aDWd gbdb-a7+"+&<$\s54nDJ`k8n"A(SP19r$mM1ArGA\mD&8UK#o0S(@4ph^[IX]@I"Jgr[gse66b5[AEG@Fa61jSLcCk,F7sF+e%\UV[_0`l)S$a<2WGsA2C+dg8lec]'^3l89Dcj8@C#$Il88b'H99feK%a/Ee>Q)%rOWf3kbth,3V??N$H,J>$lPUiA/gD+#!cJ=a4]ae!aD&.fL0e67s+g_?D*&aU=P.n;4EM]Y/8f4qPVAA^7ML>7IA&>*T =LP:VB"Q$m_q7U[X5!@4Y!pe(UF.Z#YU"K[[2GA5N:a7f%B]N$$OPD_(t@MD3<s$]A"8K<1ff]MZsD(e1`'A0S?[/eK;"(.j9c<09/58p$5YbeP_LS:1'K5K\Is(9jT/;.3"NtA^"WG>r_UEa#*E=Y%f(@GAtqfV@d\:0]ZN;B?JG;-C*0(-OcqnDQT?AS1Zf[Uk4s\>`08cJ?h:*,$Yp$#M'A^jq'DfmVA=QJqbo''r<&f:&`*+I6m/,`Lie:5lgK1S+e',SAUZ0>2LOB;_%H?/?Mt`MlQQ.5[ga>tPdD]&&a\8Al-Yn5B]QNaN!dkJ*!`Rr-;%WZ5V_FgbX$"AMbL&CSYRhS*_WA0qZGn8UYIil:!.[7XsdcNLYm!=@kfg\onU)FT^[(GmW6@lm7=2rGD3.FO2b]+b'l+VAo.]c/sHE%LKr;l@+A9,BP&p##seO-I"RUJ-d4]fhX'4B.LAI+,eclYrVadm#aeQF00\^MU3R4eUj-hr)jTX-F(SZ3AI@=k8bkn"]>&.(Ce"fT\50#OAk`RedN!JqpGEaG)Dr@a*<]3`.#k/56P;lZoeQqt%olh:,_O"37pZX[B$Af`>r/&DL@B\1tso-;2.frdR/[@Aql@D95JQP0+jc#FsrA!814#c!ON2<$bjejUOZ*9FO\=4k_[[oG1L)GVVE.:4)P'^r(JHkV5HAj+`Z2,AHjJmnhRLK$=<;=]V^EV-J@4XHc=>@tYL<d6 XEC.sm(lp0UAp;2 ,OZjbJmC4TWLA#5,Q4$[.[-nXI_/Mk=0RZR5Y*?`4,267N`Ja'a)9CA:p67de'Va4ZTs5*:_g>P(^gn8T;ELls#Y0qZn%%KZ?"4EYX8Q&>cl1]5` V/rMX1?PcbEN=+mf?_mOgpAEB;MQSk^\1(J])oAdGL,F'KB5iR'(:#i<&f[r-9Md\E(#2h%Cg^_:6ISQ+(Hk;fa7A(60^Mp2(Fl7`^283p."Y.bd3CMbK,b#/sXc6Oh:pKC;VS(UI<2T9A%t[*T8V'_AJ)m/P- #+1i#90\;(!)e<3j$pL2L"#oi^9L@)j,^>si;LXOB3p;tW1UHlHo)&GEQMN]_A^DN2=$;M3q7%\\=0V0?FGd269qJSih>/acd9njGn-Q-Y:n%>For#\7'o@Df0Be._`)j[#ah"PD:-+&k0,onnBgH;U.qN6/jVT(.U5Rp),hC7$_b]rT1<d3r%W"L8!M.3=`52(1DtP-X%`dSHZgI*1p8@eXK^DdYgWOt59-DED+56A))BU]mU:n.>E"-b;caM=YaZA=VB.k4EQU9qH@5R-K<!k6qT"V\j9SeiEY#"bBoA;HIUof: B%ACMn&fPsCpBhqa68)6>>eimVRI&,)q(F:AaE^4gGOjb4XtUpotYh7:DCk<`G,d8\WDn@pnDW=%j6"#PU[&?1*9R 1nINUf&LE5*tk]L=q(`+Pp'A^QFg"Ff,!UpgX?9_FhQN9 WGn%"6/TXB0i=@P.]qGlBhG-TV.Y,&/gU7AG2#t6+ZDM<Hf?r4/`#5hM9U]EaeVqRm'0@aA!_4XWM3-i=4X7I>*e#4)N@Am"8O)!YZT??m@,\CS3g$3!2_V)SoXh3ptCNXA'BS?a+Icp$S0Fp,+:rO%TP;KW'f2Lh3ap0ngKVc[JIMRsXf LT#n>6G39k9dj,4V89ccR<&bCnr$Jft*ALJ+Kd>,Em4p940ItR[1Lg,A:(WA$d.Z)PrBJiTPn;kB>7(/=D[Wee5:T;n:2CfWM`"T#nW2X+_09\pr;KR0j]R;s)9F>k[oK;c&.'J<%,Atfb4a+8?#U%M7RpAT$7:!ir$YDY2$5lL,Gk>#JSbEA,ZgeQ[BEg""FFc.)5Gdm17UAV1@?E'No2ETDfp!(@>0=.Bf/o% lS(b[:Ji4-9RRiQD8IT.!bVtCSh\c\Rs7147GpTR*0g"o`D6 3;iHc\Qh8ojSW9*Tg'.RU@3]ai]O3Dsj-a@_0TZ_9Q?*<EcLfr>poA90%g3mkH+->"sD,^TWp;W`-3pP??NI%QjO?lVqq3-h(.W Pm`/[`3F.'4.6/:@%b4lqtnL\86s8@QLZ\On14Op:jRkH0q52s..Pk,<0%gq"2%jdS>(RAVi:=7N?deR`1G"N9D 0`c] 30^+mBmYHW(,o/:*g,VfP/?t`[:i1pd]g___+t6IH=JNUI>e8SCpa:g;OR:eECAj`6'8nlo@s53e\WB8j*DF4C) Jd`K#IPBX?#N2@#8OK*EjZT oMhTfLjt_TqAno*3`1T'.d/ R.kffa6E9i @=3k=F&h/D/n5Z,c tZ63f$=ma!%BOq]1%n's^k'ZmsGE4*:Q@7/JTY]iA&\KU1q<$bk9N9j06e]F&m\207TRX[4%d4g!3,sU`cXAY9$de]E@Q!C%q8P281s_d7d(bpA.*`1in,f^pnIElntTT`1kJop*<<2^r?G5Y1dP5BBYQZ!btf3G#1oP'EY%N+'MU2q82,SQo6j,oU?.D9? rZIdf_AB(VUO!M*_7$,5QTTX@(AY7IcNcT>-U\r!$.rRF2!d$=MBkBQ*(A`Om5)LJ:. 1*c6YAI/f4o&%OCp33UWk ,#k15.:I!@]mT^-<;'_ANt)H0)!FSjpBV;7[;I1/D">_4.!p3V\CL=@slelia8UIF Ra]t^X=mFrQH.Z,kVnk`iFl?mB^;aL,6DA_HZ6A9(9n0sZ<!2/@jT#d1GRR;tkP>a(q)[`!!Q9,OOd*Ua[>\5kXh,0Qa^j`Qn_Dc,&A\BF Z\]7M77#*e<X[tbhG&Zc\*j*O,ETQ<=$P_qL)ssU6k^mf])>'a>HGXk"=rbL4gF:E5cQFIS.0PWfh^/cMi4DZtk3;f;:]-QKmP##oD>`;KilN>6f&\?Yd-QmLoZs*7[A&UE1h*KCl02W)R#/c>>E!8TiNCY[NLh_aXo M_.7E9g9o]PCS`/)Vs4P9;fXR'3!XTO8*"LI37$RbVf8qYC]Dqp%BdUNX]RO;=OGd:\icQ)i )XP#,C3( 6_S9ksX7Ar[760bhT/R:r`Y-.\cr,Q1A9/38#YJe%L!rlC4mO;KCPMm2@p>C aQe(;9LdA.M .N\*A3,Xkk3p>HU,'f>J(m+&eRi`,.10dWkf#rJUAW!Mf$-6O""@g f1[Sm@@]d[nmR#hENkFb_J^QQBo@g+@2:e0Z2A:^^C5io&\?;+nC#RYC?-I*e[Pk3iA^\P]AB'q5)_ _C0h7r^mbr(VpO^>?0K(ATS5Rah[k j%@Z`[!Nb J3jAkf_S(\>jb-bYke>_@]4A#QW(M='_pm3FVqkBG1Yem83gB!E\XfR*!19aXN.P&@`V$b^+6PV/Ql1@Z(>`dhXh48@JClL=aFea=?dfo?V532QCAKYXbUlg8;_Ubm,!j+OSg?MJEMMX/M%[(\WdK :)ibP?LHj5)ai.pRQ"dt<=mA#E-`t7C5]DOVN!!mlLfC\\9&oj%AX]@1M"BB*bm\ >L.sAJpoI]m"IOMoRRmgD,Rh/k>_KT.m"8``%f`:2\bn1]!!B9Me5\@,?8]59]rrR>GeEJi$knYBNcJ7Ht4&TWEg-[end5AZi>8"WI!LEFTjp#e&jOIJtQh'%c^g14TmCH ^"`A1]Y*JU1JU>TU<#Lb4)lVVo1Lf%mJkS.g>VD1MTjo)-P&g^iL5YI8Li,n_!;3F3/e.\I<@;C3E"BIW:X\<%ULnr#W33Zq]KRYjGXCoU\mK!l.B7 7,/!_XK/jQ4qebJ/F9jh8IU.8hJ8V>]B$6_8NFc-bWtA`f.f,66;1o"QkD`1<# 2@HcgshmE,p&cm!Q_n'oWB'RlMl<9"DBtC;"D[P1:b^8gc!%-e(=?T2'_ZoiqWiA9&:57Y"PXrTU_'!UAfYA]H21M(lR57/e=AO'9SEUFG 5_^"^k>IhTkL<7Gq/gaFldm\F=.* (PA;n,QE/q@N9^$Vsedg+ar;;&AK\V'!7>1#:_E??M\l",@4da:][-dr!I6.'lrarP!TA06=8*k-Am%osAr;G]9MdLjSj1>ThQ^Q.8JGN-YT;3=C*a9>#[B5NnablrMirPbjlD65!$Of:@[I25EWGM[X \nsIXF=qc`Z-\]^Vq2kSX=G;$5@LQ1>9_4*"4Vi"QmAkDm_ST*7;drHQ3if`J7ng5ne`%8aL4,f:Q5GS`LRcp7Z(4XVd^Iko=$]@V/ta'o -9hdlF@Tn]%86a p$R7Z.7bWcpgT,87=ZQHX:KN"6a^*0A/ibL"U%:E$&= )bjRo.+g`%JtkiVXN(o 52Q]K,XJ8JLf=T=$'B1;JI^5*Al'A$$!*PB/%b/5s[M=77C3BWb?Y\hb$ceQ[pm+\:IL`Zc1MT3\a_o_T5603tl?dg?pr6&\8QkeVih6QD%-3,oT!$bc1[+] 2I"dh+QA1jrB>79Ud78"mnif$jMJ5qH>lr`ck 6[fmh?%2%9F8eCPJ/T7<0P%kP DFG!V4.N9IG"&-T%p,5PLA6PTA5`_6Ibc4lb9)#eLH("Q=jOq),ZD$.'55&rl;`54' ]&%5W0HV[_/=WQs7b3>7[I $j;SDo&!c-=P@cQ].GPN3D7coM=Q!#SZP09*d,7:WjsF9[6<k!N-/?QAfK<&.1$<-dO30G6tV_h5T(45a"Hgbse"TXr:W1XDcnUp"f*R],61TVIHW+0L$YUS[h1A=c".(D:^eM@^\&UI30.aURP?P72(17NmiVi)LGWON0BU\45;oaHcUOhhrT;T17Qcg6O@H(#4r`C65*m0R4Z1WpeM:nEjHZ)sennKseA;)h@)a0f1@91A:r8Re_p[CJ9[o8f>^2kLA=3"kN4Kc0al_W+MeIk"MhrUT>X":0tOfo"U[A?h"AWa8Hd9Cn_>ULQY"fj>[:]EBAQB-9YW4\nbKj:aNm9(Dpbc[jiVb".Y,A^,F@".G=iF6"$G R0[;L547[.g(A+I`+8!]d=$4IY< .b4K3&+0-H7eWgKL^34^bQ]*I:eC%qFtmrF11[jIQo-QPG>_XTraYIT#+T#bc]D,Y[nf7-l.d9JO%jq+=Zd91c]3/N%r-H=A)T;SMRde\KaV`lXS184CL.7LW4S+<^*2hA`PBFIUVXm3Ngfn;jCjt+VCOF(04T()pTfY*n]S^c0"!O5<Am+_b)*8*p[QDj:;/d+WeQYf^5b3^$CnK5MFBV'Q00JlLm_>d-6F/M9d.p+V1_AMJS>1(PWBZXG`hQCQ1]\7MS'im!Y$N\B%cJ*("f^Qn-XHj)$ehjA?TmM!rLA7c9N**Oq> DK5Rm@[jes$PclOsE9EmDG:)5[0Ct`5_,Y/,/dbc\:ZG4K&0DbM.<]d`YWcPqbnQFYb]cC#\JL:^n\'s6A^GJVA*.8.k)Q##HI+&P*AldtSe%O=5V-U+`&SDbB8iKa4"'1MA7*>/BA&m=W%U5"U!$M]l+mm93_Bs.&%VqA9%>UL'?l1CH'\#5D';FF?ia-pi2A$P=Eq+R[$\3c&%![H60R^2+/Dq8m6^rk.0`YeU.X@2LM_j-.ZN%An&EHGc4qO5/ZqXLU4OgKnr0AH8YDn*Q"o&YQhsEY'^KI&d@sCZqq%#UE?tNA,9_E8laO%Se\R8LW?HA:JA&qsFB2_HI]k?'4$-@-GrNisQ>$gaAALde9n?Qt+&L%1R)4)^Tar\fW(Z9f@%D,=K).sVO^W"WVP[X/-M.aN'.hQfO,N 7o"2`5Qfg3RLhkNjW#,qWaM@:\_=OGg]fSKrh=[\B=9C(t>DDr(geZF_l`,'&"*Ifp?N)cmT,6bOTRCr=A6,s]1sB3n,5PpRDC@m,,'jEo&:=@%Mdg:<^p=d:`8a<_D=bD`f/,([?%n2e\YK]"D*5Zc@\`3lnF5jLjKcG'A4RJI>J#(':t<rG9Z%&_FF[fj'q>LlO\$/L=/>\0^B&W+RG.iIhaJ8rJH5 sI9-$*o=@LKY0@c\8oVO9_OZK]eDqm]7!9";e9iTo0^XZb% 8gIpesVHaLrgR?`B\!40b:@j'Io>8&$fKts7%c\>8WkhB$/@It$:oAlR40A2&b(4"/d5+/'-k H4f=2UZi/QWjF QBX<"/ Cfa7:JNN&<E4a-`b=;^^G\'BTG8R)oCOc_@H,IIG<&3hMr'*(<a.&DhY5U(Qi&j[D]>qPeg<QN/o,!FJW@-0ZHG>5?cBiMK$l>D;mCQSJC? dYN:Q8rhGa4&9A>dtLGUkiYAL(N5C-/,NE;^lq#%c-GWh[A+f;20+i*BZ:+9=BrO),&(L`N^s!@e:WDD#fWY8i_^dYReFT4? _"9hh>)k,oE["p-)2b_j:)o$TRU3_4X@Tf-E2`1$&i[Ar)*s'-AZdQU9V(^_mW0sT1V*/W[m75A(_4jOjRAc+\Y9i%fH7$4DoZNO3r#^=`s;6(1-Hf#\'@&R-TGYKTNG-gn&"(jWpA_,a2`tFkM=aAPAt7)Xh\]g9P&S*qiO=+b&*Wh`OL[(g3CU3!d@."+<%?DN#5^YXg,^b+%b=@sA'-i"TZc6l0flWAGJF#pL':>)`_(baUeiis+5q4"s!VaH+X4I@e_8>^OnTMMEaJ7Aa4SY42kjoR _d66kF6iHA%eK&s',ib[G:>2 70/dLeZJhlsLba%R+9f1/XosAdmAZWbC[\g#_c.cJ0VA6gAB:o(`2>O*$NO_E7^1Eh!in[dM!Y8r>j@dtFcqZ"la>,d]49+e!Tf_J&A[QUCr,c;?HO%ji7g_9J)$6kd)ai-P[^C?Wm)M^ \K,RVU1)iZP9lmC2(Hod:#@$9cj6+-X3r)Sr9`97JWA::m;rl[9J*2XLE#F0U*IB$P]+\Fn>[%cWjdk._ tc1"2eWIR9#K9Y^5&%jZ$L,LB_K+19gB:AWdR!g%9?e>W/Emc26++H.\6F<':j#P9_kH_KGT88=4TmVGm[[N_)C5>;O3+>i=1F1UAE# \"J07pp!oq8d..g(((deH1[)^[,= ((s_9p*%(M_^7 l"rJT?l6n:iU*dgfaM r#e-_*+ADo%N`>Abj9'"FoLZ#db$&7Y_U^?4*SS>dG;K#O's7lFWA=6qH'rC:0aeXFB<^K(DV i%3)I*JAX3NNL jgeG7Q[XHVTa4\2OA@*5B[AIF26I]:,Bla4,I*ecIY.I9Z?8*)k`=#]88N;rHN\R_9414grVceT'LM[6IF]qaa;:NHd@W!`EAX-D5Z?gU5?bZ_TLR!llZkUaiB?iD8cjVZX9B^'(/OVNm0I_0&6NS0OD;;bK;',UX-GlB'gpj-n[fKaEn>sUb05NM^$HNR-<3V((RDpGKA-PdUA]s<)lV@r&7(n$A>M;D`0LM\ekE\Qjd.';qdO7 9KC6g`Y[N`.$1`raN?o;qR'r Vm@_'JF59($l21"`=A[Y%\(GAG\qIf5 )N'C%">WGA,Q>!-#RTW/?XRB:_n)^(RWBA]r^GF$U@A=oI''fAZ+RY;!EOV6E#sr<iH44G+hZ;`hR_Nj.CWM(Ns+_$a $-mrSr5nt;(0Y)fI)S4GEjX=`Y0n$B(q%%cb1 An;1nAi&-3\#Aa3jU!N`!4"^IqAU)[p$Us9q&"WLp:@Pe:Q?cLY(:Q\Hf"-V9?>akg=f$,Dcj&7AM5s-t3`N#Al<:"UVLG+c&,\k>ejl_qK?j6`&Or=Vd"%Np"b7q$8Od1:;*dfnp[^UJ[,6t)YsVkC@aU$>]3S/LKp<#40TGfNP*+8K*NUl!!]piG]O4A5#HQ@mE2<rXNH"K[jE*5g^(5R9!Pi?L3N[:3AWOUkH@(%kZr7EMbnRn395W/B57o7d*pN`iHQ hWbkC$j%ge:%dT#6LcPK81jRcAd[%s_$c+q>8hO)l.bbY&l%>Z^c6i>\Cr.GY^eU/rq2C"mai_W?,@ JTTS*lHpL.DD.\BBEe<:*W1db#%+*,Ql6?+X=M_nb7%,%lh[Q,['nTHTgdT7j?*ls;GT;;"%7+bnB>EK43GV(j"DQQs l<0A,/o (+G71o"@McZ%>0c'Uc.]PXt\>X@kjXWqP,,,V`^l*L&6(d\<*cc4L),GbBo.TmE6/@7OA^/^gA;!pPs`Wjk!RGG2\nG7aa>C\W@o64tKl7SMAX>k&L,0V19b.YK_:P[DGZEPLHX-/`*-n\AO'CjV+&Sr/!>)8r>&diAJN)I0aWj4m=&&&=Q^Wp#pU_-3Y13Q/g#"EQMpBS_1YP&9\ABL6Z6d)f#arHa!Hj?*X+W0:'WWOGV/1All"Qa"Xk\Oc UC>\AqRtCVbD)X<+9pXrR&`"Q<.0-M.Q'c(XYRF0^%>#TN-V1g>Gik I@1.R.4@"HA;hWF@Kh+X4kt$8*&N`;m7UefMH)W6p]ap'J)fQ;)<`BCa@iqjGCDNlQ&-A@^+H)q0CEYsfBs^9+$b!A?ifH`4e`5YcN4WR$q?i;hOgQTJZ%^tZ^3bV>;+FGPDO;Vd^"l,TA/^&.UI-A]979L&'/4bQ&Y==om?pZAVf8;@A(B.FUY4Ao3rcKMJi8&V6pjTW9 1L-$M^@?Xo=Efmp,!#2B0 iT?%d\^Zeej-I+,Etdlo;GeXtq5Ei;N+QHKEa>:p70G6Ah0t$DC[:IgmKiSg7/3hl#Vp0B[;2dKL'SW%pG1PVQ>U_N)0^D[ALc/QTOaA])brkR5&Kk)K8WAUkhpSEj5nB]MLc#(T9Je#LOR$=gn>EdiskF\p `roU>)7C<G$L2gPH`rmc-AE$3=D]UZ@:UQ`q`=sO)18I9L!pDZ&nNoiOftb^1l(KBi9k#Ek`SmF&_d0(@t$Ybj^jnnXCVAOft4TD_s\%K_IcT'C","lpJjjtl7fGG1;J*@]BZUl54j6VFW=+QjTO[1ne*GO@RsX=j4F /^nFZWSPS=VE=RJ[?V$21hQYLS[c<1)jMEQSj3p;s)_?D_+s9I!jokC8[3Npbd+kW fo)kBat,qpW_YspA_A!fE/7g@YVTODlV?f+9LKMVI mW-7Ueks6oe4AF4]Qe6I6W!J8M+?IGr$&/r@EA,d4-hU$]bU-bAapk6/*_ 9k(1)<,P']K-_?KtcGg>rm/YDhjO!3lpL,t*D4j"Z63)kB1_A17LJ+B?#(?9*:q=X)VQc\pR,o:J7O"gRi#Dk18$\Mr!:"m*_dh9,8g0YIX`Zd0XjB!S+-Pft(n.?'kD%%`K>'",Oircg1L^\+iJE]!QEf$J5l&_nGWLGI8[B:k\qpJV1N3(/'/HRLb3G57Hfn25*[:*\E`^< ,rr/oRh ##dl`7>i5"= K&;;2-8gsF"=(*FkCoFTd=_,7\^R]SKoRlkF8]sLMXG%Y[+im6_^`7fLgk;lC-)BpohMn0?p"6`ebR\'h"%UqBC:?A0-YHU%[^K.=pPMhB2K'q'oYgfnhsdH3:(LTqpV6;'q9pBsQR?X9^6W:F<5IQW#Sih2J=D"( A0CT9W_nKmV2,EH0$JWV*6D\s?!:8`4$)Q_366,!c(ga+Jd;lpk5gIE\k+&f]o"^m-R)A(M#8%rj"NWKf"NcE$%l"!;&lkQ nB!cpgJ5hBh@Be7go+o8fd= ZelUGrT)o@.,EQ8Z>@=elER?'\DEN'iJrTYV*7&EQXk2kLI`CJDZ^,!dK!U1o1 N=*qq8[>t"sJn9 r].E0b*>+S'Y`s;hpAZTDZHX+.DA6^0L;cA=B!12p#P=Nk8V@[7e7"9+YFsD[$F/TKo=>C8K<[,T$JZYs(k+cK?ZXgNtQ/H*9'h9@f%Ih>G%/U]V]VYXE_^o1h=a:lkC4Pb.L^eA4CXn>st4+jakA@NS4O#gD1V?5kOHNC heP&X6<>2UkP5J0Z&J?/[8ZElsB@[TMI^N3-85UZ /mUYZfSjGL]0@si:nj6;9;I)C20)BO?W;F$!G?<Y.:s%e5Ze3=7b8I#TbITfnK8nOrLs;*(GqG8P"HX(67Q&0I?8`DD;N9k<_(r0p#=P:FV^W,#& [H!tVq#g)rbj69M[;_aQiSN%r0.Q]$jAiIU7Eb\PEJK[(:CHjkg!U'>\?b #k`'>t"C-C'+YJ`@#Y 61KEb K?Z)5FsC>IIfH+RpL2>W"Q$JZg/2Bk;%Hs6(#a,_S%9qQ6_\;N_Dh"BGrOGN049+fbDSANG=*P"RoDQk91S'nQCIBeng42;,>&GA**j?edh,:>Aq\]5q)c[$E?('Wd-Z:TC5DS$BO PTUELG`jLS7_N> bGiU 76%\QC)5FQSdDf\D>T#"^"9J] n/$aA^8n#t$a]%-fW_j#%fH:JTF0=l3?oHUVZIpJoHlnM:ponE:,;">)l:Hnhg:@bUq's#DbK`L(,MU$,N+% r@@4W?cc[I,_)daC_?T"tSQd9^%`N__pZC:O[gWgdhG'b\^0ltg'O"koJB)J-V!iI3(1fjq7H;BrMlc0Vc"YKo(C/Wco2YTaU?s:YE2rFqB81/df5\W3[#]'0IYYp/8qQ0[_*tN!3KeAI5-4`d'G=&Z)hpqPfLVJUG_>>>-AeHW&9Mmt,l1T^hPoML&N@T[[deLkgBa^pGoh3rE66BW"?%K))Nn2X*=5FA_6^bT2hnC7/H%cMkZ-&MV'0JFf#_HRNV* .@j6eU`&l2"W=R)_EE0h[-,="/m2='J2>KF[Nk['@K_,\%BHY4]P"STZ@-Aea<&'BE;]t8No8RVf',M@34\/G<3jI`A(T0"@b,Fc0;,AfqSb0=o:a"I*5`'>ep4#4D&nQ6\=Lloe5Qn-ed&$4W.KN"!i03QP9DW+:smc2_$gO*T2MV6;';sd-06W:'ne-fpapE'j1,f2ieqam>mJVD0Km\24 _\ApdeB&@gq4%fJ3oq`.&tiR-(A bYiC([QPaT6].XVe'[Z-6j14_K3is p!1t_l^;?@SMJC;pJ=_6LaUer7ZpDO"@3R:lqT_(ac:bSd!EK*,sD^s8R0]as0lG17)r.(W%lA(q!b=J:E!rM8^dA1?Zk^ab^"c,Zd(@tD8 sM.[E96p.DKRG?Xl)oWB tD)(>REQCj(OlNi(gC]=!1ajYA0AHo[%2cpmW#=YIga?,f1E*W>9Vk(0DS[spBF,]+a8NWn2f3A)kOs$eG;5 *LGGH:3ZDK!B5BZ+bX][I,Jc47T7;#i2Re7tJK&]_N(e;qSY2l#.bU9mebC:8EE"U F+B.-o3GRnEtA%NM]7ICk(+h;KO`I&\LDE. B\VO+0T!-OiiOkh+.]RE3DDda0Mj:L^id\d#PdKc!Qt/W`:m-aH+8*gq\Zd)0HoGG(T:'8LH\Oj0`oJ(YU^_6ZKrjZ*t(S2d!8qMTUn 8Wi38sSCkKcZ"/_5n%fUZ!HRiaMYF'g^EXj93.-=(/oHe'!B,LGG9?cF[?X[WcE5\?=7% ]OQs6nJnRJ/':A6UGZGm7g/Ke%F[7p]Bs"J+>CCigJ(T%bZ"jnPIU@G$(++1S_@b5%mREh&2TbH5II@A,jS.[MH\1-b<"?Ak'6,(CjbRG94=qV%8 TJ6Z6&3(o?hYfKn95Wb=(=m8.IF?JS`Qh*R?@IEp,o7U-J4qZGjLnW aaf[VF(AD>YDU>0@ZreJ0L)(&F)-U$F@j5msJn)t6K-SGr:Td+9$PJ2j-s9EU6\:N'$=7BfT)bcHS)5AeDqbeVO6r@":i09:':jY_-2'ZY5['(PYtgge0LB(n/fK"i6?9]4)C9(;g= G;" AZlZW0t3bPYs^?t$OtdRVn:nV/m[@A"p.%9!p&AP@G&S^)g="qA>AVTb^=6T-HAJ@j+Tc;GU 3pDNba3iS3[$*FE<$UE(pF&@9a>)k&1MOK1MTY#1?df*dn2C>hH$;dK5>1b)=j"CNaV-atWE_"-\'\OPdRk;b1U^eIA4e=7k)U9rDASSEhs;H[*,Vef3PhO@&?,Ri,>BAqmEZ^tm._A#[@[9%jb!G#ft"Bn?:^0G4-Y`fMSLdelJrVb3:"KDAlPH#@m1!MX#.VDA6ZLIdnF(6Flqgd[GUtN:YDReU`>pUBBQlGhQbC:`b)A]:'AfM86]'K[A1G3[Yb"4oD.V=NhSl3JH)qA7TTW?)`2A[(.i=S0N0%!J1D:#";lcAWp>,#d+7MgM&[8%'>% P* kIrG4,JZh6ArHLiW<30`[U[`n0X":Z57 [N*HgZ$I7otWr54/Ok\NEQTXVZKt8D6,q.R3mp>&_IPAI(%?e!5?A/Qbe@ g5aGG(ni3aQ%8;=R7B4TgE=cNBq+FW\An6k@VSnE<(EC-dYOXi5P[Tii;s=l&'p1UFmJO[#pNbt8/q8Mq:I.Kl7[5+g8)\XkA7=1"7GT.4kFYob70WpJIM/7`^?rOW"*C\'\[Ot%I@a\dc?'cjQPlh\h5R/M@DqMap%_lgJ\f!Fn(UQJHGTlr?>6mA,VAb3793AjHbXFg`E"d-kr59p,"q.g1FgFVB?%[V&V2T:?02JO!OEQ8?_GKU!:6^lAL7C;Mb@2b o_s\1j:e]df*LQ79TSjDhM;AOd/9Amf--]#c?4Z4DA*h&/?MH0(=W[H>U,j'AQ5=Z84qS_]io5sdC/Y!)Ro/#1-8eahG<=VGleBq$GtMgJ'iaA&!0>IGh<Ar[[r(DdF1mRYX(:Ah^8=<_HA:&X:*+ra(p/_Dh_,i)B7 WFq+ZfD1/-rZ#rM-i\)%3a@Ud]n*+O;b0j3c7:&A,T=<273+Ib2EmD[`=N&`99S8??o&/@qoP?$"H#EL ER[h^aK(iFGP%TAeefT$Eib^ "eH`n!A5\Tl.DjW:'CC!8/rt;Xi`S_Cj$Z=H490!0#9:$A!52\G@WG =]X`K9CI4)gYNKW0]=OP;HJ/%pakp c>":0rPlQsSSUKaEQY2iD/7.]oCP"omV(OO5WnrAI[&&A`EL>R_/"r8.O/6cV Z$JsGlfKOZ:6t!G\[[;\Yjb42^6ROJ[TA=jbf9AG>t9_6pnNXioVqA=2<]-;[t7LX58k`<*K?\p8IQ0At;LEW0+H6+*fd3SaI'$abi7rAfNh/,V!@M^H@_i&]O,^,hNt"(mg!7jji^R\ 5WC=]M[q_[Mb9.nl!"BTOBj&Zkp:0X],&nJ$\]]S1?Ra^#V#X3](Q9qUlM2FqQefOt`oLUd=2`-ILq'kl';P-$m&dbNq4_Xmcam,pA6ZI^Z&eX3jLk'W0^hf('1^&b:oT=nOhOTQA!oh'^#R>P?3+L:XM@anPUHL8pEW+.d*,t`Q423Ea'3*,\8?[_7i8SQ,Z8-EeA(or+LtA^)r,Qdf!13HT>+l>jp'qK'!5\S+\1R[T(lAWG@*@WXWjiJ(-C,:$Q*g;ZAs$K+Hf3f,l'(.`2+Ltg=LlUj]A)h_.D4AVThb_:o"E,Ac[$r=`6CM WM85D/Sa&]RgDY7Q%1/8AP\-`Lla-5N?aXpkcrB7VV`E!E8ClT8gsmJb'3W`?C9rUFac[X^gUQ9TDjZ"(jmU54^H*-E?/q?8cIS:dL0@ b]9#DoU)^p5b8X$*I51q^WsA'd%2O*N$0gEfr(ZTj5]CgAC2n@"p0tBEHN1mYX"?InEGR7A0T>VMD`$`9?cmc+SA!/^SHKc6PB@7-/P'NLQ)s%@ (7\Eh$-;DE*hDtr/PG[]J69FRXG2K(MJRMkOrO(Z`KnNC<)o[<;`1hDl#((g:W$CrPUn(FVC =a9A-p&SQ-.Z9I o(1,pIadRJHa3ZLTVh].bH;#MkK<-en/H^=(/"fsg&B*bOAQE_X[??,*N/ ,7=',iAYKN OnML3[P^e;$Xq/Y-%i@[)P9cim"-8t<=^bh!srU3cB\&^^>O8IjQm5HNC/dnKsYf:Bj0dN_)i26qR\k8k@Q0]_tO[dGBL4Prgl'n@/>Uq32\"I/pFTG&X`QZDM/,O t]LC\nSP'mjQ:'NA=&ln^;D\nlQL&M;kAniTD](c28,8,18:6!M7n$&RVZce8TeHW#o\G^F%2_XM-/U5UZ9q4lg"St_'MSKisb"#e#NfZ,Ce(=nU] h/$U.Spq*hc+e[@1ZC^=2J\P3bp8$c58j3_O:0k6WC##3=jW!& .f!B,H^\e0S;adAUOo;6ekIP$>Rh[\-nN+,ph ]3C1"AntH(F?`s_SB6CLBsh7D@7 ]SAJd$j'.-aoYTsN)r:=>*Gf:U/! -03/6n&B$JBQ'70?@&G8eDUk:-tPpsa=-lYS'G6,^t+WNDdb06]"EpeqtZ"fq=P'"pUgVY*r#D"JNmJXs1t$;P0;%$ORIhWYeAbL@ZSB&G'n4QD*L/nS/^GS_9?9>N]3fFnAGr!neR5=_cYH7$)Pcf<Vf[rh+C"(2A?.m,SQ+:A-I-BU-Kk6prA&+><'ls^\6#l5#gEl0o5l784M_U3.=W_qGAmQ*%%^^]6j$/S,O0"1e5/YmQMqj?<-TR!*0lOrtSkQA99kNQh.%r"dOm+eGSXYY8- )FeVXEH:P@Sa##kM\2&7EY$WsDC30'l"h>%Ar#"]CrI`Y2\8o#-\A+qnB[3Nqq!a+'Cab&_3WC@]2?kr66f$mXoJHVQb1L;/"E/[_i"2A#O_@8!_onZ:KfIm25I;qhK"A3L@W2?$7>_J%UAKVto3lMX$-(b7s#nZRWJ C8^J.dqq^X+f;:nS.j'7',)boQ07P:be3Jja&_SjlSF/KCf]MlAj\q8MYh@X?E9PZEAhdOI9`bB0)DN3M[)i!`5iE&/6cP,K8fd$Z;6g0ZR&MA+m"ikA`$A2.0e5!2g==^N`#'j#rqt:\ _q.1dcbKhVo5QdUjl=<^Q%pF.J[KsmE/p<.0(?j=(@bU7 V`Q%*Q-\pdr%W@>etp(Y+?H+WbnN;JBNA)3Vh91?M<9/f7_j,B =E28rLFmb9C64o?NB1Tf]a4#GU:!(3o?;79.Ij^jkY+e7Q^4?[f:@sFiqGiP%`n/f*IHLa0CepA>VB3hJgZe32-'2hf$1) BHM#5PtgK/B'5D_/qY1=%*GQ40 `k-S D!DtVCL"a9kLRr;^Z\S5?4S4abC^_Ji.9=:kR\r=)D7H=.-1r.OZa.N"T7(U\snk_BLVsX%0AJ0_%V'jK_.e;o,A=ercfJTZRlB:js__+O%m9/`Z]`[CSU4%e<4T=F3NGa83EIc^MZtk;J[Yt=&hJ'$PTA#8 F?B]XWF(CAKpLX_Iq5FWSe5._?it'%Bh7EAbZA"95NAo;_[WE/Z/0bGIP'FkIK*/Ie&la!C\nR&'>'c'n2C(t-ZcodJ" %s04ZBVLT1OpehGq-lKmTD1(1"Ds^"^Oq(P?^66F9X\HT/&MUTcM 0OA;\<[A=d\TRPmia>:qdh@qi.IOBj]HO#"0.h%nSlXOGY[$mrSVp[Y0NICa8RL-.!ClD,90Hk^'k6a6cin/Zb!&je^@+[00bfcGFG(LY81#7tpAeR6Lb=qT_H("eb:YOiiI6hV*SF3:9iQ\d qs2h->dl6OT#PDQEbJX66i)]FtpBF -g/J^S\sl6n=G'Jr2:#B8)KM./9:S]Br[&7qh*'hl6L;"4f'[e8njR^#S@J6]4DAJST!XpW>?UcZp.d64.E#fAR#AQ"CFqY2BZc+AOK2VqA6I'YgjrfqW1rL?F[BD.fRm6+@2nsc3/liS%:$83NB]RUFI5I; M14H'Nik4^<'eaTB(=6L E*d$(CG@ >mUikAR:"3Pqd7$''eK1^GU`>aMY*;?gnmc_E_1ct+b6LWJpR_AJG$b&?iCaD.R"S7VkB*8&"h`YciIiHg_3%54DpD51IWl=V:5@t\EJ5I^8K3%8#@l85N#[C#<7]!*1MpRCS44&TfRhG_?BH 5;)CoIJsT&m9KBB;C<;WK$?9r(h$W0X5=W:_B+@W>O@dJL cU' fH,8;M!O(08I?W8S [oN8c\,Cc&'bP.;Bh&(+$P*Xq,DmW)Tt t/(Q(EtlLC:fCY&XD0d[BZO0^ht[APo#Egl^c<\Z"FUY_A!K=j8?9#/N30Kc)n78ib8?b^7cU^(fT@q:%(W-k-FdA4Q\_8r9VB]%SP]?(:>DYF2H@);(A:!2$'QhpD:B40!K.BBlUk-,W5T;#QD7=Q;k5,$:!,OF>XA/N#+ia]dUIF:!i"9tl:a]$e2=CE&KdWFBC0mA/(%d$qgD#5=e?R=S]\$M5jm)EJE4McR!Y`olVI#D%AAe[?*KXS,b":;275`hGb7QpHA5/'sqb,m@pXtWq#WC",L35mH[FD`P@mTP8-m=nQ5lOpVobKa##,I^iK=Wj8SN@^^sK(]2\<@W8oKs:<Ur8%E?i(4?H5(,5GiqX]A4:"rD*\cg!*$*(DN[2IaG:l7S+(K@%G%XGLW`5ld VRXkrEIJXk@,6RB4RBbrm%i9rYsE`]&^' $FpBbgjj8[a*F/,7*_Q0"3V"e2_&NW_Q2nM?E@(hjd1lm4O94'_6 IAJeXbp;m,!(J?H6I$k;(n]H1a*p@P:1+hdYQbTi.8>:j.H]q*N'cZ1a,a.IsC@c.rl"*q[s8K,kg:3PM?:t #s81l&,"5]]Q%N1H`D\WUS+AA!'\2;4@Xt*2b:JI2F@ERF@rem +O2.!&L#sAsZ[U]B\O$p^=;_WUPcp $-W/#_@jmh-kiq*5-LC*i>Q1)>7N;k[_jqJ!p^%sYC^*h)k tMUVh7E%P&TgZP\B_^1/SS](B=e7C3?%C=f$$?D+R-R2W)[ln`(Zn?\/k\;%j*+_;/AK9iJ Zb&Ic7UW&GU"b"*sU_@D 3Q"oHbX5;P3`UAAqF,keZ`8 "j6_fld7YUI94*YMRE*K99rnd$o78=?O>:Zh_ LpQ9F_L#^A3QCQ$Pmt8>N^W.)QBB#b/fefCTOO\/C[DbqdJN;iQc)_2K)i>tEN!t#Eo7EFcDQM*/Q$DVq73A>3q"?rs,DC^<@Xa*UNT)3eJ`p,0@eB-^MdL]-+AW?+k'TT"=*QA_6N#0QOFGW\J +CDa"d]!*[O+l[\"D)aLG*\Uqo /lpZS'`25':Se#*7@QG@>i1.@tN\l0)48QCp,Be"c7Vd8C!NOj7,,GA03+k\JAPm6'EkqMBeqlI`0o=jW2AD#Jr"eLF#K#DMXTA?)p\WG.+)@aT5$rEkal[sh#f)7D1:N@J.hLlbZ5gld*A%!]Nj+93+Mdh;e8oRR@(OQdp$:KHVG"_>S+"/0$AKK"iET>q4-g$g`'GQA#O`iA Qa AP+lgoob, QXf&Bm!5/(8N (/Ht#*%2/dPin7^G+o0+$6<8RAVppX4`\eo>*RtAe7)'dO9B[GH:)cl<Aic(Z-4gZeOn1Bf]g 9epr`)8M;m#ftY:ZEMI_8UJdaqj)q ,h\piI:L:%#+*+7o.GkgkrmKBU"`WMJ8$XMWK=hU/AR ZC4IUaT'24[l.XLM,/.K,qtV(2cf:]Y#G0O_92(ALUY:.'q79aqZ4CV%P? VF8qc#^Ss3fGdSA>8SQdK?;MTW_UK"kj2,F#_OA/objAB^k_BZ%re/blK+3Rt lrAJ#ZeACaIA(jh \(Ne]R_`BNQ>b8A\P-"/ABZ[KA38!pWd00d"FSX/]S=CB=,)FO0QioNX76k`K:9,YD5HX(arVUq_-Y0co*V)Z?h`C+Tt1o0e"@m7SVai']@hMG\*)P9M7S">c+bEkkCS>Hlot<dEmi4$KCat_n#)QhYAUUKX-ZU*4O;D=/4-OkOYdbVm)Ng S:Ia5MJ),E33_<^dHQ%j,t*#?M6SZNUT#CH<\a82m22`@NpdTH>(1[6)^ZVlAKE5i2o(s)rskb3MfU6lYlss3&96[M, .fSc`*OrF'.Y#MpkH/pde%<7m:LtYY&V)miFbqegR7Q ACrslZO^J@J*#V.H"r5m]5j.A.U7#82lN*]3'4mC2fQ]*n*`M>JZYCoAr6m[s7=V9Jfb3U3o77(9XYT;A!MY>ke"ni<TYVJ$6k.#. PMphNC_J*bi:DS"BTb[CZc92qjomnC;Xd*iHA3@F*C^Yp?Fa6>S2[0 r*ch2+bA U@j\VAZrA<6[4b08g*:-c&ke ?fU9+5$ bkkDB#9?FP_C5aTLiHaY%D7#empaDa4W%`KV$<"tD,H>GSLPNO'TEj./\m,jt6TWP:*hT'eP[?V]-Sr_AbFZhABkt1n?t0*Es"WQI1i',F#/=?Cd<.?!LhStaQbW0,1DS"<A:Y]5rIq'R<[j<!tYP8^mf=,n[J"]>V<@dCam7\A-[<&3qo:RSSHB8\8qVEAlG8n#$fbnV$5RHEtbDJ-6QA%J,OQ47n@#mO1'2Xt)>_^ocfoAT>Q`>GkdZ$$aM-Y"6acopBLJI!N`qA96bBoap9c5FR&(T;as,B9.D)"6n6A#-Ikf8YJML?$N?eT@_]@Y!R*B!J&`0!P#IW6I`eUO>qm-NA/W#hJjN!M\>=%iXX)Ik6;G`Rl.BJF7b4+Sd7;q-Etb0Smtp`7/02B^]@7>GHJn9XdWE1LL'bon0j)f7=9-I9'5gi)-RHhV?Y+gWL .W2*XAT-qg6VW,)3>(86YA\cIc6%s(/M8FM`/3>#akaIC>"I__#?ls`7PJ*Q@RZK/.-%%9toT/m/V'"YQaV1kf-Pg+$;\*grK1KD2aQM1tLp`T -V+qXm%=$@/%'k(!f?'HY"9")?KZ]<13,lPL A.CXOJN_h5$m`%a[S)fi,2j"C(aAsK#?db:m2EG\ Bhq>Yn:VVQB`VMLIK'P&n$- Scm&j=ilONY6qSNS?@j)'s,(K;K%\1m\A$Y'GHCPG_sJ U?+S`cXCrDAM0_jq3.q#R/FMf2JekA0bWY%UPQF>E3g&TmJZPY1 8bj\Gj^`q@#!DMA+`1rhm:]n!D!V#.\kA485=ACZNRP]m"]fhcJA.@&14C25=Iq]FdO7+XWe+ )S*qre%GN[ 9=$t8,g! $l.1$[MO+FUXqq8o$[dpAA()4[8^> 5p-9i]L(Y=g:M%.EM:nCF6[O&"B4;MQQq;\E@t'/1,NZ>:iXc6 *QXIbbUMA"[jV`iAVA4i%HCStaApU?fs(_(&c-`?C6W(TD:QAABR;-=p1VhDKoQC=Gj_DQg@j?;_"Vm,8Bk#OZG8sCYkii2AHa7'-Eet/>Z`(hFCN ]Sa';LE>#qn5:!a#-WGAQt!r'BAFI:B'r>6nqngBVHlNK5Zf>9VQ9o\*Xi(1t4lJT p#YQ]1c37h`mP-8J ?qRg['1UY2!KB./E,`BP#Ca-RNbR5+#o,npPUNdCp]@0Yk\D1*X/+cog&LS9?O12P-:.9gk`)K#=SWI0]RV\Hi]-b\^N&F;tUQWBTY3"[94O!8mc`?__6,[ATkf-X"-h?Qs1hs\1&AP:d9R\!Q]Ul&r-NgC;&D'_ gdX%j hX[hk:p6khM#7'8s'/AfS1.;FFji7):shg-1?LcP\*0cVT^/g.4WU45eMOms'FX8+ihJ!\ip/>)Frb$pXtIYY;U.]q`XC8'->lm2?0l/_9d$1R#Q "MCPLgc9t M/hASnmMmK[nMXJ5-Usj5^I?Ut$1:O@FYsRm*V<@2W8EhOA,g_Cto"2b#p_"m[_^`Yr%O?g);KE,/C4+\;drM)$*$UZ)7_.:DCA+k2eAk!sB5[I@5m$Or_+:#^`M#L%Mlj&P$XtBA1Z>4S[rf) o;'?;E>+$k38#JNNke[RO*!XBKMq$RaMB%a#]FgtKLWndl3d"OF;/OTY'2a56Q.TpOnBT'c#52Po"N jpRV YaZd6\4/R0E/ZY8@G*epS7ja&_M4W&OI=UjQFmR:]kma"f_3CrNdepp6O_-k&+Vg4-A)H/d,@ZZ;41X]XB`;3))Af12R8d%nqj"9g"%XJiKUWM3'l`:-9<(cc8/OAUK,G[f^iOMoI>t.At&n[(+Q0@pq; l4ket*a10XhApT`(0H@Mtp:UP=5M<$SJFm%r!/J+2h4?:e36P[]54Ajm^#+*R*=eW19S[$&(psdMZqX.P5:'G5'@\-&NEk+(Ptk/t;b7O"'H<+Mg4*Kh7(c!nZNQ=;i_)3iE:gDgIl;a^f/l/Z!7j$;p16Z4rqp5]88j[[>1\?psffh;Yq6DBt7joW#+T0E$b:i]L?&"LR7`(N1cS^a57>O-!LOG^M'bH3VqY];-:dCetc4UIM`ciab,_Ek18dYU"g';'"HKbF ;>fLTPi7@sQ-&er``/-X5C/A.G%q:e/I(I]dWTV/BAj\HjVtZ>aO,gi#o=(;1D%tds3@\T;ZDC^qLV:Wl[N9i'=VWD!j9P0hBZmE>1dDqS][[ABO)H(%E:'R][551":,UD$*U^`lU&9WD=@eD!]R74X#qo']*FEO3tkId2eEb"=cea?@04l ME%QZ7oji'B/l`r+.F>9@/c@dh:W]E9T?e2S?W"i>l/F;f9jF9/do%]S1-9Y:sn[8B.!ss^bHB7[9>TQt_n7W]2f&IK3KZBLAR5M`-:SQG=Nm!^2O=oXjQmN**Bbg82=,?%1 ZRb;4:-tt1RM5T`%)5X6Yd'3`0c"UT$-$$ ipE;cs9ng;KA&- 2 p\0#/YI/D2S=p7qF%W8kD9.T&E>4[d_;s=(*H>p,ReVWnLW-U)X!.A.pI'=Zf*SapAW5/$+fak%QqgRL`_U"CA!@LAAfjE-Cj>A,`<?m+,,W3XOVQr[kTQHY>@1$PE:LSf!'FjLjR;;g%j?P0?LiC!fU[AY>TQnp6[*!Pf60],b_%DI/%`CqMgDp[?3;P`M#8U2BRAm_^PQ_8,cFB!O8*ng9o#^::F^AU_JTUH(IiNs3]a9V;01;<7Bf-WaN`)F^"Be0RQ7LX)oAFlTL9krLkY`V;_8qOj>k#1;Qg=@sNr)I&/gAgX lVbhF.FCEGo2ChEgGH0:&@TBik&Tb7[``d7T>L7-_%:Xf2n.ldtlj>@Bd= j&N[s[R@5cQA*o^WAB:%A=kbN?pS14eFM#Y3Ls[b](spXdn>7[1"(8XY91\g"8jdkQ_)P[FE`O9A?,!ZGs&l8>%1%6EMTA_qEqsEZcH!ic:.=[IP^7/q0"JXId2 8Hs+2AtK5l5ZW^%h8([?A38LIPT`PAshLUs,''dC.6i0j^l.'U%9Z!"YEal*$6s2(N$nM21&T')KNc];JP,K1AZ&HgQ5g0i;@Alof@02jOWXa(mdOktRImheaBTF"+_G9S$6RSn';FoDmm?QeSKHkA7.DfA]b.Fi1k1LBMXk'>K&Al..qA1daLmIQAgD =bl(WW rKQ^kg!0_HL08,_&coL3"L)8Zp(cm;K#J5-)#V*._78W_AR($ZKHP4-:fPm0@/k1!8^[BXSoQD!o:Yrn2"2T^"Jb9s=UDLX5W@Nr@'SmXd'1c'VspfP#7b4@btdUBJN3!^Ye@n\;)Sf#HeATK9mrVQ;='!-::"IJk[^1n2Akm>Gi,e,aIAZ783dI&Ns93`,i)Ml@%l^Z J-sqj"b*a$$9Wj?h)>a6(0a4@^a`NoF>EA2Z"%6O@'9%.2PaXIDk-MB^h`RTrFG"Ki-]4k,[2kB63/da"r,g)*cH;HC-daTZ_,Bk] W:? ?`,e2`=TCLJ@knRUkoM*i`_Ah9PKTTIatn#:pp0;T_kfn+$c?Mq\S$_^Yj/?fOK^&Q$-94\0iF%'8D/C*3@@XfcGZ;K]E*)T%llg]b^SLSt Vrdt4)Q>?k0SQQ6:Xeg@pm0]1>,TnkC s&LKP5n:EHp2")g='d@s)2;-Y(Ud!A-'AE4R dVZL>MT)q4<'9Ymfs*9?Q`d)b2H]Om:]r+Kn`gt"_>:)t7!GA;&6'h'-.\lr'erd(b?#9?9Yk?T%;AXE?=09Y[DSUh4)8HltINi0J#b]Bdt"k,Fb ]NBR2/8_AtKDN06M,(Q*0IVE:pG[%)2l@A`(R$%8frtGF^i!6c*[)*Mc%?+6q[0@Zq=V^]`#/U&BT_'6FD*mS,AHh["]`N(QVo'7Z-f,1_^s&)nG!,A4j53m`k,%Yl0i]A2S6"DHDUN_,kR.66#dN];A$\_ggOGpVsS"p9]cN)rL#C511GK*j9H(K(0dqSJ]Gdb5A!Gmn+hFB2]jA>'@8iscCUTqIJ@^Sk-GT'pR9<P_Wql2^,(O&'An3QidAhi-0VS=^@dbe%;!On(OYba(j[*dJ>5b16&<;>3DZ2G L0,]6V$0)Q(fK9o6g&439WHT?C/W&Mkc&&&7g2V/Kq"_LqJeGEJA,U%Z`^$eT reZ34p^FaPAKF>]3RJZ_,)>=r\E1 I-K)$b+ -@[&ZT,mc0b;C4A@T3,]Q97>AC% ZHN b"f8D *a(! YCXb+^Q8j4V6+*:<]j+De"ZeR(fL(/@Njn5'&JG`?@f.$AL%Ht-:iLUCa*hl17k([ZY\MB kDRh#JS]J.jt@S?LBh0SVG`AN.?!gqAH,4DjnOmK&iG#[P2X"H!fb(35A[cr$HLcY`cp^Sd_7N[]@o2i9,N9Z7:STafZ@E>,"oXL>W""!IsW`n'9%>O9 .]!-O``>qCK02AHnPOAYDK:f][ZX;^E.mF-#JpSNM45q;7Npc;JsgQVtD@dnT9n,SN4Z_8V3ML .Bd1brK:0]9[-'!?gqOl^$g9#he@F/#0AFi44-GFOmX;1Y:ot=40rm%G)rZAp*;A#$]bXcR)FL.ot!/ HGcOY6eboK>T;c`Q@YZ2)E95k0(Q]Qk2mG!lA;3=?"f+s>Z9gOJe:`%EA]IsP^bL%a0'Qns/V/oqN*X\A*SWV1 7H.;U)V,f?6l26J)'r9%S8DHKYBSA'6>d#Y5bHErPHIH)h ; dcmLG9=WNP^dV2+N;./c>/.'Yg,G!Z ^"c6S3H+AJWf =i\^@CX$IFJnC(,AkAGfY;jttXd;0K+,#j 74DomGDbk'5OeaYs;*0R0b]$N4L+#f"s?8$`t9;OG%Ya@kQfAANhdLr=qRH:2e"T)/b`Bjg(gD( 6Pc+^[&VdH@`B>"qJ8NAa]8A@t%qd>[l]RHQ]pZp2\In6]5?]l%j`&A)5r2IQM:;Y9rN+PP*lL`ZCP_@tq:r%T?B_$39l r\hehLm38iF,_7?jQ"=.\Hs^+nEs0Jp3[d.3mjc1]OH#`oM#1ikiAL`]8p&>Y>.AKBB4KGA2r%(Z0K1\QW7!X- =.BLhN=d3as/*B^#MY7W>5hH,55H1,tMY9]Cs?H4/6da 2JSJa/t.(Ms+LPPirD0MXP0!NF6 =`!+`A`RfU,&d3Q+lK`,e)6$IcpA]r0mMfncKc[1WetLAXiV7]U0AHB3/"nBr'kYZU_/3:joQ-*(OE.2,@L`K cM;WT3sF>(s3=-i`o!-XdtHROf@RQKdIh<+\b,GY!d$r.8ho5%KDtFok?`?bP6:T+D?(qj_=htP0r*[6B'WEt"m',f^<\`noMW!_e!c3Gq")i?spm/#Yp BAQ2jmc9G "]FA`L@8h2aSZ9X!Ym`fKQg%ViTALaF&-3%q/BE(s/%`A7q_lf8DJrfgT,'o_(dKBR7j=o'G2Y6"O`<-OCWTGRV/=f8HPB:d_/tg)@'" DjV?mI%[4fE^MtHE8eeH"h2pS./3#@Rt0%T"-"X'aLPgmk&1WC7^$e,Sq%Zm;%.+=c)2MMg2@k1JfBNFJO20-$D=@abC+kKf5`\-g9L:tll4(mq\6X9jH(?dUVK#t>9J]H0?EtAO&:BW_pV(mCX1qoP1&ArT[oU_NWphc14NNs60UO9]gbTH` >n!IH%IO*(FaeHm-ePb(>t'beip%>6(FHP-)+JGN`C>D4ffmfcYsWcmJXBpOVON4``0Q SHQG?@!cW/hoZ ']MH'^0T!5"(i)h]Y\(9FTfJV:4Q&ac[Z*f:,@(pL'T@0:ooO73t*S.S R?@3gc+=bcCM%M[$P:K<;o$J='rX9Sr h(fI^fR\'E/#][^@Y$OZBe;-88NUnS._L,N\$5cs atk#T3A$ffIU;''(A$%rrsBGD;)f.Ar(>3/\BQr\Tp@LX^_71-\)@q"5U+dG\m45Z[RWI,RY]=UE=nSh4\4*(F4K?&Y-XSFAP-irK]<">lYQ-?o.j_N5>#L:^aaA?%Vn8VQ3'@m*sF#2Cr^CNV!f"S_WMCICaMih:_?p]%MLTPB6C3o^&L!<13?gm_qY)o9;2hGRSJoD;Dt-#Yn#e;<1=OL7LD74Srmp5&UAq(t2;"bQ/\5n.@$kZ5VR*(Pd -Uq%T`9j[S4J@*g14fA-LLted[D.m7f?"#0olA3Q8%m4KIoI("&Ks,.d@5.m%7S.D*M"XSC<iUQRKUHa%e%8LWNS#]I6]](9""8pJL'd'ba\l%9Rcq%n^hZ6'=pF7^rYsoBnGcg_T+MFV<k0-h'*YjT[-#DfD/L`6gqp<4M^M?<`Dt9NU^!=UXV*Y7'P=jA.:-^ _hP5oYKAgO/-VA];+43=cTaOg"(G`@$6M-J*C2.jPo9)Z%IOq7K'5",U#XK(WTc:D*s0oSK%(pEl.Do3Qof+P9A"Gs &o-20FR_;G3Ab:KV!q>'JBX,2'^>->L`,,8odNI"\<&PEk%E99kZB'#\R:.bgbgUj5**>=NE ok7F-:0.&DXk1Y_h(3SI4ki"GTe@%(rc=t4>jk#o!@rTC97+bJtVnc^[*tVpW*6NIZC* ;kAf*))ghWh+T`47Y^6h?s<P*0ds(h*"8Cd$ ()W&_95S)U9>t\MZHTgTBZ01;3;TQIMbjC\PA]r0$D8Oj3>n=O ?N\)E e>a@\+AS77?%N1K[qjLVAgob#IUGIFa8lQ%tCBIYXCjf?iH.5]j5+*!k&DsG_E_H+Z"(PJ$+l'PRmA XO>5BpmN(MqiNP*A,@?9Wi44tbi4'0'W55LNmM2AZfU;DGU^l,g-XENS,rh"ZU$E3\=S&DAEm9r;iK^N-]cF?I>n*ZLbA`2<5[7KBDLZlA1r1%ls9R;oNZJ.9R,]eQCnhBnF)bUL&L.?RYSbFONNqAka]OVF*#biD75m(&]@k6d5%dNiCs#NN=e\=^itmKL*UX )q\j=hb'J=.s`QV2hFD1K r(oZ(lmdXR7kK9`j?MN7,ghZ`r0N:_>A Z#kS(V*C Y7bAeYGTpK%;tl6P!>Q1W!SKT\FS8hq4MV*:leK^H;N>pFkI0)F9K7MZ1Jpi8Mp2T\_(sjO!b-Eq2r1:[4%3V%gC)pmecS,cs0GP(/(l?X260AgGL9:&)hbAUX0q7Wl!Vk9$D3.X8#,COLJ^a"B.KbmT.*%eJLl'HM'i81@)>>qfq"HJ4IZ*e[&CF_FgnM]WT%;Y.H2br/ir>G-]="3TJ]/Z9&1i5a_DArr$d6ST?+ 606gF.trN;AQg?2TXfUmfNE0P*Tt&AGpK"*,,]\k':dVcTY:GPXXW=6\cf>C$F@-KJ$B6n2ZR6U tYkl-'1D\A<l=2E9TBINsjp1(&tsc>Z $"%O+e(QUcGiXAO8JtZ8 !K-O]NEbc&R*G)_:D^nfU7p->OA(Td05*?\`A#D1&$Z,L7 3Qh9i)b=L737;!*a8$%j?Snd3\tr>gd\5tXUWs$!aB*-67+&l*TL/`G;c:^\L j=pV5:[,pE`tKNIm:"r%`b&^61IJ)$2Af86;=AFkQ'4H<`L/S'X.3[?VXa7@WiOQl'oV?Eg"j;m4Zj@$][-.4Ak+3DqADc8+<9rZ+h/%:6+OQ=4-(^Om*s"6hnAW_3tb=?H5>"f5k$bD]a1ULOWdf7I$/j6YeaFq+5rrJXWkAGL!;Cq.P&KD@IJR1 ah[nI- kM"l5=bj 3O4F%P8s\M4T:#aZB 0"dgA.V3*9L[n s>F+RW35/TO<.5iX!P;X@OVeZC=p&]LO1P!aGRn\!MiYF>n`ORkFbOenKAD!FKg.RNAl2jiE t;,;,i#k]n;SD$c+1b9'j471C!/0I RFm?:h,Ac_Pl8orLp4&A@oUX65JFZ7,;?$ZF$c)!Li9Lh/bLr]gCRKA#U)ZiE>g?jIrAR-d^Jom7ON9Y?^kaokCpR'QhF8M86-4g<TF8\clNT =K?Y',qiqE&3F4,T VU8f`K57\j@!sO(Lbrm$c`GYK%Q$fn0P/,telXc->@[Bn!UB+l')=]A54'PjY3$-4870FO^0+/8_BDHd.2^4.`(/I.dOY98T0NA>)t^h;5*:+KJ-6#@`=B/t@hHR#p^m&k!;4K9B^4FMr &70R(ErANQ^7U 7E123;pZtT+72f69F>4;HDg`kAg<Pp0IBJU1]+cpM9Pl,Ae8X5Fo[Z9[r(hEd(>hLH@: slgm+_4Q@. =qXge<."NP!0A5]frD]s%/;TTUDfZ]*\p\c"HW$=&-#,MA_VE".&+o%3*P+O?E$oE>2o/&R.ce-ST6kE<U.G^PPZG#;,8:E?b<`3QWMa>!X6NOT5CtIc9D9\h&YbD%0WAPh@#3KK;UgB'XOp0SP9/6T"mA`>CaBeebX4eCKBWtOc"'HjS6[.*YMZ5'm'R)_88g?P.cEnRBb+C7q>Q@TVX]a-DfE,;Z4n[0ZV:TGQF4>cc\IeJAlhNJ3`m4A.4;fOtMI]E/1C,%>UrO,spXDX^7pZe/B5@='S7ChLD1DiY]U6"VJ3"pUPJC!`A"2Whb4]c:.]4B3"#O+Z*4*%aJ8BkP+7E/jDcH!naD+iDmS`3QS%OBM>Q'cZAaZ!a#Hh?A(=H%k!;]/:AnH5o&JrV8.sZ%c=S0)oA-lG[4_Y2TT/KW@:^gtt$eq?q]R?)ZEC`Y!^O&/k,I?A3:]<`2:As186Y0PPBfDm34gtctp$8@F;BVd(,4h4[QAY-tH!TA*nY []?mQMIe^R"jrNMqs*?KF$q*00tT.l7t0M9;S>]MOf=]62.RG`arrBH.`(ZP5&3POn%=,aSEW >Cb&Zq51r/^MqQeX!a4U`H2]$$4OhKag8jdpk-JALjcp8M^J7*ga7J0!jTBPa AfR1_1aD"4@CUe9) k#T(*3WG?j2%-m8$3>.A02XQ$(P3>IC7AL:kO$7kJ'pdWi]A-)tlA&3 9dh@ L-!oa0r%7fg4i<\TejfAKt?FVHV9b&3Kc;fmBi`TF9f'\Sqo-J%`F8,;-&i3=B+F+>qWglV;!\T52SeM0X^D7nYjm<@1i4]j/X2Sj[L[5-8]r*^h2_Ega6##!9Jpr`a%>+1RDg/9"G"@><97=!nW>cg,r=HP2j:8Z%bM,3)&^R+=dqhRmLgL*p%Qd4cDnTJA_\kT@E=_^t<3 TbBON/N4p+ohs=)8d0AT&[[GU6rQ)U=@AS3!O.:ae%$^a:eF$E-B*)NC+I]RMb(OP:DcGh$/kmKC^Fa*(aQUa%aIhe@fTj`SO3p2hf^cXp],Pr+?^N?qi7.+PdZ.Mc7gKP".^,^M^>)Tkg,15F*OZebWqLVtmjP_'tX "dJgUs^=('a99?t%3is^Xc=b?$+R.TVfX7LQ_4ZsSs* V<E%#6d69WI>:bQRrr<="DSFR;h[*=Aj4j:3:3:&n$LA'="tGLIqr>Ho4k0[/k;$_abW0=ne4`NlXo1!VN.sA'5'eZ&;%9kq)#s!IAfo(KD+?ds*nYSVcOrhn%PFM%hQ*Zh&ArDNHq3p7TS&Ans>Z:;@:a3:8-T#rQfUdad/nX&B/1%4SK\2H[]k(42sTnPa-om6ofNB52NMl('Wf\R;G!h^WjmtRS%`R's ?A^KUf<>E)aHs)mUo/U_-,1A(MS]C,0,3Hkk6QKWYOCBhMp"o.T/mi]3Xd8e9%296>X3>Kd):Fr41"T::Fg&<ht[WAFrshW4"bL+TmSsj."XRSW9gV:hBk&/'c.K_&G8tf.$o(W^'EjdR=m>k#S'JBX4p`d+5[V'T!rHTV!fbSRST$kr8^*s_4,n_HRXCOUb:Qh<:f.^A*6T@nb!eiPa$77Q;:-2lE=FC9"Qg<9>8API'1:-B=\_X=)8'UrRgU"'4>V7Jr9k+lPGT*tZ((i.OfYj_N\PPQHXA23G5pC6NgFAYJs0#+'Ha`1hVf/>td- ]8T[c:qm^IkKp1*!c1)m1lYmKj@V"GcI?^ss;ZJAk%SnNfbPPI^>t:Bh-BaWK.l>W!ChHrtKEZ>ee_\MC^\C6]<:C$]Aa=PnMq(l%LsV`b&A/?iCoX;oXsj2Eh-NEX_'"$p`1SsA+Y;@/U3R"4TmTtRS1PX2-N(p(tE%E[!f54H X:=RX]04.tMH>kd"_qmXao4"PhQN [)2E3X5^KFGUs^*6nbXPPB>`*m_X"bPRr_j09<9&MUXsHee&m=pR[d4; GIhr[^A-m5:MN 0BfKb"V.72m`$R[rbZAk)o r%KqQXP;kG6AS9oUk`rt#i\T4@'EhXWqDk)s2%VVKYrf]>lZf;4CrH&LMT-4_(AX"amL?UeerlB:f&+"ko?:K e4m2!=LI55i;jg,-;NXPU3gAhbO_7Ga$,1FG<)lKK27]2468]I9NKi>c"&B4E%Ga!qWcc>A0Rl\EtN!dkfkBM@.+dS^`+nEAiaE jP^7"k5do[g*R"eZ!NM1_oeq+?E95+SRZbZW#mq/-p#jL65sA[TfB+V_+8YpG%CjS/R=eX]F@hf-H8cARJP-s2/A'A[s%+% _d_roE_7!J] qm>F1&7,=@0c%0o6NGP%BA*Fc9@jmKL_"Y9PSG"'FJs#Ki+T'cSb2 8ZA?:kYUQ[UTY_Cl)%9.'YjB c%[-c0/h!S>fOFV`7pFcXEo$/.k^JA:XAPqg@\ ?tl A(;C,llcO%HbKGJiM7);(PK#*6"df'QK@7>%_ils n(J=\(=2mLPK4#@.k_RRKX8qAeoR%-'4(#cF!Aa9^kiF8gInAM@1J#cHN)D]eUSh%.U=4K#<:R;]ApDS!N/UAA[@KPPQG?j'-5HoMK"a"P+=6E\#a)\/'$XH:f9AK6lAPk=HH6)&a=,[L\[00iK8Jbgj-lqA2jX#fp^Vn+D"'fWg%pGM0L;eLW-]]k5a/fhh,#7`75hhR/a*L0;3pQ7P8$+le8YQ0$lGoObrc=N@fA`_m`^S-C-:e"!/GZ@"g2;(+*7AJ*K8E''4_Bh(K0;,)3, g't>enZq/"VbTGnJ.r`9Zm\P@MV2Pg6b82'$X5%C*ccs,o8>G'2Vnmrf%7- Y<^>TL#be(V*ALae<3r30r\^=a#^o!OA"@F9=CAgO^nUC+*_%b:VZ<0ka>XB#,t;4]S'Lf[3j)7,Yl=TrK KmJ1@%QebB.J7 ^F=g)"QP,LH>45bAF*l @Jh!ObUpj;;eH](mN#gAiYNW5VrcfCc6GV*aGnPh'S@0@0;K\it@r`lsn`hWXa!mQ"Km gtp-:^;>O-4kHE`*MrSq)F^0RI<8mBbo$=0e%;)YT&2+?(!jjaT=2Qh+nr=#078':9DA9m7 jH3gh5YM\]XBls%gibpM;bm(T)ResJ$LGs;W`!GNs7R387UL3@CoMX^,BaUT-Xaj'6$,30i/VlT08Ftl^R M>`ltK`/?.N,MLGN]?T:<Hl):)U/dG@X:Ap'k16(AM-KPd3]KQ%/=eGFLi`UUr\:?>A+JMa=C^?&(5GchU!AG]GlO<`(qinQg/2t7;E[Q4>8^(A[>$MNj4=/K;S53Kj1_[(7%aL$.t^XltDja#<0,.#b0lYG%$9SAALMIcSoa7Gl:`G#W)4\mH5"MH+WL7FF0EtR6K'.^0Qbbb6pkdB>]6/Fk#`MPG5BC,V6BfQA`gpEEs(*M?rl>-RI"'b=jEAtl9J5Fhr,BS?EN5#83F<").-s^i<G(pF/=BbrD.o;hgGmbSC"0Yog9B8i,??ddI#/FD(WZkI^?(G6,$2[nE?QF+THAUsc*SRE2QaA;Z&'d5QFW/F/K*HB]%VeNK6_'XQ>">GXVQC] 0cAL$p01/sK\ !gR23"/_nA g5\"'Q,(mW@hMd`;-S^A\d_d=PP2AP'VC48n=&[(jA\Y0DRiID>6$hAN@ M9=;=Do7=MipjH\DMefN/7Yt/h/e]AZr'6XQhPVL5b/.?Y;S6h-cMK`-Znal'^>.E>BSW"<*!)h]TgMVSBeV<-0X&olt*fk^3T1otA@N>Gb,Hm*"MY/%e5[j6g5PFUo+.qO$i_1=s8mf]I4dRSW:4da'CG%"H@m$<_cC>*#@V\k<CUit>TW6+6i1&Fqa5Kmd0LQH7[EV``MZnlDDoTjQfU[eXQ3RN=SF+pVc5o1Q:EH4gojn2$Eo&Mf3D._j(`fcM;'gQI>6Ec&qO%55jKt^'5AF=]$a".(A_Q(p_KhMeD(mJ2H)=gm$L"`ED1hb.FY`kR2>FcS6Wl4(7*=F9l,4`TKEB=(5Rr5"P ?h4$f.@p"gQO[C>n(gPR&l>gU/I;.PU1dF4DO?%^m?AM,aUCGaP@8_>ABJ>/jW)m4,'jUWTFga=LA9A6GnIr[*r9NDRPd,8\S%JV:b?8J"Af8(tf*6LS3^`_sh86/FZD0h'.OXjmoOOipn_5@6EhHgg3Em/k9Z>C< jP;[EN4iLRPa$\="`RLH/7NS?OA /kCX/:Kl6A[qZUrl]dgBfYB^WjFj[Ho&`9:s8a8ik/ ]d-=[6F[*>30 )c0"JQ&!n1pde8*2Ug?0"E>S_1+lL,eV_>16D%8iWW%?^\cbNC?hQ/mNla l;fbt_!NqG!!2rO\=pH  fs`.=XdqGr!AA)H7H0lsAhj;O[I*F^[T"Nj <,8'1F?U\': ;JB=E @L0B&&4E>k^=oC;(ARWB>RME.iU,nrF G_U-IM!MjZC:5h4?tfT_GFe??DS07>U0RJ(r6&RtPR]GSi ` L!aebX\<#;-L9ZbAR3f\cs0aXj=/I(57(P27:)?i,%[9WC##2I@l/MNB Tq4g^@PX"f1R3`)c(G?AWG9]UUE\G9&s&05dOAJt"nmF7I0rTe\U"eUm;H&]Nb*J ;k2?fLYAetX7.FH;qhPO34e;dq?_6 4W\pQ[-b0]q]f@8rSkAhb,[0)N3t\CM$%I]T@J&1McJ*QQbK_%:tH`2AAGo/nAN_Jms5N<P>f2Y0Qs3k`<9p5Lm/C1[N#OGK?42e(7Zg>J%"jT"LE]pJ&fMAA,Up+Jogd#?A+HI[8m75=C5/g.SpQC3bkVMlA-ne\9Z%^Mb:G_*P>s9*?l'NU_OTLIQ3lgp$`T-AhF?Q8W,]t;j?m^1"C0%L`]9l`WA%A?AEhEqagE]l*c6;AK7HBsZ!O ]!BSebksPB,p7T@Q>5CIsRh[:1Z-*(g,s\I8o;ZFbE[R)QO>&.1fXW;XUG#7,ibDMQh$QA#,cO\pa&G]c*"2!rZ//k0Z':#"mt&!)[(./8VSA\X8%teD@itpI6 8lQ/1^_]a cKtH6o%*C=AOC*G+Zh,7K,);9iVc?bm:VAHT?/_*U\mAfAm)oGOA2q!6!QJi4"`hsjR36p4K+LA'pt[J;1tEZTs!h\V>G<,pVpA0B0"D&ckk,QCRX]K2]*BU>8![4U:o7K#F3$H4mI"t?r=%3rj7_I._+CBYa]V_"% n%9cN\)+FH2^cl3mE\=`)OLeEKs0AFIFBlGtd> kT`s4Ql9A@m54)'DpL5J:Qc3:gK/`>1AfWHcA(+6e>P&]9'/0U`(NpFd)A$MIFPM'ansaARG*TH$dHp@@j$&T+]A75M7)+gbBDI]ACmr"E8kDqA$JqXpEtH3Va?QOY&!A_=/=7p.&cG5_K8Z?+H$rdV5p?3ATY+.ea+k[8-Q;]!V2\AAc5g24:,^MW?hc= 7tAeqM='\hjSp.?p:O2BF8$TkH>#=6:Ddd9,RDqm61SIQ(+_d4">YB9et:P[4s>6>ZYeL*E415.\=PJ;eWJ+kJ3':`s^H,/7:iY1=Ek5UK^8CnXV[@^ dEACT^^;0^H\GUFTa@oRb-LEcKo33\Zl]0*`lWW4:"SbaDkO5)"+3X_,_!J5c*Qfb%X#Va^6oV_/V^[%IVlYI>r)@,*D%dY;U+B[`\L&J/XBhMg9CrTl7FrJBJ_$sE**8i2ae:E68aGQVX+Om^q\GM6q2F[m[[B6'h"lQ.Xejf,5`H%[Rh Dhg59IPkQg[@UG6l->.YJ0PchkF.jU69ia*L]NBA^MLliPJO*UI&AZNDf%qX?5UXW_1:AOFkC$I$Q6/"RMZ?' K;#b[7IZA:;)'mn9oAc'1"'QM?#!IfT!tq+<\A-51sS^s97deem-.JT]q)7S`(N]6,,j#8G8TCC/M6'tjhLIs!N?7k`F5jsXQ/^YV<1l,#![c`mT6F',B4 ZRb:=m>!Fq;jfLX:;9%tQI]&NDA7U1a8k=)"AY5I-tPH#$tCOEC,->'se."W%R"\hAiVcnMr[[;,RP8#+g;.1TYIEK`&NRt^MoF7f+?>8`k 4Vckq,7.AJ*%U5nZ&1<8B6d 7U#aK^NeRQbBDWDhSD!?q ;AH0#[b/M$0Stjd?p[*rM-PR8I=rT,U(/E;gP/\@Q$ZO.ec:)bfK^189OANN'iYO=PEe!99Gek=2BAq\ctHAfK"A9B/Qr#"=YSY$N$;OE"Q*Hs<;N_OkJ>U:(BSS[NALge&RO5^]XqCJqGoq5MX)b,eBV,6i]Q)a.GcMpK#E8ZEALQj`VT"nA_VCjINfki8V1#KOMYVs@6*$nt". s^KA(4B-A%>H]`[Z732#CRNFEZX0*XmWcr`V$/#DNc(a. N 9NY&-i!D&]ET:/pB1AFsBQZ0>.U!7f4pAn_rgO8VDWY7ThT)H&3C5:T%@AqIK50Bn2:f' oG]8^$Q7VQ^N=TQPrEm)^IIbDB\oA;AXk&F;*rPl=CM6-5fB(ZJ>#l[+(=0[HXjC='iaOHfO"^BFjN7YB'o[,p:Ei%HM7&kZp9"403BHU#?GPN m+r\2j`,T*XL-*d LabS7 Ke. AtPe+9h5A:rBbLDU&MYk,Qg.V;l30V@jM(ZsZ1.Ic2A[oYE/Hl`8'1s.AOC$* 0q(^1At6LA.7Pb1*'ElHDN"CZknM&pK@+MG;2r8SCWF3g'YRb"!CcY!+$rc]Fs3W,jO'dFE_7Bs;W2`SK&qLYo=?N<A%<VD!nAo[Hj?bAf_A*Af*PpIfE4Qo*9RH)RKTI-gdD6/Rl:G&gGG.\t"DeGGm`.7oJ?#?3>8q8<`CE$>p0h0pk&E8!17`N7?XmSEZ4jA[5]&99$PaNUH(-biCJc.IGrEP*0"Y;J%/Vm*A`mmT2KN)iS%BG 64Qk?@P/a-Oa6f5@0W4*I>"eM`q>X)_-L[\mmm9Zqbd+#rYi&%@\doT:s^nMTa5]].d?< _,r"D(E5HYdk4GdYYbN]h%QZDi7]oc+l&b`Ld>o;]40]V"V.FtPF`(E`nE.]c)=NfAN0<&+cRhi?>[e1/i9m4=RM&<;GW:VYO,$8gb.M;4>_7<+DM+.9/C_[F`DC8iQ@p;:ji-n94iBF-D8o'pO%9%ANb>4($nEgT@k2bGKXUNp=V"Y!ZKfPr3BjT&cOLLA!/Ne`o^+W02Hl3J]_9q)AEqE)MdYf;1tQoA#N`jb"*A2FiY!-E#Y(OArJI+8?#$?Jre6gmP=R#bc>m"/[U0N+l# k.5IN%FrnJ`qIerjU(:D/\ZF5l4`3qYppHj?q9A9M rVrM5M!ng9>Z .$^2Fs Y:tr/AgR_]^6^FRi+8#kss[PBAcW#KGe@m8?PVRq1A#nkFNiT`_QfJtM'M-sBDdDS*D9b57SBX/e4hR+b45<5<+X6i22k3LP`.X1:gOVH>#mjAcq-jU&f$30$II3Jpl76qKf42O7t,s_%NRVQhmQ2Zfh/?bX!S+f6:A2O1OLM4-o+KJrA1d>2B*\F@o2g25^LYfP>r,!gB.DbCs>dfAn?p:LZ2V2o+&$XaGhB&MBZhZUH)oXgD6:pn*(0j6K=rH;6??\Qn7Qd-XmqlA.$YE]`54cOA3(["9-*\#t&jd,6eaDA6"D,\2D8"mCM9$S*!YB8A! \<1P9MVXgVjp$V*ELGEY*>2%EXTrDO]^.9m:mmh^nV#,o5)$2.!["@N5PF`:(ljL[^ES^"1V5g,*%\UfYJAlssgLlT-+b%kqJ hifHUKKTc1`hB&3@Xf/Sj;((5HM%j hd-i>k\4(d\@8t1gY!Q2SF>t*O&Z[?QYdoI_K%NG3"-dLTco&-,A\LY9s8SX(K_S86Q[I E0*;!HU-)Nr* d1Dhll_G_O[c6^"3U_6^`O#]8.6lF[1AZ=8&lF-TSp9N^9Cm'rR_dfblH%KZlFl!Q1ZM]`oBi*YA>"dJSO2AU[5/R+`-QI+cl(08btkfVY^$)TL'7W`#,[*Xg%.=sgDW:D-$!97NarD.k"Ya@XWOA:Bjb<B%6I4p7cb6q(*D]0+\Fk%g-2Jfif1pkcs(!ahc.+EQE_e"?=H<`[Tk<ts^=K4bX;5lMB.D%jIGc6AHBc\gUP#:f!89g-%ato` h>TT;Ne>bo=?cSkQ/ n^lSUMn6k^+;@]n`0&"V9tqlOi>9ZCjNr#bof6(12\^@fEqP?F3U!W;6D%WUd[>.SQN@,*j:g;g.hL==7YMI4$[g\8 cW<.:8gQgI$n$=+kT F 0`"e+-mp9Nk52!"srFN-hh9ft2 =[q7YDdknBcb(_??0o] K\+35LFQ+SKUl*f^8G`b1 R4NKb\4Rfj4HN8V7>"Fp-9t`<R*H-*O^2QTEh6ScZ#oB AnS(7Y/40ohoYI`+!Q[2(s5aSOOQ;0gA5-M_SEF=0O/4FE\!C")m:SC"]@^6=%6,BPGNM2mc'Qf\8<=.sKAM)Cqp="[(7`U(QL*+JjMnVo-d-J"'0,gWsff6[3/<;=j@^Sp? 47p3P<&HU;2G0;G[QhJV.(m8Bi!DA&GXQdZ4>kr9$Q?+%4ho=WMFE&B4Q5=AT6Yr9%?[4]&6<elV0,,p[GMo.1o(gj#>W>]m6g:`_DC`B3!kD\-/FO_5/iI+5Ls[p2A_b,8g_aXt^g7ST!"U\a&AfN=UF CG^X7I^5/VL&T7pD]A:E0PQg;0R\Hg m&jW:= ;tQ.A6=F=%:02SI"9 ^EZg11\e0=2eF^/ZSZ#h&bje9%.H4q@'p4*YrB4+ .ZbA-CdN\30^(JNk6cKJ\Y"EKH+STS;Z:UVSA1mtd MXd>*hfa'(A]?p3'?ZNC4p82 fn*eZLC8Kp:)0@mIj2)";9SeqtBB^+42=Nd3Gr^Vns3<-"+WF%7$ge94WS"+%[;^#8Ug%R&spIBgUX/HJ(^K@BJTeFYGI:jdSNX1Qo&a.OgOt70s])D ?S`\<#-[S[W"aQkA0m,FaN+4:_%F +m)a%BHkXB@Y61/0 YsS2>.NlnYZm3&n:rQEVZ'h<4^/M[@$qaXM#X(O7j/_iekr,*7M#><$o:f-3D:mUO2gTK82A5,a.IP&ScI+tIdM$)E%T]WnEooPL&$JqoPY fb^D^&.?\.c:_tm0AE+MB_B.'pnltbInSb[.o8!2)I(XA3_+a?#DA4o[k7]2%,B]I['0eoZ]t,,sXd?D+AGN@-9c/2Q9'p(e:,hh=5JZjZMg6\_.n$#mr9f[-A^kY%@s(@Z [8m24'C!,q)=9*Wk$,,,W:#\?HmrlG];sRATTY!29P`MR3B0Di&b+_h_,jrA0:E54>js>bs%8).Al9_(?6Zn)JLa]S9JIApaomLeo0$sDEe0V0,WVe(WR>Gb5#^J$n+7_c=V$:l([4G*eX=2b3pJ<*j.l='>A5OhP\;D1nY%91q)!>*^J0G&1&k#*3Spm^]3r.rHZEki),`@4CI,2>mJ"QXYP&k^nI4K8:G/2Lc!36TC$%:0 AAgP_D']j.)sQ =80_XNqYt?E#S59#CR`B]rG';Q#tj^LJi'SQ&od9WnN]CrNf&h?n1lMD[nHA>3FV%=Jrh\kj'$&$"YrQ0k$2I:8#.!07cL1#Y8a)K[r:eAXSOJK/aW8WAd8Xd>hWLfrDk_BPN XW44E]h:#ai*4)k%*638_nj^;grgpV&H%"4Wti8lG"J@>J+M)#hdtZ0E7^?7`PacX48dPYEk<#TPH)$_Q#,d8qi`IA$!ZmYB/rXIS];mFSI6VUAr`om't&oa2g`th1F]?4\G,o%>t3b:4UgqbtAqHbS$#cD8I8k([]Me3Gm@)Fq\H"$V(s1h?>_^Vc;a9]kg+5\)^+MjVj07]=JY6mlk9qZ_:g+Jre%+T fQ.cJ9TK%YG,71(:kV74(Yir%i$,`g#?sM2Q1a<]VZ07FX/A=qb[?1KH!\nSq:kLTXVBmW?WY"c])sTX<\6rGL3FiRU3.sB<60=/,h's3N=>qs5Jit;O?nEam,7757l=6LA-.mGbk3:q]=#oC8S_$c>mGLEio1K^'/h1.=9pBB!9a(-&VgPglM A8c14j1O/'8M\M3UoBUccC8roZbLOep$ND=bjQ(2%.1C"M$L?m$3W\n6K4&7S!g !4,`pEJ4F5jAY$E),dU&jUiiC4><&!rs<)#?JoWcc6IY0qtb9%NF\/p89FWK>WH.Jq&HTdgddl3*T%N]0p !;"2GWLf[O9KWhs(h@Ac[oj5t@$P2M.:A>PfFi;3*Pq?%MX0Lt)hLh5 N?D!si%hn_Btp2Qagn>T\hU4gbMiqO1.'gaJ"ioTbn_T+M%hgGPmU$<0Q*4rnt3bqR3)d3kTnN0m\;a^W<#@MtdscIR'HZjl)01*Zae(Viob5FC?O[#UKK^Z']$CjtT8B[O/p)h4Jm`k=2c*B=R$6EX*8I*[jgd,>)sp:AT\fAZL?G7!fBimJ6+:O(j/4o+CX A")c4B:8=Qk1V-WJ.kDOYK8th[#Rmk&=f4c_f-R#K*?U9%,pNKDeL+SHmbcL(6]Ti<S4;i5NKcJ2&lm$C%?QgT141 iPob=k&RYraoEj [n_gdRDGnc^qW2srXg"s")HY AAD_97N+XYql<$@6]1?Ksb@$='?!RMK;IAHH_k R`lWbJP\B;XAH%gWptjHrN['tc6h!$b@ l,?-JU3M\WNQ/M\Z.k"c3m#R@]gP ,WAa/Aj=JCg2egdf cA`_K1nrn40JM+[OFk:2.3J5A<71USti8Hg*%TtdXPj4"RH9m]K?kR<pcZtGHA8ID/I8fRBQj]kB&\mU25<"DTp#G.1N?54i4bX;(kH17'r[7]VUrNnnN! H$&;>I#oD*&2EKF5.44;Y1j0[08Mp[n$+/eg;Xs\sfm\YU+.XcP>?sGfKd3QqC\JRS]ndgoko$'JYSq_/QDfAQK?9fT2BW83L*1E8Hf%"@(]Q Q)2=g47THjh*p(_#o29^/g7`/'==eRQ0[Af0`?&^D]DM\!?:+J X2bG>AiJL#kjd0_1"IB%)P'5o2Vb!s`6ASOobS=GadjR1q:MJAAdtIV:lL8eXF4K;^\iS;f>5fF!TD.tGSJo9qp,]!)YsSn3VsiUtqRq!01`QG he7)E-sBRXgM67Y%rACGSM1EXn\R7$7I__*kr0A8"3F?17i%4?@(lQNCm)acGB;G3I+i3rO)+2"T`J>A8I_B=*Q2:Qk-mdJL^3]8Fj0t0COl^Ln )YtroDj?J_cJ*%".F=Wh$=tO-9p#="/Hr3n<`b)03;iOXGGdDNAEFA/s40;X@9jrk4=Y>7^V4s4e/]-2%cL`/%H.#C/66h0aNi8W+6BPLi![ n_OcGFibhZ1c=sO^BRO8JrpE8n\15]l3;9Ra?;2X;c=dTZAkjJ`sc@SIAkoBIl$QaJS&,o"B#)(ec*[ehJ&?ksoSn0RGC#ad\@WCe,&pDS0fmJ`KE.iod_8cQYgO6p'-G4?"\-5`_bjs2V)t)3-Cf:SqBh+r_Sl[8FJ+sl:NIOL*E)/P0 9\H)Z<$c+2fk,<)$+=5UK 3_>]QWK,b3X_k9EI2Zn1.OAJ_+Kjc:.>iLGEUFV#U;DX";n!SG16@3fcP?[6JMlPs"-j0J/:i+1m":VsTss7E-M\Q(VR!;R3#SHSZl%JM Y[@,-(n /;"h]WIIPk+ UMD1P]gobmSKsdM.J4&#P3M9:ErT8%A/A+><`oO<"0=LK;c2Md""n]o_TbOoESkPN>Fr1PdB1j\?5*.V,)RAJWW`@csFaSWE>cT^PO3EL(=K%]=3ld;$fISk^0@40)o,P"W__$Z&Mhg6=.RDj?hB`''9""+8jeI5,O:s4.[ODpEbr7cL8YA#*0l[0orYp?I]ld!98YXkL)XQTDp:?Q"b<(gY-L*I#f,]4l_PO$&o29Jh3)5Bo^FLs`mbH[F@kNNAnIR:aR.E7 !2U9\1RiE+ml!J?ZTWK88Y=gAoqE$[iG^2&#SPp!+_)iRrjUBm&`!e@]b.d^iP2eiVIQgQSWJa]2Ik^mQMPJDO?q?7"ONnK*4$n*jG"/pK*bUBHWoM#\YQ1D1a[t3_s8N"$[!)'ifH Z.DAaiX7e_Ub`\l2a!Jnk0'!Tl]1OpfsO]jdcX?PbXMN4#_DE=,V<]kWX\ba6#V:GRH,*>BYKS!0ome=EtQ^Q^#[kW]&%e5bkeSY:p&'=J+EW=iRQl%3# Ar36ir:$M0tNsm3O;i0LSj,@JcK@KQ5F$#?0;p N817&,m^s7aMrdbsCph_d\pEqLjrJ$\73G`Z_janham:U)L\f1O;^-= rS0pMF57Y-fXA$,-rp01<PLIpiQ;h``1rlTF.)t#Cf8*:Nb<#kTYfM..W&r<`pa>>)B?%3H`VmpcV^>TXRi9]mbnb5Z7mR=H_CbK[:aAbaNpJ2n\M40n>nOe' XG/Wk!-'+MU"d-:?kQYh0it<#n):+ Q+km?m1kCs,^Ui2\WlA*#ODMPfKHEG]("XQR)?Ohc4YPr?t?_>aP>TFgo)c>`Q;jokC1t=Qq%#&=\6kp/sA8+"MrD>apNL%`Y@; ZLsPb4_"FkgoQ8*kNfU(l[8$= "er0G1Fd'B:AZfAlo$@$O\Gmnjm$P$=f.Y5Cep(jc1\:5@?9pnn9MmqSoN&WQ.L!5FsR 3Wa#E!7_fD+mq?OK%#=JUaH0)BE&;]Bs780&ptA YMLt_ptb\8f)/AM of6QC?#hmUEem4MR"IE]0:CT]s5o[OZ$soO!:7I+!LAeCGH&?00pMA/Et)ip8&[%@Pa&^?a'F,*DEe:=i9)UlD] OH@+55;U_%VAPCQkVGk5;7' +4^W.=OP2SEB@?(.Bk)ii:+&^LB9cKgj8Btg8b@=B5K5idP;n%C;N)*:^'H_9aHLmU":r&d Ff_OWB5/g;M4L@X:D/2JNE0dAj"Ceg-WQ]*7I:D?BW+#?_FoSUs*9hCUWe`lK9P^fP KGGI%)"sNAQG-Xr:opbQ7IO3^#GY\Xs@+:0qKBI2+isSbG+W7O8dm%7hbllcY sA(d]Q:io--%h*4Ge$cAgr`6bh0Z8siL`>Kb=BO_*&ld;k%B+5d@AlW_DBI" <':R#Qci-7Mis#?=D#9S5^jn]EHXgp*H_HALM4!&L)N.IKDrXkQbNTYV)LaJot?O6htE%^OE+mIrGUKKGXL:R7Ji:g\UT(*dMpVf\:a0co7H2"6qUnb0o=.B3rI:@pKXMA+_UHaMp^>*>Rmt9m]La!GGAP%0,"%MEF\JXr<%n^OH!c_BdM?NOq[DKqdBL_WC'$D`\qa["]D'c_[AB9Q\AO]c4ad7P-_U"paLAQ#L"_"\-U5b4HnsjOsV8ARl4fi&q=q.(JO:iVZ!8sle$0D&_Y'dG/oO>\R>t4-?kUmH2- =N(;="ShBU9hGEVK P'b/T4-9:`'`cT2'_jTU(,)`p"=@)8"qg4C2hh"A*'3nJJ0]V*89-4t[SPOrkbN?KEJ&#4k3pUV=irI&8gAt]`4iM`r>A`3LiIA'E`'V<^!3mRn$sA*Ci.ahto%Nd8rn*gast/>8)GANspk69PoA5G&>;:9!,SO"0OMa8r`Vbl9B+M>!>1!f"+:9-ctYqdg1fW0d(_#/te4N/b%*DZ%b1OU9sr)G9Z9eGT*aMKiTGY65&8*N35siCZ=:W1GRK7HmAXCUF*_`S4g 6Y43V>rf:rAEV<0[/,UZ\q5?E20A_OZ25!9T!@5 lm4S"[NjK lC:[(P?V/if]#;Ie^k7gdO$mTDH.m4[5>YIi$hgA#*!]k\rO1U5"J`$N1''Y(Kjdj>Za8.12gsSMk)XY99k8_f1GYUFfn!--Z'0I$hLUKQA_t@W@Un%C;NrqX;@%M"DZ(ZV3UB'B<#Y@,$.OZaKAsmQb]^Qep+OCC:Tj-.W?P`Naoo\W&9T2IL$BH\*W_%Oo:G=Jlr:fiW+S^PhWmSog;i&lO0A09jhl69Fb_,Ghn5TP^4Uh$i"%;Fa)P;>TPj;W#r\%=:H\q`*A)/EZ=eZ Y?'E75_`*pL6)H6#ed&3\r:Ug1t*E eT-_$IOsA8!#$b5m$(O$bO$(6kWG@\Y5jl4R-98lt\Y\[tA)IJ a`ALi%)Q*%j,!tWYi3[oSc+HO6oZ>;a>BH&[@=kh(g)?1%s36gf2;7DcC\9)n/([6BQIOB8UFV;K2Ad%8E+6MgNeCff4G3?cFN?-_joN,$<=X+m%YsA;OU8%?/.Ub$fFtQ:(AN9m70K2XEL%[XA-L0Q)>4(OIWAp]qO[cqL>N9&X&qk]]&)?r&UGZPQfj4["I,1Z#QPq\p%_J 2b'nn@p[<1M9K@Tc!<3D,ESNOYoK<+gV\<(ADKc#Z+:MJs8hj_=ae/2m5S5.9<#$hbTNo"^G6=]e&2J3F]$=hS;\Q"]Akt4hj+MlcfdCWL64MR@-^oj"HY=,FeRtbD\[S0P:fo 0R3O t"*#k#&aq.5bbOf8Lfq\f^=[6AN)&oXctr\mNAJ.dt\F7a>GV pnj2+.Br\&:0:_S+Xr7IQ`bU?Vf[:asH.!W6`<_(?BUIGe014HDKZnIDsY/K6`hq1jA["gY^DH02R7#cXmWYh!s^_ A?@E44Z.cEr*b;cgY4.FRT%28's"b/@6,7-c1.kHnb2$ZjHd'F#E-ir?g/Zf\_#AdeSl#0YD4C##4Gj>$D#dbF9;n/Q)a&cNlM;]&=Yk6k(DQk(=4@'RNh+=*e+kj1AcpC%N8=r2;G+<So 63NJON+Q*aX-+)PL!0%k(:j@.5n(/)2o][O]45X8-Ai_NQISKY$(&r!3:5MM6e"8tED@6FADKQP+JB!oFsAZ@D"39`glmmmR:UW@'8"[QH/g4tr'Uep[+Hg$l*,8,ZLn)s#I(3WPLa.1j(3\_DKW!\BIj#+1N[GAk'KZl0f#(cc=)?9Xc^FG*h[516XRZ3-bpie-0>$=9,4J$0XL!6D0)'Ob"dgmP[20BtQp>aB7D+-B\%4P%\_9Uc:bimEB4od&b!@7k@V\UXltEis6.R,&'; U(]P>&XCp-;XQ\-cU5]9&n)qKZpfC0jEA^++9MA@%LEqS/7Es`Jco=Kf@,Xi.4_p-j+=5eqP\C#qp'rKebkWK6ij!b?V=4-dr#dgXF`9qYWA.nsn)Cf1/0Ag;VC<m6E*i )_)+X:Er\=dg$;L8m +WECs%3=O[+hH'h"Q>>e>E%m27a1"Q.#ng['MR+o;03mp_%#9QlAGKak/A/"Cf+5,Ic)+!*IA,h&jG9(A8"[YMVMCO6m)? V/hN]_c1BkFTF3Sso7pGQ19;m>iCqXEr8:Z@6!eiepA.8K^h2_?Q5@r_8H.5)*d_gH;41/__#gnT8%KE+dqqV cpKtJIF C9^Maq*,]P=Ct/Z-c&E^;M%rlA1"t8Ji42gR\c*EoR)J9.6?e3]_^G+K$:)[6!Rn>9\;O7(`8)jBj[+4>AH*Ei@fUD^A;gbla\d7MaQtH#Q"`qF:"04oiKV=^Q?PEI%9eq$7"-2pMH3<\X5L5LfhiojbbZWd?#7m4VESC&=K=5,6Zje@e(58Tl?mmh;Y)T%EPk1r/`H4j%.\p0s%X!Lp2m:L$7KO:B4F/qi0[Wp!O_lO$^*k-lY@QfIDV)sWY*5aD.&ctt)=l-s-l4KTHGR]FM?g?P3s"o2[lh[/Y_!K3gIUTiKfQ5^!pX`md#$hL*/S3=hVT/B(P^%8&l7l"'hprAqWCl]c[O=.2#8oJc#A4]F:%\_0K,>1MUd4=;I9k2/Dg.Fo3AJ\q"JZs%XdL7UXGPNmSO![L7acm_XG3cLP886lr]p0N]dI99IKZDEHU9:oMAj&Q/NH+3,28S`g<>RDo\CtZsGaF.m&d,H>*aA`l/.q6d3T3[r(Zi_EoVf?q"UfN\;S7n,Fm4es"OkbE3X71]T tMn(/iQEP>EBM'M@8pa2f`>@VODBO&66T>.3F;^2P?7B%!V%R3#1n$>a,PC5.s'me%T$igaenhZ/';-o&YA+7g]'?9R0 HP)q`g&.N"$%3a0d^B01.p*oAV*A#_9D2iY.Y:n#kT7N?XMp%6(HC@??ABt^H$%ABY(nZ!<"'Y#!$qC9>mr9/3fdl,8rl[ rD_fBHJ8?oKsd\3hbU7*dB7g:RHIg5lO(/Q?m1&Pjh#B_^i?ZC!3+W6O/PE$ZKKbnVHed4A9aePnRZ4_X02CShsUb`4W7CK4iB0,!2iE2(1 gHgQ(JAAn25(1T/g8d*I+*lY5YG?:.0j[5iUAjmA5>\U"&Y%>A47N8,M\)4B(iobO%XGHK^Sp$:o,BtCTsOp?%cnFK4Z'D-f'4&g;5r>GB1)HApnC?DOCYj*eF]N]1Grg[3+LTKZEj*3S,d]MUsrX+U>EEDJ"%K8lPT\hWM\VDa# 2m&VY&SMB)L2Ot0>2P)Mt-j,UYn"ei>WE%g30n*I@@Y@L.P/'&t">8Cp1',b4*h0pXQ-TQ[_!m>P&>H,Z8V;-[OMTS.:O\+0ipF%P3m]#k?%IJADme'c<9Li(0rHN76C&pg1kA7!G-,.+83dAE*MN1e57FCNkkN0Y"J69C\k_88)+NC`Al_o[G?XQ1VAiMS!0.]*39J&P^+:D"4VUN)A\Fg-0TpC6j))C2\>;/gP%;C_%NTk^Q^2EJ7Pod8Ia/758r)aF!V'i%Kb)MGGg-Zd#.HHc6^h/^2nE #WQDEKkJmP/7AE'pT?RMRN(>?jId//^M8\D5A-rDDNqn9m=Ok^%CSZ1V^6SZ<9=Wa?B_Q9>lJ#isoZ5-aS-BOdILmhWf*cih9fqn4n)/9V-le Uo-'=@Y%>p1qcQPPM63TP^nQ iZpQM;6kfIl&o[6_MWA$I3*V&nS.tt',OLKtnrCS7Lf.'p Gb1W3RJ[V]7^e8UV_T)_d\/d f+`a6t&dTjV,AC*c1E\[f(FM?B4[3IAWIH]=K;n&rK5_Ts7.T->+;2QEL^^Of`[mY3\Gmo)kRD?`hFU:XkOL."K:a)<-qK+e3^`32^7^Ah>-V.?]07A&m['DG7SslHD97<>@rPA^$fE;st ;UK1]8)<,qSAOS(jtr!sh&0MC0Bp8:dMq)7d<G;mJ&to"t"g;%)M'2dPe!)*2^mE-^AZK#Q&d!.R(LJW.^Q43d9e[O(^-G$oJAJL2%^4p>7tAO< &$=)]3r"#,XiA8T49/[C5?md_+Z9do<;Lb8s&4U5_PaJtN.,jVn^P$)<'q8QE.8V=r90QcNm@q%\kAIN!E^kCF*B0+'qMf'2>Ah(/^IkHc]fa"`JAS^$$fRX&o813E;hm'U-CS?LR54dTU82 %'^_MsNOMghCH'tQci%$WPfA,Tjkob\\,5=qAQ#&*#,h`.jDlqi&qXS#e%94D_Tfl&^R=:0he\FO!!ZLX!=d&,8oK64Ab*rT=9IQ.lHJ-gPb\-K'njG7W$`moQnl'UsIlA7Y>h3[$.50@m\UFFAbKPekPsUg2?A0*@-cRT=mP7TDER0\1gj+WAQ`i\Ts3Z*c1?;jqQ"CQ?^L4=;./Wdf[`cEsFdr6=0QD a18&gs"AW7"nh$AH08?M:NkAGRYL=q_6".6[2Q14nKtMpP'C2I^8/OR!JfrU+'#q[*O3M4L986/%E< Ao8'5X8 O[&@L._>$ZYe1PPY9-7C2# =YUqm+;/5p2_Ann]N-lL*l:tX6AjBiDc`e%!g4;SNaV)>99N!?(KPQ0Q:,]qL>;,.`EUo<&a$=PpGhXOm)t _&;8#HfSRMR? />clW,HkdXYVdjr`:9k=<[WZ7EJ^2l$\=`lM%+_bAnd[?9>jn_n8RL6kpI=kCj6Qg_!6$;,27AAe#bV>$3gXJXD`>G&VB$#H9A lhGF-[4.2?-+;VV02.1c%2Ki3;W[I2>qa0J4WM`K$;[X73`flB,t;e6GRh)NXkqRt*Z>f$fN%_o&6T@0QjL+8R1O)m?!>YI^K3tWc95Y\;5S*9?Qj>]h._Zs^EQTJk;A?YA^Q,c81pA2Kb C<*dEQ@PRtlj\A,l>W>GBA^=D/<9jZLV8pB^Qe8S#BiklO0EQdM]Y8Pq1^M1;rmMHLUP\$ Xbodoa%^'9XkE;MmRtT;!W/e/;`^&')H.sXQBQ*d%EKgop`o!(mi.EsCk0+lONOnlM+8?W't^k)L\==d=l[P5GYAqgPS7TX^C2B:p8\6B9sZQh?j7jrTk[q@!$o/G&n@5E>^7&%A=-h_Fpm&`\/)3?GSTBWjA/6W9p3bf5Pm)Wj 2M>5K('Y.V"rYkNNDVr?!G;qES[Q7)&_te dYVBJL^LUrQl"25['"`GQ[[k2>I02O^@0sOtNq#Y1:T__V('?=WI_0&TOOBe8f\Qn42^n)?8-YH7DEUq;lLLZoUh@ih'Og:-A"WAK6S8,'/[5/B TlH,%,dO@; A61b85dp[a*F-70:9d`pih`]V:_XcH\P)t k67:f)85Yh6C,pXq>#aC61*5r(agq4K=(,2btc 3CVe:>tKp&mp_;<8KCoG-I1-MgYfDArQRN@1`ds50@g_b:M\!?(4U7AHQ3'LU\=l?CG$-,VU\ii_oUnOGSY;f%[mFB]G+e&q/P*V]h!abF`R?;DLen/K;&#e/@V>qZ=cK0ja4KAZ&WlmdCDeV)BA[Z?=4SmqV&lC\%g/6kR!!H)'k<(Sl33W')p_5ko_,=q&nS7J7F.U[Phh+4f I$C'6FNtAn[@-&p"Lp(!q(r1FJYc$Zg!9FE.e0JnY"blEYo;r:'Asf(P63)8]7@!o &"?dVC\$n8@^N4GVL K6!:'E(GH E8#okq*n7>,kD%arjH:jgt@p_&6+pTO7;*=01q] Zd@D\\DN@/G3-<[Zp]#">q40K#E@LH/I(3ZQb!NA4cO0B'@+D#@@9naEr1EGW>/4bBj.`lablik#;?\Rc+":=$?MoF5Acg(TDi^ s#)R'lTA>89e.bmM;jKbJk5A(RRJN*i(`d&)5]$VcQos1/#2phBoXB_&VID` _+$V.@8AA`k@Ank9)V36/O.3Q1ikgAl$TZQl5X 83(?dTPs?F!Mo;9L?AX`Jbm[s*2bb`G45<-NM$Uc/ 'rV0!gHW7Bdb`2."U?5`[Zp%Y29@F[Qn_s&nnqKI3o@UH9:hVoH?/+eF(jk')AGn%F1dp/PA 1pstn8fRi:^AL^9sF-!")holtVOrB3f2p6^LEcG?!gmdh9tP\`YU0qc>_!$""8^)Ebf!dH#D74(H6K"e%+hNJIfqCh/3BYAPQ\Wj`-AI28K:3Y2S[]Y4B#3_N)X8C I.h!P)f84RgSPCq5B3^J@Y^E.WnAC\sFJ;!E!/bEhsFFSb^JsGAA7E;&%P]c+P:1N3`X5?:A,]%L1IPV]H@Lclptin_V&%3YCo_#q`k,*ZRgL PJ[UWm;C8gkl?c-N(qRHO/pSq>ZOjA8&'bm5e?Eh]9j-slrO.(WA0>"?pMKO`$3MdSGlj_kr4#0<#Mjd_bff'0]O?'gC-dAFK2YKrA%MUDn /=g>K%$mIpkWb-oTWY33@42n(*PNQ:rcKA./AOFI)o '-12j,gQj_&fAH42)VeIR#"]>^B::]DQgZDLTG_9s#`\4\s[BH6gM(k: +2n2QFZ1!clKpAjG7hLn.F$XE^L_SVO*bU+t ?[QX:-cgYH]Fk_?:/sKq22<6L!0hnU-m`la2"Se[s3TOG\U1i`>8]*,j+A^l 33gKkB,l)a );aoOlC<#nf?hf)6g[58_'A(N`> t2f2/X]ZAS6JhqllB!h2"Qe483 !ne;)2$:jbp0G0gC\t3/&b2nRoa;`lW@p']OIIBK&Y)'l@$I2kDEMD:*@:M* )tCf ^:JUa+9,r+FG<;;R*klWW=7O?J2"(4>UUJ:=ismVp!o!.Z6_4aM7\op$0YAK\34V-LR*2ISSKr*+Z/j^L4c!'>%mW%QU"PVbHEcE^=A@B:#L3g)N'e9*m]B8T%m#p[hCQO"k`8,B^j4&Z&qHa-EVlGbn,^J&hG9'9AI=Y3P$tE_4AW4Y^T.p@<9d;9*658d$aS'5f3lXJ'3!_U3M`8JBC-G(FeeG[Od%he_"%Zo(,qo(c33 .m;:psTHUiPU;^lGUshP%5%,l?(]Mff;n=[1Wgb^Jf6Q,jIGqAGSTVHpWL5bLj'.sf.-UBjlJKfqd_d4rKEL,i2\/Xciq_f>44PRpROh<#^&H[$(RYW*^,/Ol I;l^9&fj'DtNl[(CdED]'QdET6dAei#G=#f,sqR@AQT-&1Pc)]Q_O&6#i7$iP@>lFZ4],&-MfTCg"*'`Rq\Hh5i ,L#+6$:V6SW[Tsi^5iG-t3Bf^FahQCOd=q*[R45bc=?GfJMY[cR"R"j9,I=EK;bh:l/^S2b=[8+JK;tZp0p+V%:D/Ck,gN'E,_%DkBeg)a$nf!!-2=! >d7j=:l\pIc!A'I$p/]c"nP/),.nt@/,7;+KVsRO-acIj`g;m[^#BkIZq_?TA990PGc\.ACkK/orpm:'/jT9[jn=L8C^-f>DhN?YX:AF&q`t/)=g?2[Y%A-2+0:Z`Qo`fH81%/d[s9oqo\P)=Fh`Wr:ANZ$1\@RYHcJ<:'He lQsoo]rJONQJ"3(f\YqO@HF!(=U*]\1Y9a''A;,IIPeHPFJ%2=*1FsmnZ[ANmVXNPRgJ]B3=g)37Grhd_#mF15;O&8<#?(W96;ImlG6EaI pY8AASA02NtR^I!7^f9k#.=R=cV`-,_&QqIFaI%oTn7an-!pO;)N >JTTeO.)6'C"AoK9RnLJ@+hHRj=[Nb!(JY4*rrE'R0)qSWPb?C;Rl(F9l?7:XL[/DNS#+QI^B1Z7b);nIVsoOl9CAh-d-- \\PIN!S*>-JL/&-RGcC1/ aU([@nG*4AN<(.7Di6cLgX4qq\D?M6.@Fmod%de_DD)&'9-_m&?nrGVEFnk.M)UW$i%kPAKUZ%!^+,2@b'Fk?4skJGKNdUgZdokFE" -7']_m. YO>beJ?g[Y#A5ARiT(U.KVe4;:QBgOM2^OZ(GK# li9G+rD>P*5o,H/O1I&+jtt\Hl:Ogn4p@@`-"Q/jcmS_at&C8lp-c`DMh!4JXYN$XKYP(Z#%gHI EV$qpVP_Q/Q:#5j\=bi]bbPUH6]sV::AK)HT^O)P P"+AR+S1OTDd$[Dl^!]if4?&HP ITD;-/KhdmBaANA#$Ll4<&rOIA#[H583h$0C##K"tCp'n^_>s4=lrM\5SED,/AF^Gn#Q,P38AD+([Ka);gF43.fV#2iYG]9m,Rn$t[;<4kC:7DAf,R*bZQE P;5MqT$M?_HfD9@];\?U5qsqL8-88l6d_8Y+ntTHYEc21Cdaa@Ak=]3$2?CN8Y)qY;H?XY p+*;IUdr]/5^P0r\_335Ek6K7Ftb$?Zbht\C9[<4)^5]HpA$T]DKTes\6aiW9S+^+LnGOqBN,Wg=L7pC:;h@o5WU`lZ^s]aNsHJ2$n-?LF5.a.]4,r45grfiGJM:>[c?PqFrm:C6*gC4[MB244"jJ=>KV*h@IAR:sA!poW,4m r.VEq5lgo](gE3$>d\r<_.U[WQ4[OmeY2jZYaF!2TDolY'\K;S_!L><t312rDS>Y9@p:D2kGjCdA\IA_I##qQ:Vmf:dS?O?=][Lh?OQ50S*nTHOoq%co`Eg$&7<=0f^J\24O@[Wl%p8P,E&oQ+S9Z^m7k.`Hpr ]cCLnZkS+V:&NHM(drJmnra+7SHMDS FVt=aB$XD% HqbAg]"BgL*!lGngo-!DW qI)=A[(jM:YV+jsZ!/Pd>d,6&'^$cDn(U)lDLN\V(@Js+kDN0DcRR\%(@:o32!p#PP6dDP!],@[>N7A VY[eOWZ*@^lWXZm)*+P[B]1+%oY1h[hma#L@#_LJT5>e[Y[&)RH7D^()tHOMCQ-p-k>f-XppYP7a2E>9,b4$Y3N1CFWr'He.?;DDHNqAO83oNqlFR@A[?HJM>4r(QJKfM;Ma-++]'D<^G.E+A;Y5]eVl>'t?S9%-)`3LDd-g''5nUQa^`#a'HA;d;:Nnl1p+SJ"(c !$27gl@pHI(gSSa0*9&ggk6BJj^o\!oV(h>oSbg%/BHeO-mQc#q/G?cGdN(T/1&>JML>@Fl0=I4)'?9pA&\anPs=2+Eo9c7=i\psA?5!5%Zg5,-9n^jsb/cU,N^3LL(hi #9lYqB,ma6+F]j+jtnHme!nd!'i-- >eBc/8nsP,PmfHT2ROo'dMQJp%6j]RdBfS:^IEY'b,*PqV!Dg"4($Y:^Pc"Ta!(k5SR[YS#Fr6JpGWALb:JGc__UGiAeXIoYAE`7( :YX?cH/Mt"c-WXD '@Wc:$s^Bod0RiiQqI4@ANe@aY]:+0XHq*c(p=sW*%tP'=K##Zo>CmpFq8H S3^L4`<0^mFrnM&[[`p:+38A*s1/CT%GU'qQnsTs7B_2@Ab`NNa:a@9AatSl(BMNC<,914O<14R(V*W[VCsJfjVJ;4<<_f@`9bIV&LBHY]RN2T nIVn-7_Re;1OkUg+XUoY8NsK26]>c%eaq*C@'>K4JS9Q@^`Ik!aso]nLZ05%(dtNH3t<6Z/ZLP@Vm911nMb't,d,.\\4Iq9[(tUT\/:[jO7PQ1(p>%/ Z2q8][fT0^:dq]J8Dndps8(WdVSpi;o+loBSpA<(KW[_B)[S(B3fK\&0eG8_^mOX:@_MiD%%YTeDg"M0+#e"nZ&o^VLJG'nrU+1K.^c(OZj8c^IH;%5?A';=sO%fYJ#mkknh`O\.`&nO]g"-^1%d7!;EBsje\tgXg@ 1LbF7(B)H<K?`$r=#j"F(0rM6ga`%#Q`P>ndn)UAU-SpX?.IVRBm)hC5^3XSJQMYo+L9f%QkYrg;:JBrkrB@op(;oXJj03j1[:'@VIN*5)*#&O#T\nA/-UGM-)_AVo/m4N,U0lg>cTBs"X*AKp1L7qfZ3(Q/7N2B5kb1!B_.*3^1cq#]Z'^r>JcR(Toc]XZ6l+6@&A_PFjDGs!Xs+V& $=kNhG!de10LY(<3B$L6Ng%,O+1KMe7j]qCD##blsi:D6^hT0L2E/XC1##jJ53>:[m*!<@8smWH`ohme=Ej QOc4*4[ S'?Jq000Hj)nS&C-hjpM%OdL"L93iNbhBl]69Oem:CEF4@QoJJaca\+sg'#F:=fgU\e7Uo$11jKI!)&1H,'8EWA+-*eRP2j,-oBCf98A@$6+pnajZo7oaPX:`NCbtfL-<ZDiG`$i@78m\E#8sRD0rLr2aN?)>/G6bo=(o&[V6e<7B=! 5@JO_J`Q.>DT'hVtM8V-OeUSi?MF&]--F*c,kS@&;4e:S_\VRka?EWj+;*aOEtCpgL$r`@fA:i#O\@p`htpaOk@h-4,DULE>%!-0k`DDB,,'^(GhA'^8"$8-kZN5/32%YDANP=eUi\$pB62fL",W%.lSaQTa3.?1"Ye54\9RtZB+l_e%>RT5bE;RcbmS+e%0 &&eg/UnRGIHB"]6 ZiA(hHW18NSP40lcp.BkhpC\44KA3 G][Jk(YFR]t-c9\17nV;XI?4l_>IsZR3Ko9-WNm7*fV=5i#8FE9f; sq7tdJ9(W-WBbl+s0-F#h>H8K/Z_[B\Y>%5i&VUIT&T<62^%cH6D&r%U]9>0M^OC1\P gd.4?^H/mp[A^TmW<0L4W>1EfDOG:M6r#/+TTi*of>6k5BTlGm[)UIJ"=8]s@s=G9;^!=7?4'KI$"9'R%l`lpGhUBJ]8ncn>D[?'`"fCLit50"Yd^Xt^Q!Xs!>8=j]fn#=Ff9F^b`Q7p*$!)Yk\=hps2(4"sVC"o]k51ro)`1_6[,@<1DnsYa ncRro!mM!?$n5/,?'rnO@gUMmaW:Bj%MbI/2NVWgJ)-W^_#93Fc35fm"M*&H;"HY;A85+eKZQ&o#'%^QUID!nsAm2+IRWJ78+-Unb/<=bpZrO";8mC5$j5q=qcmg)WJH`$D?>l+0k<.+-YmXZ(,T6"6h1QA,8>D1p'!(N=!:3&gO:C$9o\>95oW'Q*FC-iK>`IW0:[. 4?FYIM[@%EO;legl" 1F?,GoqD[B5*3NhfAj[a5oOk#dWAq4!qhpi=67X&-N+J9 ia@d.VYOe.M`K@,"""fE2sa]I=-1o$ U88DcaJX,X(FTXOb87#\W1@='4"3#.BsP Qm@s>$I5+cn@>DAn_RB.Q!>[q:p-c_Ebt-Y4leG0)8nOQJ7"5Fb7N(*+)9WtJ1a[=j4A@CJ!T_r/[-!gL[JrT,t@k^iPAX=roY%)G=W:mjl4-rZ7bK+(B[R>6LmlF]]nb6m;".rfrZAHWoZ_bO)b6#?lNc^ 9.[UV+M1Kgap<)9>],RN9(3MF[Z.Ro5a ^bfm,09"iFK 9S37-<=A-2n1Dmrq4rAYbF;LJ++UXR_E[jk`tdmUEaEB\TR`^ZZ5+A0i_?gHjfS^c!t&pHFc73YsNVI[)_Ut-6'e9U%2N&&r>\HX`'GPo716A8R3C#rN[<2,V_lZ[?QkL4>R>f%EB5_*Y\2Yn2q6K@"7pIlen0cG=dC$hen\dj.ho-0'Ik. c:8(+lT$Agg/`LIt/<2PH3>$oW!Y+DAo1T-"YJf"_`nWT_)-F0-0#TV"\*,/Ai5VT@iTnbAI0ornM+k;QZ7hkX*m=LeIHtLUPD!i=f4E0$h3^C/s+".a0/jgoGb0d/?:ID0jt)T%EL4PLgpqkWU&;d2"]Op#Or@7c#p1r3K&KKUs!3^q:W-B3eAfc[A_=nR3lN\hG5![te4+Ealfg517GpXQ*cZs]US@No>\OtkFUXqs`e-7#3TYYX;;p= G`kGU6JJQjAChM9^P+S>qb%ZVL*a5LrMqGjB.h lTo@_H8AlHXl1s_LHZTj6TDPX#KjrO1Ph,rBN* 3 m]dQ(#QU#5s3shF,*rZAW$6Sr9T;4WAQhtZ%3+ r.$%pDG8 <VB>M7AEZ*m'k-3N@(KnjQJ3"A*EF/h/qst?U:Jfjd!)MmP1!#PGL9:J'$sE M.Hf]]Frld-%*HUVWsUrD%?K"F/gXPe!LjmKNSM1tJC$NK*o5Le#ors`6iLUg1=2MaD02aaZH[geljDkU'qc(tg&nL'102,0V>W?pZ-CB!:$H\(:dsB@b=$R+"Z_*ZFTDkp"TAD9bs.88&8?BG0oA`/6_9:Xfeo3J+[BYcc&Dk!DAhQn/HO&mEGsZ1A1\%+HmZ8AO6`J T!3:Ggj/R4V"?gW2sXh.2G``LIHD`N5lC8-4X4-9nBoZfAH!;Fg(mq!EO!#i%Gc(1ZE05MaV>"b"OT%F[U?YB.to1!4S!WG#g>I-YU"s9\s*H!RTr]jS0Z)4[9ig)'"brRKb[pb7 7M[k8.B]i.*)oHiFnK/Cb.qr*OkY@jc5>^K8g;gaf;Eb %"#?EZM"6[H,7a+s(XFiP)>dd%(lLHTUK#4pZ]&sJOa,&MRZ!$2oGO&=7Rj7R8\pA/p)0a?d6htHH19G)ej6sGfjWsS2@*1^c"$'0LEI5*!X8CdC%j-99XcPs8X+s7H#H06$*4h\^KfW.U$r#Tb+EG@Vf6sphpDc:A5]9hkD7`ijZd5^00%_N0B$5,RMN7M>Aa;*Y5.F;rFnK;E'):kMST!r\G=^DjsGF>!^\4L8>VY4$VJ\WUpegjJb5ArjLWkJ8@W'a#p(VW%7S*YSI;IH@A\O9)Y(`5jb]F )5S?,I,F$./qc@SFmHfnFf!$bW+erR:4Y99,OB;caB.E:G/B>AnN)jF^75Y)Mh'<<\1PSGUta0&WVn>&c]ShG#qb+)fNmE(tX/13]n!'l:EM7@M9VX_AT$\[IsHA#NQ+0:gZq'@W"\XP,<*tJKl#E$*0O[M1$ii3;CA.>bT8(1pp4+Z&mlV5lspqsJ)?P0eXGmV%CqZ:P9`KJc9TQJDqa_AqVgGKJQW`\<%>&@"2W+Gg:akVgpl1><:,N[K(d3H[;d$L8)!9tn7 >P,YPND1Ij%bJ""!hm!>VK"AoY8[)gG\@ F1^G[m6=5Y]r$knf'G)e20=.Kd;\c*^*;"Ds*O$K/kVOp%PE33M8C8-3]Fs=HH L](7Xi;BBRDW<`p<&^(IXmlpmT#oQtY>:T[?W`Ze^_' %2.93Mt. $`@c`k=h/nPPf\Gl655MMb//13lmfahEaDQ(+47_f6g)I?ok6C3DmAbbj@Erg&S7[eK\[C2-oTtY<`7AU+?tAllfsA9AL^+5!EU?bD ftpGZD(COq/dchiOg;]F7b2-Y1_mcq"-d^ 4d75YdVN9U%AZV:99,YIPrG'a2-Atnt!<_^nER.*g\cp, QW=?8AnA(A+eLrOJ9Ea4UeLi6NAWJJD[Ai$+E?>R*o(WHjq1?"+n?`",]k3kX;'^SeI)]2."\9>EqQo2K?^iG)TmRKp?=Q\DZ"__Pf^MW#&+Zpj=/B11Wa'Pk[-.:pr_1.L9YfmM2NT/X(6-NEnK'Fl>t\__fN- ;baPoO<4E8tNq8UpS.(W8t[_B]oSl/A:& %(Fbi7t55lf3LigGUo$s.I-_=4,^I;^)$d&92Y$_5McBg`]bD0npl#ILcRXjMdP<&@H8HQ:%W'!p-b@PjasM$c!tKpg`J-dJ-1sjS5+cAVplC@Cf^F(k%PSj4/Y6h+!:2pXa#55p?s0)oMCTgq+mZdX*%,g:L)MPG`qi(PmY8V=9:DOa]`H\MeX2BUd%GYRWha;j8kkdDkb!o6%.c!^o=L,U/Pnd[Bm35ED] @N&;,!'_laMA8k44iGQlM?S'F1\a[qAlX:$4@Q/^jMojWh1jTBTF@$SDRlP,%"W7X.-RSkeK*KV;:tDILZ5tQUB!%\P.HA5D>m!q,qVD@r1+lOFE<>n*7D0.F`HHhn0q d_0nFK,1*b^^40GoR@1lSKZV&N3FQ(BDcl^B>3!PHCY *E1bHs*Sr[j=BXR-k/6V0#6_R>VYs:VoaBVCNA5,&r#;c#F@A1$tH/V@4HTFTHA>%IJHFV_=g2_Ue;-b?)pM&0BA`(`h,f.XL8U2CB9Pt#]HNdPKsQ"CXQ6MhQ )poA[s&c F"RZq;i!=DE[Xl2MH"DYV`D8<*UcPWP&i dbA[((MNLT>hFpROb'7W9*&m,`%@"40b>aJMl! 1gD&sDRtAd3I2llc41."H37l5N;$hj,qI.M0KO/:Q3.f\hobc1^e?4CTh/HL]9[A)-c d8OZG J>eR#Y/EIhlP`22ce&C-S>c'f=_mS5m39X&(JL0B?>B`4;1`nR$DhTHFQ=*UdSa3:BA63T/D5-Uho >6iZAH.[.q$jVZslOnD)T,=(''GYSAA]t"M+)H>"k8; U4BWgsni\beh.YDfrY(,LqTUA:K.OlE^Q8f8%Fg_+eZFZfn`XqhQ]?%@,X>,nd.V<$]KLbA1k^[M'?,ZNBrEiS7s4to=(bAJ6;O7C/arKE$qk5>2KkO)ic&hPmV,@!Q"2Xi.rZ-i-tT:t^t,V9%rP8I^/nRIR-H^bKP Un)CRl&BYVMc>Qf?tN]8'`,-j"!["F%"/P5:QcTgZVlMXJ']t2A,Y?(lkdTZHnio,ta4J`QQ-Ro;)0[.=D*qSFa!KUsM n.A[VN3FqG:J7%THcciT20Z$-.Og+It']r7]meY3A$`*)UN;Ep9h3hEULe"i a:'^bR"q-J-1\V>CmA2liB.fQ\.>`oNB!l5Af<[7_;5Veg]JS3MUq.t2j19N[kMZIkodDDhXNNl@Lk['\(\#Is_V%M,li?I]V*EI@\sJQWRe6/QH:k>9[pf^+[C71lGU<@Vh>5Br&3Ss9&,9M?QXKL0Am&*VJAAs>pIUjNE"-/T'@gFoAt"*d;]qj gU-/lRArHsq]5q =UkR6(Rm'(++,o;3[Oo;WM6U;'$2X)/qY?JG+&1Y7;EGl"E%!rk,:]A@j8*]A!3'-rBrKlpBjX[&KS[\@0oKa%/@F aGFpV+Ak1$@"YBk/,e-Fh"S@JP]IX[@ZRCkVb9[_ks`jDFpC26A\>A"lg.q_q/?BVN(PrBgJ.(RGYArD'Sa.1 UAC]P=_1_Qs6%bm$UgJ)..gWeGilHJSqjhYAd+'8jYZ)[YelNG2%T5F#."W:S; m_Jm`#) E';U(]\\hosFM&ib[@OdZj,mdF-MHs"mI"0]JST6n=e>s^]>*A"P/a)#n+t9,V-aI3Djm(FQ70R4E:g@CJ##3IgOW!qe:hNGW.m`0._f":9&ZmoaYX`e@*eC9isRL^iesY#gjoFR0K?$!\Xl8_11k&;+!%V/QN/;G"g"7]4*BX(.F'#[ET0[b8sO>:A:daV2\OL8nIQ6PVqcVmTFb)qs%$D]-:Am>re,n6>MI,4DZ%;CPf%51m?BcB%"]=snZ9BU9[ X/d8-Vc=tqI&P*pCTrS8=VW2qQ[_o'*'AENb$ac$nTZ^6oMUl>_EH)S(8>Bn6K);0Wr(cfhGpI=8& on-C)Re4A%Z9&L*XsAAWH=5:tXD-)ApKHW;AM5X;dd`R)3<85dG>KD fF+`oDgsgL$knXJn!(`Vs o#5mg=J*@DKNeAgTgPEQp[(]me.4H=`:\HnM*j!eg*ZIb+EfU_op"/FWl.i&TI]gU<&aBmh5:/HG7ct`aFABOhS);p$q(M(%85[[$X(Ab>=%rAZ^?!>D#kmq[OA;W*^Z*R#O^Q@]HnV(7T.\@XpomAO!o2fP#nsdcZnIl=%eA*YoA>W?^J+Xt>ZMeAcHLs`D_1JkBtWt>F;06h5#4O[4+p.tC5K)L1D/(0:^d(lmalVL[Elc)cR06B^%J>^s3DhVi^Zo*?C+>T/"J4-6'J%#A(o/?N4*lc5mOfS3N,$F4AfNMj8f)l8p iYFiO@2e"7/nE,GCblomBE7AJ9!p3:AMPme &Y`o_Ork6`XNEMo_otZa2N3h4.+c$!+4dT5C1os+jGG@pom5=sbo+'2TtjigZKr5m/pMP3@/+#%HSt=)SfU\329H^*NA+,J\OAZId;&EP_j'j<#/@a,%r=L'1BPiH+.LgHOA%'%?W+lO"RgJ)e`o.[WPo@$2)GEF1BG5%lZC2N7JCB,L5h!3bIX@AMj5%W2LI%;Zf;fH1`PTIQD'-r@48"V;p$iP3KJ.U!*E!n76L64O(oW7?CV7<8:ZhPPZ\E)AL W@5e%8Oe2a9@BqA;>k%Xq&ocVJb,+UBig5<$7d6P&[ \-oMN(V$L9-Zh:Ad5:BX,MA;DXKIfk/^N*$=Jk.aH`0@J[!j$2=:"n`MBMQ9i7^=3*,1C>(CCb:d>D$E:=+H^Ap.th9KA]j*FQ%\FkMeNiq9+?D"mZS<[Qi(O'Ra"22/:)']K/@NJ)pTdka:"5kfC$/ljl"[[G6A,o(r_eKjHPWiJt0iJ@3FS!^'rcg2:]^t/(6BJ[trtWG+DP,b6;l?K:[]/RDo?>!a%e'*NOcmqj #^3N#A?N^M49AQ%-cZoMAm)a"F2EM3;Aa`_\:D+(c137HS3F-2T7VYJ)U6'Gf_i-NG89'R'hg+GX`j<r:K$VK6I,SdL/giQc$E\Hf[^C%C k!7"lZo8@^"*Y[\X\lI(pd>-B[5PPFK3rC2Zt\[q->#*e"$f,dN$[k5k&V6:C6KI8fNAD_SIW>@!k*o Bf@&m;H<jhQ+U;+gACds(8qTm2#CQ7J?.CWAVq?7Jce5H@(CQ$IX"7$mATFZC@i>r8C]IjVF_#Zc>q'5P*H6iARNP1B&)$oqWLG#en5kT,em!Q"c1J / hZP _b*6-pp-0CNBP#?^K?\&\a:`T1Y.k:hh:eangGB8K"HY?n 5Hg6^8:oo>=8tKoIPkWsZUg<L5jc/AZ,:A$]K%oM@"MBBY=\P6:;V`!to2CFRDeh6No1/R@n$7rI+2!]F!;VpFaY#)f%#4\<-r6CKbfohI+sMZ Gp/"8(4_WJ>SjN,NIY\nhf\S$rl<#WmAf%j8rFg,K4F3`]8$H=8N';0n+D$oGnVNKU.F-Y7r0Hd*&`K7A7E5X2;OMSf9,LO0Wl]h8U/FW_d ?Upf>?XjPaO.iN9:DQKA&M>t60_t)/;(,>^LK&eIknR/^DW#U/.m13+4a"V?>#ABV.>*^;#k9&^ZC2.sSo:2aH%=iaA;*TdSZ+?NK:O:LS.[&+_?>`W&7Y**P56Xsd-gE3rO_b=qHI"%^]X76o3 Q )2^(Y^@ZsHYJsq@A]&J4l+E]HO=T7p(`Vs#/bAsTCLE2^mdoZR(,.A8pshE(kWn=EtMh?_h2d/=-bUH^F<'q4.f%H;Ia-BYA_q0jfH3i=C+jmYk0+CYEhH&&^D+0 (X9_NUfNDd.*PIHHhL;pma#bRED'W#D2f!P1^k9,#<32j+ Yk&UMl,tgAG]Q79kf^s1IpK'1b9?P`:agbT!eLS@+IiIHI6asRAAf,`4WaiXtZ+A<BdQIq/%UH2CCiQN%BaDrAc5pa(OZmb5!fBsO>i8 Rdj/D8UgIo6=g7fc`*YoXU*L[>H*lBtQTA)=Z.OA'f-F8:jTsoDYLr?B<OC0djT0Fq4$qR$rFha3?4HTMIL+0EcXa3iL2;3YWgee]qGV^4J*:h",BA\>]/-ns9,F>^<"F(lH4KmOV8I_M_#ioPU#Wi;;2r*h)a#tr[">j-Abb!>13#]!WK53-A368__:9$hC9h7P?tnB.'O4D*9>7/(nU#\pAGQ9'/ N"H<_f.XbTYln786*;mFsQ.0hP9X'27a8047@Qd%E>a^s>L$:M!Ej07sZ[/IOOAiU,;[9FdG%Xpcnh,\:qc3:WS^JBH[S>AR;bM$OTP)2'QUo1.7i5Ucl?C#p6^btCI0) qAl#l&]p(00.8W\at&1CUAa)Dj ^^!IY?d#.K20Q\rAhXnj1b;Bm\")io*SSVTd_P*$+>' jQP*#]re`4@FL)M2!i;HYZ_k pN US1gq*%UBX1fpgiM'+7KGXF4o`-RYY9O.; "g>`g,Vg?NZ3kgA90(#Q1aqkD9.MG&4DFnhr/3Fb:T0`GfgoXL T'S$/X4_8nb1I>SY@9E)6?7M)iS>QfQC*;r&lRCG,Kleps"JCo&T003jGAU.(#"]WnmAG^rHh\h>6qcUC#ldB4DHa(T$^$*rO5[hlhLS@q@ZAOlaid]-O['(8o3=.8>?gA>jM=tPW'pX!aX#IgNAX,@)]!e;Pk^"\-:mbU*gdLFt-CmZ@3W_567]2V.I3ntMIYBen5YbQVaAX9] rc.Q#K&gC`Q%b`NaH1FAIe]A0%qlG3WhTE13oHrOs0(A,[X/q6G8VAT.%gk>+>;;Y#B1,1?s]sWa`'/gmT_+Dd+lVGCLskmrf;T]FXDjit@=b.`mC(LIiY mK&YFUAi$Ka(,,JTH!)9p^-NkGm1HlQG/"%r@@@c)>]7TDL*G$_1l]&=_('hJ2VpX&NE7$(etCjPf"nHDiN/%>KM\@e/;8C#LJHBX,XKl0$tKE4.:KL;DHF52IVY-aAmsZFX_&7=_Lr;VDip[UA2D36E[P=^GPJC(:N_[?qZjrI_)ttY9rF(F9 #h"(<@k%A8%"@ktM.$)>cSd.1KlK7WkQZr[TQ]MK+rZ35A5il]IMnqMJb-U92HRGsAXbF_&[hAV4]02&;Vr;l=Z(I4cG*0f/91;r/1d*QRY//(WV J_tY,EY+_9eaYE>@tGN=[ ;K0#E3OeCP1UfSMH14#P;(A&JCod>`_qB9H!kDG,\GPVr.>*OS?  Bg>,m@0r f7&GXIsjJ?]cK2?/^#)snGVDjB*hmgik?/SpPL<]$*,HkGbmPJa7Z,H<;l_"-//L$Df25%(g +G`X>HiIam< [A%dkdB1856D3P#dGQg1?_a[Q8bnRAmskmAkH=p;?WMKgsGB9HB"YDEZN/=Eb[]C&!+Vp@^lGRH1p$G_FG;O:AA*hGoe=4>6:C)ABX5!;/o2M+X? 1t&>8^FmUO\s.UmMO(>a@mR08HJA4)@dEP2mn`/'&+]k!e8L2Q32*'r,Ad;D?ACnc&*o9p@rEV^D7JG$SZLS1i2q51:sgrDtWXI?4Km1c,NHe&P2rUlhea.f"*o+ksBL<_F\pf+sD`n8](PWH$h/G4df`THCo7-6,&4d,C";%*UFQoWOMWrG#T_a+[dQH&[1,\#!Freo'D1">W)d[=bh6YD/@YURLi]GDU0EX1f!Nj(f'^Kea5K1+UO#f1"O!q,hA`]ior/]BZ(iQd#H_2jj.*kcAtq[Bk@hhCpB.Hb+Ud%@A]NBY,^Uh4^m)?2ORP,C$q#pNBkU6NBB#_YV"_,GeZU-'VSU.RRPn5r3'rm3^mXr*&%$"diWq&[RM$G7(+PjT/plUcS\Q*UA-YWn\4;e),MoMYMXV3Q/r$MoHnhrnpqn/)#InrT8:G\JRA>GRfk@t(FTpr!OcjJ_=K8(,`_FoU[-A<4@Ip3c'M36V+2EmLU/2sb?Ad9];d>t&_NEGhdbs_<#['6:N;tnY%Uk#-8;t;VmFEms(!&07?`?2"0VR"7Xg%/?A;k>A\,(1,Aj,srR9)%qJdji<+M*5M+pU9H"eW?3jrE`apa!;qV0UKIT6R?\TY,a3oWBl9k<pXr;.*r&[MmmQAA%$oLI` GEkfsTPN-%5r,"]B=Y[fd39P`"HnPA7lAGsHW@NP&oN!>34;P49"mtO/RK EP6mMmi9HYi%TG$AslA@=M]cN8A'M>#=-[bGdLh9cOXh1.N)?H_kHo4nH\6II>Lq5'VWI&56#\'%qn,L[EGALMb<q#4nB+NralWhAE\]fTQpVrbO'((nJG.^]=bS]'A3_YL^(HM%V-GZS@"B[UtH1\%)-eN9=R:Bn6S+se&9M9:gP81lj*h(8RWj`E\Lq"L2$W/rUCCI:Ylb'2XWA?c&=C8_5/P86_fhg05B<=NLpDcR ;rg' SE8'L%mUI-9Xa**8@6'WJ,TTYjO66V`8A#olMgs$2_b".Q23Ai"nNI"4ECibgbEnr$8OD 4]3b=#;A@G-.VYKM"PKmq0P7,-0eSZgl>=Op60pU6=;A%U'LW4 MI;KR#qa;"ILAqjM000Gkq9KkH+;(:*.!c8<1tjH$A=c@Y./ikk)r;ZV*fJ]<(JA$teH/'Eg"Pfo"+8`/TB-r(% l2K'E:_Wf;5t!rcUpA%Fr3#5(\+PV0Jl;;Z'+D''@FS%Sr^Pi'=sGE'&;ATs`;GiaSBTjPkdiEce?k/a6+16dKP.?n5h3SXOa,c@.48=gqN/!sRpJ5G$)J2Y#.8no8d^:fVo\Q30HaWP1+l/]"K.oG;H_4AE,rd]L'G5(:CgAqFsoC:2DtH94<,D\=!CiYV8d0(j9rt-CaR*$#'pL_kZm????VMfoN?tIlB=cJ>HOVH:$]P-1mHoXXZ"I00Wdq5j]E!)&#S9n=%VV67\@B*9?CjlV>AD:J8/o%PG9[lBV'3)!"]%Z-p, -B#[a9MkZNTQ(V>Oh1+L!q6?]jc()`?20W"6I8HA\%4'q9J1S]rAb`Pas.Ts%7lWog6XQ\ *S6dMc,-Rd^C?\@bIFq` 3jO+o,j-29Wp!mN%e3P8_La[A!*UbM+mhJri`a!$#8=\,J.(->;/%$%L<^MRThi"s%oPQ,=?'4\1;SF3b@/$HeC]P&,(^;Sg0V6ZJ/O%k_qF:H+!q<)b(]3>^VC(@e,FT1l6!j=Q\"rVSSZjR9N]_<\s*@15N#06gt:J%8%4EFbktD1BZWA`RK/l@K43K#1.W:;jQE)cN1Cp@A?@RM;<lHd)q!oq9[W O5UKpC`#88Aja0i.fn">`%>+]5[oDL;N(+Bitm"Vk^6VJB-[rJ#6#GMH*je^)pM).U9lZGQXE?h?jkXoZ .G:T'E<\3#0apXS(#()fj@^0A8l3S"e?r3E/A2]hbSU\Y%JY$<&Zd)"cHs`jNf_8)*K75EGXaG02T4GY42/?X>#HNEHP?]ntgZ'l=I2CTa"TJ#fELgaMTZ@X/0%?s3%c&#Xd"$Zgo[oG?)?TBSoC9^%"\5)4Ccs$l"k(skSq`+C;D9pCgi$PkmfV,sBPInTf[s) #"q=KbP\lE$Et\pfaepfX@<=qHrj1) E!A2W:oFRZUed;2ZF4V9NqmU$>/e$2h]rHJ2bl.1H61)5bZ@H4I/e?T.3cN=YA3<fpigZ"fJ$$!$n&tQ2N:fO'Gi(CHMe0L2H(Q8M"7Q\<#n?gHFi)# Vk+^pp:rfc`cAqarbFsQY+;Ms_0/m&d$l-.+SaG#GPR0\K/;H/E9S-9llAZ0Ge&3-[X>B3m[^;$r\NlKb=ZgkVl0P?OrNR(F^^NDQgV0\N_K$8h&.1?QAE/ada%f\"NL&VYpfk_Ah%k.g$VrU%15WYcA"bdAKY<KP:fs9a6db@*h/<&O5t` 2dUJD@Ai. [nKs:3.U9iKp4ANWJEMZN8n?CrqG_Cr/q+h#3L%\)HkT6)OP4o([CsG9@L;-0#f8JNGYFc %o]n@IjLJCg>af8B89D0`mmRsTD6QPP'2EUOdV02/23/07NX]dBAC^CHln(7b&DGV4GdSVE>5MT@:g'<(I%E@Eoih:L"D@)2[rg)3@Ctrb'2()Oe1/7MpO"2A!57c_[-A;*]N_"2&;A/k9=!Ha7BYAq+'1(N;t_DA32ml09.J4RXaI4#NK'=8>H2P8g]9g;_#E'H\7R?1'%l3RUl;WT[i>.YkaKU#1IH4?YI,,CLSHVBVr=S@Xk4TA?%K`q#\YjT$Bq:Sb#U;R;%WZANs+Wf/eWHj*.,ZRi>mh7j$[Sn7m8H_&gH+-!e(Z7TLDOqI;pbJYA,aF<Its&KI5Q?;_E@hONF:Pq(rr`smD9UoHEaqdoj7 qm3G(c+P7Qcm[o&:+LC7]p/GXXH80F33??MYp l_8q5s,)VkZeJ?#s)cq(/fAh"g\n`j$jm;afp.&SqD$&]X,EAK^8D[Ag>MX#t*/ASaW#+)o9gr:/]9>XE_es6dO3RUPQC>]HS%)#b_%[Z^g0rm^q5W>[Y424TcF,mi0<'JU3o_eGcqKE%)Vj8+1MM7HFt5.Z2YcZ?WW4W*m$U@(O1-"imf_%1kgAVHRJ(:GptA!1id\<;'3mV][Q,bqEk%8 L/[KbsDk\h`pirL5\pp/?to+NK=Q= .s[OHR. 3>*\Yt4=6G5&2U1Oqq+bm8dZEH.Qd_Gc)(Ze;&Zn?:jC(3^2-W6*m*5:GrPS(JE&#MDIL(Td&3nrl-ge87?mtq )"(3$r_JCWcj'VRmd-24+.j3I4&X5fMb[sntUDWci$*K 3U:[]/YZLn08 %hb6GRFRW2U(p56 /Nq-Z]3r81kDG#p+E'T-Hhq$"5G"e)irQd0J9"&QB`ZffD&5!e]$];IfWsQU?gLS+9U08.4XroA+;s?0-k2d2R8`.m/UlS])l7$J)j`1:I-tffj$DSX)t#U;KkO/P'0^o@Sj+MO^lF!tAs>m&%XS'RYdC4Z<1_FY'[H".-;[&NP^ ]2nHOm!^RO:V9GEm'8sifqpcZ>l6Z1OiJkCGse2B!IL7\YP'cJ_6!CEg.J)fCi <5.UfrRlDY'&""3e`O"?sD7e:YrWai>;a_Bn#fZF)#8h_G5$Bisde?Jomn^@o'1>5LO`NbpW6?NJ!S5'iVQqi1862S_)o7><'O+ p4$/d!dZR(.&iplrrV7Kr@Vi ^G8?P8sn)XZ4<T^qU .j6tQ@a'n(%*?Grc[>)1L`^F/K1Q?`'8lA;DLDDmp5VMbpi+7GOd2$:pD<6%AM(Mh0kg?jD?NBSFW,6L&[PXNo$YgY//Ac[2+A7X7R7ZP#1')sAEN]_A2[K:M9h9lVE#\=;+Do&cnCp?3"'S$0YsF!7Dt><V:!X%lT?orUNR)A4#N:Wr'FMKc7_fD(e1g_hkV^'-Sa_MIp4BAFOHZBni2f$(1jQ1@C#no]N#j)LV*p6MT_)Ze9rF9ql89QBsGj2>3%2<_@#.W(\G+mcm'+[q'*Oc4a%E/A]MSncGaf;B(',QCGP2eL@%7D+g0%!FSLl]]L*.F;o)qZ@63<&F\).cDE<&2e -(5O<;2G8X5e[j:U]G-5U.WM)5#40mQAUSr)E":a*l7I&W[@*ZlT1ESJ3OQZ1@1cL*Ac<]MJd+%.USp+(=CAcI)_hnADV^s-GW6Fm+r,?$S28i^PJ'GsY<>)7<+b$PWq c'jtT#nr#AXVBFX,pcM`%OeGKWT7/!SqaqH9@X57F#JI*FKA_/1:*s&H#XO;-sOOS&G0i`]P"^1jo5W6>$%Bs:HgZ.9,WK3DcQ`W,aP+4:s5AWjM35_1)dks,7`f-VJOsE;D:c)H=7FZ/VC,t'csDfF%/Fp*T?@ie*VKUWkGTsa<9Ud,l;kR>/7jjs-eH4^j=VF.l@Tl7a,ApLbj,?PmL*t37#R)TVNE>9'LjZl^+@ha;WR'X9FjOU*Ot?k+#YE:7G>nW+<AT'8p!TUpZ,+]V>rDPR(L9MJY>ap?'1 A\EZK$bliYn&5&oT<Yl>P!D!K%BS[U!j;b0pY2 L*gBClCjlt*&<1Ko`FXB\:*ZbD]9K#`-YKZ&+g5h)F/^=97iE!ApL^rdR?1".l(e)t!h<0lg^;6!4@#1jn\Q<^$LBt\;  8`9V<`g4LC(so`<% sAY*a.P'Y=M>q-C?;k!?knDk!pZ%%$5K`XW,b8H1k9,)sEbWjs4*AC;!&H6fafG:Al,0c,eWQ4>,lDnFSf.DK;*`F7`b$WmhO_ZdOa01Uo#A?,RVD=,@H-%;/\CBD/-Jb")HH!(0XgSnIhK[%b5-/h^?Wq0Q'n!d.NHig]\K`5c"X^b"h&t,Pg- W"[X(gqPQF4W/$GtB;%AJ6[#VaHTgV8HNNV2^rKR%R_"MU:Y+-Ms4nB,1#ArtADMSY=\dYXeQ])g\M!2cJg#SPCHqh711ObJk&HV"qQ^od<LfK@:FV'm;$t^k:qE>*Jh2f/+m9;\Q"@IG$0JE/Sis9XS_2T!;K [nL+VWJG!s0&:@klHsX@(f*4R/`sPYR'>8og.[LK-Bb cq+Zt6JFbdaM\n;o,ohqe<mOA$3@5dfO-)pI,e#[QOo.k"Wl2h[Q'jk0[:4p!LVWA.+l\,1cRTL.oogstQ#6:.1=.4)9q92c1]LcaJ-K'n=W!^^Mpg`5/<(6>1r 2p&'i)&bEGE.ftQfZIsRh\C4H=>3M]d5@c+3?F`]MNZeKh:/[(JWbXNa]q`?F4jl8OJEQFI\>#B-t1r?1m_[I= 5:BHcP@3$d+aG"8;Mg#TL4.lT2A"pmGo@a"&nbID9)DCW_SVJeZBCClsPG/03gddPG7D@!A\Y&j5s93d:6kT'LX$Yt7gEP_L?(p.#r=*b-'sc@SE6F[(>4nn(ZoC<8AJ*k@(Ua(mCNt,N@b>qm,o^LQ9W&V^9A5I%Qh;RJ\E+\BQ%IoG(!3GO>l>CAi(a%mmB*\4V9(lAI2J%?7dS^3/b0--0g25foi="!]`r3B`ist5eWDsqF'GNI9q%#TmbQf.L#ReEont*o+oebK/OH=B+;*tiAsbQsnUFeLIQ?j]kr1rjM2TWiEbkmP1]eKPmR9/A]t!Te=W>9A57.dQP^mn2Vob'5jY,5orT*p5*`'@'^GEG[C`A-saaa#cQUo^#>i+4H6tEkHi4@6(]#W.HQT0FQ0IL%=-(!r9^!k2MWXTN-dt^BU/'"0f4tZ>gQ^4/6>3:kb!8h gZ#`[kD7QBPK8AH9/loBF`d+&(.72#=JC!egf 95%>9#IF]0.T-&Y%IUD+tLR1:C\&R!rZ9Uf2>LjOMn%Xn; YMQ5C[f(UhZ3nAb,CO7LW7$^!o,bB5VRhSt"i4i::S=7J5X[ .Rp!-E5#FQN;+qI]7,R(:SX1%qCWK,m\9="cesMOMHp$pS1T0 \C^,?Jt;_Mm4]=i1XCD!spSN?1KInk`qiFiWF.]NS(HN]_bh:VgO7'\etNMBrm,/4>&o`W+tf4 -FUmm5\r3[ALm9[dUJ').^8);Y^`3P'A^iVSjaXGN/sQhOITrQaU"p&6?$4!q6CE)>Glm2pGe-)AX@4V,XDT $`)7npm8=e%*!>2FF^aXQYV_[2d5C7I_-[j]DE^\J#Q&AMW!$W]G3+N,.\?h>%o0s0o\gqVHL:%N]iL=]9,j(m/Ap5moYVK^T"Sc(\^qk1pe33N=`j(<*V:b,(#h;6rS8iq1A)RBW@!G7O&V]l9?B;Mm+8<-fWe]Zo5d%VXW\h9a4%4o`NKq0B/n]i1@%9GQ^2^Q5k*.$=LJQ8kXREg(8RK8c#.^FYVT@_$.N,j'sOiLfPX4ePXH;)c3jd-[9Te2f;dqhqs=S1Xcl&KmS%I(;Nrp,*7Z58NA/4OXlQ?[%3.2co(`#KCT;3SJejOR')!?]^^1^-UYY/.8 823gU]>h=#BjfAn=*&mDcSKpPsL(G4KgA.5%@acdimWp?ef:eiQ*@X)Z)MZ-pe72V)P]e l-A!=/Z<%80KA5*$0F@:Tt%qDNs4^e.Z]CFA^S"JhaB7r?A-n=otK*Vi#)<58lo/R4l).aDAeLSFsno`1Z#P3t2GC3FAal78/hoK,>'/'Z>h`:8[-`^7G-#Q7d.Vp.O^b-\#E:q86[UP@32gn-R4$-dN'48YiPh=Wj/H.K[^>0e],)7j6tnNq=G9(lHZd=*24"@WP!\.rC_R3V>W f0CF;SKZTE1ZgZc?$p&`.eE]:5^?<`]T")RtQJiXFI%U$Y]+cc[ 33SM^_RGC<;&B^XnoL>"4g)6RaHjX:)!P%EA_91FCViV7)"lR3HYXWpet\#r>+f`X&g[tAHI9iZ+RB*!4/jP:Wn?`*A5Y$b!eWe_[Z$M\<`@OQm4&(RWRNg4@k^D(KhZ.*?K#=On8L5sGd?::5C67$Aa[.t)9S\1"(id(R)-O5 GIcCO;05;l4;MQ4)K^-i;UHS ^Y2]!ac8r=K9#i0(YVENL_>WO`dk'?[m0AQOSqX_UDGWBkhS,.@W)J6s0aAdj3Tk>I' $ghFc!V[+,SS!:sAIg*lao;?1Ule(YLR*M5hgS0sRY-ULD%8"6"Y*CFA(V6hW%KE\=V2D%:,63r^g08WZV:OD'?-pdNq7Xs i$aSa^,'saNZ.?M+g!YO(Qs]>N?IUY?TSA)=5QmS!@%U6W!MQ#Q3rS[tnb._ab&BM,OnhAE$QlJXT*H3MH$jKa.1sV+aEY5p:[5LgFE[+n01)l/B6iA'4kB6NV!#.,^LAK]r9Yi?mG?VoM9RkW6j96cnWCLG`4EGS+b)'_!4tAfYJN)H,'[:^'7G02\eEZVFkL^b1C5VW5%-HC5 Rb8"E%5!fJ#@l51_4a+j>&\36@h;AW;GpNcg)QVBS:SJn.CE*(5p'FqT_fe$8=ILSaA]KqU-'S-51i*AQU5d\m<5'VZt_nJFYYPa$h1NWY^[2Pn8rm[^A$K5!86p8g@_m@i6oAIE4ScABg2^@1#5c&V$G%b6qXMEWFP=hZ1I4@2,Z9OE6AjkPDrgAWXS!Qk]M<*%H0ck/5Q\[B/%)R`\]%?/8K-\VM3NF$W1s@Dp=6+bk#H2KV`b989I@RUiQ2[\5LJkcA#MD/ah$-g4GFC2&/>F][OmO0nT'ATVfl+JtK?5OeOlmXOsmW_]2:a-*#!EDefH(RA&d3hBVH51b`JNNcZjFmZW8LhhCfRdsX_;[LPk0^Amr'Y]MaFM>&"Ah@5oag&U>0sgOh4mqCk96t-5CDAAIrtBjMt6!'K(j/!Y (h/'9m3N8:?B".D<&37kX3Vd?kdMId!r2N VO :#/M9pebF+)s8_`k-jZ KhD<2Qi; ]"&.X8Yh=`_iN84L^>.,okJOs#e\:V9)_As;W7&fsW\9M9A?bpeq4[BAJj)^GanF;dRBATt!MoskAbDbjmkS7)(,J#<3n-$hfAM lP\F0Go-'khS`KU^>%d>-ROR%t?Jst90nsR3`9OO+mE6X\japPR"54,(bhMjc$";$h-e_H5=tp,[YicH^1Y`<AXO_"0M`/Mda?f4A2.oYt0CKf]+2D$h@C<>#K5%o%)D>QD: scf`r2dgX">cHlTH:>O@ZHq=r1MS^$gGN'Q'_MHD5n%7m9At6WGIAXS'%V*C%I(Hc@=aKUe]sWo LZG9-?USAg,kG:bZNZ\Q2Z@-aM^l5CFCQKa%(M=APehR>Q;-8-0P/!-'q 3#apC":a*D'E*a9[*!Q^"l-Bf=@@Llb6AtdX@D]E)T@rUe^+CUqm:o'']Tc>hSVnI0*mTmJ@r5`k9@Fk`R)2 ?`!FIV[Km(<W:a`+GdRnS^/q]o<>Ps)aAdN?*,Qk!,[^72@"0Fc!?'pr2jVr;W,Sc6>C*Ttp33,+@[p,/0^N]>b")p*3^c:p1UULHW'`Be"Q]%:>>!lJb:/f`j-Gisba?UA#G)FA^tE[=KQFMt-s-NVI\03s>h;`@E-D6t_6L @ Hq(Yf[.O(@;"R2i)7l/>4_`_NaT19i26)Jr_+d_$s X:\&;O%@[( :%Z-,$!9Ee@r5MHL6G8&?^!Adb]e@oD+9ghjPrk8-A&1KfVNA+1Yf1;04dqhb-<>5[#LJU#;t1K/!e;]$c_eMG0s+F%Y'6$A/5GJ;U])jA/JK4Si03G$`^7A0J@g10a;Z*B3IjG4@@R$G&oYI0W=!m6CaZ96WZSC7"=QM=FKpoGA)m`Md7:.amAMa5BToXgk@PAYXElF[]A@U\>AAU]t>MALHRkqRZ<(*o8coNQks[i(rlXl1>/#Nn2`GSaAE=ab>6Rt_` +=p'e9f#9QVU[#UgLV7IM*&6lRf8(.'-DNK>ZTA;/hkV`1&k+A8n9!6JO(3fb_;O3.[ QX4+o^09RMK0-'bi']\J\g+#04UmYei)g]%=#-ZG&PYQbY34(8D$6Q!PKT$+U2CrpR"[K6,\XAL'El-h&TJ%VJ'-qsL=qVdGNJo`V0bn[)oeX7S"qqLl50T=h*(d]Yo@@C)+)(6QDJ_[O&I=[:(O6ABIPAg"jFg+gm0=kl,GMtT<#L@ !sjU%S85O.iG`1SptR!Bks[AQ':h,\FM_#p69ZCI:VR6M1M/?ASYkm \ng;kEZ"<+31"U@(`*ar^?jd&M5Aie`T.RNs2$H;0BZqep.33K $CsM-4)9Af16*)TE>rZ+5b0;-"' &edIKN(`N7A8)8qsrW>)_s%d4f3o)lsG9jMBG ;1nS^#QE#YkA?,R6R>JfK=%&j]0*(&6p3icNN$h.:P1_t=!00#0l!SXlAPP?>03)\99)GUBkPlAWf`6&?@!l.BZqq8D n6sCeXg%M:EK2`%m1C$_kF+PW%IS@.%9s/CF(Og_:hT5 MJR6W<-:S99' d!:PgHA=.RG6-bUAcd1.5eY7&g]Ca1,;U?XLD]J)\l\rkG=Q4ML#9;HD$> i:;On'i:k4G:%F_6i[FG'2V<>k?^b6.lF;leO!GN>`T]$\mH.J9*mdF^0kNC:24 !5(S@X[AJ7 Q2h[K:1^Ab*J"56tmB%7$Rln"q&[h&=,BYh_At:?asAr#-fM)n]lK@%lA)h=%.%-X+LM8b=K9`6&;$0D,5X$QHS`hNP3m9tZN=s#:5kd6!Tc=&LW7br/$?6YN@L0E4h/Y&:DeAB64,D!osg%\Ij0A W(0A:QVGh*ne^n$m%K0tPW969Gqf85jH[*=2;8V%gpHV3KH'bqZj#i]QImc!'!rKVP5AP6l1K9^T:&DmQla*='?X1SgmA>;@'>K!n7mL%]]L+L_)NE*c36S6pRk.&P,#AFhISXq1d:(E@)ltEIq2Ik&KN[.Ln(AH\qqX/[87\(P]rM3Q[F 8hE:![%M/*2V3U.Ncn$8eT20-@NA*RNt%p_-"W]/fsC(Nop\Am"f.VW[0,jQfLCPm#XBBE2U^sV] GasoT^9Q (HDl.MMKbU,fNR>.[N28U;d>QHeeg?RrMJ5diRlXW4OdOO'YSL[Tj0KE2k1A;g,+3da@N>X&iR*DVB$hgOrB.0q%iA[/LU!#f-s.1gh/nd,8cK<B0p-.p')jE[X`VR6-2V9*0":](e*6!p7sFhgmi0a*q-g(t]^eOQCrO"-[SH0#0o0Z^pJZXOO`Z9EaV`C?^m#Iog#sYVgm-hfNIBGUR3tebZtKE'aN#Mr<QcE@'<M_Qo6<1k,s(8#k-p4spe`o#\eUG?- .;tNl>H9tlP)mr3Z$!'o+jX95fDM[t2"1G?ADrG9j7EM0,;WB-FpEm$sE[&"::Pnqq3/@H(,bW,f/KJZimq(WYlJ"eRMO`TXOpSYM6-Ob&d6S+Sf&+!Yg]4+A=qH5S)3d7*\mdiP?Amt?[ANU>OW#L8teRfSZ[^67<[f: _tX'AEHnAE[W.oCg8a$Pt_g`'hUe9L]R)93.*,M<X0R&t@#q\qkOhcn23?on@ZHTU-;\qS@%<;P:?h>W!-2]Z`.hh(;BT)2V/2m(LY&)<[1I">#]<[nSVMi+"9Nf1>_(KKoG9mT&s&_k\g7%o,qZJDOtRAl[#@\AI&^*fm!No$e7*4r+i^E^T<k>s/=osO'Q.`OSr_Y,L0TdQO!Gt#A)+2t^X?Li6\p+PB-4A(eI4$GBrC47;&FdG2AB.#Mf-_fP#W@ro;\jcEr0/ct12[+N%="D"UF\qhD3nJCm ptMaZ!-bS2:;0P>&[T]k]a$b-3XT\-'P=KL]A%Xh70nX:Uaff`i#Pgf,edW'_GKg7)g5gYt_,9\L]>go,jr!tgjAOlRTI"3DnSX(mtXKlKgA9bD35!>>*1_6/"@)NkVS%mKFfHmqZ7`.LBR;,p=_Q^D63lt\Z("HjpNb\4^0<m%JoPS:ST9?D9YciCmG2iS5Zg<02U*Ai?nLJ76">-<L9\PU Pk?V7NZ'd]t-AZ'dlO+>U0cth)+ZG"<2g;Xc.n]L$btADVq.e"VWSL1rV>=4C=0;o8:9to5FBNO,nAm^Dh3fR1j,!M2*\*;0e(C_i,km\PAn/fJ_^5nfOMk8=>,d;!ZB(#TKmVTo>;U\Ckq5Y>[/b-JPf7L@tL#d6'&NBV)f],\5I-S:#ASCGF!XI3BH^=breg"m8lAAbV0k_BSC2BZQ:U5"C0Jo1GGd`1gTH&N,IhHff.UnfZTB_WfS2Zn.Gqlnj7sZS?L%R_S8m+P)f#BZ,.]jj9;Al#9I";l:4Z2-IMIZl\]4KFmiq=(t1N&BA8L[H0r[Wl; ++?AU3o.A6T)cjD()7_99M"mVd.S#"LIoicsog^EW&k?V*X_Y?j-)4AT?Jr^58IJ:!p2G/q;iNrQXTMOF=JOBfL:ZBlh"L0"PTK5Q`1p\sK0Ne9Jn[I@ P&/e<:,>J!0k0iVd( -oVhY$&PS(>6#6D0R?@"/G;cdJJZ'kpIYjE0^W;XF)@6)ebFR5 D$<WN,Fch3(1j? <0DW?a674XLcm/TTJkg(ScO[?2nlkA6iin !4D"iL!/W.>i_h?4'XgH)kK9].eX,I+d 5@IUTA#m/_>^LdkKsCGg:6%?`CO-*2AhY=cAfQE:jq/LUfKS%Oe_%Ac2571+OS^:q\+JMM#DTiK$?qs2qAD?fp6Q'!4H*<07)Q`Qq/1++o)VCNW ";j<S&+-[ois:kC)MW,Ba'35Yoh1hR#"JlLPpPTXZ@Mr:fW:PMcajPaiR,"+a_3$A%YA]j5SdVR**sM9K!(V/G!#>0_l/:*MEAiXIPP&bs6%ea@Z=[;l`TqM1!o+7mHg-YD?3m%1GS00r<P5t_Y3+jVHRR-*RLOCFA:="StiBqqsoI0fGl!CV]PeACc.%SA"gn%jmS/Fmiqq&3=X!NUBc]E%k!5nZaJ)VVX;9B+pI2fO7Fk!"Afkr05Bg&-_A;IIcQW1EAK83'=;% a.Q8sA.fk2.Qcdm`,g=$CbdABJ)[&F*n')mgl`Hst,f?QW"`rU(a9([[\2Ikeb&,_"i_"r!E5\rhS6>^EK@J'=L"Lk\"A,VSWrSAki;r<'_nj>'B4%O*TQo1D<"\8 A J;Db)5VXGp.JEDoU&cCGK8:DqAh'DJ-@Q@9QmL9"3Vb6-P!IVl_aXc_Y`6,d4W1#9P-[O^$-$XpP3a5TP9QapQA.3Y,>S\9VE-s%!'-:J3[>@E&RU!B^l`5[/]5NF#E)KN3iJDVli&(^APc=W;C\ts_-A DQI1G&DRaQ["gUk'[.-qf<_?7:DTEOcsA"WZVI!1DA?6jC*3"KF1dik<9ZsM!*!sIW9A]?1A3H`Ggn."5\R"m^cEO0nP`UXAT^:r@A=GtfQsYK QCrXn=HkrAMhY24e-qFNG/N(E?tFiAS>++fFKXh_MKkGI$_#BhA]fm7W7nL4b-3>dsLfceR=.-644QJa@%SREh[fB%lQ L2203F:Z[re0bL*j_M<nstP<:#;\VKQGLs'U:K]h&N[Vb4kQ&UYN,-D.[0S_cUkC4G1f70%nI%T&[rTG`WL'E`j:Tk.>qpjB.=$=)1F6rVgEehOOA?,8Q/AL@^'f.=D&;AFKtF1!qa38E_e4EY.Ul/.qMA-^'-L;nZ2+k_!s-*Z\f?P&D9e`+T?U;X%EpP)+m_e`WaKK*S:f%.L[9Fsng43neJVmSA5VhlEhYV<4Qk/0$?7?!OIH7/%T+k;h.d?e;,Hp,FMVjL*]ZBAjbHL8e<:)#m HZC<]:3D\!gsl P%%k+#`ep.P@V8@FE;89DnX/oW*/Qleh*]5O=#eQ,h)6^XMds1%Sc?s*DXTj/F" cJ=\WI%pj;dpFa2Dbs0!g-JcCql!(t61`Lgg s3U-4*:f)@SG&dS.P5i$9[T/^ATKIBllJS$Z9-_!Y7[/`<Ao\GJT>QWbd]X9K274$"[1K.<(j;7 h=::Sm_hEn>l;kaZAnVtEV/C*f^n&At1FDY4nqJ=f=( Jnro]cA&UqH`M+Id@9h7ABJ)2&6%@#bbRJG5reK9l3ndDB]KoBnB;)/t 7QPTpk@6g(?q,eF'"rBXXI_-LqfA/cYARq0Ot?ANt95D3*f>1e'#2o*D^->`HJ(@q5E ZE%&hM'okp0R\*\MAAMoAMje-0SAU)%$\&bJ]49!njTfPEA*?AS`%2ecd)A>j'@S(Sl8:@@?!]`;6o,$k#J,LI`T?.; DaUU9)#^nCkr,-I'/*g>QJ:Ol% [<1KRqcj"TD\'O&Y2<%X0(Am=7o#VXg[h9Y"@1tV5&#@--Sr.(QU.0nf]P,4MRAl7\_H7-f0 \M/l.UUg\t/jI:'Zs!r'a%^o[k8*/hA0g&Ht6L(^A6Z*l2HK$1*PAZCN5fM(G^nT\V^O";oobZb>;#1WeTQdB;9%t%E9PtXBsN'QkjAi_CK<1*do1HS$lVpatOaAWH4`.*)7mP%gFIAo:A37TFF?Deh)B-PF)QP<'8p>A-D)\GLG+o_>+O*YepW=P[b]n++Sbn)0J?@ehKoD?VSmHiK++E\;$,#?,j#Ks2a!c3_R=K-DJ7.N,8aJ(gIfsX3c2)r]W)=@e:!-CDW`AEM-UBa7/MCc\GVGa"C+pN=B6Tc)b-jcR)?`?ljG1'4XU/7j#qFqg8>@MmXD;,%mni&W6U-9%.#A#J1)j6S:qe:7HNrN9f00@"=@g+o'=bA(LB(#M2Q0#(15*,#hI=0ei7nsbYW?rl0Jh2_'m9.CLpb2f^DLI4'h;kDoen2D%[njMd*]Brq',GS%4Ti'&lri]L[^1,llHKBI#LA_]"5F,^ .G&,@/ATTj67<&QA;A\[C5bKT>p$*d"-I?X+RFd=Pcm8WOk-O(+j[0inG64`nWU)>UX2K+8r9]8s)NXL'5L)Tkn/i>P\UKVb H-#/$Rk`J%Sma#PO/=H+gBY"1PWQ]-$?O/Xn"k09lk-i+t$&aEV!:tgY?5>k?Q"f9#HmnZK!Tt$5Yck7V3c?ngJ7sn4L8'kW[U7CVAjhCb`F/Q<RU*3?kSQO83c!G]=76=C6OENoL"J>q/6rP6-eIQ[RNfOihrr%[ta3RXVhh2Nj4A2Wd&<;sYQZXpo+4Qgaocf]b 34B;59\?%Zp_8TBbO/`4g2lAm'H/2%9/;eP-0.U`[,SOYJ:SVE][itH,RW"PbZ!MgHV4%[&-9LQS^O\C?B_YL%W r1/\2l`r5r-eTKc7:jRFI[3k(Bdbk5$3E'NGeg#!Y),<%'`Q+$Zh>N! ?K0:2:H`P`H1mq9kG+',b]^`-TJ6!VDE kXq7ODPC'db<HTc8Y \?'3?CLLWB<58:Aa3G$!YP9>FaE6>YRi08]PTC*GQgeXpnS9djJ\/8B6\i^40"ZC=e[O:-^5'F#3B^MlD(j,SCA\OLt0@bK:_6]i^3/QrapY0OcsfO4F-h(n\FqE5JT[?s?qF._HG JiHBZ`;*b#m]=(2%96l#.!rYe4((6K>DN;40gp@=iV_4=@33s=!+%_Q"N.7W)Hb[_/Kfh_gAKBL*NtJ-_!U(ms5KnL`.37@`C"sO-R#rNf25)WKiB`CM'7FJ,!b9#&+:J-6pb52+F[XBQN4WZG1fJS!Z*s,JmA6[KV`g+q6pq4EAc*5!WA80f_Q[>0]2*[tA<G$Aci\tYO%Z?37[Xl-8)9(<'F7r'lO"^*"rf#h1Vi#6=TtDmi0@#5D3?=^Am`GiK"R:N7*]<"c4# ;gZsp:3<69dbiHc7CG=Gr1Kgr(rt$,e7;.(oA3C1AfXY`q6pO0%rB!M+a_AD4Pj46.O2mI@7n/Q<[@,n@t5C':,T?AN:^[P57m(nl+Ud4el*[,M2jn5!(?2'M\S*7n(EK$TqA?THdj*g"?.YM3F'\atVAkckL:E;CKEA0_!dMc3n)h\Or^A'YiLPW&I3=NL.Y+B@tATD6MJV]=j[F8N'W*nA'hWpm(^(,*p.[BYnF84Bk??ZfX7(/i3_Aj=fKl/N&#kIi8dIAM8Q5Z%.Q2A"KfX/or\San76C0)s&Dlc!MY_R+-f4A.H;'$H>os4rf+#>f;'9)t7KAqc4nj+cB9)%]UrV6P\pS abT$k>HB YaIYN]j3r[RM;I&#`T-ADV52bqOo->D'X,3R3:=f/$Le%Q#g7qb)2[]^mJ<7+%N%%!`#A'L!tQ-s?Ri??bX:etWR_)R:."<%g2VUQEe(&'H%/4k0eD,Q%g9+ %O9\0Jam:+d5.aE+):XrnrDCZ)J1MO&=)5G@`bQS[Hn#E)N_Y$j'^N[&!^N.KL!^YXKH6=JRr?)Qk$_c+N(38A=_BrTSJLh;s].,D^-)U]H!*80l@_XA]<'iCPF$#ZGM'2,JWo=MP'&Y?HlMKd;Q7L<1#U(3f%8"iSNFfh.iFXTSAJQFgYp6\B)[TI)]N\ZNti]8+$OKoF=eI"AhS.VcC?E+7I1IoFV+R`]dJqfrF#@?01]/QVYk!n2aiq3,RWOJ.d!VR&h.RRm5"C1-#hSAI1NdXhq'b.MAP#YF"Zs`R+Uq8tV[KQs!bOlAG35odc0aHh=3qirWAd"?Z6I^.4lb^XHM"'X4E=[YDbS%I9pR[.J"kY6H,)2^Gk-K9SiUN"o/S-;0_sgoNSsh+kp.GAX=J5,E>\l'$. LGU$=Q$Q..^_Y%gf5ft@6)hX;6SSVD(2ES,cA,i9;&9p;U`sirQZ[_n_QP/,lBIKpaEs9=#l+*n=cJ&3bto9DC9UN%ZWiW?l>TE26L`D%lcqQ:U_Cf*5d+3%Il0k9>Y7D[r`#pPm[8,.]EiKIIVY:jI*@tNioeS-plYcaZ3YKc^3rUr8kS$a1:Ulll&Kbcs8a)cCXO.n_/?DKneYMB_AlA"giW'AkkjhA$5#Fqo%4khT_2ABAA^QI 0JT>b/E`r!bNVVXXNG!.*]i!PVfh]MT q@rt@:%d3mG8*qq b<17hcTcU+Rk ]d#.Aj0:Sgh)R^:MN6o[R&2i,+GdVdj-0-QIngWG;N`$DBX]l)K0%n;3C)A6$N:Uqp^=2(XBb!]&AS;Y1-;)IAY(o*3,"JEAmOX O/R`(q>=0P(3`rSP?:`mR3N-#En].K6e/h>Qf6[>WT"*pK0=6cMAUgL/hR=e(%Gg"nED KptIn1S_8P(ab9M?RY#^]G\3s(^qcq-6E_K.]hRDiM"sEU\ UWV\4Q7h;[2V9Z+dj!(E+W/Fl//UFb\`QLN%>YdO90@4O96K;_:M/4)W*Kj2e,QZXo!Xq(l@6<'+L=c_?,B3VA2AS?AfU R`X js9,kLt3$GCS%21rQ9seO!e&@;3AVdl)&3s@HCfAj:H8l,UUE^*b!0Q-AL8l\:^#2+ $KLAh&@C[(Sit(tV27A*6rlR=>7>6dM5hHA8AXh](F(==jB"mT&mA],Z#nU(50e\=8lQj[Y3d\N/XQFsHs<bNM/_:Yd+-iY2O_$QG=EBqmg,[LGP[d0cAhd_aXZ]0+TYT4&`tY'*H)m!ZR[$T?^Vdp,RI;oJVfKp::cpH:\POOh>7Ye^I1aW_BoEl'B@cj'pk]]3EcShAoPXg7jqHI6!KlVl(kb1"]6W?7c>Gg!,;m4<]'.XQ[DcUA.9/UnWfWBf`-%DTS&g*O#NsfW9P#Ags_HW'$%0RpUZG&kK45VaCW@;7TSA4,[Zt,,-@b18*@BY< ,1.Z_nlhV;:SXo&TpqJGWb99j^lX^,qY>%dSGtf)M'FgMW,*c27@0]ACL4fH4HH4rejDXr_T@0IA+LW K2nA^0ZTG:[B.s5J`0 ih'!10=[:OtA*W>8Qin#'1K,OrS-,1GT!,5,+2EM("!k9RAD=M`+p";q!S76o79;Ii7g"WD^DOT$k4X7E&-mZj&GfkZa sl:G;(05#jSq1Fm"Ym9q 5K!U.G%_@Eh]=,M(c5G[+:l-/)U,)Sl*%A\$3rW$X;AOXhAX'sf*7DBTi>9skJ%GQiYSk');4L"tMK<\(HVF%E&,coajVoUP^V_T5?-!MIkCnGC-m(2`mBGWj7(5T?(9AQ )0tYgAo?&:U=Bm"7ia[?PC>0)_qWWUU>/jP(q)+OWn6LTW \gfa>^kXsO^qQlD33@qAUseAl> "FdoEpAY7jtf1mJNj0=!/sSpBU[Ghs\q4j0abhL,A"f,4U:]21a*5!N$p$&9 ]0A;EOf67e\04b.-+3d].\mAkfdhC=@.ZUgng!9dqF$7R;l7)&lE&mjN$/"E,MAsGAQY<4&AF'[s:lG JT&lO=[ck6$$TQl*B@ViB#gPRaNF:oKs?GHXm$91<\D+J#AScG\fPC_!D:5iHm0QoU3aUL? 3WB>`C]7QB]pQE,B#!]CGCK66p%EG6[8AW@"*Dm<8H2#(:Fgtae4#!&CAV*?!A,>/5j()QJid19Wap'025k,sB(-1NVt\KAlm;/6lnQ'=$EoDl(A!I^6?0JVOO@t5Xj6a]glpg`Kb$pAVC`$Z`%*t4Sr^+3%CT?H'Q8:_C9q$qeDB2G@&NAN?3"2ct2!R`J`_Rdk<[2?#'4I-&eWNbEcH5O^A<,45kbAJTng5cjY3a$@#"7D>DgbL_oY[>2N<37$)A1o52B\fR mdT>'igh2Ij)VtGBU\6;<?g$APIHf EQd)f%VgQ0 &cdkjm\W@4KrXW09na.=?s?6\fF8f#<A5dDVV:peYQf+2i`FH2l+5VNKe+JM2i>d6C"t`L5eqC[KAaP4XPLQKYB?Dhmo?,Ul3(f]AdVF6E,#4?N;@+d[fAH`GcpAl j %m>5q\/=_HrDnj(S=l)gqNXXt5i3tOl$/3P!5&dINtg7XbOR)ngTV^`f1!#/[-;Jp%Jf$@9VtfOQbhA%%AbJ-$@/Tgf#p9ndpjVhjT:L0e`lJABr5<-&Mo/+m9:.)>SZ*%LXfiJLOT2g)HM,+D[U=7hAO:oLej8=eg7#`TK/@FFm8/l M"oXQAgoEK(]IfTt16t]=Cc9t1RKc+1B9ZHU9B+Xi:j^Mdh;3QkL42'MUp$ke?IdFVP@'>-W[PqLNLQ>P[P8Y-,ZtJ.2rlLo:pb1AXoKt^Ql]OTo/5DMrp_DDiAi#Aj0];_#:9LB]2%Fd4ni(*BrD=7D*MfeX"aF*0o]Tb<4mN;!J"N#g.Z'8p>8AAqrY0< d*PTA_9JA6<^^cW(E2g_,.O]B8XRHc9 g_1A)f(*o^=.TQqIGp1>6[Hhbk"I"rJ'D3Gs2*IA*['9aiT%<#+UB@_Y!IL/`k: GSk7YW[">kK=YP[aj8^X<`&?;*189@+ 5A!';)=k!n@&>K 99BErIqF^-HYH(tsdRoAD,-B>2K]@SkUBhFWd7/7L>ABL-6[Ai_!!X9khq_IRcMM<_$/Y]rBa@t+ab/`maX2JBXqApHG[0>sq@o]A-"EY7f&\VPn)A(%H65WEo.?d>CJBMnB/sEDOU&6_OtY,.)QE?j-`;qF[MQN?[%l(8M6)6(50.^^!8!GPGer__c-dA:TU]Jd)K\ oC+,0tIjPR9:Y&jMEk+E'p Z?-S?>Mb6eb3(j[+8^-Il=2<#/OH2hT0k>Z0[[ssS% jc&jJDqIj05q 2H)_4:tIeX,9O#k<@3j_kI(\mG`MJRJ&lq6Rlbn(Z(iXCLs3W=D`7O=%qE/a3L@rF,2 LHMlOd/+O85Kf%FH:Z5th-l%DNoKcPk6qHA0 SR`ng%p*^tf^hl;pQaHdRsaNiPIa%H$Fj['!_2IARV6nks2EqA$2Fg)]/dGf?,7HMD)#;=[es(W=gOOrQc%Afp+'Mh<1#3mV71a0a`R(b0BEm%H1H-j-YNWd338:"\d khVYX$npa2m\'p,$/C/,iPijo\,'$+)$VA>fX(BI=5L$Aq9U3j6gQ#&A1,V]="AX["74tC$$h:@12L8BIYH#2`h>#p)8,PeYJR%Ji?f,8aH!N6oQ)I%_d[+0aE$a--fXo"o?P-J/5T4&& Q]@ZH<1hindE]&N?!fBjUs Nt6>.(*Il"`3bH2M;,X[_-tGAY-or<3jPBii^BRB6e\_]%/='Qm?YO=BmQ;\o>6CXb _jV-p9Gi32@">$<__8(mV-2onU;SI4D1 @+7H%d3Na;"0MRd( Ip'GR;Y9-U+%tN;VZVe!C ;DKo"FH69j$OM:8![&VrKWlmb`m )W_hT7m1Ki"lERR )P 7Roe/E5T+Yr6 aF/*4\VFg?),8H'0<19moRd.P:>;:37Eq)PLcE(m+c2_i`L9Et+a[%QA#dhT20^;fq4Pi.b+dYh.fnaQ`K&_s$;7+2DK=G2sBY=Q]D05AOSgkW;gMpJk]/^e_8Y'HTa@hQ_4 F4k[Q.X.gH9,Z]MBh:@O,%m1<&&%q87meWipq8,BTSRh1jn2Tg]tJPjU4(J]$PGCb!jCYjt(=e51DQ:%4ce_e#61K!brrMtO0K^)Uc+qA:"bj:P0d-9HL2oj%72HJGJ^@Q)m7A(eMC"AM3CHg-@6plUUiJ-$M]0V!>^E?\M`Apcf&@YKq33(Xm]O`:ARIe@QAfsF!.QnrZ1"11A;ioWci%j3rETcn.?8[-b!^Am39b''D _kt,;D&^\moFpEbaFQk.iL0gsh!7`g=!=Z2mIS/Xi%A,sJQnE^o"642#0$%?"&5of9d<..7 $![*BQ#DhFerH@#oL*K2[oPr=8.pr>,Y%l=Aqar\;_UVZ]YBDO[IjF*M^YB;>ecZ@OO`!t#!jV7C%;bAtf%:gnfgDhkb"B=_pYmF6%WE@_2gV9-+<$cCNL]oAaM&5)m.GrSno/+>Q:^f&POh#KblmSf`3WtZo8.\TS[.6GLB+a6"%m3m38>n@KU\K90Aqn5j+,`"\F9Ya%\@qpK=Sa<T!33fYi=[2jmA,/$ r0a.C".=aZK@q$$ Ecg_kl.5^Q'Se;=/UT.age >g3km P9- 2,^RpC[q?9r[:m GcQJ/.M$OO&b.r! /X b.[_\moe/C-kSpon'7eK.g\Apt]612!=B7BS+)h*MY.9Y5Nq'5l\?%6[Np&!o\7!B)6]O#nDP,MJ-/F4PKCL46[EXg->I`nje*+1EJQ4_Z!W?98AD0t">@J1S4" 6DnV-?T*r"MH`!$Ec6VU)2gH##7P !/.Z';K8R1Ns/$0A10KQ9RTd/nel7AndJRfEAf24+#[C/c,WeEn4/Ws ALN+QJ!Q5;ib-Ucl5>O\%0//.fFi\S,c)%,K!,Y_6n0^nD5k\;nmbSLf_l <Yf.cs"o#gAZhK'SBW1-'&q:@-p65!GQ_&Uo!mN:kRl\=8_8HQLX1TaOANa/?(8NtU#i<^T!&ABOS9:^:PULc"ghLa6<9ms-QL'E0UWUbYIQ<.hIbP]JA8qgb17+l)shX(Lt8D.8?d+tq$Ym3bGk9Ng(Jq nOlf=C#O9+Q:k^cE=,]+c^T2UY$GmPqRK:1qdH&eH\b%N#0d#%P=%5Y@pUa(m3J=^.OU97naP_H^Q6=X5VgnEB\Rc\R]_rPPF +CjPJNLVfJ(^M9:L>C:RaAblU+[7UAfQHWP+q.`rT,PLWD)<8PB LH@<*lanqM=l/.\OkXJEFFV0tA#2'o,Bt7#PZ:bb3q0To=)S%N&rL30f.Id4o,3Ie1Vt= '^'3'^i9psXE\M"MS\,?S-Z nG8[C&V5TMabH4XVi9Gb.GMCP"D*ma7(#;nIn(WfG*hp;_2HsUF#GUd#=&7XL`[sVMi%j2)/-:->AUAHiQE"GXQfp5Z^@TKQ)YJ3E,)!AFb\IW#ETD$NZ(<;)L4D#Lofa=)(G7QR MNZ'[)?*"K f3teIhHA&A+Z;gN(2Db^A,M9Ak7 92o5EOtEhe%H4AC">Bob^kO_ o2)`2'1Y81je?]k_Pn]cY&sg\pb?c]"_ERiNa(5Ih$?aj`>or.b 9ef3`lX+^WpEDP"sAK7E`R?t*R]""hf\a.5ch9@FNE/k`-d$lO4,S"PLKkFo6pmpNX?-!.fN,?rMeIA5;^:m5AKA3h=<m6>XqIRgrkS!XW/W]RtKDUVtY?/Hg% ^A_#tU`%HI7`O;:=fi;CO]t&+=cWkkO= qW<&>Gn4DbX%WG^@LMiOA:DM?F_noP0[ti4p=eb=jUlQr-%?=tI_*h;j,FGg6n'[1+/YL2e%XQ%5Za?H1 FijKT=bQnh)Y,L5jJ'i(CiWe@k V3I(3\..UG^D,1c$8'^E"d1&OPb3+b;9'"4XIGCYW"3rc@7dn!lHr2NVI#-@GlePX,B^-/%GM_?AWi>=UO42JZtbN[=hB:__5lCt+\W_,4ABdQ,*aU V]ZJ8>7g\=L>KWe>'!C?6+Z)-0jRE&CA-Rps5K(70Sl1roE&LBrla.XhSmI\UtL1mcQ8be+cl4S+-aTsWbdr#fJIVl37Ap$.$"jJ;B'nQGQWIXlTh:(\9L1\kq'h3B9nm5h?D0F6"mHe:8WfR,:FZ`?B:Ls;/A *\FIk_&W!4'B[q=eqCG O74/*A)T;>1s$\fnot$3M/YYiY]U*S2808n3Qfk!F=@lZ=D(\N6ZeFj+6"g!$.Q,J*0,IO@Xc0m+/P )6J-K_8@A,(]XdT]DQ5NdUq)2]a ARkg"jCl.Chf?;X+#Pf4UtXtT_%I$L7&;t.4dr3A^eWFCM(l0]BHnG"r<_ ]3+&RcIbb4/sFEg=Jlo ZO+@;_]qG09Pf/iN+o*njqQ*]V6NkkH=o).iL/N(eaS[;Fm37b]/hhD9e)Akf;iWg:Y@#=RI`ke$N(M8/Vh[ih9YeB/kE/]6ISo:h>t4PVNP#d/I0jN]q0-]U0)5RK/B8E\ D6.O$J"^tm">HrScj`3pl/G<h+mG%\Ki2JHQ[&VaN/R2qUiXES^'\*L5AIV9;I/Kj>@m[_tl7LZ"K_V*9_:toSt`Jb&HKZ59Jd)M.U=2L*MK#RK]D+k_1O \rN$SjGgbPH6c4q&940efHh`_6pfr<`;mZ!+'%QF #Z"NL;b2tObIKb,oX_<]5?L:4H@.:^?Yr1N0XKrflHFe08O8iAoC&%_]5 rGLQ:;+];W-d5Xd\m@cMfo]n$$nbFR$D=!*sFI9g=t:UA9pGhX;Z_"G-j[XieTA@N8=8)$VV R#seSQ/-OO1g@ho:05*ZgY?=F$L$8FZ7isK[`M[P"#r9.8ij22-VnZmCmT;Zkg]fT_D= kCt`_MU#4HfD)7#QWf8 nfIKPKFK$lS=$n!\5YB)*/2<)1iAU2"8;OGU*M*j%A `i?USbJHUGmrenT3\=<k-J23`n `r\71d3Z3qp<;*oA2Vh,rd2A5/0%BM18]8j_!QkDN#6oTX?E9E?bcPpA$A*VO!nd3?Apg60\[o"++YAJEYigSs'(p9adY[0>#]A3NM$AnIAo J9E];p^10fG?g./pNe&$.o>&o>1eI/e &n^0m'Jc8eYdG*AX4lLWg9eAJ/d5;Kh-T'O%I\0)\("66bIG"5+2D@,C*tf#)_]ElQom_j%%ndqP2i]esMMcetM<`?5+P>K\?9?A=$*OQ#UA]\b[o+diY#>"0g8S]475sOa,-^)"nRcF+)ALo_FpEA,+/j/5!/4pR l<^g,NCj)eD]OW,-T93p+T<*e++H.#Y=/HAmhBtKs!7jc`pf6kV1aEA( 5B]9KBeVop.NV(:%GT.b.Fe`RcrX$-]aYZn$m@4t`7n[GVNm=i`0sP_$[;,2q=_4QW @bTWV`dCb8<^hcrBaqNB59ERMDEP[ps"4lRM0R<50k>osK$U0s's3A_n`1]6igsA1W1PiqsF3X'ccZ/9AO,YBP%m]q7N&+Vbcbr8_b7X8&n<3mbD/."]38%>p=Y!s1PhSV5ld+qO2oK/t"D2mgS)r="TmFF0^5 49)qG-GBn/k X`[J,nI/.>Wf,Cm'mI7B9\PX=.J]00CBkj)IoSG%isn6.K`cS4.rX-c#`.IPfP:I2Zo3'F5Ybo7Q4.24%+:1Z#CiiK(Mf9,>VBh'qphp%]56afof\X;UXnqL5&qT*f?%g2RT5AL R $j!.baUTI57,H7"[m:A0g;KjN,g9X%4bZl,f=nQ6.r;$'2=('\pb5&1hAfB"A1!F2!Ig>M5`Si;dk' Larm2<:[GRk%D6WCL_%K*to=+]RhCCqb(\EZE#.XU\geYpA]Q-S\Z24Pf(.FI9NopAptQ_94Fm#:kFBj;DW'K$a3tAnF3#oY<%EEiskpRq-"q_sPeHPIZ]O7E5E40TMV q3kU MNVRlRYRWI?tLlsb!A&-ZQ2Q0:j'AnA^NC*_N#Knf%+RO6EWS5b&s+hp9n7Jjt`NBHoTa5>*$C=q5=Zt[*jhRQRYX^#NaPfE;WB>NYk'PELnsn5.a N(8QWAa@VpQYUMO."U_U'j7XFVr]T ?Pk[HDbi6$Y8)8Jm8ahPI^3]$lLeRte_fA7VA.._H-GcAtMsC%$k&Er5QY>] $eLqENb)rRA&]"L^!0p dUK!l1NUh9N\@1rS1MiGSN4r&B\Y59U38)E+C:[(=bi)ieLR?jTRY;6,f%A#^(qC%j&2:[bDN:o*thZI,HHk7`?o'WbA=$TfEnGj3&^@<MrOK8LZsF/ie %+87>agOQJcpQ-[)W?IgsXO4Yl0h;fnKaDU5oI&FdiOeC$S2=p\SPR2C.pdn M[.65Y:b",dsJQ;acF=pP P)Q=OZ3N3@kMp\GdI4a7DUF-\r=^^jJcK.V26Ul#2>=A260Y8P&,g&aYR^fIh(rV5dRt;IcInk8E\Va:++%D<+1ETI>_:#"mjF/k(SYr0 +-@.+mWLM\=p)%XBFN/#Ao5MX7>$BFYkq`<7O9[;nXPLO)Fm$h!)[O6V(/hraN_=1m4o1q6benTM+U-FWJSEtI$&UKQ69cA;Cf5qOaE\A$B$0W'ns/F1lJ3]sl"q`T#b)o6@CGfs3N+i#R@*dsA;bicGN3I`ABl0pN1[UA0HKOa(RKdS,>o`R>?r-D'hWG]iTIAA&GJ_T)!`0I$Qe9MH[]3Ar33D4nd5(g><^5 H8-U_0 5c')PJdA73oOW?I],hh3C1.m3Z?:AcWU=p&7P!<^>Es_NeEiN-!$S1=r6/4WA@`LamN!o7>Am%Z@"\fn*O8IqFGp3fr6SGN*6BC/`R?> bt\R3+3K`2"C&AbU?>pk4]+MjSTrHs(F-Y.S4[9[ZL\@$IIB[W, 5.AWBXqJ9`,9 /k2)G PXeir$/jEdp^rdN&A JfUa(;<6\4/`_^OkN91CJ*dc#bjc^31p*Idd@hkSj3)Ft^P"oI*Rf%OlZI8n):UC`R9M%Yd$>"]25-_,o9"[bNAm7!@4HeP/9@O>rR]HGHhJmqr$Wnh@:Uc6\9.bB7/-QN,3le@Zk.T"#O#;g8[lU&3J>U^G;emN)b7gHi*^i,h(^I6riL0q>V6%ON$[5 VU#k#O&KGXUBAoi":>TKBbOld8Cp7Z*QedV!)qEp;GeRmL#0L1t)Bg*SEp9ZFWDZ!pof[[tfifAtE'[_M2ODcYe8G-QP\%`JimAQM'2=bQhXtt.=]a\17:QZ]>^[KgnAgU=HPk0\Jl2\L7=c`E.=*?kij%`@&C6fFG73qHg$%KAP6r4CFOi;7G^Y`3i[2Y>Ub&rLr7mp1>Y,F"]_0G!b*/(rC$Lk5F%`'BHD%AU-s%oSq[Ti-#[&^0Hr^j4b^+d@1)J'onFnf"KL5;Ar=Eo>,"#>TGm_(Z\/M>JXZn!-i,;&[Tg\`TqnFRTTAR[7%@_C^kA_nfNXs's!f*G;-ZW=,/%mfR?p70-Q-iA`"Z4:qM0SX?tB?ao1,O%ZS4aTe4[_(P6*g&7,DPj%DKp]oDtlZn9sgcK&jaFE`TjQ[B]05&\E^n4@e*hA]ZnnhoEA.sX\MJ%aNJ]NQB3WH]`[6d!$[m X ?XZmc41Hj3A`gd\,XKf#X)oCp7pgFt*OtSUEe>SdPD`.X;b)JaNA\^n$Hqq^Mh3_r?+eHn,8$5)cDH)M-!eWgOZ(]mlh`AJ^,tDp/$$J&;pH\%^\Y[API^i+AHK/i,3?26(PW55Hd0RC0VVPF?@Af?AViM.k brkN5LA3M?g_dD+(b8.tq,2S"F* Xtj.VbXlpKtTmP,mHh`)HLeXP#tpcBeZg-K)tlqbaXl'!E9%Ejo9P?0<=T;,ANC"5Bn#^H]?-d9!Se'+mp&o6YR(m25k2Rf@`CFUD[kdAQtj'I%NmQ/`W,BFdMG;;P%XaZN@D_.TTS5KfG3W]br<.]YjY'k.V+O#[0l1O &#g6C5AM(#_I.*\F.No3^C#s6][S8\MYs[iG2I2dPPG]W5JAVklQg_EG25j7`I'(jKo'IQ?0D]L#X,pf6=-RSB9j),A@6.+@#EM(_esBY)5>PX^L]&F"fgaFS]2TBfVJ*BEc9@>K%D#:>Hk9R#n8Hj;n8F]:;Et8UD)ArC:15Q0+1snt3Dj&\P.<q6r-@S%abjA)K6qe*+\#tIlsb=DQjS=.[[OD;&k;T70#&X$'A,>W/bPTOr&dUS..Z1GQK*KA(X%%$k/md0ZmN+E21iLMiJK'GFdS'@5L5!$j!JD#hJ>9s#UsqU':$(#)!NoWq*k$=hsXj=n`,AA6AAP"]Ak*5_P>0.VRZcP.A?0]$^P.94Xps^Me753/ONH_i*`*7oG)l!g8CGG%=1-fH^BIU_t\#?Fs);Gf('Xbae<<=:l)j#h\e;rY.ZU#F!N-:o.1-<$Qk. /M!rbGAc&r%=Vj&_,i-+M-"G]fX@1Aj#j7J+$/5hfbHUOA>bmb(7]@+jYCNCg>B>9M;0#rCq5oZ]r9@hb$e$R:P"+2D,'J '"ps:gb'TGEc@'t;"4DJ^k6aM-)(E*pScW4dAq%?Yr^,[!`.FW3q?^6aF40AYUWn,GM$Q3ZN.a2Oi).1P$>s008oRAV$XmF(!X:HeF:EJ`E$tnj,RSAR(`(Z_2"=A,)WE(j65.=r-3t&6b4[>/EQ5Iii1OBA:o;''k6q3W$N"+DnJgNKN^2%:[Zk="Xpn[f@7#GLKdFi<[>ZO"Y@ 7R#Vn5DNP]kl.6?QX<]JJ>"U(G>6;TV,'>X`N/>^<6e]Y=rEG/maO*SWSH5cMYhpfT:%TC3TAgm[aO&f2R"WSX39mtB)ED:`;-;W*7?*Oa6_I0YY[HPeFAsQ'A"5s_f'H^%BUN]1f\] ?p9LX+lWWreE"PZ].Ef7Qe2P?s6-^$t&'T&[0,EaBKthk\9*AlDW$s)CS[Qlib6-r[q@UshcoJBUc7ndrtbQPM2K#CBm6SI,i&A5:]>C +4_ZC#R%:mKOq0$FmMCUeP!Hg^Jr8P:% ?e%Jq19AG.\OAbFGV*\B9Y.?j98=S=bJQVrOjV&hHGTf+kj6@%%l$El[B-U85[bg""pjC6;r4Ya[dN`#[N/$1\YfI*l:DiL%?#N`9AHh6A2rLr(Vhc$[Z*C^U?SM1I86hto\\Tb6@UsglAIo%L\"lbh>h]G8/s+4)a *4olRYgfXB,!]:BDb=DA)ICp#)6c!BZ\])'K>PAX$,'0]5^E-ZI>MGac F)Jp9mi=rhr"%n[W*BMPIHkU"_:]Y?P*\N]AfdGkR?HEoOn&Ge9)BkUjH ENcm,MV:EP?QB>0B!SCDoBWb%I[A"8A7Ii5A2A)>e;ViJ#bC1XQ.g9jqLAO$nQe'g@ISjnFkg\t\Q^EVg:e(XaU-AT2,Xe.%D-g`W$PFDP7c_C1ln8Ui]pp@U*/2)'lc3Q>J$_5Nl%.a.=1<<46LR:WBdA2ETem5-^'p[6G_n;\gN=)N@E0DP>kfn!_46eMq`2Di4(K;+1G,X*!KZ'&(Gs6IdK_c<4n)p'gP.K!hp%g2+'pAHPdX.kq4.H10aO($ns)&JtK:2?^X=L$T!nd`:oHb$,O/$PM1 hGkFY5mi"^ZHKFN<0*\0rkWB[()Fg.1'^8pd#G`sA!X'r,o0[eiF^CM%G0pmYKKHg%gIWJ I1']6cLlFKg5nW:&:ofb+Ejk&naPs3iQBTG7H`.UDg;n'<38XtqH6-NX!5rG*h`n>r@'`.c9&F"eG+A?3G![`;O%*LiB;koOJt3a,\aG9L??iGc?RF,Y9)FH 19=WQT0W_bU -:J/!3Q(R5f! gD9&5HK,$B=d)1i-#,bT9Me9+PEY4*#Lo#bK6(ADp+_8MLO0!R/esc`#W/,ksGpTGJd1k0Zl8dk"LrEPI;`VfF"&]`bl<$9A`NPBAqEV91:IH4-mH-b$?W7oHKX.07\hlj]G`&QBi 4R@+l16$ T&P7KhnF_LKNG;DtSR&ch&;j$&828OT==(BMt,/WGBil%iW*j,HZ=HRO.TSV7m`>kbWTo9P$;l#2;spkK\j>E3?h-ZpNH!:&50TC]\&0-%hiHeZf4j<39n1e_Bl^+JhkBJA? DAatMI%1rZ(YF C_c!2D+_`t+kAFF=9@S)fjBPD8L]Oj6%J"5A S`4(OidbFqk",r-O N^g9j$C7Io9^!]KZk"s:m#90bM]D5E)js"Qa9+lk'Xb+ONY=,(-1 4aA6OgC(qdOV^"N] $AhU-9&2Kd;^UM9K`7$6.W3F1Fc\sp]/%]rG-Fk-(jj1qNr,5 5QqnA]@A[Nt/&0U1?eA?A[r6&Bk3,DjS17B@g4o[6Z3lAT>PXK"MG1fl`U27L-7IRk-//*\ k+6OJC1M;X:XY?s9-VjH*AOQ%QGK#o]bm$,`hQN&$0QF_.-(2`$"cbE0jQrH7pWZ99Z#%]*s&i/ctQ?r\9K%gjYMg!ZB48"q/q+n.fW6'*`0D3]gGFQj-B2X`&e&*Md%lgf-2:>lk1AH7h5>6pL3p"PSO)^)!=/?7(S:5%fpb<.]"!frm;o5/.qtpr4G,=Et+A"-_VS:Q2Ph&A#?p*FVUi9OPj)sYJK/d#Pj6ZU =gXMCK?h$WTY:#JjN=AA]K.dZY,B;AGO56C(c'g]$P-(\/DF*X"/jl96JA+gJn>l;]RdWp6jH#pNdt'1U7^4qgNl7K#O;PA&\;1a/s*,PmG$BZj6L,5+dO^Hq($;\je4;`5`D<"Y0-[o1_6\r.AF.emOM71,=T])=4RlPMa5g6.)mheX*t6)M7cVKQ8LV!BEd$R<. h2GqHFC0Ns+s?JYeXAt"C=H(apc;]J0pAnML& $Ma55qhEp&k=:9n7mPTOA7P8rS_E%an7;M^(:aY,D`U?3YH*^Zh)^na=bkW@JOo&f?E\qNC+Z(ck7%Z/r8F]c]M/si't?:2I@;o2?FT8O1,iGhM9Lc/^EB5lUKa-Ilj_f'b?KH6U)A&A:YnG.k8;.gc#iYhU/5PKO*2CkC)A=Wm9hAF[I?7rA=J;Mjb'9n-nQ7c?_Q/$L[VOe^_q;%%t)@\A;G&r3E1-Ce6hG(sYt9)qtJhs!gjpPa5H=Y^sj`7M:3l')69]7h/>Oo !E]7oAFhAf]O h<=)V+74ipr4'OWir3bB(rp](X@B9(j>O)&UV29,=r`\E\pgD6aLVO@4]p=QrA^d"48KtpS=JAXLU'U)FVN4mQ2helEl]%kf L/aPr4R57HoT+(JOA?Of>:BQ_fEV==N#Y=D-!jeEcm"U,a7HE!AI#Ap=c=p!?jq8rl("H/m*:3iN*+YI"cm?&!;ESGIao< +`8Uj!FAiL+r+lD(oh(\G\U<-mb>Zso$QRskn#&=QLl+)M\&D,mmcP(G.V@Q&\l6]%WSNUaJ1\EV+-Mo,H)f0c<Z$>@?=/-?hU\8n T8 9o4M.!^]X%i5VV7kL[l$UT4?D!aJH!:Lp`MgXJE_2LYVSA0s%P-a0[p596d%s %V!@0t5O#e(+ `E@" X[B >tQ>ai%n/D=:Oi&@%,Va'npZ so4N$!)k,_h4mpg ClW+6jrf^rt@\7:L0AUVG6j30g+Dmda`I*AcG[r-J^]S5ER:L ([\ 'Oj^$!PT^/K%qWl&^VLV@'Zq`WcbF+tL`M E#RJfj27.I$rC_hh.W==$s>Wo^8U<`3p'\)>6#:Kmt[IS;/FA1c3MOO;15qR\k%b74fT`^j8NQ]kbs%N.5k2))oGJ]GVe\gY">Cj+cc^:RgbqaGOG7*aPjU=4I1h8%Ym&)O/^UdMO]s_i4aCp&:Z8C2`R2BDAj['ZE(bY 423me^/KaMH04tC(Q>3 V fiIpUX>EKdp_.bCc2AWW\Tk>?KA-Z&jX$iQ/*iZO#HFd1:SrVX#E[ZkG.3hbt@*r44i4&XC/K]9%?Hs3caUV+&fIqI21*h4nnW4tVD&tVK44p];U,Y;LsLM8&>4l3r.:'YiW>)q2=K^!3h9O29F_m40jW7Bi##fM1^DnJ5oWrN_O:d;&SX=e=Erqo;JHn\o9CD00qVpT4IjMA`r1')8JY,(p8d5FAb1ERtAsArdH+)1!>c/As.1Af4q,Ads//k1^V%4q1htP*"KAAU$:8Tl#Xp' SY7!a0h)GrV2.g'JmbYRLO)LRA<4b>"`LY([l!QIeWG; gd,hdog "Y`#g+M:b_O0"\.f9E"1'O*o'eML4nD@:ARo5/G>7[rpTP\i:7 tU!rb#sBA4EEN)o)Ni[ ;2/-_A>F%U)GMj c[_s18UoP6k-A-t@"aN/KX9cA'Bp'hAc3Zp'i.O(iH=o4b5JRt6&`C\RE8D<.*KA_2fRf-IR?<aDo#7oeI+ @cbq@6QnaPeG+q@RXQSS,A2]J:ce.[VMq-8H$dJ2?YPGfr,$a6gXYkkZKCoEYMCe*HFbQCgYn$GfFr6ELPGH=QF7g%p;aj)dPeUmISchF\"]6P'FAH0f7iDjao-n'[qXI"PT4la?DUfc9k?'m.-N\i_:dC6/'UfH8BSZ!rAAd/+58iD,\I;#"kZ-NoUr$*li&@'0d W'RnmA%&+R^lS]WQABo2P3P^#>;>N;G2K-fTeXB%;%8fn;A,Q%%ns?><8o *QJF]rt7:1#[loX+;0\@"RL&[*9+.d^2Oa+2cc<d?\&kY;#g&CC`ik)@6F&mP/(#7>$(O>kMPCp3&$1aAV&(-aL^I$QM6?5UnJ"@]_Vs dBbJl_681=,g7pNAcVD@6MFFR+p=Na^QKhb5" m)1P&9d](6!0QB;@ZNN"[^RIGq?dteA/H&Wg?!NmJj)n9j?;Xrn)A.G000"[?bIi982-n6rAf`gnb]Li9_pD_00p\O!VJD#RJ:SM7,.OBk$a+/%ehlgR/`-a,3Dl[6U437I(g-dFm?3a,"0WAS`MSdckj;^91A,DS_jlfSnr'NBPn9An^:<>2,tT%e2IF?MH:%T:om3@b-H's/A8hT+",Ho@<0.:MHts;XK](7P9ro#NaFHsR6n#Sgd#56*RM+t95gWAo6;/RK5Z\\kSam[(9@)/;_!H]eXco]q3+hUF Op8eZt4 `OKe+LDOF]qTMDnY9!M@Fo_i2LFLsTlnM@cqcl(t*a/Sd$Vl@8Jj;a*@diN/...8;bboWLH ";eFtsQ3!S/U;]UA_n@+n2://?H"OZg!t/8BY18p7HCLq,]h/O$M^XNV[]B$!2mKZ&Dp#0dPk1lc\9`"OC!j^ KqIoc#/s\GAfsW18)-XA8fkOT7W;_BJGar%p`pQGl->3%W;3kb`NBh;jlPKtiT?opK"Z)m#(?2jYIt;c_Gi=m)noCh3nM,MURUo'"-A@Q$E!/YanjTG)F'>lV I!6D:6iX]8;[">h:$aQZt[I8J5b5ha'':)oK';Ah",Zk)mj)$IJ]53kP\9%bPcf2q1>J q;4c/b7U 3]5<Ji*PH&"e!2&i%s,PV&:+mM&gT^osaiZ BA6 jIsjqOJs[*'2pJWZ2?!MPBB[No_QWpD*8=41&0ikriorRAi3[QaID5ki5@SIKL-P7`a h9FWc./jQndQ3gC&mb&>EHe(m;rHk*JWSC `[`6o'U#MGFW+=#%]>gYQda..\Uai?714@2"n`26b5N]AKfOa"@himgc:Cf-?$K3*Na%'2P$R)OmJ48%&[i6c?+#f4@t?A!jBGktEl?gF^"=rbPBle;s0WfFpiWKpOO;#/5`\Qnghr'\0&QMbrZYB2nrrB"E?n9@F;/:;!H:/a5`YB4"L%+ Vs)6n^F'R\fA(C^n3f:AM"`+!#Pr*!k='5ZS'<lt8a0qpkHDcUiL')5+0S6>Ka-B!S]7\]W5DnaQZLXfeT0+l:PR6l[ZhB<6p2m#$XUl4K=-00dVAat_b371"\eYVPe+kK'?gFA9T;PAG5SFqN%;Jl.&FP&G?KG?`X,hdZQr"3)D#.ZrP&"eFHP4\>,>A9e_M@,51:Oc6,Z*`m?k]Ej@9B/l1e[/NSA#/PDK`+R^Z0:[$_9=1R,$!PhSOY_#c0\<;"J$tt:>s.0Vn\L.V07Han]b4!Ti"d,M%5)AC(8JohVLR5qJkkhB 1 4h:t()$A0d4>=k`nS$<^*T`,?-#4Lb/A/HC7Jfnt$Ys;@p6%%ofb1eg1d*[Ob%,S?DP#"[2Vt3,D[A'')R>XQief!P!GT>PaSE4cD&5d2D B=1b-*9`kAinr6pYq7QA']!%JA\b;QE&-B%76m*3T 1d[lW@nf(o(264V s];P]5A=;Ad#a2BsM1>oF^A+ 0fTQg]\ofTp`<&_e[A>YYFAo7b%#?\QUVS]l^AQ7@a2>WDBm&T)[CkA)H>h7q(m4)-Ilf6Ah%*rZ&Od!"no"AFLQFg\]ODV+j+_/Y#%c7fLZHD*USnfmKn=W+J%Y>\$H]]a&eIRgLgm36@KthJp)6^6r:AcJjicCR+dJZ)8AmNFH^MkSoG9G72Wq"oRn8bM+4Sj0Drg&)b<9s>+SJ:H!+B:.R$rCl%@r*8VGd7lmX[/Bp(\nhtU9No7OG%Z.n%!t40&=RA);(h&2re#QVjaI">Ie+&DpW"%44A@l$_?P*S.q#Kp;-?\1<n0S,C+^h;RfAG;@KdcrCfFcYOl3+DW!+89kD$>`((G9c\?G(O%^A6I1(%j"6_;(h-oS05i*]PVsl!B1bGr+,#F9B"Trdq2\#rXiV>&q8BTf8)ZPl`P[0dd&chG=?GiW-LC80L`6GP8/sf:S\/7CJ_,`sU!VeToliSQ4)oN,E2CjEt96D'A'$Jf_GHlPW05caah,O.?AjL3EcW0 U7,qU-E!pKce(2/0`8"77bgBQ*"q2Gh.+[@.E"tn=X0[h%CU1g?Bk&,>2d7nS5qtU!%?b:3<7O[!Ym;Ws&F.bq$$8V/-@D38X*<\46*T VX7rg$cCG?#W9 =CEi(:AYk38OAHBbo@6gPSM\)FF29a!l6U9A9iFq..l=45o23O-Y"ql1KW?!;O=7TFBdokoT5s(XkbBoRGs7pZ[s]k;;'`i*2olK%K6=]eapN&*G/A30`..,U+_n+;Qai_1\t[4%iXHT''ABsqHAWO4c7(!sY7@DAt>rS^`LJKmC)62:KCh!L>1>M0Zplodd..Kd9 U^c=h)_c0->jP=W+9Ip=c3q]Vo93^ZMQOG:!#ikFbN[dV0*+sK]A"q^V?e2?YbA;()aF5od-c;Uj:(.d/$C=\o-lHB)4+0KiAr`>Y%A$A47US3H9Ml!/i1I=&!Gsn4T6qY/N1Qio+m$p9'F:VhR q&B>XDo6'$>e6pdh*WYB7[5`k^"HtY)0?V]2_>BWto!K599ds]mUt,1KOt=3B!lcQ'E,>I"A?O`@9qMec$5$U-5\3pE:TQ7F9+]!"p`K=ek@>,dC#O/$8BpkYbVL\*6Wi8f2o,;VLS@RHr(]NkRQnk?8IL0oKLj'*N\Vrq:AN)aZ!"i;e(D(`*F:_.$f',ZEg]NdGT*S.:A6PkGf0?/@dmLP^A) Jh3rjQ0-kZ@OA^T41[DLG)O0Jtg'A#G+c2^X>l8g]1A\lB*)c&bnG8imS[ocBS.AXL%K^ .*L2`,CUAE.'DkbK4LZ_@)4MZS:Wlk('RHFUO&WsM;tK5fL5dm<-G_tmh><M48CSG#aDd =eP*OC;Sr6-64e74'>aA/"Rn>e-@cKaUr#`D"A%Bp2)>#0 Y-=s-jr:ita j_jD`jN+i(GL@)Cm%o@Afc`c$66HAt[k5gOGJt-=tA9q;%*^5$1[C24!O=7p0LB8c6EQ:bpii++fSJsNl3$mN#K[2eL#%d>c<39pV55VfO? t5a5 >+g-X9Yc=es5sI-ts)A9R5TqE?/<M.C8Zl ^n"s`BDQp*W@oVW;]I'.h/b1:4!=.W%/01LcYF7=Um1(.GNWiH:Kp?Ch12Bg[5M`,TTE5TN\pba^I;oM2Z*KqR@#RqN\;Cb99`H0d5^K*=fJ<]%Sd>i1hpA>313bbb#MCtA</sM^aXko^.Z7+VJ+(EYJgJ;j*\%5@13(Wd^;PcjC44A  I$8,VM>Eg2T*ancMc.8]W(7%'g.#VpQC!2AZ(0oW12mIhnJ-G]D;Q6OF(eon*,UL_H'UE 4Y? 1?_,2ia$K^X?R hhS3!R5BC,T>@#rs1 gF*lPf8,*cCi:nAaE%*,qP_ofK]hZ@>cQ?A;,EH7fU]GR2p25#UA$.oE5/ETshg=9Vk_;RC#<^nK?)PKL(YCWdtBChB*T>[%;/@Rq[Alea)>Ib^QrKHG2KcbE0mD&/'eS*tX&\8+U,Q#Zm_`8?%In$FLme]D% ()6TEs4q.E.\S$= 7iO_5W?K\UA2:WSgk?-p@=SQU#E/1!4.@--8IW]kLr"j;$TCUr,R,s7OlD-(o#dlEef9VK?'53Xq]/3-s!3B?ZOk&d'a*X1TRs$(?O`DTmX3mPX,>=,![AO/gEO^,W^00>Aq\)M=a3:U`AVleR6-Y[4qdj1Nl,gEDi']t&><6n0#)'Z0Ci.pZY$d1A4E?FrX9Blka%LHWMd ilA@#'i'db3# ]+Mf4VRQn6'nXg#E)I(8<5I&(lT5Y$1s.5[0tYd]IbLkgGlt%?^MHq!k!h'FP18>%"oqn+V?WXAK,6JP\KYb5jIJZAG 7F"0a'"A"g<61lB:'^;idCr*82Z>MEOCeHqH^Se6;OgKSWR]"Kji7'1:VI)AC"nA7mhWM*okf"4,G7hm:c6B&$3CM.8fIbb[kPX',j^&K6"IoHXPQgY>@E=HE0-$10tpQ mXol_g,-rmo11C4F3b8t;@JINZ.t#TT7eG.+CjQ&NN)IqI3hE6EF'h)!f6spqV,fm4`Hirb'7+pr8Y,NqR^eF_23mt@C3@MGAHm0d;3rY&+tsK(BK30:V]"gTpI=$ms8j*+qddro#A(Y64/i!F2PA3<9/WQX?l6QV^V&)m!C]F$@ 468?JD8p``2c.;]3mkp)Bl'X2PpYSi+[t<UF\X)=EGfr K?A/;Dgq)qD4.4c)7Y&PKg>Es^%2h ,)YbjfMA5:dYE'1)rb]]/j1?:Iq37N8f.>+UQ "f5qFFYloKPQ`I#0ZFLrgQ1WQ\:)L-6\$Q1UDgI!d,_#),YE90K^EY0*0saQnl48<1`(@3L%LshoA?:5Gd0,6/b0!pIibT2UW9c()EH0.+>aoE%`]e[:.A!9^rMan?\peDIlNkjaJiX-=gYcFoXXbTYD8+Sp8US^t0cBf3@I?<7&f 2%n9!]t9rF_flN_U)74!ghb.I!'D4n5dim##5j:?GPH_3Q;gB$j'qNk[H,%n6dc0aBl&>PN-X3J.[pNK 2S'oEm_dsA1&+b`$3h32%m)"QNiJIWX9%*49_)I&ARkIm:gM(Vh!$bI1iSC/;/efNr_`sWbT'>T;fNIJ<%NW0%A)]npAdI>\KaA[.G-8An8&VN6)A$o4,@31\];&k4*=*?pasKksN1=1l-ISJEY/_`=U]j[Td-9;(OFh(IHp70H!2kN/9to//b/_ar&/Xe9CmaqX:`X,S\^A+AQes./s'F:2ZMY :m H+3XS)l35Y]AicKV"G?4XERT;gD?+)S.0?,8X=414C$hD`@?3"Sc/s>A[bFPR^]CnN8ml`[pD$q%M,aSCC$b$#D!JN=;^9VLl>P$8s).J7tC!^LQ,c4dPAoU,M7NmQk=90>$=:&_J;s?Y$/#I^h_`%2K$[^S[7f=Oa21sm+aM=G89g8RD:KQ)pRKLf'/>$ciA'Lr7+X'%1D+6hDh@8G#+B:/_"EaEc)VPU$kLC32rR-?HCm_QlA2Qlf[@n^K'OC7CDEFI]`;C5.EQ$V0,V.<E#;<.J8PiYa`M$FYCP[8$3Dif8K'RSc@r@MF XRPUqE?nmRhVE4D<^[%5D(^.>V.t4OQ_mqq37`53H)8rAGPldR>'1DEec?"2IGY,ane;V7C:K/__[:&<dboAG@@WqJZ:3<^.ffSXTgT(X./0T_"B06!]fejtX+?"dGC#nSP\JUSFU'mS22bI#WAp\83A2T(Mah,S`@56_B\r2.1Q9=f(-6K6YZ#Gf\;o,  7.cIAMP_(5X2O("&7fr`;lO2!5=W,8`9`s/6N!+6+A!PJfWK\A< XSr6gdpo=eE!e1jqMR"ptea0A+i[Qf<Y ,)YtQ4qA7e+#E6pcFs\c^_-Q(Y3DN39tKGiOML4ZJ/]jY*6K("f?j]d5Q`"(!a6^EnhMXs-4(YR2'J@A!hV_VYI.'P,/ct:aiY%I5X*@<Xt!%`[GkeOtZa[( XBpK2#?$1UiL2i!?t8SDQ]UBEW@5SN:$qlSg'CJ>p4G44h[U)U*4s.C'ieWRf:.VF]R(Q.iRPRAi0HUFmR8GAtnR1D&03T):Hpn+RlJa>:[U<*83'R8Fr%W$]?l)KANM[Ttj gKAfib:.oo,D?jMTW<3DIFMR\io*NBBA$.9'8A6g#(FsamZsV[>Ml`Y&<W"Tq)i8'ROHA9<4@#a56nIM,ME'>LJ18>52+]9pLqoAIWG##HMS2`^SX$'N0dP/)7*DVh;<llE__mo^GAHFXh+,nhg[,\S`oWd!dH+iUA)Cg@qlT jQ?8()W2`0RA9_i Y;!EBdA$_[IX'ERYmL[MkeMnHN0 R"8Nhn7>%)Hh\ e7F@VP61nAQm%^$@;fs\@mrNC5=Or32)c[O6G3#OrFN>k;m0oPe/]0!.i=5Qp+Is@bJ<-cLh_.Ia91f6M+7l;+\mH7V$Ai"4mAp-#Y(jDKCL:4Vr!h#k8R"*n88`WB?N)/o9KG\8A]PmSnj,=q=h!%(X+*%Z_/ApSK0`.L;*%@G22NlmG='pP%,JBl$WZ:AS)rlaK/^(J+B^6fW*E C37[ae^A]L@g$;/Ho)o)1:W6q>GbC42!!oDY5#cMQmK3-<)(m#=s%&K37[:CU-hm->V"/AM\ 2BfkNtlILl`fPWRG^+d_9rcNQFckrMM.!3jP2V<b(:QZiAo6XdK KD5-f95M&=Y$'1hV=]F?b6E"^W.I2<7kgnUQlj;YQ'W8NFe?Pc%[Z^BEnel*gUJ:gp`7lGRfg5_YboSY$].O r)#c8_"RFR#WEt(dQCYF8h;ngfPe^Ero9^bWGha"p"J]+f.<>A`G s^Xs9s%I&aF3k(BC@WZ"J9-425-K3884cC_#0Z2 >%o&UIrn.]!F8I#*Th=17cHo>^;_8dB:>NMm'XX<sZM8$3UsY(sJ-An`L0_.!/GhED.&$37=>@beT#@YdX3DFir7"Q'tVgC2$3="Ke9<0Z/i"]":tD-/nfkbdT_X/f)ka]=.l!c?IXTW,9!34IK/'*,/.8OA`8aoXCBI)SGDZdi3b?a`%bI;nNAAfg5KXSC8NdCa(!E:T*fIo2V)8Q;j q<42ACAa.4[Y@<OX&G&JJ[bW[3;Akj&&e!.;;=)abrA2*`5TQlbpi!?P,f_eV#Tt G!rd bi-Rf'-p%U@V7Q\/I?J+mR0m/p6VW4g26;7BUGfQscTe-Af]R9Z!B&f@3T2^G+NfGDgHPP!J,Qi5oCC\$B@I3Eg/6D3&MOfs$K9V),ESse*!h_BL_h-mA_19@P&s3i_0iHT+8#"? A)te`srfDN:Qjr =9Q5@m&S8U*eG`k+UC@Op]SVZp7bRqca5TaQ@_g,K"O>Mk8Tkh6K%[TeG=k1P'^k4`43Kp'N+A3+'>e M>-a!M@QEPf>BY.M^D#@!8RAn&" lZp*=gJD#>l.44)c8kJ0EjKn@q4]@Y"mKH\t@=Q!ISeN@[A=q`kl;K32M1r$LV+mb_ni\;IE,6>d$t)B ABH]7&-OK7"('Usf4U>;ZrgSANg+q7P8tFk0)r%3<-aN*%`ZUL-142$\*VD79cs,gWm0n+DS7bcA,c14[CZQn]kb/-$nM,K;F";E%4X[R#GGdpX"!h`j=A9_%pt4mZ]LJoOMh#$*nX57JktJ5HI?#ne/qIMd:?F9:q*_UG%ILCdH>fQ\f#>Y7OP(+"C'HD9a&F`'6ir+QkiB`,/EAT'IaBH$'gIAGL>;RtSL"1gO>XeX.L 1SZ+A]31S4W9T>4EJSpPk<4#("#CaOV>>iGftc7?5[?(T^qc:kl2I'#.t^6,`H4W!DfMI9oGt$p0>5f.Z>JO`^Be%q=/\eg]7MaOY:2_,]-,b!A;;_OR A5P.n%Z7YLIe^)1_$N$?&>oA6$59qS8"@VbD8bV:ON"!]`jC@4n:6eDT)3E=(orMJr+U/U-E%h*J> ]QinJS"Z`-9QP2rBF?g#8m PlBDJg^)p'Y4bRk OZ\`0<"p0#`FqLDRa_Md",AR>_7tqgAI6q>F\ rUP2h6P5Lf!WmaGeslT$$:km:"^b98>B@[58%Vk8o[4,3`i-j`:lG Jp3Z@RD+o"K;Oo`cgPBOm:XS[SO/hl\%V"K%rXTaOdA?!`KL0[jil< IE9'PaXf@/tA#eT'SBZ]es'ljk^/f?i^b`k`CeqsgEah1N^_qKFOQ:V,nH;?rWTWAh8@J)AJ-fdM.Ub'>9`Ht>[4A\. HEF2YA9)_X3L^H[B`)dO UYDPi]b&C`-AD`ettad@A#nG>L4c\Wcp"a%d1Bt4"atAn_#%3>VCJq$l$>O^!?$WB17E,NMQI9hqOM,Kl#0QC)5_M%B2E"K7Dt9XK[s@_HW( Xp8-1+,k\hs [i?3?4XCQ9R@I1c,D4?]8FU17BbSEg^J]H'(3&Hist50)n$_k1ZX=$.[:O6R_rL`V#&"GPi(Zk4\Tk?UAZ@,gt)S#c&n/KSYnFGZjs^cACm;+eP6F^)MAGhoqV4`@1%UMmfNba+"& 0sY!5$N>XYCnoO9^FI6'Y >U,i^S$3>sW3#itq3RnU@rgE1^8\UTrjTcUHbl$CFC%)UY[P:8'M'a6^1O4Y!kgi@n8:%j^P-cslBH*r,-Q"Psn4bKbHHAUVLl%F_fB\P<sD$^O&VU,5Xf';b#cibEC64s c(Wl+T+UE&N,[r6Z`Nk>h*jme`BI1EhITO9_gA%]A"i<37)\jY=sD8sYN^9XFA/Ml<+seGea<.6D^$UC[=X-4`tk@fIXG]%M_h:kVC\&C#1j,`E;2[CP_;_,SHb+MHJ][=@?Z\J[!ciZMSC=8T_P^+7+4 #0aMJB#M7+J9Y(TrprMRVhqp%6n6ph[#A1N=8i>Md4<b+GoT'>mPMB$b#AdB5bdamqKn6.so 1O2dscP,`V1#sAjYn-$).Ao3moshGH`Y^-a>1T?/^VeV aR(MfbU*_)lDiE%8OlO?pr$ZfBJj5#^-GX'h(lCVdm<9)q".PI$+*5j!p_'3#>\Il_VpFG6Zjia`Dtp+IWhr@EH#]l0o\`js?_);^=90%PE(m]hA-Vm/r)\W9ENd*Edn+NM,G^,U/n;tA^+RQIGfiB9s5o6`RjM[ALmTXqNm@Z:O<6NTbU`)NOr.a:gm^b_XYn-Va0`;P? RCFlYsq/5Pr%$G?r^AZAE&/d*X7AYM\AC,Mes7G -Hb0B\BfX6kcUaJ_5[W1+lp6<;T$WU=C&\hg6A^NeR%bIWE6ZjlN\:k&Kb+<V9boOA3We'Pp+PkF'h5^NrL(PC&SIg%Y$%fDpJA1Ol[+q!_>B7A6N4>?q&C-pLlqE@c)j/Ml\i'J'\/N4((UnMeLVG-?rc?_4]>TAn6!eU_:tUA?OYrAJ[:n>nrn>tOl]L,L3tb%q1"TKD_Ggo :+r<+/L<-QrHM<=)i1La%Yj*#]#`akcXI$cXUbL:=!nNd4$]flE;,Y4(i51saE!5.n97EkgA`IQUb$1s_<[*SpA1j/,IYK=$^.'*J;^U1Aa:r\*[5'BfPm5i\R:Y5N7XT*fJ;m"f<-*_ ePoqPlR7d4nX0[ZP'7CSd8!faj)#/6e[R+!^]L[R:N:TNV!(Kr]OV]a`% 'I-L hGX.orUtGE^39%Nio,O9MZ;+bHD?BJDBPVAk'SV%5rFKf"?[RX`W\t+Dp$)0NZ_IgY*9I"+GSj3NL[k%HI-fm9A]*9\;\>CTdiC02j0G04t_2C)XN&a6!NCi&_[W*E+K*."oe6R:Oj2/4rU6PtGm9X]s>ho)^1<44a0AT%ELqE/-UKgS#AB$kVBmie4$1Y`0JHGlRa#Xc:]60EN9KE:of(H;ElD[-b]C6hOqKdd#&8/Ct2<^WG->k1N._J]6)TUC2mWRXrPD"Y8'_,rqThCrN+A_oEMMkM5-rY2:3Xl1 @J)D=WVEo)paNT7\MYaD^:\WF6(/m:-oEQ98:]mn#U2rTqm7W07fcC6V&pFWgZ!A^-Ri>AAY?!!sY[:h8OB'o6t?3_]rM4^IfRmA$'mPB<X2,@j62V_BkPrr/6H*4NiF23S%(,EO!Q %$RLjP5X& dHpAUB h>9RjB34sA:CJ(R;lN6,kj1<ao`E3p[LNKFk4a!+V_Rh;;O>&;)P/*^g?AAiJ`@*k?1A%p<4%9L2R:C!fReCA[f#T1C6sYjI_D/H`IV@*N6LX'`m>\qeb %'3.)%;s#s!6/B#8dd`5di,iDPHo7MQ$AV=J+V0:(\<8fZa%E@Z7)"ZlWG4;b.0*S,<"K9#CihF83rBU(&mA&5EDV,'WJ=3NXeAW3@.j2/:!+an"I%3q(9(kqZgY9h]q,VK&![P9;J=D07JI_\6+/:21[RBq#4%?Fci'2V,<%6krSb@]jEo:YMGB7P87$W;76_U"nHlgO2 o>'[KdHeIl+n@'5[+Bd.^:\Jt&\Ap\RO2Fn5C&`omaZk:sGJj&_SIO0P-Cd;G3#j(I.Z=NCqc 2%(:[0hN1FV89i'a+ed49r,f\kNa@_KE*@ZZP\GFNRNQ;"+ghd]$LgM%3U05!U-$#I2.6 GM.Cq7P&WDYj$qd`V_755b9$K7,9(Sf=6>@J9pbr+RAf>A74AV_E>Fg]^+-0UtQi_m3+rkfFFEr'<%iHE/4B7N'sRWoRIc*U_qfZ(pFqp,^'0-ja;tcTHL5:+gJPb_qrZl.X(/0TeXTVZ"4AR/'lPAsqA<$@Ej%/0XV$:][.2mhWZ]lgQ?eD8q:t>_himc#`.>6[$mMSG)7CZBZ\e!QI7U=HDoP,3)B5C7Ulm`8l&?97]9bV$) c*11'-:+% f_[-8hncgs>Na[J (jUgspZ80?Ia_'AV;n/VQ0I`\QC$>`:PG6t >1!Z%s\a(FNgB;;HbsFWlOV93M8[Ut%f/AT2]4a@fo=&HiQ$Kkle-FYl a@C8F)*S;lU"VkdR9\LfU/TT!@.L'+ZhI,!?G3A!#@-h)^!B?)c>:O8cA4gUgeE#kH'\>E:`Rn#i!@2,*)H+HVeRB,cATD8U;RsNOXr*M;O+NTMJGe6$J,BI9'cg'=ei>U`gN41oN#SSV`o[8aOLPjsb0pL^G#MnmAgsb=(`-0T)4mP2A43]F!Uh\hA*V6 9#@Za_'IE2Ai;qk$JQY5>o;L)\]:h7Z)^G7#b'r-KqtTi'dWAC^g,"^i)abIli*HV@7rW#;[H.^HAVDU0)J:8sn2XK+LR._$[Vr,4Eb/7LT^MBL3gcWI7E?sZRn0YPA.\N%UqZT"H:5"Ha +4&mLinhZ%SHpLCjG@EpaTt]I+&VgLL6s%+epH56Rq<iMh6LE_Js\!*V6EAJ4"tQerAf'c/]icOeFc]>qJahlBP61.6Zn1e:I5 r78,#,F /3<;SFor=OJLpMlGrc$]/91SAq6(c[(Fle]DE#!/r\CdaCl)$0R$4B-4bm4dX ]0#T,5#9#(`J,Aj?&_%EcpA7_aQJCpFA*F[0r;.q*f0>3$$!_'tRVnR?Q$Q"0XT9?Tq+c_9!_^8eph%AR25K>)6T%F01e/>&b2f]l+nAgmQg8kHb psX3`)5MpE1O.Q!"DT'`;7A-tWqW@P20f$$T/a>PebHtn1!qZT'&JHqr[&'* =52"&7dpe?g.$o%-kKF7q,O0.i?lc698?&86,"NdI3_=M]nkAfAt(7"*tEfQ=-K#II_0q:N.0:K]80%4=JdT[F0n":o%VE& 7;;]E)'rAS_Nc-$P\NppVegCjTY>\lcF!%a:rq;9ndd'A:RY&IhG`p5>>Hj^/Wpn)7-f6$8A)=>0+* 7$4o63)&!i-YA,0;t\MkD(AgZah_<[k0o"0]af<(rDd%XfeBU#W/^QS!LTO[PV+8,jY_N*bApB[$!`-QWWA#H->hAJRlr$UQN(hAmmN\m!Y3R?nY'"`Rr4e))Ys@rQ6(FW9+m(8<6%1roR(^ERjQ>Aoab3a1MR=_]O/h4Irsl=W5+T3ZFSn`X0+r#O*iHD?bGj?I7m8IpjrFoa5J\97IJE66Ob[-4N_o,d-KP#PmqB;G=fXB8#]1AL7.HQoXm-[$A\\CQb)f*TfEH1Q()dJ?f&qZlmRo;a%-LnqtW3e&5PgT5d;Has=F2_VI@'FrHm,WN?2 *"=U `K'P$PchrWcdt L92Kj4;kTH=#?H"cf<@iiXjA_QN^rj4qLV";XPD9j:bV01]`34N1\%DX/Ff@#XBI/Lo#c QCoJ\IZ$g(1KG2#(:XDi8A.P"d,A_68DjmdT!hT<G[=Z0H@%j]'jQbkp"q)+)g_:[AYDW,K'LPY:rM4t>.V&m?$9OAM3$5kn+,%0o>W\pIXT`^5!6<K>k%@p]Ybdg-7nI"A9V]]2SWb!JA!k)D#W8R2B'ALHClX$++inHhl,8AXH!U j.7%W"Z6tNSf7STULk#,b=c2Y`\M8=j>!LA\i$qn8!`$El*4qXlSbfb3!aDY?2R%[1R5Ah"'$$j?8pp1qtA'Jl$%CW/KX#QcL%9a)['lmKB/(.BG]:TpH6$]M$P3\E,H=El.).V_g'G(SKG/>Z +7Sg  PKXjE]t+.WS^o8?G+9(9o@9@1c?LgS<$&?)tbb^'g(er+C2@fq_->mnAkE5cCn*<>AI/KAoGo>9TcH+h`Wd? FbbjTld6Hm+oYiT&XBq+Tb/Yf9BTIB^Ch`AZldmX'?0WT. @VSl&XcW:#(FW^.IAG(a&UF98DfaUc5>!o9$?$41o7OMdQN 'CCF=3n9,H-GV1:C2fre*/DfeAAgS<E.bQ^&4b7:#ChiO0/(Hq\S%DaH#T+7lYsIUS\"[Q60MRkTZpC29Uam&%?)2LniR"^$@&4Hta5=hQXj*M_EC.4DGJ0,V:>Cp#^OM0Us`WMg\KO4)#5VeCjJY-3Nn8Z+dM8HLr;&bU#`l<.J:+WdI9TALi7"Z.An&t-&SVX`XOY)D:7Cd+Ddfr!Y-0&jr9ie)OCg-)sqid!Q,>ghj*.<4]]ft=rY!g>i%M`] kX-bg;:*`c :*FpCB="6Cp?Ksn1E-$6*nP"]JM1==QSeI5@A"1AJ/Z_F%\AC')E3ZqSM3L2.IfClYbSGOb?aeeqJU!UH_2PI2IVoJ6q7pYVa71dJ%G/foptEZbhC#'i^4tPXI0= KDT Y-TRaHabpCCf="Bi`+t-V#dP>j"+FJN/KL',;Gpj3Q5Vfn6i?8El?H4p'?A"h)A'K%Sm^r%a7-\YgE9pLcSV!=?p%(7TIdC,UJ?]b+L0LJ3PEHeXZTr].8CR?b;,t4!C'>Z&UEGNT$PlIQW6DSsF;WeM2&o=mUA>cAhf-i$qW*KB I)9.1Ae%^ICbAe2h7.Z]$UQ!@G,pCLD1J>:A#U>hg/fathk5@GnFm"/:HW)V\+\*c)m2Jk8DoKPOBc7]fSih46G/\rq0&rm#,G3J;E-*rDh sS= *C%f.NATZooQ.modqS#(%dHm;?a4d&b!XWgOmKTf"q9I -2%%q,8R4,J#$5gBfZTYMm,tq2SA+ifSo/r[#P]T^7eX0(.?F6`%@`NXKL=PX\?XR7=GQRsCYK 0Q\S/ZOS`W`[9W)X7V_(iTHfR:`>AF:g>b LA3A@>8dj3,0ned.C9%JHBg&lDPd9#)n\@9&p)jY]=s!9 :qp)mJ3#7,;-Nm`e9lY@:m]"The#>be)i8Ahq]g 7#C_o&cdPH13j;Sp$)0sqL`Z.WA8[L%sSPF@E-(\S\9Y(fRCOm4p#A+/.-O(a11A$tQm_(R)NjCW(2f_' ofHL0$??.r'tB.`X]ZTY-740RoY&iN5STW5I Y>I!rPHtYX"Y/ ]m]QInX!&K`NQRU)A>OG5&En."WC4<;4;\=BB.gia@?>Y0'ASF+mY*2#Lb[9B#JZ%RhJ<>fc!Ae*daYAO6gYGjGl-!/h69M)#jlf86;rhHb)i)DV\@*_9T:__^KQ^l @<85s9 M6]?eA!#Cps.,Y$ e-f$32>G2bhqZA!B1LIA6@arX(5L&:e!eg0X=_bWcP-%",09!bEk^C&Y!irAW36XKqV6/MbI)Ak![%,TPZ/AKX0]*\WPq";OP*pa)Ki!,)$\1N-X$@M$b!8<;O`$8OZh_`N0mh_cs1/7&k3=["]tI-OGV.oYk Y2+.riBdRQ7k\d8GFpG/PVm.]tlq>RU!J_h'fVdeSAbW[^.iXN!f#;cO[m]U9NstB?Y`+Ab(IDE;'P.!Z\N@8!HZ>d>(@m"p(lS4/XIEKNZ5h:\YL>SWGK#]2OP.q;][.s$84/9FJeN')"(&q42g3SKpVUbifkn,mpIT- @XaW8j?_3AJT:Voh==X>+ ?1)iFM(aWV4]1_hI,\Slc#pWkThsicBRV[AhADB9KKPUJ`KL$eSSPC/['K8(hb?AE3^sJ7;;oEH6A8j$#1`AQXq]ps9,Ap08AYc/MO]IfN[.]7tD;U%6lh8;XH`s+'p4diRJ%oF_4b)cOH8 /J=sS"0kOl)4^H.]mP3:cCoJ8V1hl+)+2d7W Dt$0'FNfB&5PlW9$M]DJE_D:(;N(?$o&d,qGsnX ;1dOdm0c.Rl^Ct/GiDTs&^SYV.PW$"J@8 b,>I-<Gm&@`:[p6h-V:)e7A-96;h8:[364n4pA5C8I3WTj%5k)'[,&4>:#.aEXL8niGh;KrT F$=M/DjA'3s5/9@r1hqn@+HYf""RWe9Afnlh*\tg\T$X6dE9C#q[\0\:dFf4!-]NS4`VIJhs6-=6e2lT5cCT"24i5G$]2n^Bb$3$,R6:ZKjn@n.A;.MEscbH4 DdA?j8O`!mM#7p (Mb(4\qBrt!VG>>(BIRK#@Z:0AcaHk=6AL-/"R+&S!c-BagoA8,om0\!GWbeO<.R":,J>2aU0%PFdYd004$69J5;\tLU!5Ym$k)$!cm%OR%btd4g`bla;Q&(f`X3:4DeNTAmo=m*:p1]Al3O5H8,'4G6c-h3;7n>Fq/)Q'@lk!K[k0:eKGq8'^Hbjj*^%?XnWb)/soo."AmJq]dI[KZDV&75oA*F:"*VWY1d`DAUtYXFESlLQ:A9c_qNT^NYs.-:rZkgJ".PD:)-#CMDPjY3^/mi\s+r67s[c@V=;W6e*^PJO9`@2fPXRojZ9Z%1+:OLf?fGi)YF]!H %Bcbh!X*+F!)/)#Eg+Z;c*f^&2;tm2;slJSP2a+& \W;9)_LH`"+S$tAU MQ+dCr^ $1(AY!.b-2ce%n.dInA;#Vipko"dmU?'\qoV[ngS)K[\IhNC`)f:On)g3&qdb!?cQ&r,.UoSd%9KA8O!L([*H.!:j;cE7V65ae>>K)=('.65D3G;+]qYa4Nd;5l+PW ACE1@pAZ!9fj`ksP&cNdARrG dHjaQ5oVOYpEt>,V3SV /T)`t (A(e3UG*B:$*U%1qF'.Y&@4m;$i R!&GXLANqSP^N1$/D5SG9AP@nCAr=gHZ8G\FWrDbm\'IM:n4b!oXSa#UmqGQ(=UD*99GH#2FAcmitH0)]lAfKB;T<fbN'_q=TPt.AbP]s=6gRTsAZ#aJ&+`[3'.,nkmM(M)>S5Q$tR],lh]mC$AP;D@ULc0jXAAT>pBH_EDkoO7H2_oUJ!P@01V94VqMXTS"fUAS.Vq8W7*8jMn9>mJBQE0?C@1KW>E7_AGr\BQ+q/kpCe2B@)'1.3pE0P9NbKC$`5X^'*+[69n.gQDdk!6N`c(r5CV8O[#$Yh Ur$&Z?,6iif)l0lTtGi%Iq;+L3_U>Y#*78dKr,BH6An2gR5bcap^l)Y3!c&>n<VT:7o<)r>.ee4 aE5AcSdA>MPOSQK\#=r&1"0_S^@0*e--@bKC&1Nc"P;&2Z:GGifAL6]:t%t"Y$9O#GW]?-?>OCNKs A@-ekH0m`@*!+J>,/WJ9]kt5tQC6j+V'VG<.77h*g&)+G9nKA#5TAW\ti)&M3$k/7W?A%\=P*&&L]kY&rKk!kjTUl,N6R7-cPUHak5odkeHZH9A3V/]e/;fYF-<pP^Vka]?L%Wt!> 'JSsn/16VA/c,(-q T)"`=2JkBj^:aT8sTp_+2o%N:b%QTZ\gnq"t4D_1B<2AXOUM;O4*Ak@I\ENSP'eanE/Y^fL4TOAcV4an>(*-1fPMHG=)$j4j8tKb`59DFSA+QR?.;n<(j:3sr33Q-o]b5;j^l<-Ua&+5%1?7smY;jbUM/7"Zf70BdK@GnRNi%\2A+%S1J/`?(NH8JFjLeJ Z9$Mq986!Pn6H8E=Eg=k)e]>^Ad=?#rpK+J^5QQsb)oT1ch=rtJrj.c+XK;Mk_e_dc ^YG[aWPCZd!n,D+1F=_O\K:LU3"G'rFViOQO`B+PP`%XRnoQg9V:YCrJjl'rh5"HeFCLg:B.Ic7r:&F($UKC>8#C"lGT*p!A\3'_A*'.InVC1n8Z@F<O&B45YQ%bA*n<&r7.WlfF@>O;Iq7_7tWk:q")I#=4mK(56h45X,q,9s.lG#mPRAAfs2l/8MBX_na39RX1B$7LKc'&?bV/'g' k_D5I67WP!W/a'l%;ZWeAH"f7AQ;OA"^*oPXQ%;8;iU46BOD>lJO;8k,[Z1W`N'Bk^0Q_7P<#K%b*cpHlEFaJMNaHL>>J(p@9OVAOb8]Djdf+69iccX jG1Q9kqd*.,"lmC3"mYNY35[,2A=oIg#`S8OJ#be %49a81hN,bj1J-ZB9MYg,p*,1gKDe=>lr'+(fb:U#_eKBV(:H8\eY-Zs4bW5CLo:PZ]&V ]tV5`';2A@r:h;k(62p]F.ga5.r%EH)=f=AlBO-d;9*;n-=Ztn1@/-,7Nm%3t"^-?+sTCNYq)pZ[R#%BRe&5EM98USIRnH]R,Ij[aJ5#GcDL1P2'U%1U4B-0pLMZ:],^f*a)tYI6->6F]]rp*Fi! h2_=EaBn5D)(F?1amaLA4)UZ)\;;4B8F8PAa#XA\=$>RK>aPcH's.cHKk9o9Yc*7CO;(m<DreX]hQ>1f5^ZpkRf`5#?(],]V@j"JEi_U&+ec^F9L+o6S`$P;g':4%8ZIGG_$22bNQ589\KG%;CdqrRWd"f"GcNj&-$QNs2'2=j6AojYZakT>_KbC4HIT4.^o=ES8*5JZ1<(!\Fs8!r;!:!@U[/oA*I:AeFUE.UE$^[dbN6./B(o+&Khj";/-h7U]"6pb4W:3Gd^'+82&iV6L$oar/'MR?Wo,W"@YY&)#&_<%eETG(I??e'7cRH$>%H&b/BCF"pt+97)2YnSV3Mc#`m#smn^Y9jpKoO=e9j+fnJ+/V]Fq?:kpU(tq8hX\Zl2#ppK'X.Xa2UdC95c)8D?q!AQmHL.qh+?a.PN;ZHUmo&jm]dEnA] fin@9St "5i+L-4s,$sW Kt^;[K.q2QQO`?!m\?:*]-j;5\Te*TYd[R*#XE?R%JJRX*gELE/ZOMoP'"i-U[8We5H5qOj30C-lI1\#MAo36hPt.caONtgNM,:8aFnFomY<fHcg[Hl8P AV!IbYROa,4^dDX__$F5)S)b2e+73K [4#q_+mrX?'YC]N2RB0U(S&QQ hOgA,AZ0`qb3V'n35LNK?FZT]%o7_G4B)+dH!WFj;?`(OA0p<tr_D)-h+-XQ:Q9,UH[4R3M Xc7#T:Fe&#h<:H23V*WWo046t0IM*G9$@%ALWR2C?ADqS3e>4(g]IO/H0$Sc3nH@nd0n)lG;+$%`nilmb*S[gZE0_`Rm/T>RR%">8C$4 be`Y$@Bj$^Sdf4OY_N+C;K8]fi!4g3cF<58F-dat-XT:DkVSopo4.^ZhsjV/eX7AEPS2FVgB$'&Xh=VSM$Ik07PPW6ZO':)3Uf7)dOK8jh_f3?H(Jr=J.LgWnT1_eA=M1e,6f!4%<&&A2&DON;?=N_kWlt\Kag$9 26W#;7 crF(` K+M`V"PfX,K%Ul_d@0i!KWfX*OGp4i=EUbSAqBrLALs%[A.^,l0Al?QEaj(amk)]FBXCiYK--?0U(pfC?q!+_=@mSLkXrK'J*gge)^B-a6n'9Hs)75QM5+cQ_[B^[je,\&h0,L2:n3+V:eA6RKlQnAh^: #7oU(C74=K*?8a@iMN 6)?Y2imWkj)jL3t=2lo%-A%Gmm6AGXq_4!Ebb6`hLDF-N:dPU-j=o@5]'ibipCDlZg8,*CGk`A71c00>eW@`lpcN++U?e,n3\;Y#a($_>;^HrjD$XkV&[F,SB1n7gSqmnJZ[Id1g^sl*\E]lIB^ROG<^fcY4L[M^]n*O[R3GnNg9P/XAAM=16F,A^VM3/HLLO3#gZ!31(_R8kt:X2EhY\#6)+[`Q$B#C"A7-qpb/JiZ$eMFkn^MD ,TL4B?tXT&-c,/po271,` L:QjqT/q!K'EqA 6n#[#UY9n`TOWqC)=[A!8`QY#;#:fLP\"n+9hd&@S8&98>gA1=@,sIE$B1.F\m[c2-092XJD<`_R109#40(RH4j$j'(^%l%LaG[tiNdNZd*L1\p&tAXEZ$g?Z02SLek*3eor_IN&2ML+)kQAg3r8Y'\^UIW-h=C1`3]Rm:6]k..&0H*fa8l.nU@9a"kZS0BW6]KU9Y(_gF#p kT*6NY\(LoI+>=7e":1nOl4V"$!IZZY,B8hj6fhZ7>HA^rt'%q(_IeAAN#$#"8MFmA2qMckc cP)2Nn9;YF3LqeBr;(\kgkAfI0eR*@.h`&A+`ESKeNB"7q;S,6E/B'U'\'1FYW[5,sBM+KgV1A\l(q.oU7(!F0!T:g&.X(<$bD-DS]3Cr[2U?^/0_g%5=6=#cQt:]hj1O7-*[drWco:"b>R!sa"'8k_dU;QMV?:lSAcFDAaK\bO':MoAp_lAh`-" EqBL/@I)1Q -:'/=tR0A#;9N?(II?^7"Wr8-.@_*/KdAbk=Kb?6/5k /l5J:::)1cNJBbV/bC%Gf<"1r>kprV$Fat17n#07s,X$5"q5'M'%q%f6Y%r'\tr>+\UpOrS;&:N*0&?rVlQp*q:9LhNVteW"%&_0nP]CVWeWYb[mIOkkDfKdF9END]C>(/EUcC3'KtX3)- l^9"AmN>%a7htW0sKW>ko+-1p0A2NPU8ZpPV[sI'QOYe4+[F%aIY!jA `E?h[:=BrTgJ4p^1d7sAitnEHsfm)?\MJ1WA/Zim*4V-B3o'kMrct@h.>*OB-/7YG=)EW.tj!CpSYMa>CdEqFI@`1G#apQ/J4LV_VFO/PS]ZRV;s84(hSM.n8(`6LX.,jiGkF5,*UkI$H> /@ArY_7EOm)/2;6=EjTI&*#\e'#*2*>k.3T'0C*o0^#OHh[&"W6Eo2A]5GB6S,?"m$ER:Pi?aY4pH?Z; A,m!K+sF/-oB >-Xh?WQ'TI)L'mBJWWF>%mY!F&X8ZZ0)q2UfsSqZ[X:d0[4EWb!S7I(,FN3F)LdFX^3:`EhCO=U9>5.6\R;PF;)`^3M4EI/A b]Re\,*TD!C[T"iYIj^+l.tUG<0&ID.JdLFEF,lrZogh-JT-;a?2`HS7"eQ+Ng&icHUr[3kn'?nNUVD /b@7[cRe(U6BA?jmq>ToSn @6G03!ngRd&*ZKo'Ue,Ll)_2'- h1 98UTlo@LX@i7hgRUb\trHlfc\epd$Dd'=6=tm#:U]S;d(`ABONL L6q,6lVID;;TVbZb3oT?#!cjhA#S9'J =Iie<3KV%eXg9ST cf%hT!aZIG74l-^bP>18WA:NRE,1VQ>8n_d`II+&4Ume@SeS Q`+>dmTNhhU+8=+gc/Unj=\LBal9)>-cT7]Nh_,!'&2Oa;O_!p:NEnWnKsUke-I@`1=nB)N>[)qs_)>E2r3B@c%N0R7PVUEf['eeAnFZtesX'+o>$5Y<"i?6&_Fj*iY\Rr]5)>7/E\e?mp^dUAn]C3?#T'`oEe&3R5g7t[U21bj#^2t?>HAVAb)D]gf2B,esZ"shAWS=WN)5P.p+TZGN3\KAkAmHN2DbS[V@R1fS`Ti50@R0>UdFAK1)Zi*-J0D7j"/FE0RKgkB;0iln2Vh\<@,l5r]`W?D2+"Bt/6X 0L>3\066f+6tYoOA`?=e&r+4_C(F?pZZ_h]2V0&2bBhp(=3Q,]EGTePc&Co;lFKHts'mB>=OgZJ5rFRoEQ6$W?]j$BT@RHgO*82+a[@NRqTPYs:Ks+^NG+2"2jF(5!\ kq?M9_GhBC&']rj'Qj)AhgNs#OnOQBXPO!o0&=nZ!i%DX?:cOY,2Y8#2IALK1>:R^N+o6hfqpU f[O%m6lQ%_I0=>bgAG'%\7(4Tm+LtH]Q(f[KYjRnf`W0-B'*LL- s90UE*\Ks5< =BWFKc485lcUBk(R%gULHnT^KAPiWSR6 ?35O?dmV- ]mH45?&LV=EsoB]%)!*$'edIP"HG+V/A::SkJdA1k+@K%D:IB_ENml)0&r$NS`[IdK@Tg>Jq5]_0*/Q-KIb IWTFA!SDl%\-:M7ni6Aj9j[^!L?`ZS^T47j`e`*lc!hK=rb;UG! #CL$5c(3iTti:(pCpR34`];*shFF]-d>MAn59AF1a_E2>SbWX_0to6Q'":44aKk4,_OWN'WE+p9GES&eVmA!ZAWe;*qsL/ l"?l1kg2d9<5jgb5\#OmVf3WH4:$$ad*b>=G)U/n7dEeC([U<@`qL2iOVk(Dib2-K:K?Y*r+^A^,72qI)JQ>.VE SfW`"Qrg1`cJ!oAKC>O @CpG-A0t@M*]8=":inR=\NnGXpC1+]3lQO]i?5P-WsB0t^VOrZ8kQAhM+-/3'N7[h^&Rg#A%K\^9XV4Rl gZWEKgPEG;$^iRChYtWGPlp<8#\6OVm7h`lDL-V11E[4QN:,kH"\o(<)7`=*@tKW]66kb^#jiLt*/%]!)A1(Vt]%e;K0FREkVrC,XQJA'Foj:?I&Zb>^Z+4D4"A9)%`=J nAEL+q\'\F$kAP627_qJekh$gb:_FDj/*fM#1<(;qNmOX/:T&7B?EMGQ@QAs.O*o2ld' jcoHpC:/'!;`CX*#, 0M[`0HB[A5#]4&jDdoo' tf6e",o(9HXr,bVrfLCL0Aa.bjVFXVF5P>b%R(lpHU*'3XDQQWq-8MECG"t"'dj!OM[_N,FfE40OCHd6Z!'M&6f!PZ0t+@\2#)&%Pk45Vf#O#be?9I.6DkcS%rV/\^Te((c*l7+cDmMaFCFhGD$Lh\ID5;V0a7iRqdV)<],d-e>q<E[ (Zg7.D!\4EJ4[U(b@(AhmE`_OS9G&&pdj" q3PHR$me3_LRA`G[9poS)*7?L"2_qe3HXV^[%rTArKEAa:S-aOS](?hsJW_/7R\[+%;pe*kZC<@(q`<8!`&7#4.OoJfbpo3ig@50+m*eR53JRhqrU=H3GH@^KM2%<`pA;<7dUD]9FE$tYmlj:4&)lWpjoXje\L;nHsWBi%7Z8@%W2M>]WatN3e&Ya$P?d1_j+a6i$FGQe [Ho%f;j#Qt=QGoBobQN?lP1[f>fL:)H^SC9A[ ;\(Q=WAm6cp29%SZhY@(8TsDkq=l3_I,h(g?%q73K`h6-55Nigo3:!<3c4d]&(M/RC4(eIiBKW,oI1d4!(<;B >+HZ0)e.bs' II6_7LN#)q0a(AMn+>q59C$8oU0La]iI)[H9,gNXL4&:BUAfcT@[h'dlY4tBR90i9=:_bb?\QZ673eo0Ea?JZDAFnHn/UH6]C0 /t-;)e78-B$@6G%OBSL1a.\&FQb-+OUZWrW&1ecmcSTKW#ZdeT1+ApR'5DMSQ, 9Am& )+ e<2W.Wa?CO"X_l"lQ/Q<*[.hDltZ^6JjC[PiL2814O$?j/QC&AnOGmtW_ b]KA( 9LO*7FOICC/7dr)pPH!B?r[;`^d[\V2,^08jK/C[M3k,V78XZ@LoJf\HmZAko6>rTepb]iPgEQ!;4.c$ClmhP9 1T=6&0GBA*(Un49P<=BR:p2#p&bO!H74&n`98`_,VkA6]t dGYqeN"grDXBFk;-"dNOARN[5-%).(_NSa/RE::QKJnZG%f"PP=6#l'D'I48qT\;))GTV2K1E51o"_6-RH;:$cTB5"48AR<+U*>A7N?5J+iEFl=h2p+f6]h.fH!E0CtSO7t;SK_/h/-^ndjRX4$rfi7Onn#B$CE="L=nLG[]3HB=/ph65]@7dB7P#"MTBSV[P-60h'#NLG=klt'MR8q=d)fN])[O_`Ia-7BMX%eFAkcF6JT8MYV!)/cL3[cj3VnH$ &O"iJ_g2HosF.@ To@V7OK2"LsYYcAs5>M+d:Z1XW*e%Gm*K>tcI$W6Q:;KCW8U@LOlgU_)VE bAQRh6)apl,gr3^#@NbAij\=Sg_"teo$a WNJ s\q8+r@pKXeJ*sh/T'M=L+QaNK!gdrAe+n+FWDCZ"d73O&/!Sn/0.[9[> *,%SA'G#Dns-Q(RBA`aO7ehjH)t4Y>ad%^:]&QOX[M[-RS5W3846J>)6])AO>s&GdJcAMo[mJfU<>YkGoI%14nSCT:feac2KYL[-! Hm.Y7Q=:(&B9'$OVjb=d*e?S5Zdm'Ar!qIRLG soR`^Z:ee +eAt.Y.FKE>i*h$BGo)I4L)L;A(P!-]ofO(X1\m,kn4&;6HQO>TAD--L"8+>W$6m'Yod9bg_4 (a%XKa;;A)@t<"XXDf7j(g6/+W`o$%[@-c;ZRqq,9bkhLBa&X@(>sY^DS2fB`Aq]pm'8iB!RsL`MeG$atMf'^$hk"i[r`s^LS>(WP-?,oPj_BMIs_1gA$qsn?'oA1Z4Jf0BFg8n.[sf@=gm]33!6m8_IK6',"ZM[M>)ejl/M5S`7NlJr(^!dDiF[.n U%6S]nseSC8=_2>bcCgcoW!sAbgRfL!kgj%81")9\EUQiobP%Cd`[S%t/WV[A`T+_WFrsRlPS]gK0G?)-l)i*_X"4J,[Vl8mQb= 9Y(a^=%lViQp(feU]A`:-MU`^2tA#_mKUjSE*h,pKKl^n\bg5LBF6AiUAt tY,8kJ; B:*CQk]!fn4<&*&JQh^]rJ`k'j?PUQbR*dHaYWN`IqI5d'*L%2HmA?=HK>g73Ih#/Xke3&c^@O\rHG&A1&F!VPW^2'H.[9WD[;=#!Wk267l\ggd@B3(CnV"@!^C*Cm!@8dg6pIAiaVY`omHsisq:(]e_iW)(,.3 '_Y;bm&qQXO[_c2L*>=U)U@@V6QWjlsCA_(^TWdoAjC-6.^kp/8PVmW2pMq]*<[rB(-bHH34$OB\;86lq!,hgU*m&"",6e6`dNO<;S',0jLdrW/-I\P1IJV##$>:TEl=B"$WHA0]k*cVFE+#j,%ZID]KSV=&2S=<XD\h!tWF-.maP>L(qS-;P%%"9'*IqA5:E(-H-^IJo4-*9o]ogIIqd^G[U"P(ngM;AYL)a\+on0"$+A,iYLYIb]Ok8_fBRloV?h^>i?A;VM,5F5!O;mI)Dp(7"H4E+C8$M,K=ZHM3iaT?t;s*\4tZ*f-!dB\9UqF>siVD8lFn_eNf,5In:nD#h.;fF#M\P=*J,DKKM\,pq1^`=90Q!e=,@LU-4PFS(IJm/J$0mrDUEDlDZ/<>SUO"MSWAb 3ER:/YH*ab4%E-KC g>8dCgZT2$7/5Q?8)&MqjOj34>%m-^a8GG*P_fF?dA5rhNmWU`@XTe,O;S)EF%,0Aj@T#8(1A%1:!?bI?U_mGggnQe\\1 1cTr:Wbbg\b 4RGo#7Tm]\@0EaI]:G>4:2CR+IQdHmOsFBgo2;1g6@jt1pC'GAaa>/HM16?i(+/9=h'-[]OL4Q0&eTGc8GP:A'>O:1-$#.AdI0Bh9aALq^#XbS:^>me<*kQ*H&g\+oAO*#U;L=M;?#!"b[^K*?iL+1seV,e4]M?p3A(=L3ee/?D#p#)2ffq\lXn;"b N]1#GMBaGDTEk:[r(4ZF$j50M\K5W6NIMrpMI;E5X@I:nZH/sA8 3)#,l,1J`/8f/gJKP[h%Z5\"ir_WiH; Gi.-dF4UA+#(`EgB$!\CiV2nfHi8bde#CNHNg20q>KZh[O)2T2+'cUU'#L>iBnDJG]`*"i>:Ua<\bJcA,b&*i3Ct02M))Q$$3LAH90I7TA-$1SWpR3JmHQ<)ki([726n)#$LJV,] k[ZnXs")+P1EUfF--*kAWRgp(e%h^Asmq_EWK[CS,AN5U 'bgNLlUYn]A/FkZ]F9KU6OtVFV$>M*1!/q2pKO]8#:Q4'9BA@6#N/UWi@^,Bsq!R32;%Za_A-;;q+5&R4?8endVAd#"[O-?b$`E**Fk "Pl@d?3>T!taRl5"Q=GW"IE2?;81%s_b-n7jH!"VH[-Y8`^?[#8kBfN)oKgJ8?k8lA#0V]i'[dc'tcNEbaV9XT_85*(<5S_W!m^l;h`Z$`U;\rVKW:V8RA-ctGH7O9roE6;F0D*$C-(n&Do^tXcL3=$%@K3&An&/?/iFaHn6&7'X0!G0o5ng*#fHsl*_BQT`N$fgYGUC.Le]JG@NV!fAS0"WEGApT!R/^)#D]m`H'O*kPd?&kkAPrR\(3?X2lX1D'"*Q+,A!:&N_W,l!H_'PZIDVD:X%1j40E[>c#3l,j,.JdXlY&NsLrL!Xff8R;6#%K2R(p%O$rB")9tr3-FJd7EYgTS A(\!dgX4Vq_'_<0FJ%8V_0U>)jDSpRJU0K79LT2(C2*?NnnAIF9a\&AI['B$EkH,Tt8:JRd7bJ1BW6 imLcO27=Y)o%j4C/6;%[gAZ$k#`cWCil0[:sbU)Z9`f46@>X/\>MO)3kLnmtL^/4Q=^9a@N/n^D4sZi)R\]0\4Q9YE4VG,@d:V?\ jrTm)Ra).W^YAq]-=@8(kKhc7O_^CUdZ$3ZlC-ZAP0"s=^\Q7':=+X^r%*," OZQ M, l%oH2X7Z-1;/p,f%i!'Qg90ll9cE.]6)=J-71ClLUS*D?Phg.t,`^g6c`q#O/NtWP1dHAWYFIJL/;ZbrMd6Nl=UDrs:\9D?#YHFK\ BUhIJD#A`faf6"1X3g:bkS?4a 5dY`"A6Z]+jeU1QMhcQ6]@,e"3)oU<Ql59VhPq IO$3[=&)j] 6e!fY+9$Z;C)%p+csgdnAl;Ote]k !n9/`Wc`,9QV4F&Yq ?[pE_lG*nmem<mTPP'.2a2Q+6.BY0dmi-U$%.Jrt37@07jAjF/'6$!#taa;Z_f0[)2l"8L8Z(-+5*2s!PB9Z4K+dUcX@PA olt(IN]T3[r*q2O( gV,8 \5 pQAUq`ln#KObIiH$)Cm=\BaQ-[+WAEL@:j@A$niZoQp*\fOtI0/peWG0>OL?Z`B?s@i_?J9<$23sGI OA.(ZQ6hotT-KjOi4ai.T*27jrJ!jg$3WWE87=8\kBD`%53Pibf[jBAnKP)\XD*6Md-nrH Lk'o-Bmk6SO-l=d(Wj"Amp!VC ,iOF8IgAb7_0*XW3o`/eXiVN3q2k@p=+sSiPVs7$1hR4b@MA-'Oo_9\hcJV7AA#it^L&S$GV(m1FWq38)d\CY-Bq)\ZaHDdA%"5-IJ\=S(-)^BHEJm>Nt'fdfi-`6%+o(qa2o;j$$AN\K=I$'FEap4D6p8,#L-8%-oUFbgAWiG[nD.g5p<%0FM:ef*AtRh5jJE=N2'fciPam'd#\@*R>?2Kr3Yn'RA)($i%$,/eo_p!8^#<[%1Q\7p!i5eR9dr9jkE#NfPej$kW,&Ar3N;4ab-a-7a,qtrcArL^+7<6@aO_ph;C`j$TeL^UhfA-BjjQD>Xk]nEKF.?:ASU8\$A!@r+XLUlr?[a,@dfC_fN810! D!KYBtmVs5+#U"I0q_F^A2nfF0RE>t&P,`0V7._ajj^<>Q?tl^!#$O:tRlmHd!BejK]aqUCaJm0[Vjh/*iQ>D,-;S]XY$Pn2@3lh1(:AnX,,`4?'Z0 J)_` -Wr5?\r2PV_bA:h2HL'/?A1($g0?SG!"=:N+,8"hqI9VYfN4Y3?bS<;[p\3/qK:D80G$EUb]tgDU['[O)7Ht$c.7WT,dep*%&Ta_R,XT=n4G4M!/A.04d/>Y8'Z=Cm=,A'a!=bhRADYk9?sqics9TMQL_1?7:O6E:/^de,TXZ3A?enI)&@ir5U*9;HYV/nn$F"oJ#@a'%*,m6sHScVQFj/Hff/Nr ZP<'V6FaDYH4<8&i7ZTs/+FDH>2F,BP&BAM`9`$NTRCi7j*,a\S!>O?4rCV4]N1_$p>]E2eg aJ&sA^,T;n38Rj>U9,`mY@_kIsY[fbd%XmmD@p7A6^01L1XcG`&t+ISC\L^,7GYI>)'Z +t2.DPsGO!hae9L0Bt*U6D4g.edlmm;g(;=:h5:@d3k?@^!mnT%cjRpQPE8r8BA-70K6PS,#8mFp!^_lDl@kYfL#XtMEG]fe;d%%5:(>Q dF`cZ/\eA)^l.`3dPAi6(4VAf7jWV#6jfVD3.-7,$aT\ICYnB#et H#1SLfA?KNg6lPl`.0bdRp?Y!rl(JUm_?X)l>$/_!5]r.]f?M/B+HiL7Mf8P;A@iV:]'NX=K8]_^$, <4< qPK[gag.V7WHF@&ZKq01-"8g3E?]VK2ZLpmLgehF%SfQ"YM]W?FRJ4.V/G:jGpe\bjt^io$r<30]HJ"2n7H8Q\"o.=BsfZ\=+o)@B>S5.f]]Q'K4^bP3Tj0(q&)eP>

6LjYG/,CVt3*DgB`+_q'9lK'-Tb+s)T27FJ[YR$Ot^!(W$beC?m[DgRN548N&LZ:/?sXs!F4]gFV*DnRMB`g8_X+a7qa^QAVgj.q0!rb/]OCp01ToFb%]qAHj,YTY2:PrfsO@?ajC$P(KShC T<[^'gO?!f#B]].HBS`3X#p"':.l^7m^,J1843Mah@-qe*)t0ZG2l3FI*f]EU8CldM29$WUD<2m-&'B;kGU\$gsib7(8d2@&-r b=Q1Uo^rGFmaO5?iK+A,A7">b#Z6GpJk-"*^VNlaY> qTlfc5K:mCT4t!Jk&1Y<*CU$'d5qL">s#F4@%W&+,[e&G(s3%Bdil_&+d=m#oR/j%1CBn,`;\:Xr-` &9a#/A`5`^e%V-iR4X+N;Tl?fAKpYV%kWL2P)'<tB?j2QS-4Hol\:8@&N[^?aG>eB=4P0)#T+B,Ll@Gr'XZ!^g7iF liLoAG#MX*kLKX:'A#.EP-b$ZDpdgQhP5A61n:&B r_=$g-4AR(IsV*9CbiWH7Gs+mA+o^sQ?4(p"B @?:B!'*kpj@'^:73Y[[P.WoRKeOm%066gH'6B558DqDXp6tOQSsD"c?6;"h,msOpSBYjLq(QAJZD;=Dgg@Nbl/ d_$0:fM==X2\=m"j][d/Z7K1[3aGS$p 0.6ED74l;g"3;7*C'c*7U8NpCZTr$^9FZ7AWf.EA<X==C-+F<:$oMa=k `=-7fS!_qfOJciIZE18f_e64JQU/lCF9Q`"1^qX=6iE)Pk@s=OPT) X&<$!i7Z%]alK'D Dl#VCl,h_c"I:^IPNUWi$dGM8@sSr@&%B'XcqA_@1a6eMZ,)ABFo< $hp]9!R_@1daHGd@)*KXpgHq2b6FV7>O1&aYi/!mVUmC1Ya`` ].M=JYJAX#q9F'k-#:.YAn!foVE7lb9AbBTX$LlFRR&Qj"%UdbQ(2CIQ"6W$NF4P\-e,<OsZa<.P#_aH&SXJd^G+rpNtIl-4#AFM1&m,Ja$GNfoh=e>CRGR;G72S1&rFhlAOQH#85[.Q0<_FNk+F\iUYK'Kg+,cYkkO!Ad6S\<9`n`*AL:MH*-NMo %1AQIYZB"lPft9$q.4K7$fiQfW@05*2M0Q,gaBYj4]Al#1EPUWAs)pd3/fM&;3C*le=YZF'sQ!pS7Tk1+hGA2b`A'cs*&&!#V2;*;Jd\7a@S/R$8mgLpcdf](QGWYAAF;O":QIe()+[::3&Xms,6G#7s04PXnp8T-Dor6bAZQ.i2VIC!BCm&,D5j!LJ?/+M*i_8t+s6:!pb^;qM#f:)k4&!rfLUQ/-GcDq9%?$qtNFe#4:"*"IQPBZc]61@(fT!7/.T7 -Vn $2>%%,jjIb,M$`L-82!q1&?%W0qpDCFWg@U18f*%::H%sRL#n/t.r!gg/?VeM"DHH6AI;+%a)h(ilYcP4B(lrq?$s3RpED3%\:o!((N)]]FrJrRO)"A)2i)t&LQh-l]WbUX=iP>l[Tf6MOoM7"f(:hfim0*@?Jio3=If%"H96(<8;7(M;/Zr!t?,=K"[aD:+6ak;,?&:;;me?f'7PGmT(B\`YmFqTaK7 :]4\Ap7$R:^?Xh0qGB$qQnjGaNR1]"Y9T4Z% T@pte3Q/??@4*p\^73Kr=s*FGJ5e!#/m33Arrl1]/1g6)jSIG:ah@9/aRR]To-!toL!hb0%I"1mJqi[H7@fT8+N:)"gCDr2\<AW`3q!)#6klf']q)P WODh:JMo!-AMX &s9ZA%:raO$)=,Sa[sBp*\`U.^^?J5nj3Z5Z*O>\Z)r([G.%e.QJ(DTm(TR(F\V^WqMk,^c$P=0^/noT/AncjC,c4>r5OrQOU#M6,e2U0YcW;*1$P"ZM/1Cbl0?dQ^\A6@3:Z+-^nph]2 2tc#>6&Z@6[*B7]fGA[cU&)Sk0UgUe.FFA,'Xd`6epPmXfSsT )-iT>MAi:\a5+gl/.pP@DE%'St*+r;51hk6,/4TCUejW %7e$D4pQKGFW"r=h=a8^s.hp!?.6lI_:h]fD:i5=@m"3>^XHa\R9KU?;Vs@_%3-3>$H4L">8ljV"O:4Wje3#D<b2:2(,`RX*qj_Bm_%sOoN/dqZ?,,N3`Y2NOt2.dW8U\?OLiMXHe R/m3QtI%f)qNU@U;sfUb*HQBKJXl?p*)lf[K"UWl@BeAHi/q=[hF-*`:JtCM)I7XD:,3%tZD(LV`d_>e@@>"LTS]ShI:!WRml\NG#cMosHE@t<1Z]"@JENC&=M7gW5t=D7Z'.KtN#r?fF/a[r-B20%J-,A&5A6N#K?;9k5Yg!:b=)Q,4jXh@>h$@g$GX"sH8]Wk$\qB"0*&3q,dE/a9g>*d^V8Rbrs&J[??YH"c9<@QAkj..T/nnaaPdQ ]s.-#&m/+,U0FA/lA[$O7;lW].`r;](S62JFttJS_!I')O4fZ\4AlMm:7d1'f@2ZE-O*Xjfho)O)/:*.aQeFAA,hiAFjV0mLH@tK5 '\F%m;g?AM]]&p%A7S&^ab7^5^%P^t?GKiYJ`"aBmcX7Z\Q_KN\oYJ%F[G'>Xre>-"9R\O\_J*Yh&0([Aq0OZ%c&RYCWJW[,.KEo;8/oUC2PRM6-\sAqF?TXll'2^$TlX2OdR*W7PX0$CmK:J\MD#C*O:^b!*+rm6/ 6HUi^hB8%AmmS=cPT>9e;EMLUrFY6rAL`Ni]UQetHfeE-9bo`Z>!]C;$k\mtSE!ndgq@2pL@ i`m`fk#OGRcTeUgCB.'b^>sm s:Ib(j`%Q#. 5T\IldJfhF^kdIAZ,*,;8dnT7Abkag,]"-nL$nb]JCWR9L$n85 [f3'd(WTmHGr>$XeM4p&fd+1bTqE_jfn% kMPkXk- (Q7V,m*VYdCEZQrda(r1>$A>;@a\/)=joY+?"$%AQs?J_0p4Q<Ihck5UXW>:([Wdq#;/>MKeH4kI@m30otpY[5jAI*4g'\f0qiJ5f6V-OmQ`B^LL@AIK$or:nOHa.N`;KEh*cQSNYD.8h9H%HAn#`=[Wk(?H)?[>6=LYJIbm"QDW-4c+ES6WKS^P.?Y^>1\O6Y44l5WdA;.=;(ZB";qm%i`^;mS?$6Crjg;;qR(Af\1ID\QE;cT^Bl:> `_ij_8>cK[Ut,)DhKX$NVGXl0RG`GKH+I/H'Mn#r?Y"67Pm+'3M7&FL\DFWN#qGIhK$N1>X\23%N#@ c4i$s,^>tNSrY&Oq@#N?*R%D$.!:QU^6B>pA^.Xd[i/Je+e+AKb>-=H(8jMiD2BWi%(72F>()`Te^1;b@]nKGrX1c!PjC"@q0f^\Ra;9r-CVIT2.XLQ\GK`/oQQZ<'WnA?@>P#*3INmY$R0N3-pAO"lRsDlts!8i0NAmC?lS"A>rdil+R?%WAg?/jT@L@@? ,3)P.J(*Ps6FHQ^lM<)J`B-K%Cr=fPLptLA'c?r.\Ji36@Tnmfb*"@gh_j*mN2EhM[]55neP1'#J[4fb!!j6eA!/jA]C]7]>mii%m=o/Y>,q^LSS9GUn$l@jn?`t98@ns`IbS:>mI^smC%qm&)ms:S1c?Laq4U:YlM[>bH.t7!14F d?pH[HPBtA%9E%7m]AK4-?q'r+eL b\ZZW%j@#BpRI#UhR:FNFBY,0 MX)UD.@V&bcVAB!`\Eq %Q74!Eg7O%CDk'-fK9/49\5_ bP*M6qTENeA[A5e[MDmk7Ncj,l]a&\T>WVPZ,>WJiK'_pS(i@HR":0-T0nI\pY_5f7\9]I(!&otDqY-MRSX+th4gU)pG0KRJ)V!VGpTDiU!:9MilXlsO9K?O.#Vt("0Rcq%UaAoM'l;E!a[Lko%C3qUa2/fgC%Ako9!#8Cs!X"!fOk*(.s12S9tn`,SFBF9#n%UVYKTo=+FR#@C"r`%rH1U*o.?Ee^YH `WRM-kSJg-80T8+$ofi&gJ.0SQbUcAm=pY63?SmfL.ZL:/rA RH`-&OtN:T$-4Iq@O.r$++jHcbd^kKr33*?KYbt,'e9\GBAJ2;sq-+]r$@St)O ,H_EFUaBX1MbN*f/1W\hjrDLK"R#ia?P(-an& <7g/@11^/Jf9%]6Pj[1)6o$i.Fc#q"5+gm-3HPQ9gbLp7FOlY[j12JE)[>Zl!Eo!F#.nSdm!s(;$VL2#W`P:.^L$0"c)/'G,H"H=08o_%^Q7J`4>Z17cX q9dWhZL:IFn5H@U,.-1;q%U)%cqFXQf^=[h5p*3C6_>OVcsm<$t#-(/g4o9 >U/T>>Le@?7D(P`R`Z)?+N`S+**I#1X5AA3IJEUa";l$>_G^4 G`\5ID8L$31/]a0V[qg+grWO*^sPAga>D6[hG,jX^W^:"!D'2WRQH+XA-AS+jOhS2nR@3b3ghn[,MH@sZQHis+d%A)=7$>IRVg+.r9.TT*ZSkmfMTg!':t7QUgk`b=(HD8ON?gf nOjj2^SPXoCV=HF_[P]cjPs,bH`r4]:2)7M[L*st%2Hlf&eq@ih+Fsop I(EV&oU.%";\0`@(;)V>2Oq3WQoh$F3:E6ai-spi^T$kjc+`rD!cWK($?kGN%?T(*]h?eO+T_E=)8B5ioL6W7<9)-r1cgW.XVf2Y3R[>+0]KiC8Bh>,C!$HAmQ1_8>2UTo._a[[qchmRnN2A^`BcgckQW]r(._m\g_gGt0C`e$GJ.r-^B"?75&4q*)2CE^$F!f.;M.]>LN7P]_(^:2DLhTWH,:)A7c2sJTbDF*e%K*OL]<9"O:tWeV%]V=h)>r3!]l"pb3;\&!Zk*iUn;"A&'Wnl!=ghSC608;A@;mj8!GgAUm&W./c$F+AkA1J-P*ma>Qoqbn\;2<1Hbp;/,V^(G'c%J!8WF76%+/='$FK)!Dt>Eg""2/4m"ok<#`,Y5pdE'$&>-K#1FnB@76/(D#(pp))6aN#*;)ro'7Eea6qGsg"6qln-An'9;TgLrhd;:d9#["e@<#'AY6PeE6DnRL+jL)A7jA.qGMNN)s,_\.6EjDZ?.W*.#S,9Nq-_Y+57LNA;qZrB+4"aOr4lAbLcEA:Md5qQ.QrTlnsYJ\TH';5^F\EZD`<$8sKonrr$J&2DZ@I%Ad:FF0I)g`13t,rgm.Y8nA[.T!+k;kjd.#Ps<2JCCb$ksm0732;Bp*XjA5F"2G-e3$rrAbc0sG0HbS$N)>L-Up?fbkQSjG9mr$f.,nZCYJ.o[S&YER?3 AV4&1-6#LKt7+C") \\@`B^Y:#i5gT0`(\E*Y!(.H%c9h1HkNC(>sV3XPgi$%.@YApoiOIm/=!4@,]9Y?p-5fN-f4@i.AIYK^QVgA0gI`W&*rI?X=Y?^/98'gIYnqVg[CkH>c-XL-/h]JSU_Wl^#C5I9GII;?YteE`t4M?f6'!T k]rUol25g1I^2k0/q6UXhV16b15[cqs]P=n];5plS6BZpITMN,$I4bm0aF'b:Tpmc^JL0/eg=Il\&:T 0JndFH$n%CUH6dCAa/+$SSGl?t/2YqPIooLf^_&/UtoL[WN/\,qn`TD\/k/-b$(!+2 TI[O@*1@h;scTFUIXHrN(+);jLZ9&oe'lo7eWcX8/ '6SQ3W4@bGC/N01^_Xh8b#Xi3rt^X1Co5OS]JrGQC!&V[bR\?++e@B:Kj:<\"#tDm*&?8bIY%;V1K,#E??rQEmr29fO!a1,hgIU)]U_6/X`6n)5rok"AXA`6,g;'p30]t$l!@.8M'XYZgAV4H%N\a1eG$Sg W!Q`WD!ga(r/tXFa3WA9mm5LMT"Xid&T.q.Q+VOrj#.(@.!hEYB*Ncq-et0bK+D1W_T2_Z-'r;d+df+7dNfC!To#[$RL3J[]\:3Ns+>?4J:Z4-if`L86=TD=M4ot8!7Q"N\+%\@`a5[0`DjbRiT/G2IkOpKZ`?)T8]a[ELKqFogA2P1ZGJd`(hA&A*':c8HM#3eE.sRcb#F&,r[B3$Q7lZ&IW%T[h;>R;qV04CHjhKr8/O8IAn;h>M:5(((d1J5?qAS']+."p[kK<n)a6A:t-08^X:TejmZp1E+%;Lg%lnDsAMt;)cqgRs.^1_W\YG>A:QH+1@H;\otrctFi96"EQF_m6E@W)S(oUA`pKfM@Y*o]Q3K5iCR.gec%4XOTf8e)<J+7=\<2Uo#IR!m::-% @%$;A:eqS)t( @RDj=GbAYn]%$H*;Ubhkm8eh\1fbKl4('*`05i1m"3%KGUS_G*0 _k,kTJ6X=?A\Y4Wdl]iTonCL:t)L.ptEB?Ab+:F?dRY[H=37M.JrRl"YAjj_T$dLtbc0Tkk4hRXTaAlFt/HcQ7HINZn;Qo?\P92q`si7W]WQtlC^`EN :akD;RZHn1-+WTX,h'0Z_s+<#2+_.4["s"tac_C-WhgA*gA4RGnO,2L&E8$Mf[mRiOj^!_Ec#cq_\TEH(>QsBk^J+A0rPl2=Q%1L+4j+TdUJ6)B!0IcqMfR&o`]Gsi@AgLV,-Kr-5l,*I9(==KW0CW-?Q"-WrnqM6"[%]NcPfP]nOkckft\Rj.?A;FbTC^MfgBhD- #;&rM$( ^b#)Y@;HJ#@2g@0pBj6PiOlX%A6A7R2hZPZk(8HfP+b1GB38&F=FO+%L+j +d:J#l\rl`nAbDEtdT/8@#s>l>f,t!.$L-XjP&Nf6Tqc h4eIsWcAEd:'E;:#6Js6sVS]eB9s)q`L,-1iNKq$F0[XXIE [#[mlZ5Rc06dfB>A:% nb[n;8kKDBN[HnaPpI;=+F*5n`Ttsr0^_&@ YOA:$[^t[#A=_QQ;VfHT=4Ir8\&" f#?QW>OiSEhrk @shHirk>9/berZoY>3bH*PtUN>nTp`Xs7[2hAJO[H,bbROhY:RFqsVN+WtV^Ai*Z_8P_D_j?f!4[X0GJk<6O&A5'/SCO;:P+1DDH;n2O1O AADT8l,d3-=Ar*V>*IFR6.jc8CN+]s*bZMR)d,iH#P33Bq1ABaQWr<>R*;-@jT><98-^5CnO>p8]-G))41BD$7M,-hCAc'.Gs_DRC!gk>HSIHHER,+0afJ#(%9jJ`@QF%L1V;GfpAM:`;<1@Of(UC$P@(2TSLo-g)M05)F&*b7Y9o5A(OP5R%WL8rJd9Wbc0L.enUZ1F&[;ac7"!K,,NW*5]>>,X[>%@Ei37q,ro5LRs$#eLU1j&YVO\@A%b^MK._QBm;4Z2.3X$U6RZ*eOA7$bPkMd37aQEma`YiOa*QU;G6KR3X*q1G0K-Q=m1Ok#lE/gI5$A+-of5>a4\^%)$)=4-stY;Cr/]T3AHqY*,W\_K5-U/'.I6@C_A$M%G<8FD X0-s%l.>p5c7/)89RL>$-P>gtP]!YoWh?LMM!Eqtg?a,o0mMrYkjrf8?\\N)A]k#5&@8-%)RlN-3-!R;P70oq_KlO;CAAP<3JOr^sV:24rt=(q= $oQ(1+l%AK55\P9?t;BKMV>5dFHb,iG#<>#X_DMQoEZ+H;WXd;G=0+ Ze&@M\A5C=B:r=1ULSDD]tHq$b2sYXAc#':I5 D"YR0=LWXee[s"f4O &-l4@8t^qL7l4UWlQ:5Opq%*_'b]j4Ik^_kH+K5(@Of_fhWAs`_D^2o]]=':KsmcPn99VoGCtCKP\73;K?l>O3gF-Ns`_O^l*e3h(FY=Ddt#M?Rhg^@`o>-OSSO&(G0Xa :Zk')4ATV0/&##cWpG(AWj ?*kd5sqG/9.H]e%GKb*bi'Yg>K2bEcb6;fR'j=Pg1rnSL<!.=h.H2QJl\M_qD,J6g^6>fT)a?@3pMXLprO>^Uo4`ba_"i#tt'CAP*NP'Xt6tan_SpOq/Hs/N3V/PR9Y.>h(#njXVjDNmDSLEJtA$\V@C[>fcWN>3(Y9/(\,]Vf; 2p(b@$72V; )\$s*HdfHp@j>DLD%N@gf?:_8[RU/O"Q[1jALA"[='/OAA)-i=@'636!el8[YdW/V(-d3>T;S2Oc\PR3QZ+7YGG6#d$ mS`#CnW9iANsQEoRP3ZU2q(@/AGF$8MWB:bObcRSOR'/;6iOD@iWh_M=/Q;fQ@^ P*ipN=7GDGqTC],@t(@%+1_LjGq"%HbLc9/IJ@Zl8sBP`Mc8C0\m5:s4Mj"gZ&Y3LhKI7+`m#(@r-R59\/I\$0$X!e p7W>""D(/k8OIt#3s;/0*7bYoik[F]4"6@,2'" WP@c5?l' J?J[TFE*d-oOSOTVGq:a%giE%Flg.bE626m-2i1h06BnFJULW#!20?:C(7D^9E0%hrZE&H^Ve4#j-W68M\.!SdPG<,UA;M)Q -$[7gT;j,N\08e"\,;`6X4<^2AAbe0HZ`Jl]\8tN1P]-HI7pV:Q6DD7$k(pQZY7#OP-G %3co4:Bj.A`A5_iJrljh"J><-ZK^Gm.b3[QcPripbVm/EU0Fj:Dq$D`/*hJ\*8F8)'&O>YHQn6MSkmMdT^gd-NqPt m=$6iY6M7;l!l4CB>Rq2N=O;YSUi&bA8>)R9A&KJJ,A\sBCm< "'#!!I[*Vm;a4Nh2^f10r!.p:LjdF77_rg@V*XU%!t+`#/elU\2\lk.@Uf>0tR8$?qQJ_:kWKJpe['.iiP'G/,Z-L8pFOqo`KHFDsWdbG0n5aiC?><Ha\cmVls(RBdo[KpER8%FWZ)gJ(4GKPZ7;6h\daAa?j$AA>`bVT_&"A+H\hW2"p!4E6CrV$*#N9.LL:5tM.KT#i;\bJdqR]B94)i0;I9)/;_5_SR"G4T/Uq?_3WmY*Yq%6K^dt:d59p`jeK A7Z^U=OOjHR2FeG0OT>S=mT-A#'Yc7s s,@_p"Cb#T>.jI/9:8;cS5=jsSXE5H?(.VlG3CVaNG(*CBam!?S5B-Oen)\\p>"\/!i)ka$m0i,8S6no/o-glcW&PAcA![7-A3DVSAA9js5H_.%CH=XT83\Yq^+er tWe,P:FIFHiE=1K&;&5+@jj&N!]%i\Fq0sD;9cR ZO0P$4:?VT.;hFi_??dcI"pDeF4U.(BS>`oqn]VA:TksLA\OW18p^FJhqX,/F&MDPFm1GfAd_sUVC2P DUC rMl@APAG9J8+r*(JjR;!7Ddh:nN#'BH7"Apd,iKd(&LW^Q*A'W5$=/H)Mn\2a'h]OXO["oUSI"$;c]YhdsU82dWk'L.ic o"Wk+<:X"N)e_DdrW1_OL0#ap []DiN\JjPe"lRaZM8r4+ag'7=*4tNbea=?;2HK)6%?tD982!sdEd*VDh,gqGpD=$j;q\mq]c=r@ .\Zo+Gj"FWL(@/4[T%TQ@=!b*! )TK$!Ih8)i&iP1HbDk!G@s5A;RAKR+JPgi\Y1jK1l&5^50S?LMPUI]rfD&^6>LAf5[7MmdRNp?/!:!`3@ @m=/9C3*c'&=Jlb8^?o:`YhO-5GrBbqW0S_*:D6G'AcGjrds#LI!^7&RT9A>"[=bOJN`4oW7f^p`S^J[<(iA^7.$q0Ad9s=6-AcK4r?h`EXp9(`g59GJjHSm%LIU+)O` +05ZHsoZN=h`'"FOc:T;@_7CPD-TWFg/7UUAQl^&,_)IAt(7^3g?X"1']/&b>FMD5p%bgqDHd'+a`\*88*$BeHJt K jm.: VL)cF_=R<IK^\8Pa-)mPR,n3bNE["S8>^<&hV'B <.p0\F'E;Ze?3+C/g@2-^LPA%-Wt%Mn?%PoB[r:=U48X49Tl7jDQ-WC!LC:%#5l[3b]>e0TDkC/Kqs->A2$7HgDU\Ob=*= a(%j89@-bhMa9GMka%/')S`S0@2kgA9MS!rtX65JBEmS?h7WqqkJToGc@S^qK7S0Mi.@^WI'Lf1NZ(%hA^))K*%mlBs7VE9M tNi@9SNk4F1ah3?<`WWX!^:b("rKN1`qT&[))Pa%h#?\O?s<IT_`'M'^tB9+grJ3'/<]d&Z]O.n1A WUBlaE-n-2TDK1h+)ig8g[K <]]R4(#9fM)C<]\HCZ1YdaJjX?+K2#mGha3>2#YYOVBE#jcI7CHR__T9Qd?/Gm5[tRf8tW8U'id fS@_5?".$I9)1Ve?9J/?hL:rHa>f<>qAn`Ug?i^R=2IOYq> Q-WJa_S&]S*=VhPS`-%pWptKBhe.?IMc/G3B/#m9lI?p8e>FFpt]bT6hP,(b6o6=''.p&rYZ]niT?L(JV.1*I#qm$qGU+@1a@cLdC+IF"Af(l1J6PA(O?[RbhZIp0IFooE-%j...DOF&]^l 7J;6pC2CJ,dd[#W1cA'0Xl!nH:a24**!%kF6\S[cp!PhCgTLWWPsr9lV.r_:HUD"PWti<@6R_W)LCkM<kp0cnA> `fcTl.;1+rhbXX5^=(Ke@^b')g,WcdX]c'j)@KIc\Ng'-G1@[:J%MJ0E<*&"f3MT*$fVTQ4=:5l#pAIm+ns-,:R(0q,.ibo*21jq`5Mn5"UXX_n/J<cg6c7j82V\$H1!mlYnj7M0AA[8X#)=UG+;Qm5G=`5g4*;j6q#q/hiOATs`oLIBa.p7][34AJe_r/q,N(CUMO4Seg%:(9s:FqBnHLm;Sp^HNf%fAs6/DL@GS,=F2<lY+b+4r."IEdri4J3-e$?ZCl-W c`+sdl8-'."@;dIr>l0H53.1=>IWA?Ac3_th=HtF?p-i^VFsC]c)4E!>+AQN@@\?IH*tN:NBt$^Ab=?jj;lm;Cl[>DV.MJjpeXd19lD4k28tCO)^Zm7kZ'bOjG-Jnd"A">-m;hHB@g)p8ZW.j4k^0/k7DRD=Yn0=-PD#]%5kU@eK.\H;H59XF[(hm]qV"R@"iOA1M"]MQR5, 'c2=Ph.2sbD+HmOZAp?_c]5mOg]OM;1:$_QkaS$csUnd/)e2iN4>IN9UAJ(J 0Md^]/dB3N8"^q.j'bfCjOSs-!rCKYUj#;_o$54D,Lq3H0MB?ZCI*C6.%P>ng>EW#9h("sMP8(B4l;!oe4)'&&,Vbd;P-%VH8&q:=/e_(4#4/:nNho\*6BbMqG6)56F>gpEgZK!nEWS,T?r>,ApAKD9E lr/1E_Tk5o#XUdGYft`5194^WV[Q@;jA)Za1NOQ-a"5;LZ'YB!6RfA#sZVIf(\6B\irp/KYVa[N*8m8O(MK9+JD=m;iF4VF@`7?mhKA>bdE50AVVJ6Xt_#pgZ7,U"B#=]*?mrF3MAYRfA"- N7ZDanqj(hK3T``#mfi,0 0tGA(LbPL0k0DWJ8XS82,b+*YF;#;_&6-&Q]tFMafcfC/\r_QIdc kd0.o#^clX.E=3'B]78%oRLUbCd8Cdit^GnMsE#pR:=qV0% skgZGnOK:scEd30<*f'dem[/$!B!jSRZah// SC29rRbrk"!A.i%[!Zlg:&O6%iWnM9 8^e)K$` .G-."W,QN2rnGm(V'LEF*IUT1pmH=iC$@jp!D@&C!nDr>5FOj^N!5%Q<(jF@5<1N7^scFZ"ZpkQ=UKL`QqZH&"6Cp'(Q,H8ooqZc.\WEl1 a<GHjI%;4#!Of%KUc\T2o ,))^fP#[OhPE$(3N.hBU(Op0'?$1*B7"I)R^IA\8_G<*j6h>UR`><5 Y^l,ld/f28MJXjV&$I&T>$9g c[K"d\mc7OV#Z*Y$M?`Q(QY\,_\/@r5H \McYaaR#CV=JK(A*.LI_aRAArY?AjK+R= Pn%t'3dX&ZJ-YA9p(q')@2F:GVe9V+7j.]pdMrT QF1V:$*`@.?atU6Yi;0+;oNA_'Va0A38-sf6#YZn_J3WIfF Fsh(TE64S5-=Z/L)#J7S.Hg_oYN_e--jU2oaK=peMh`Q[$D)dI5q3tA7VDD+,?iG=f*bs])J/8;qOam0mcO$FXp4jQqN!iMM'KIE:l+He=U[8o/9/sLtd[c3oJ%:Z5hVVZ"dO1$;idosNDg,(A'F!NfeY^O!akMYg*SM??f73PL6.lfHY`r_I]-`V;.\A9j8h0*Y73ZUQkqo!Io%i*+hO.G@,/d_%'FO9dP@^D"l&Qe*-[$!^=X)tKAH$:TAK4KQ"MFTAk818%GnKgdSG]J4p\8K2ZN".1om'PN+i5)lI1lhK8ik#m3jVY'W(+!%_n*W@.KUQ+Tq0-JE -7G#gd:ARilZh9/>]0,_:kTKm!F_oHrV8Y<*]D4'tSieR&AOkf_?J'/o:qPdReU)LmpB j?;In4k?[tAOi+DZ_7&<2GMK76BM`qMUc#1#^Xi%(H1J^OkS;a/^ANh8e.=-"J.f0\P$,h"s/,sW"Oser6QcaCK[D<^:pbTZB_$q;0FT//eqJj-%KFO37,%`6kg6B%`]M?"8cte0V\*W#&WL9:5a+,-(h8`;;D*I@:ZoS%9(oJoYfGoSgUJN,N15"(I/G?G$G.t#nspAmaV4KoAIEQbi-\4R?t>Aq6kVE>3X"XFVNn;<:;]r%'p_N[pjjeJ]^W :(&NdMqg"(!'F*PoO^!\f2q!S]\Thf+s;9AI_3-SA@k>p/[Ah'WtN7=#f-+k(+p5]e\^jQB6-rDWMAb,+K0d=WmR.><:Xsg(fR\tMOkh!5'L5@BsTsGMd4A+[ZSZIp%/$aPAAc*A>I"h?d:^? G)snhb2eNC[(J8=I-e.nb2lLLQ#TVNLli@WnK`PXVI]M[ki^r0Se4?W_&9M%)\]r/0lcJD[Rl4rI2qG(_]^1,`_RJ#YA&Y3JI,eHKKG@p2##LQX.89hjBo!t_,MC;;I!TWAp>!sjf.^,+sZ=Hr%N2o+cSk.9lg1d!]4#MX6(]ReFA=!%"gqCc-MW,8#C;c=th*btBtJap]K\^+lV?\>[;Ap8<&RsH8cH`#VS^J]?gIJ5lo'9Z,GC@f,AT(>^dS2StQ+mNQm0e`6\_:)?/Wr?,_^'ea6XtD2fY3$hTp?eTdaG<+,!fsOW1-^B^4:8d++a'ra]JQkMO9V#V2@U_YWLW0L)OSU is?CXFt'5KA:p3ZY/Og!=ImOhfIR4@Ebg3AAXGh-Xkr>!!?CbmA;M$=]<'C[W.i=B+s4"RG.)DcBm(Q7PB#I2MiaYs?\VeitrGO4@U"ZWW+>5V8/C#.hP(`P.9,&S,8[6IO?BUO.oU[*OAmm("Z=4_) RX>'AjKETf+?Jt`28%7n%dnU3bRc0=>PnWVZ0_j+/a5&kI$G_=Nk"nAPVWhe0PV*tIZD&*-^]gpV0E1P4A]i,DH8j*@-@=W9'B2DTA\Q23k$K./AVc':YSZ?%dQ9[d!i58q!6$qP*J-.i5JAj1[1J_`lK\6pIhQ`;pA0'"XDL0#0oV;N[mZ)e$qTtNRZb4AGH$S(J9=ACXY)jG%^ggr@%IsTQkk:ThT`@^qJ8[]qPj8$.lmTp,H<71TW@ASeAY:q.[0mZ5N,sA;VkN=6?j$E`[SPR 3n*:ND1c1-L1KU'-WPH6QA+/E_bph'83j;eG**giUl6ASo[]7m2[^T8G6jUUd@prbCrAOVlgIU[9_chGe;^X@ T.a:+&tptA0%5-p#@#$>r5T27#jKEjFHtS15pplmSM\mO`"FsN)d2jm9KKme *OTa="`gABf'/O=2@,e19XR&<8p:1L&U,(@DBYcCGOIeD7ajB<-fbp'\V>q7n>o8fBkERO\?Q4ie#pFb eSs)QTR[pd1`-YS=Jk/9Y**^`p#YPQENmk6UU-"]E'ZP?^,L5SlthTnc2_lKd_>imUpXBVDmRbd5r2-O?G8;6=,.$CRMUdZ9RVs'oPB *U9T*&Hkf^]Rn#VHLZqlh/JJ&Y`At `hPB&TR"an*#.J0E26`+CW=[s;^?%gebsV+[^`EUZ'aFMS!NjmBc cAG=VO+]+M[1rgR-?5lOMiXm^@0X1"7j_=A& Je2mMh_>M'mat?$)l[S'YjOsH]l ek+Ls5l8 cP,=`MW@m UoEYnV^MD/A>4mN=4?S/Jf3*>f%V)B@(;A$Bf^IkcLAq-T(f]i`7i6Xf:%=0U>X[+'(ac:l7o#[Pp;;`&D+CLq:U"/k<";m/K[E/L"23TMi(bf2L6A0'D3*B1 U.-]Z3FHJ/#@9'V5A;Tah)q8)4]JBp+%7>nmhS?e79@Iq/C*J_5r@9_ZdsVc5Y/k`BkgialL8::XP*%V[cg^&Aoje_/c[ms_4\N3`Xt^(KCneo>^ogjDh,=^/RP'-=q(!%[B54UpT,ic%K+RcrXP9sKD(0/m%>ZA:s==@cAdm`aT]JIC63Q0209[%MM;9:d.`tnKqFhg,3(YO4]4 =@&[?%6VWTA+K=A%`S/[jRA/rCA3#BBhAdn D8p'l/W+tiilb;=^'\GRM(8b"I.[?*VF,+%1"_#J8mL7EYJ#1T%Y3G?K^57Xmk(TQ/&Ajl6^mhsR0CB12Q@$(tBiE0YB)Uk;A@'tJYCab76t1Q9Ta*0f!AdV!5!3%;K!b<,N&mO%TdK 4bOOfn;m`I_/:nHcOq]Uc:3ljjJQop8strF,cY'Z?ME[`ps[+adMHJ2A:?)ffMG@OHf6*,W(kDNM:P&#"f=)e3h%4^]f=0T]1+bapD=A60M&l'b^4HU\la-I-j<`A_"/V#h6r)_Ti8b)KG.K>6ECdLQL;d`VeFI`8=)`Qh0ejFQjJckrf,><6bBmIUJ+rZ MAs)AJ'*[qSIC_e=K*1P0G.nW_A]c%)H*HR.-.g-oO7C N+Ie%aZ]_fDW]:S.9TZcXq3*ih*a)U6k)iqoXs\"*dp#U&eM%A6mVd2[bp&`r$'^UEi&jSsWU,OjYX4r9$AG*r^Db71Ul1M9m8g6+s) CaaTI`9#b)U1AOY3ALhtA#q\_+]PE2TiW'6aZD\HdkD)/Up.d++A%I^#fGKAW]>CtGt@A.Qj%UKZZHNnXer;a(&?Bq,]W*ot]P9e%iZ@]lXcdPU(h#TA7HGT.E8R(h;EB9JT15I]q)XtH'h[0IjLYE=/RFFlcVS)&GK"[Ag`+GcdI?tTD,_XG..XfWAl)gT)7dOFFs3jC#ctjk"2lpNM!Ui0$5H@ja;XZXDT\FMh-m ^D%AIc;N5A.j%o%"a>#'h:kjq-Al`V\]Ih H>:F1hd,tSoPac]sc\'j:4\Zfo<-%foa.F%XN@]ZYm+SIFi3f2)prdB/c$U1)["WitMkFS5N?=b.\XXf4D@[A\\jpg8iNkRCch?pB@R3$:G!X'O%-B!HRanglMWA#5eaF2;a 2TCs_>cEXqFAo7-<l$ ?4krlJ/q]K\Y)j_$AdU"3'P`AblRql9t06f8(bRC&*:[#E5c6cnNWAQgS7aSnn1X7rNM<c-tV+Hpd`MN$R!AL": =LdPZ[D5mg=%sD"TdL)m;AaQ7P_-9A2s[.'TnY'6"C6aFL!a"G][8>&Z0U1iOHNSG BShrT+_I.=P0:S]oA[]6&,W.`4_+#j5G7Qk+67og`SA8X5RB1)K9WG\go0C_ao<m$^:m[JAA4RiVWn_V`c/am _]F#-;K^ HV\QBI4UD()0+e>N-2sI8bQ*>P_NM#%ie,fA31lW[sYn)Z-r#>4lA[C@Spt9bG0YQt_;1$V%O\-Srhr6H?jM\GX"KX!CpVK,)Z)Sa/YB6&^i4TpU\FNZUgPQ#`l5jnK]-.A*l<](I1T)M mQ[TM\;AdEF-n'*f[o&=$SD`oD#*7Kg#R?0'N=FomX:N"m$rM H*_2X1o,RRolm1@Pe05A)X[3Asq<ig!'gbhLPd`1t_,eA^O9R] jl+a=jlE$g+k<"$lm]FUTi`RPZ?3BUU8A.F0lelo#drgnH2oJ -dd6*>n$r0RHNDAfC`JoA!e*.E]NQWh.O8CAM_Yk%s0aaP22;=30;9p`,liM"tl\@(q9K\<%V!ifKFoh0>QWs)RDAA=Ra\o]GE"3"T[2iC$PL_ M, TFR<0G%iR[j=4EJLZ:iHnSsAGCQF;-gd"'f^PI3s!WP[gbp\p2Kg],fl(NBF,k;l[bE'27W%cKWL(J,8RH^PLqi5d[&W%Y5iU.IH5\6PfP"-2htG-L#W8b^"J%'XB6nV:Yk7'bE`sp[^i"l@kZ@\*T0jnA4(]_pf=R^SYRG+EFQe[V&iW3OMp!VRghd)Je+^<VM5=f^)qNs3.KDRBCM#6gJL?:(e1@M\U.&R2AJtbdNO&9 [\-T"p$+PLQ$Bco QOiA;o;N'HA`eAV+654S[o4[>]AjcN/g'VJHS9Ltn7b7*kF5\\`rkP@ChHLh"]W8!;V8C)&^%qLE?Mq88IHbJ-eA$;+qOaB@4kCGY;O=d8\.oRU%s[]O?\D\0JO98 L`imB\!#rHo0]i+02k9"4#)5:% A&9Q:,;sDZk0[o(GVlI*T-W[-G#J+-@r!,AF3NG6OhUcK-hXd(##J85GUGZp0Zi"9_Pj4^e])>UC3I8T+Hol=BE ([Y24p[<]CUcnR-,G=hO3WH`WDo]5;`=EGi3^d7aj#G.r2kEP6S];>ab[<d%03jh2X1\'!2D'sl/*+oZ8;&\"VXrI);dL\(c?1; Qp]/?g?:.b8%J!N`31"B>Or&U"dHHk-+.`=27f%IT+#r:$0SfoeZ%p7[4RG!3GTUmO/JVKYm=5aC$WQ!X^@"9li>0s2qj)2G,AZ6%F&N#lHlaA (B5r5U5*TX\LJGd1!hOV`]YpD)_>[i*T,(*_oi*"b6a-am,)Y"nK:-T#Eq"-l>R9TSU310G8h?gm$[7DgXt4B2i7fB+IEWi`Hi<^lRseL7U>f@*+N_hAsH)J>f?[B$(-,E*58/44`l%/9]6c,Kj)TfCDaNAROGXnlUaN=WIt_!Y9b5@@?@57K-68'\0[`cnBG.YRD@coGCTG*&ChORm*2%a"<'0s7TKC!hp_`.A2Vi,d*)Zd Iq6QK^KSO9[n`[soc&tHMWD`s=K]1h ?BbJ?pH.n>A%CIWKNsboRXU"/p%Ma"iVi`mA V'R)b^e^Ge!iqH`dqTs@a6\7EA(lWKVHW^,,2o5@moD^Q4\GN9YPjq7K4e`AadDQL-R]3/b89]MJ9jf7*2#m>=*RW&Dg1`A)dAjA`^&]^,OV.iYWHliSEStGtBgt71qQY86*KcG453U//XH5:'^R0<[=9h(IsMdA)$%L(R'mAW5BRHkMP\5dm.:"J?0]+b+=Eta#\XFb9VpAZU6;?1S^VLWq$\!V=./:2\+lnHEC=.oMSj/E72a7[kE1ZM$ h;m1=lfT#32?VZoCDnK?EAA*MJ%MGB_l\<&/P:3%Me(rQ3N&'@,b@>KGk`4D^h)Fl$DmI>L:J>^1"MYHK.o^!_]!qj(Z[=!'3S._MeE1GdPrI#i^#jGq4"h\DZ,?i?jdXMcI\MtsT1:(PG8#?DM?Zse)Gi1OC1W:d`69"akP7!>:PcQc64aGhpcnC/A+d/nn@fQsG3D@9+i"GP?G9[f.3W!RACAqVrdn!k/VWJSfoh;f5C!H:a,M@n\7_]oT *>nDGh*r@N?2;9"6cV0-.e4](:FDEas<%>X fle&l=!C,q;6dNIU`;?C#[p9*d+'LN_aX;a.e2PGRkcVPFIk3X*q qM`"jRY?>#E]"-`YLK[C:QTa/,8p=1J7_rZl7XX-\rlM0;$HGfZSt;_Pd/DPlGJ+E*aaO!X['htANedI)<'j+s!KKh@q #VO!HT3m\SF$Bt36o@0tc-ZYFs?VnN2)D,?Nf^['h4m#0;OLSfOA/dcHiX#L8b4dnDs-nV_btDU6gJ+[C%Q!&9kL^.Xh?JrO7jiCTc^3d@;\$,t,+JQOjjf^FUj+*m+*A4]??RgFBWlA]bs/CcX49ejPb08lN]h)>=g_C9`9sY'g+e3;A7At.1j@>4gM^Tk0S]E=;r1Q*p)8ira/O:I+9/_QiRc.\R<,PDD_lGKK4ff**n2A@HK=&?4IUAk2-S-[E E`JepsjP*B-$@`KaMlrHo]6i-PBP]%i]$/FKR=$>-Nj9,m.RmT8H&h.Y5o,Y4)8.MPWLmnRC$A.D0pd>3C_sB(-p%7orENVmP6Q2kd*SPg?M+GB-RBH0'JU%NVt-qg%>-A-Xk'!V2sEXF*"<2[:htt#e L*[AMYK3B$ .lH-Pk85-mqpcW.2o$jlf9>%UCd%E2(O6)#kR1,1K6OPDV1[2$&)bJeFc/R@(2Vr5Ko==WmK80+s(4>Il.0SE XX= )-[W"=@BNT//C4EGCWVSGo5/iZKJ@$A2:5Z:02L1eR-1Fdh[ljahX"+-XaD&c2`=eod1g"_l_mIK,kVP!.1^7J3\YR%G0Qjr9N/]hgAdC3@bE$hb`$[A:f+Bp1rYU6TH0!KcnRN4( r9 ][nqNnS[brTD(`CEkeoLoKAZ-Bn227d-k/%$i?aU2kD`I!Cjg& 'H-/o"E'7bdaY1gL6bpAefnAqJabJZfnQ"^G@%SV)S.4 t>>rrdNp7f5?Rb@EmA6_q@(%OCd^_]SDsbgf+C488AFd%Kn@dmQ9D\8P9dW\^/+g-;_?fDr) qb#AY+T"R^]JkF-n8IP7o:;Q7W=4s&A8?IKrn0U9URPPf0Mj7^q'AL^<(D0:UsbP>HO>&N6@J1`s,&^j/Gi@^#i+YjnEf>G&!)dohal(\&Y^d\Z0_+LC$c6OFV>iPn9WCd`?eM:-Ahk[#"daffELAi^sAqbgKAf9q-+=^V#4:WJa#fI5rFrU'BM:a?b-&_-j&[T;,0KH,!:poUkAORn6L-U9VsCX9r<25r9g\hltAV79W%b'k2WC"'E6H*:EA A!V1`PnSba\kVrr'AVShRN[''U60+%2)kll<+f8+MefEDtmsXgB^;_O5A6cG5j8GpWVs#bGp(;;[oNB9tD,/D3[pcJ.@+@=n\F*l!CHa%KW@(&@0>=(W%mOj+"?og>4b;3Yl]ocT0Nr'C_o< P':8(\3.Lcs9NB8*WPk,3.[_29,Wpt `+h%:0\]?>$5s56aeiS;7;tHIgZ`5j_WONE,e`gJPR^88K+b VMQ jWI%]mc)3]1tOt5\/?;TM`=$D# d"#pfLjUn"Ns=:RX?gObQa2a[i2g&<^(jG.ZQ]>rJcqWpPjlA#EYif^<&.pAl\3=H05lr.=K'@dWb@AWZD .""MQ7dsXcE^g0t9(:TYUlHjY>DB6DgGP>'9[$](VBh&a 0t&@Uf1B9Bq4ef$]sPI'S'"=ef&b\/j'HAM"s1tPkh-^'GV4j"f5sAl%WCp[Y)9HJWC]@VNTf:o+'5_L5 =R[Y50##nJhCEX 4(!G#<9A?oi$pq`Pl&`lPWVAMrBDYaVam"L70VbSbACEAi-;]WP )>Rp4ep.3Ap&QF2Q[C!LI6WM4a*f)62!>29VZ6NG]7F)M'%H@Mjoq#H^+.XZtnV'Fp4H#Cp?055[?AK3LIt#_if_"9msn[+Z V##)Vq\/_>kM%I.,h=WA4[f+Ds:SVRAoHdn!o:CS;ejT"?@k-Qj*2!#eXpm>9RN&JS$Vn6kq%iOQ-g%Cof=`\A']IGVV%0O O7"qqeBtJ)Ula4Mm*86#QQ\TmkR/!J2G'?6e`)6RVq5%*ItWq)P:5pC#X!:K^# 3 E-"eF@s5X9=$AZgJ>>YfZ.iq_C1t^JgZ.4D0]^88G[gsRo+=^/8d3e/(lr ?n4_4EL&%VX Sr$$S]@@d3SfX:\!>FphR;%P$R;TX>\$q=%mafk\@Z(C]/UZnI9R"P%@0U^_pf`opkp8.>?ZE/c&FVqlGBdYsj*S!Dq^8!K1?%mR:g:PCNqagL8hS"T(l[ ^<\J&9ZN%Q!AtVKS;DDkbboAKT'nkBqa!Q90#LJR;..-te=aabVt@40KFBr8h/T`Zr"A-P\1`84Xq\fCl:USe'(eR>dblk.#l^YIH,*rbK4(Ws,:?Gp@d#W0_+.,2aiK5trRDn`KO(+4kemO.lJ?g^bOsWG%D^P5NP*$nf7kFG@%0W]MlP*3.$TO^l 9;i'p#OMAKdl/rKO+jU3F!JBFdg!qXAl,&sR<'o]*p7V[A\k[YNQDr@"oct>!h8eIH.QU5'6L]Vpe*-0XUhJ,5aAkK:6]UlBLMtm5--at 3PA/YT@^D9!E;%cUR(ec5*-SHVfBA]86_b$]gT@ FOG!kf!mUmpI5A\lH,^sN- \%?.W&ReT]TN*jJ;3!Z7GWRW'[\]=Sf%A\GK$6,s#'Hr_ME8DKc,HiE*H@0f*_TC(8^'qCZrbh#.`50hC]9A!oK-Ie?]f^gZD)'sC\JEmKPK]1&6U:A<A=HOlI)9?$ErSj8$\)6.14Xla@eN,lj5+Y;g@A,=V\l7$h&BI];RMK6(__^n\[Z6rLKo`oO\q-p/$q%AqSEB-X"A=:AlDR1lKCHVl.Cgn`4?5C2iS>&g)d"GQDg4PJ,1.ADoP36IMsso$*m!@4"Geh>QM@e]Xd-I"C)D=`:$5An$4sle" +\s/k".M#dG 3T/,,LipcSZYU%c_T&O_/HrO+U,IA.$a+=U GBt4BgpPB`!Fj6< &#:5M<??Qr .T[`"[Ag"O^2!9 DWIQp_/7B.t6+aA/W9DZ($JcYDAf+Ne@iLs\;P`/>C'e0o,0](Clf:Dfg@-F"`ig:*Fr%>HIQ#V/?,t5H4B<Qs^A[l%88+d<$'aMa5Cm.fD9:A=LAHbpA3^M%5=rcnMAA$pCANJ0qYil1jG,8IPA/4.,b/JX#nhUbM%Ynn6S1]*=`pO^q_dlCh7ledKj1HfCU8$"sA=<\K=qKAfEX5+*?liR$rUBh"W`p8m(**5--fCj?,18QS"?h5^iaMZZI'V_qC#JPCr.`&0Q=n8LmNemp1Z32eBO;EACRQWaIaj0(]8dalOb@!NV2!tkfsC?+)\'f783/-1Yn4lV7c*A2Al9*8:;(^JSd#W69%p$jqQKJs8L,fAaCLsOPT5=;+2Sq%VmEA<1h#6J-KpU$0A-aA: $a'NV]oQkk^(f?eAnQV&tVO&a9p)A2Vf.ata,FqU]$KsTf']49JId2t'R"j7jO^$A;?9:0HiEii(OrTP'Wc_G#2W[Z^L2AieEf%=k&&-a0f..E8?2gh7=S^-JY'KkHm;ABpb1&)@lZ!eQ*!QXs0.qnTHkkO/Vi?pGje3%^0`EVcan>G`Xi XZ>kheR`oFNGZ'#pRA4:^2)Y).tsO%g\YYK#n/sA2gO*?MZLNpFXVcY@R;S:X3;9hHgF"N_JDmYCE,=lPY+"&qkIgr@t!!d?I5bMd^Jg2 IVIA=FRRat.b16dEc7l-V\7^Om3 LQd0I,tsa@fG\sOMF%P-K56+\82XDJ445em!")a.*49s@>W6`j)>]E$[5h+b`-ji*Q! gCZ01k%VIBlCt']*a&1 MUSJ4H+AH(BYE&B$7JT/TLbqtY9%K,r)Bt>XRsk[l]^9G?4p&N2.5J)4#k''Mq(1/FnAeCZrKqWASh/Te^'+p>)O\4rL[hY)F-Y+X,,@"#J2m:a@\Wp-]VbfRRl^$tA\!)('E-KC*[K27;KbY#$*l")_lb'NtU:GX%n=[BX`.$6RN5[["/$pA^,H5/*/;WF/H.D'As+N+/6.YYhfjX-a1Cq&?6I48OVR*"tDZ=#p\&cDnbnP6Qe\tN6C_Wt2f@ATsR8]9[0#s*IUI>gA^be#nKI`4fl-]%0qXQ_VM1Q=bY1hn*,3UIBIMOF 3@QLV' )F>H>lfHZs[P[B#bRK_f&d-5_d)Lj\*Z\Q+aI#U)]D9TN'&!pG=<8KScpJ'WjU?^5&-EaU$aU5AK)E5eCIO[TKt[&WPomg8`m=S5j9lUKB$`i GK5+qcW/>$FKQ:_rTG6K,#%PWP qM4f'E^ r;<_\Ja4/2Bo%a:f>)Z`X?)]0.V-<-=fkPIe$tRoPdI1M;;d0&1W5T$^dWVn!CX&]b8@:_AbB1c_V+,_:NtkthMM6m#Lh/PR?VEqb&lrCXFC`O!6+`Ce^5Z$s83MeK2`Ho_.jo\25P7ghe3XQb.3bfF&+?#sGeBp,?"*KNh\1XUqdn>j?V*Jm87r%U+ZCAgeF>\(9SPU@GI<<,C_j$QjT>J3k +9`RcbX bL!&*U5Il$PjL&^W>:$=FcVZ'qg-8VGg17-o1"B:B@iI$$'h:F$5#We1rS,^onIE?S/@%_gc2oC_ AG-MnMZ b[i ,-#BG_Z/jh0;ebCkqCQef8UO"$M1cW O"Li;97/9?Z1bH8MaXEi;3aAC4-2dLtfU@_=>R:[Plg8NkJF<4,dXk\WOq)tSP=T^)b#G+18Emjt.eHFst,G`]Xa(GBJ=5;"/>;/=&* +'/3`Ag kI-[i*Z/T2#ZK'>7PaVO,kW[20(nU+(BqGB@AaZ<4:YdG6jUAXB0CVteK!7Tn0Ai&rq_J4>O>siC:?#FqO6n,NY\_;SElXKtLD7WQ+*/J_Q19*]D"H(nP4,IA)p(M\X`or6MdT?RU5d-Mg8ZU)FIn4Jn4A-AF[mQ`f.a`;j[AgZL>3$<:jcnWk/!+Jajgf<F!&Ap:Hl \PE$KX,Jd,bnNr<$>:;p3reF6!Y!$f`&68$COR <["a*O2dkf]hWRNjKkl2K/Ts+m=@TjE2%^/R8ST4?+*cSY`M-+`dNhd+Yn3d9GV_lTP/3#^LKM!h-j#0A-QJ98d8(DL]Zjm?',U=+O5e_$8E)ikIY\Fbc[PLVco8:NYq/dIE`bYm)0@7Y+[DtHrlTd[B?.TYG02neN7s=fF#HrcdSe#B'R\a(X%hKTUN>-Gl]VnX-i)cVVI4'TRSP-X3Y<7,K[KAqoOIWbhWD18$\*^h P]LL4s7*KdbJcX5HSOLjEJ:DY&SA,nZ]\\b&^r41nPIoQ(83k<:K^]oW940AVfHYIb`GW2,C.G9X*tPI;G+RrZ^c65Ar0lp3Ah8Pc2CAgZr=9DBe8X8JmT;7*%Hkb9tWg;Za)Lj(VUX.>9/XbC>GrRHqtJMLA,,Sc7X:<,SPAVF]iC?=7CX3(;Vq es8I8Yjb[(mkYc%"+j!hTkP_c+_K9"KLjHo_2)$^;:;G;B@`!$Q6(W0G Ajb%tsAI'YWIFM;gE2;05=$db5GT#s4i9)bp//Q*GT?EknHAdeND;ABONA]*fV&3'-.@ae oWH0dCS[?5DK!gqA-b)I7!6-&ND<'@i ``I/YqMqY-6d$QCGOR-IiDk93Mbrcrl4K9/mK*5MP>AQZ/m6_EEti,m"A3X [fY0f"(g'ZQgE+@-OBg]=U CN"=?1m5\=&h0C2G3t-a.Zs5i-PaF1;QnAAZHeio-9sq9\UJ6Gj =W^(rnNgok]mS>Fl3Nb##)6#&DVWKP=+U3CWfV ;?<?<+cZSpd-+3V6o"!j]p53_b3KQUP0G;72`'5_ipWF59>/k\S*EjnOe,Ep=WhR9ABBiWS-%?F.6NQq>n#6k<*H`8U^B88+:-<(^=T,5qAp.OW%i5ncXA'[#2@72_tArB3s?'6=^faQ[ak/XQ*bqmJQ`C6SLM'E8i^Cl`bp!c^f,_5=t)o;\G*0(U/"m:)1qC+JUdt02caN)oS(WtK$=pB/A%qC6:Y`Y4E[UK5KTG47mePiqFRacGX9,ps\M1sK%@r@S,9fV((ond[)ZL8@.PR_o+2U"J[IADF 3!5sF9>UJIpQn830RX2VfpQ@Nomt_h]R0#pa?lXDjhQ/ZqWjnC2T-5bNF 0E'L#-.t+bNE!:U_W/4Vr?Up<\Kj&/K.p@Zh%PAtdXJNA@F Yp4D55m\p]-[/G2PUo5>haQq/^^Yhl*Tn?Fad=jp,=Xrd_eN&0?8G`n%8X_Eq98n8O$hY=\M,[@n$b32JEBA(9=-AcX'H3BX3\Xs0U'9m\EVs[(4)&$9AkXc:(]HX.dL"Kq_mb^2O"nJ_A/EbFNXT9"pqsZ!FCDZ5sg%jm2fIf2A:_A23WTjS^?P5ei0iq)a/#:jV8C7-r;SP>M\c_coqI`W3ripm6No[M0W+jtcAZsPS+)BdFVh>#lZ7De 'ora7XVAS@cAC?CCs35JjCXb9'!AJ-D#2U;MO](q] ?jhTskl#V9O-gZL6!ad&b95Qs-UG5hNWd%a%C5B;Sq;;"A'P^0mJ]F`SfkP2aQ_-@BpC@TBV#DdfO7asSY'!De! ]IT$lSo-c;qS"Vle^I:k(Oc+Y4DD jQrFXATEUlm-3&3Za]Fg<05T&^!YLcL%<))1A&>1N.YT/D+):#!go-,+31P"MC;k0Y'p.<;CoJGo+a@4("!pX=?Y"$0E1Y"%UAZo2_]&KiNjH@*PKmTY@7I$_a)$1cP;OVU>I/$tG3RJ02Hq`X^c\_EMCX8Z4#q,'HF/B&KiY"IQ&p+$@:i )1)3/D"*m=2MHX\CX;mQ+]((C]`%$A*c.L+37:A!@A\66Fih9VRW5dQD?1'"t;fq3.lrYB@R>7Mc>mpp>g_DZ$Y P@VE)Kr.WAjScRpf:d+af_S39#79BfE00ct?DraP:=\l3hNQ9H9>3_Aq!lD^-ta3GZ\W;Aa7l&s`q1?"F\JOpAR&XW!QR\(AB[ X(t34Rf;1X6_%d4-20)=!4!TO8I.&#nl/#.P\CAYeHJr'c$b5EJio^a:e%m4tqZ$3H?%5r)E$$5q98rtU2-QbqXsLmFA`q7AjqOIK&X19N#beR,]q1>^?(Y*8rMhthFT1qsjsTCGFJ6BPpJCVZlWC>hpKt ljt#+1DDZGV@eci,19LnK]j1sA!g>f9G>&rDQVA7m#Y8a6;1q8f:3Gk(VAc8gKXh"f.YXb0(H4mc%#?sCOh#jX!/Qa^c]5@*NsC0.;WIMJ2l W/h2FWr'Vq),Jqd:Zi$:!eDaC'k;qG$1>?Fiq_hSJd."BEJFU!QIQ4TMd%A"5rD-*WAmR_BF;866s-s&Ns'D)fQKWrp%9Vq27(fZrjKA;3"NWDl_]WD+_Ji?lY"D%LRZD*7m+:(0UqS`3WA:;AG=rKUii]qJH[$+Cm2c;?te5#YeIjm@V@(E$U0XQ^-Tq/*V*@hniBiK$M&"3T1]hV3""q@-^7d+D! Ai5D;=k_t]Coa&&4UesRq(3!S5XQB"j`0B`VIhBt&O9q+YUUn1f'1GdoKk"H$&[A:bst\+V%FX1,,]m>k%b!ZY!]mk6Aq0aKQfmbA?`-"@&_si2ig^KnJA2i4)5RR.m[1C?IlAj6X cQl5)OGp`SE>4&=%)ofQ;O9.0r=.pcm)HY*AMC86%"g`2_Ac2n\?AbA^p]!,HKj>g5scI[8cL<f/$?!+5iQVL'_^D6WMXg6fE\ImXTjY2pN.aH-Q0A=/SNO'$F6%#B/;AgcWY%cP?14a`l=2BoFZk<`2R# 9snT;^9-*N3BG"rq q#R;K<`"eb+`<"ie:@sA:89MVQ8N4>2 9\UKt':KMRV7!>j*Hs++aWcJOOSg5'QcFV%E7"_I`k^G:Rj"rH.42PQ1fF00L`f#pJsroLXFr._M2]-J] ]gPaAi#BA7M8iB1e5P-FSl4j!GTk'*U3PnPZ)lQrQ\Z:EUS:9i3G87PB. GMM?=jr]=D4BWeWWtd.Zp$1AbeSIAr-+-GJDZr)g: k4EOKl8g?EMYqAmK0U&N7ogmHC!A,]kGG<>!qThP`+3n7Htdn9$#*WKPDe"Z@7?MH$6AiiS[RMsq+$2f-3:U7N"X"(1I?\="i]1(-JmY%Z/4%)^AMdk/n%=`%Nom@Nd13#(YD`(k0FJrFiI:a.F4#N]U2WcD@rkT!G:^k3t4DC'Rm8C]L`ND$q]WYe[5$m[4H(%CBe7.;,t+ArTW!=lTKmjn!i=_4#BdX(ds1#1Gok3GC;DcO5WF:7@BT7[Cqgo> B04p'1LQYEYR50PSsAE@1hi(*fjocJ@L),e>[3AC:_ )0G))l6p?05M\n178XlA#h^lpG)>\]DS^_D&mULnqgJJ:2^$AVa_lIFh^dkAPo[gt?C'B+H>,1`_gboi-M* 5 30GeG$5B*s:l:O(ZBeUt!.o#'^86\%Vjdb!0tQj5Y,IJ"(qUD(Apj-s3[2I]fM41Wj/#c@?HrT+J=/WlpU\>GUj]so=jIqEV5BA13AD"d#8hl[#^2siAb'[&!F_(fRH&%h@NAm3,>XE4&O4>f6IP\6%nTrb De@EYF,/Wbs3%@p@E$YHQE&Y`Y_D)g2@'/$4]p/Q#N)$XnatM:<:HrPg6&F7doN,Nen+bHtE4lJN&QT9fl^P>W3j&Y&Q!kra_M9[192YW>R`!U^!AS^62KE;=[AVrPK:i^_9] A)mU%SMngF]GZ D-Y+5S@HbHp'X^@*/V@QcU*>iA1dgK e<""`R^YY^):rZ!#9#=ApYQo.EkJ4.*EXcjqmS*:kQD6gYdi$.HBnsCni^5rq+SY\0hC=:t:UH,Ns9+V&k,Wt$DpSF!3HfAM^fI+-A*"9!=G^+hL9R@4XRG3S21VGfZ5a c!(:r+c7iel3(ZAIbQR>L1BsVnn3L :/Blg))[-&h`&IR6YGFCXBKV&G0)@AGTW7QY'$XC0/U<(W&*1R'&Ynk*A8Gnl]3j20ReM1';6T_BK*9h@bB k83;"nq%n]FqqBQp'?QD4>6oSb[4dm.:+@YRTFMABYW3eI.@<D@,'o##hVAP?B*kMl@cY+AshCHMM4UClWn#O4tpgtU1a*"5 cJ_Zt8E9640;C9AkBabe.0nZ%VYBYF8;kl`9^^`aF7Hg''q#]bcXKV#_@pj:)Pla@+ +!6A*no]^?$V8($RlJc]jXWj6]=9M61r*f;btbBT*(N5Fl<[ON+'4#X'hsGeGWpML5&6XAIGWjsRs]B]8'IU#-m$7i-RQ2HA)MqNU?/b_KnsYSD7=8>[d.)*SQs^K/"+n1Qe2B`R/+oK/3Yb@C.1O,>kG9d%=D8A2'aG6Ln-P7nrtoBE_;t$aA#OSj/#dJc=[X9D#^-#i1:\rjR3A*5aZC"2"bQ$otgkEkES\MoU%*H'/i;T:`f(n8:\;"NGRgBQA<.Z@,7a3R=;gZA9MAV6!KOH:=tKWJn)fdoSC=ttJ*N,B5E'_L1?Wdl-M]bGpf@J6'[gRU,Y#edf=T[($O:22\4Mo(Zn1E85:6lg4+"%K3`PtR9*R$tlCJ7FJ,bcbd^T_N/nA!7*QO\0t7JPSrlf:-Tn=q`S7WXG1;7d!N7a5<_6Ul`M_eTE0eZbfb0%E2])7@P3hIDkf\S>#i$Z*[p5>s@ZV9\q=n_O/Y)G;*^S>?/NXM"t$M@t'am*M92] \VEX]^G_XTfDKL4\tA\Ls)J;%:1E%A@8d>&[Am,:Ke\'8kZ$=(+K[s)R]rj2X'!ID"#VO.>Zh?L"0o-=pY^!=BRMA5g#ZK8-/:ab3:mo/F6tL-jb-N)At;%VA["R. _o/Wb#;5C_(NbF1F"G4N(oh`^$18bA8aL`8[>38W#c6t/dcEkQUoZ0+S;LS;G]a\>"QKCsKT4pG6dTVg@kPTZ6F$&*/p[c+n,XeFd6YiaE 'a'n;C@t".Bt*Z?Tb8A`2sErW0CXD:rQ&B?]Ys)+`St-2ikC#DD5$!LORR*jHj^^eWiQV9GF*EYnr.:RT<+^oe^,DR XQbpF\JalQlP2%"%Q9U(?XX&ER:`cSLl9-%78O7Ol3BJ")P![X?J?))$2T+395?;[A5/<4kqm<(tKhPGf*D.O2$-J4t2p%5OFiQ8Y^1#b,5gNYWsb"e/t[`JqnF(*D+5aD2!_"bGEcQe1V+>BARj*J:t*MR3.\WiSNg8BP53,knAVNm3:pD)pAh.JmTnC$A1pZ_$9VOs^[n26PgFb5g2 WWr1^#5TJ)F,2=R%KSp2J!)?Q_b$s9/?lNTAr4kb:/Zq'/%o%K>Kt1$=L5Nroj9_[3;.;+ld=j/a0kq.LE!Nfn?[EN!1@:GsOElhN0=qVR=ik0I<"r/m^ZVk]3.Ee_3;aACWCV<;0thiq]hCj\^3/eC*8Y^$RKh7^lBMQR40A/7P8Ap>4P).gUKPe2XD,f7pAV:aL^d,Un`am8iJ"+o;p7<(VIN"&q#g's^eQ1lj<G?q597IW]g4! F=<7I5A[,H@5GlLT"4dslHt[^Bl=0fT\3sY Bs",^K.Tdcj1H#Mfb\@cb33pkjI<'\dAk(se592g-ja-6Qj^(PgBUL"iSGhm/-rs1eaG2meF%8i7K0besQKi_?L@54>k&LhTHR!F<92ZQDZg0"GKS&9^eE]$7-fad7aLC=2]h.4IT'`XR(_s&#NEptr_h5^>5[2Ff@O[gNZ?\Pe5k/AO?MlfOmHL&jk`ei$r9hArAXg."tEV1+1F^e6WeTS`MjTM4;/SpUt,0&O+V'41Mr%%ZI^t#gk]<]Q[Epr$VD^00[rP5lA'OdjbU;R1FO&*#)e _"N/8KCEOi)QAWFl;47_k<[$PA0RR c)HAB52JL<.+TLp,!2sJ;,UGVk&L#ii!4V\mibWR3Kr6hp5;e0>]d.XHrKMg2*#IWT@6#f$JR>W6U#BnqeJC.iTePg9A?TE>cfs1Ip_N#L$s`X9aJN\Y^,2CTllW%8#r@MdsB^@7&MEfCMpFW0Ze#2!:S0Xm< +S]6lCPk9L%AFM$<.l:V5hF+eXAt]i>%)C8:VA&QY]q]Wg[;@G21#mO*5"3ACRjDO24Iq6pf8e,L_JWU )8_'+&O[Li'IJ#<&(IUnHnhP=7q)kf`2lX4m;fFq0!>)p9k+]a2 c*:'^,>BWlUD^W-63A_O&[X]Zkp\da)r !WRk#[j2H)N^4Ss>k3lVpgiLM&iSe\L4Tt"oO>s=Np)UqfAY/>LPQ[r0L=?5lMWFS03H,XM2J, VN,%O5&2@msR\m<(%sDJDPAT,`BL%sk@a9.sq7*]A;n5iHY^?&ail;J?0**s.^'C].*sAKEn4[D\Qg.gSg>jXFfX!%6AhFBt@mM<^8jOr#Ni6#U:icok"'d!r>k(=E*5sQkX?^<^-4R)X:!a%RCGU83k"P*:eNCCBfLjtA],k&+;oKc D+`slC\c.m8?LVsKJ*2Jc@%FC9Ql1*o%>!2hFqnKD0cUh/Ap(_4a!AYA(gf6?;L0"H0R#AM(Lr6%q@A#qfDo8CaZppKbk:H,UJepP'L" V2pLY@eNG`;m!OQIE!^?RABSLA_pb.FbkNoA%m_'F+;^&AfA@m]<*J?*!$NPKr-=Ze%kRU\gkn^gDsB0_?mk`QFsHcpJt3n;A`.0.5)5Y8NttXQ;]LW G7 b_3,XhdYA0Ak1Go[1j0K!-rC7X+1o;;U<UF+c]GFkWifp/XqsRTQI5PeL_1`b2]?(gs4b2PIBj8H$Yf?mq1fBcB3W8^#d90a2jCkkW&].9Dpt*)&3`=L_`i0UsGc8JEBe[HKqWJ?da9A)*hm%Mg!ajr[tm_V\/PK"A)4?>*9iOWE,C*tkLVZ^U-olaeOWM?hkQ2mFLlOfV5Zqt16o&,C;<p\4sI.a3-1n%"O%;]?@&&Kkb'do] r,Who/hQU<`Jt ^N0?d)pHl2h+,,m3o7\4k/3]4f78Y(=N"JRm0V1U``6Y&rBfgfp?'FG!bIFZ"_GefA#O.b>(LlZbfmbX N0q/c[@WlhTsEsWG&2CO=@@EFWdL0sAsk99o## L;[f4-*IE>7;%X+:A@F(=-U6o>nQ<#./LV7FPb1q!6aROsa[[\@I_F:/<2(7^TAL&8@Zo0ZcR.YO<+'cniABAE'>O:"iq<j/-P-VV8+7JALk;f>^=5NB-'3375YdeL hRCPe7UQXLT*bcA[13a"@.TWjViKS^rVT.L.`-o iS$!Mq?+K,Q1Y %%94)m#8g*i QMdVkn5X*1=`$&8jNs?/isc=b,*SAmYT/^MWA]"@SM(*Je7G;7QtkMfCo416#Pl:.*NkfSc]T5J;)!ff0m&q]`7,nC`bMbpUn\)o7=LTfP-c%mTPhm:?*![U*"5((V?8,FC"$3JL]7n`.>D$AjCl?Y/E%%C,+s7\Ee&Ch]^ m-tmoYADoQX6Vj>df&lXVCc?cSBbdCXEVaI-2;72PVG b$RB*iBT]\O!)tOH&fTbp&LMY bAB$3,m$SO;@Y>&>"SqE=%gLQKq@9A<%'_f6r-9V]`eC,9`!"6cEn:@e*W%tI Oh?Y[j9Hj#"t@.#K5tC<rGR=lk;8)rk]BpIS(8MCRU1c<=oq%&ra-'kPVc(PdFK5,ES"@(_I*)8\"M7q^EeWflUAVCDN\M'MJsTZi+kXPX)43T$.aW)-s<:#o8*Hq0MD1=8B23Sj:>J]qVVVN #A0/A#CMrgb2'slW>-"Wr4Dog[$-j]eo"P=Q-cEVCE.4_/'QR8rT+8=8T2h,A@'N/\NL8[.2K0T\;OS A?(AS&o2:S_TK+b`G:bm:e$N)[G=# ,@;\KF:R$&`D];41=E9aA)c b[Ks+K9l,3r>lZ%LBs`(AciUpF;A*$"^Nt-i,F6d22+Qmrk9@s 37'LPk3-dHad;Efkq$nJnleeLA$YIASX_A2)bq15M'1l@W@=7Y&`bqfWO,.6p/pj2^8/=C._bId'"Td*Slpmo9JY\@Fj7L"(YN!jAON2CAtF`:rDtL9b3JQ7\ZmWZ1LnD9bi,liT0(e HY);_0Re%r1=X(>fl\9`[Pb_.O)3TeSDF`+h@nQfA#3SZa@__C#65Gc]$6J2R(sBFAj)A+VL/"LGY5Par[F^bo!m=sbTY-&aa^;LeRCD=*JNrF0H[p0U1*U@TL=2]O.?iK6,$T<`@/;Gme^Wd$\nN_/b8Ra]pZFeq#g,t?D-V]M5$II3(^b.17rU:(%_I!:.j3M1oooLBP2SW#(V 3I$9CVNU4mdl1JpP&oq>,`mJJiIf5e@\H8i@IcP@8hk3]O,\;43*k4?'q=12)$A6>0DB:7B_el#XZ!U.5C ;/?r:qM]QbO3I&gA%#.RncpfG@UGTU#M) /SH+"r;Z(mJ+M?i]*CcU#dkn"J<4510Z.$YcW=Gs#0N:7"?0X9(C$7,ZITf$-1<(YV)i/8it@m;42Hs1b1JZnMC[t!4YHU] @*!q^3l;bhQ<F&4^(,TTgn]IP:Oo9.=?>sQGolboCh0L3oO\a%,eHENt Qc&R24M$j0Q;C?b^=I5=A.ZA>_j^GY]Ds/D"E(jRf@p%dkE13&O8AY;^Or,!?IYUH%F5k_oCpY#A"FUWrD*R9Gb8iJOi'HAKZ/2:RYhToX!qIIp+`N\Y2K@ e,_3i;9f.LMmEO.Pg\6b$tjF5[sQkd,3XHK&HqVJJZ'tUcnK\gikacet-hQlH&pPAD5TM[ehBh;)LL1[#-O.e@-*DWq?7aeI2;LG%UF;_QL*osn[`TKs^EqZ8oaE'#:p23P7h>HBHd`#R;9&tS(& qKeFHh<$4'tG!TdG[L*-';>+RKU J$aNR2O=E3I'B__9B_\BFolMh"6O\4rPq$f[mXa5'3Tj4I!5t!D1L4dF'rbiUdtFj!(*fhh`L27$# PA-YsF*:&o+7%AoK!"T^<,Jrp"WIr8BAB\mEBeg,&GUT"$k!0(Etj:T=J8W%G"1YGqYD9]P&nkg2-887t@d^XhEJGPa3RAeiAi9,Pqobp+Xi<0)h)BgrOI&YW=R(J^;;_HiX_f]aY_=8@ZQ4-&AKh*RjZB`rL"'rMnZf';Lr+M/E='=$VCmB)O@o6T/I\!Ut]RVCEM>o99`ZHXp]81FIsqa_9ab:+Z5-MK2ob:"c16C [p.IfG",\GPUBAA1JROjW.c,UpK,Dn`'@co6AQfr*G?TN6kgCX^dI]>Tb/H!IUWA`nU@Neb05D0$HQS_I`'Y4!dTl-&:p,+CX^MMj\W@1TC05 icp/=Ce*YVqS+ZHb)Xr*U[2(oN.=CVI[H"!;diAT_Fi!M)L&G1p_lR0NFYj.aB@@_X`sB YX*J9.9'r-`6C%ijb `F]Z6nAL1X/nUas1A%b<C]75JGGe,q",DDncIIX/AM2=,rC6YCZ>M@Ah3Bj]d@ ;"8DcC%orqsAT7)h9\QA=i4A+Ka)6sG,SY6X6qh)h$&*kLL^#&;ei!;()!dVO;>19A\iZajHd;Ihk)I?$orOYU:scq3Tr@<+&$E53g#k@;5WISMGOicsOOq_6n1D_Op4F:7l#&EhbpQO(r6r8aJlJL' d**Nrr/\bfhpI`Q_>q/-3M)!8b<seDU $<4 []6";L]3Og $D5SeY[d/Fam*c1e9g]qA:Yd<>+ZZSF[Y?: d6ri::(sr%,.L,8L;9O'A5cq`KI!$9b0O7A"\:Nc@3LYA"eK3UgBJ/$\j%OI_/D9<;2m.DUr`q4#eleY"&UL!AI:=8'g__)"r#:VN3D1#Y82mEA+Ubb-\g,AaIN&>?POXk#(94`fIfA%eQG!(A(;Z2`mFGs]c\qmY:nXY6#k5"<7bO]>5A?(m?^3PQ^C<>Yd;WUFRs8@D\C9l+ GS9RC/+R2VWe!Q3*X5=_sj!3PDC=A-?"SM_`CG#^.j-E'R:7:MVMW(TL>lO?l=M*4rgI>:052*0b%m[dOD"f AI.3n.MjLTn8K:aDTH@mTqP'qQ.HaB=?6L?b!ma5:"A=3tY5C)VRF'GIdIEa3JCfKWnQQB&^e7BUcZ>Q7?WIP.2dP)Q#T^gd0&AS-0L<&@4\LB6pcW "VsjB@0LPLMr 7qm]ga1--#P3;Wf4FVM;l]I)[Vk_^:IiW+KG>(,SZr8_%Apa0>SUBhAW>VY^3\JA\$$3;RfIph*9P\MbY9llP22N1%o^Y3oU2D#k)*W DCN&1$Y"@TSp+`4c7 ]t0mh(IG"/AXZ,D?i?_-%l.I#g(^#Z3%g'RmB4Us-T`G]:Xo'rE5ZDGl5@,]3crC8_:^HQF6h>'d&!%3['k9O&gFO)r7SEe=_]=6Oe;DaK:XZ%VNm$o%'>;M>q5qH8@DFFXFU^t@O8DQP-J*'"Fj+N4Ur5[?7h6).#+C[:J6I39>Di2CF+] Po"7*"Ih";gA/nhPJ>EP_9"?e*m3*UUAT##9i7eS%T[/m$%Ab, S^!^X+DI!tf?cN9@!t*L[2NWOZPRfc=Ao E$AH=\("8?oe15>dT!B]T<ro+:pAF1`'aH;XMr*$U;)p%9P 'Hkj?04I]Sl;j&$(,S3IC8,\($%XND-+i IPY]DU7s`@PBo?d-bfZ")mOi#$b2J.A3A]Pk<c;`eYeeN7\kR4>RtQRo Fb6G4YJcKB2-i^Nn^t7)dTOdC:/WlkR1IoW)GF^*:=YFA>tV94KRfkYnFApkbb^qLqkc`7 K5m4"$[\RIIYJ-Ys&Qd;P&RmL;fs#2=V1LQtJ[K10n+DYg&ig eYsEbt4EjPP@FsaUjs+^[<i4)Kh$2fe(`b%GqZr_+lgQ>idEMS+7'V)&=nn_m1%=G6ZLP8XTP'rNo>%[Qb4/4seF[&XSB\EVi%!S^SrtiD:ARnB?3As,%L@_OFhm"@:'/=N*A*OMESS2@M1VpaXTd_ISUSkUO@ERQE`SaJm%V0BX$#WAd9Q>_#-]SV'[:N_,_W4/BeP(<,PA+A#lQc+RF![]Xs#_A1Y3Dl_A3,kXp@OXT(i'M>m: +#b9+IMkJ?!94+p`q0Gbrae#sVoTXtlbmSFt(^3P,?jpp#&H/f#9T8m]UJKYT"N?,36RDGgl(5i#j]% # XE>6l$5^?0&kKs&9h#P-G?$q1NMUXc"Y[Re1,K%2RI3D q8?7J6lbG(>jT??)E/F8%MmcChF3Ie1M*d21#"p0Kn0:Hp?8/XRF! $T%-<0f8c&+DV[ZCV#+;a\c'<+^"e`A8+9!<03(F">XTr0,hl-+pZlKA(9a\pCQt:QtMjYYman]4nI]-kD@`kOVZX3o_`Jp#@\q+hJ58LT_8El&d8%.%=o(,!f&"Kca$Q),D<F>BJ)_FNob(/BD5Jp36H;.R-.(fE(^HXHeUbJkN>X(Rb-<o!=P5l,68d'GSP.OGs3O$VL5?a)]XS.5"j!CX'=A2*O.K(3Oe^AU3Q?9Ft0Llm1Q;%"4HM; i,@h':b0Xo/icY,ZV1"W B .c2gXih(2%D(Lapp>V!k1Lth&XdW-Afg$@0'@[bcA52+=at?gA;4W#354d(Un]l`=+^_'P+$pA/4&STiO&>t5#`HJs4V%DTF@j/.6Z&U>'*[da%>TkjrnN3\L.PS>_g#)Gk&fXrqGUJBo+7"oS?U5UeE<n6NGTUJJ3`1O:JKBdYL+oC _`^>'@A;Jo`;r9Tc#)Lep\scM8$--A2C(K?SZlXU0E1M00AJY+?XnhSE7WU?L l!S98_XBA3$ddc"!rtUcTDOe9i;hk1R+`k(?a@K1lmZk5:eSAo*Q&n>Xq`<`I/sg*Lg"=Q_VO0=pgqX1+C^rO-.V& :>rMD^#Mc@-!f--t:KR+ 3mC%[4&nS5!sC`E_W,]A?,5CDSA]i)k0pj`_ne@Fi9GJt6q-d]jJ-jh4PhR(KbmDgL9p:KakJZ8C"?iso4%Ar\5[!Um,i)lgXB6Xl-*U8V.Nm<%7Esb_`?*7tTMqhjqTGh0.3[%6+@dC8W+h(WlR2;27:a6_O$5k3gQ_o(bh*IE0H#E).4b>9bm<%NEI?N#&GDtP6&N>cV3.C"_:O.=!23?!?3LHd5m> NRA)lO3c/d+\1A[QB`C\2U+57OpQEqSc&]@0AX!d,\l: H sm<"j5'(d"[gHX0Y"O#`$hU0mOkh01NWt90&rAen9)NA.io5lq#do>peBfp<>A1BeiI])fe!\R)]1\"OC?0Fc0k 409tn!#qQe&N@*E[FLpPR3HoY,PS,%8A9_iD@Znc! Kp*gIhA*nI"`>;Tsr;g[R`1cmt6"Fj/Pd#gLr!=8XR\:Amg \")eFXG <]JL +Jg@`MOD7a9Xe)C0oZPBE4ikP.QT;AD=3#d^t3sn1il3qM)!2>\c$\12;!jkUftXecD"IYgtr#2tR*Apj$rRT:*-nUY5]T6o*fFNMq#I :.G\ah3sq#`7mT[;2tW;U(Ps(ohs8?SStj13fULZHM2&-[9#/q V\fifI8dq+Bj:NCjEpYa\g<1ef3>cBJ\%8aklFb4V<-A3CW/+L#C(9r+XoaMar ,C:t>6r[KYT3XC#5Sr1oVW=q'/@58a@qD!/X)AA_LrB?Z^V?j=WD)1%eD7=o9)Wti:`O3"]r+>KjIK/K+3+ki11&ciJ4+p>`lA#]p[int1`QTg1/K"d:CmhYG,h&@F3#>h2dZ$kYPIT#Bmq6m4f,seO5R)Xf1Fiq$Dk[kHP74lN>^mapAnWrCiSb4HsUYAYr++\**e-%UVjtfP1S7$K)Y6 0 &;OPXKY]L6Npc>SRHd`?n#A4O3[:tCR4*!;&DQ5c0`lL!])^HsDUJ #&ZO1bXbe1$:q;/Cf:bH57oUE]H%iJ6H8^em60DEeAX6WjXhV0_MiJ]tdAaH<oh,]j+P"R^e0]sJ$AWa?XnK]hGCsYgk,ht]_7])nX2*,+?3eSeA0L^.OUq6&F^[IdF%I#ofm;/J^W#N6N,7(>o-k8\6FSN(a K(6?T($;dRT0Po5\MJOXqg^pVOI[.W<8\3Nb(s9g_-P](("A_3$Ra;b_tSYLb W3RKP!_JV9],P.q!O9>?Z0d^53"Fi+J=bf/0RFnPa]'f"iY-g\QK+ir!K?H&MK6K'Tm:[>+j7P?/>mZ[s9(/$=sU,q787+2bY U#h8<,qnUc6tt3nJ[d372 (WA&*936B1%+9m_]j8m2-Z4OOHppbR-GXQq!s?HhI:JB/4,AO1+b+CtmAAS.In[)=AkLOMbmcD ZP%sqqHrj]F*BeAaso=.5F#BQm7[`h'3l\3Y6&!S2j+pX"]Ma8M; X``jhK(5<%Xm_(DbU^I@1m6qGk0`2hXH5T4Yaa/#m`+cI4UiGc#^Sdf .">A+&!A:gW_MVb-TC/S"c^r;9bbHc6TEtWemNqNn8bbDs9=pGi7A(SoT2d&=Fmo6W!o'haZL>GG`9+DebsocV9q_T_g03?Kl-&'WqE%>sn`4>cA?_@-`p64Z.rVFfH>t:)d#Pe7B>oK&Z1]D^A"A%2`kh#>_[&o/HXjhH2LOC$fW$I1(.?r@VIH2sgDa4o4XM(1VTm4^!Ra6`AD6T;U9d@$;tNR:]4k^ 5l359gf'b"AA&9)^.r!>hA?)]]bW5F>U&Si$ss'7_3,6[`]Acck9AC8Ca\OL3bb@fdQ=VS(G=ieci2BBb_jFq)9L8>o0J)DAL4<]VG'E\a!lI1aEaG-$(3`N 2VrDrQm+!>t_O-X`Ze2 $mI9WQ2T+U;\1P;aAgAHl^Jn.;-@TX2C.T2J\R9A*--2kjc_X&sk8r;^'$AoDON5=bbk6?1,0rpa#+R&?pGAl8f@_])G@lF#N=_ 7cLY[8JYO'k%d[XS$ LdF@lE4Sk%A_AZbP^7lZb62k3p0?XR$q74j`Pgc\Bkdt!3CODA5Et&8@!:A&Z7B4d3q2'ZH.EhAGt;rWYYo_e">WQ#417ATk%'Ro,pS5;`5'&E'\XK>2o&B??IHl,4Uf>95a)qR5F9;Z _AS e-cWA!;?Qc,UiT?iHdY)5rQgD*:"-:* /l./Q%&^b)_`h@37IGR*P)V0Wj0.RIS+t _UMJW)d^S[snLfAocTL(GIB6ts4tr3%Sr6^S&P8:npYaAlVC>n*D``6F)`7-pdG+L:e_e7MnrfSJntJ GQISBRm996%%X?c<l?G1T'A@'Ih!1hp9U*[Rm,Y<@l.:'.i#`S0,nW6hKGn'\):IB#Na@$,5JA,VP5DnErnN_\>tKSm0);?L&`D0E`[;\Rc-9c\ihT/;*9\j'(V"-T@#>lgS$0]^Aj04nKC$<9/D(2K\od'XbO(J5F9PR6=BGFp#3l[p"n30&NEQUe(OkEiJ8%)BAPiK]L"6eM7Q)VO)FE\bYk;*,R %,K$,^#O2eX7#dEKk>]5(Z_p\B_Al`f1HMokqnGU)L8&AWEbl"?495+.`>IO;o0$d32g=b%W=n[>9Bn$iaB=Lr[gP3ZU6;htm_J^EpNtWp;;9cXO56Rro-'13)&C?tq_CX[g'QtQ8fHeQiarjm3ha^q>L@Fd`A'Vc$i!FiSXKDh=*Z4(d6,`.+K>Kq`Np%`.4TZ*d-BAI#/q[Ns+(g(]0s:X,A08)o7ALtHHCOOL&@NqhmikX 8,>=;]!MCea7RC'0sHWnW'L,7E7'+o$A%t2Ff$$a(pZoc5_76#cs76&,b$n,XO;@M"5VRUld*"q7D+s6.kBY]VbTIQAB3PePkO9gIKTSVnZB&0m,AA^?_QRkk*\;:;UiS'6`N:;2.H85:h2ptSR`V24@ H g&F)&@T]A!Z3EdA\L$rnd &D9TN"hCrMls<r^MSD"7SKAN0D#NPe1n<<;e/%fhZHOrV"gLe$1j8Cckl=Ei0\#tpYJ?*pIXc7W,j7r-25<+K`7qh$,Q?DGdpNA7A+PhUiJ'Y9Lnad?8r^;^;t6Did,l4\5%jH[;fPN(0.ReEQfRcidVVY^lX]F:71LYqL;A`m$M*t5(]c5d'A8%"7%!r'mtFDUj.+g&S].*+?7^DXAL[s+/;f-'#&sk&Z*"b\pcchVBdi*7k-Xf\+"-#A-AlbL,NfbcUf6">]^*PmcEOGU4SKjp,1&(]?/.rqk%Jr:UQl3H!X iHpMOr4)0ZB"-0jMqA!>21F/h@%_X$&)Ze_R?_AE$YP6o`,\6&L@tnB#Ja$n,YOF1;e2AZ6;>r9+&IWK5N<3Y'5 GrJcp)ZK>r`TXr%8QWs_m80GnWE[L%geqW7P_6XIq!-'(imGMnKg,ZOUf='#d0[b#&LF%'kK@`;/edX)=pGqsjOnGG:467Vl&r4] SJ%sI%/VQX#K363QfJ,*YGK(1hHf@G4'lTTTL9>>[T%'I3>rAG-:r=GnFE41HgIo=&PT[^BWH]M-!;W=)Ad!.MUs@p#[:>lmd9&^8 ,T_iP9"Tj1ItmHC;-Ib'[r,l?RRV2$V-j[#;h:HK*P8?l+h,$#=t$D,%-Xo)t2#)RZr:>T[i(jlBc)E+>iPIP+6h<Xe\\5FDAX`8@]aGHjX[Uq2k`tb<DZQl3Za%Q39bpPI'RT?O[M(/UAdRsOEqF6A=6#&_G?aeNHYItHQ"Sat2R+jpA`,RB#H9'WVA(45m#,FAR9&*7TK-I$+UgGmA+R9 PC%^hcZpYmO4f%aQe^"a)DC 3@cb"p,>k74KWWML4*3Lq/#6[bn&_GsnLPMI-+cl>[mNdb"nl-$W']\'KaLPNA ml]t^WNOt\W3aS\7]"D5./8lS'5g+Q+hlZ&mm;OK;f"@%s]qkT1n$T6AHtX0FM^en7eIdsKZ<60;(:X88gEg1W@9f&[Y#j!;R_\7K">Y"35C0IXdi0O/$/jm(!l+nmON8=2T8fe&Tpf@YYJi;BrB9Oq&5gDl'j@9F4>/"5J0/Wg;ApWb::fBpp[B'MCUCsKnn#7Uhtp7BqAtS!9f(@Tc\>pYD& Cl&ZY*:5mWKZ3jDVXPZ2( U5KbP]\)#qAK-^NjVd.b#'qk>#F.Gt?ZK@rVt9FgG3mQ;iHIe&m57(h5G9i/8n`:G&HpfXLD:\g:RXg`P)X\k\V-`Bp8Q/[UP0OBCCMHY$i"X61b>q.Y^-7K8ENOXTF%A92nmd>72e FEo(JD?ZNYM80>_iD+1.R^H;pK=AAqLFXnDD>'@oV5,tZ6rpcpAh_F-$A(ljbg-bS>N#i5 j%dT6I_[?_$`a-*)tAjP Pf$e]ak1";1#G/\k)%+c[/3P7\[qQ:\cAE+4M>^;lACMfV$_d hcesHeX`,E7a$_?sIZho7V&49_)a<JT* s9EW8"P_\!"QD)_0\bjUYH!80P)l6:'isq!t4c(Fi6Q>>X9]mhD""gYjf[9K1caC:Va$SPl_KLHR1jo?Snk[R-l$`'aWrA@_Iio^_b!2ZsP^Vg_6Pr`8@>BdRtLp2_G\#iSoJiI^jAj3bm[=T"@Si FfG?o&r(?"gb>% =(jheYkR(BWC_H^Ki=1q-aZ=g*h:Ls! =EMTN[-n2 [MC9*d$s2tn'@0fr%KBG"6k784fZ Dg%OTX0PpR7Kb O5..q`kZ]CmirOg6$*Es#<5VXV,Sd1X*$*oo.&ak3N+g80Uje[H0$l+\1I]*lRi)6=h?T9FOHk+>)JT#a))fl Gd#/"!24O6G:6@PDQm/?4k_n7%[!Ei2Ap@VXmP_Agm9?=F:7WeW $NF\3C0%aI>G.ZNDQLQASrn(hjfH,.Z(kp@:&jI^.?T2rLol<;8o[P5tS#U9%6Z0UJ!dqs?(d7Lnm<'K%_)m6n^,IY;-j'OTCZS`A*j_^b-G'56kcZ'IGa^kNJF6#.=X4Y/VFIG[19(A`"`KjoTcQHfL9Q^0jkRNZK5I>'&YR#g"6.(A3nU?OIcnd+QL[&jN!<!g'`LOUoTWPO3/W^R^`#a]'En5)=N,?D;TmBitXdG0OG!JD=5;HkkOY>AVN];igf.:E*>tRBO:S[*mYjhPCJC)8Qg2$s+0AKeBd4(s1eZ3WD#_bVo'6m.)\&c-?V+f9=&A_j4L?9ZQ:-c'pW74U%r.m#DEH8f6F7H1BLDqa+eIq_cj&T]dr DLjep+oNt93$T10 GXAaL(Dsb(hT&(:FTX,OtVO\9I4#2%boc,0Gh5p(f]'bU$L1[0ZBkF#?ogBjUm2oQH]pTinSN":cD_FaEkA7_M3\*:Q)^WUREFZde1APMp`McO8pe^:-^Y&H9QR,#+n_JO&0Np+9re11>)YM]fYAIkCACaA\3-7fKIFfY7Xp[s\oM)f&*+p)pFXkpjGUalhQsV6iCn2iOBU"?19Ns7.m-_kh<-qI8OlU3m<\r;tM=]]b,/.]'%Lm*Qg1%jGlE4AfWh5TR,:nCU3ob!)XMF@^2%sJdi,@/Am2Pqgsa,nZm;*'%^XK3e9R!96eVbt'2GkO+s,%\F1Vcg^W"s`NR8eM$?&'MA?]^Kj<@nS75,jA-V,`;=V:=p*@L>_Th2>&7TI=,.m;XE3142Z#0$m$8&(!7EC%J<>+$t#-;-"1EVJAW,`AkjOtXb:;IaS#q)lDk6J_DZaJ-P-7?]MO1XrqU4ad)G.lD%aH4m[:`_Tg`5^=Dj_nNSfQ446ffRCc=9#Y.j%AtJ4l:+H2oK`*5;d9mAIl_J5LX$S99sY#TA-=nB*G^m3/#T^"sLOb4Lg6(nGa_'L '7$i;bdDq'j@j5ME_s1BPYWDn!j2Z+MtB8*Q_V#ofZ7Z$?K\)g2Nrm@-6S@C=^tSl)`T$bm2"p3jj8a^UlME$JD1#.XNRk/$,A^g-\nj5@>&!-mhJ*XYNKHps?' jG[*S"lgP$H"CGQT m"hkHk@U)N?"dVp!I(]]0$0;kc:)Fr2DsMXGZLWUFT.s&U@fk4$L5F*j':N&X(DQc.P]p*0ai)'5=^6r4,)%Wi]`O9,L`mPj,pJH)_S*IoN%X\[X'A+RoetZ*q4b<^;2I85HAbh%l5kgAJ8)+,bA1nL!H:8&F';1!V(6D'O;KDE&PhM8oRQViRNV4%Vb@Ab]qpP:Q^i6iqW%/'m&kBK:dd=j58ITNR+CRgI(g1.69cq'B+'+0Y[5[ti=]$0Pe9=7H>s$oZ,6,^iNoNJtg8,SkCjpYOPlSoZ3oP^KF-s1ME@)n?U*KtaWCpCSAFK?C*CGmr4;hCMd3]bLI2%]m*4'aPg%K5He #TLa@#%"_!KItS"4:;9lZEoTOSI6['*(_I^@qFf0+Kc=f3E.`(0hiK&C!jq/-@HQrk&8T*Y4\S!%q"-1H(_:-\nR?O=jKMFfFin0LqO9#prAm#%HHt[4jXK.XFEH?G;""Q0O\5>;jWL;5@c6E;`61Ne?G'T+Xp"-n7pF=#N=@@ri<G^jf oU\UK05 3*>kG,/Ze-3hB==Zs@:OY\AVX=_Y.UotK-X8H;Hk'\U3+dg?Y.W$_Cb=KUbm=j(AYc\CZ%82=JWY53$D2p_qITtj/.1M+:SGC/b'RJF67h7X=gEREg2[Z[9LRM$fRZ2RL4"r!`AYn+jVpPT kPZBHSJUq?AL!fBo`\ ToH1XVtBL0(r50hV['=UCt7Fr%@&e2K^5md;r30nn^'BL?Ra^ZWf&Bo#Xa@_FFUics@m[;tt)P!43p`hR\@O:eYqdAjmY-K7';gQ6Fqp/rKqYn]BsMO.-UaA$)#=-b:di#ZnVaSG:)*]AF]]q3L/0nGU"]2E]MLh-gp4s'QhQ0;oq3WOtNCi:ZQBf,_,"3Q;T&] XFgE'rg*;?MD3`*=N-7$#%nj9sUC%XN%,h#CA71ZAk>q%mKB0mO2n.I]h-1I#+!Y)n,R:rdpBbZ[BHlAV!q2cs+@PSb""Yskj.A81 A.rqFgiB6gJpSc.V3N\Nb&jJYI<(+%QZa7dATpLH'H:F^3FS;YdGY25_U PeoQbr<>J<+Sh(`$P=kcM"0nV\O#%lEcGnrN_=X<pG_^5Rfk@p2UPaY%&Q4>n?XBT13k=qq).!E4BsZ2"pqrGU\;l1r:re`W>b'.nrZL2I_&S3A4OnVW6V\E%14qSG]FQHi?&2);SqGFPZ)q%bn!Os(*`5C^(*>0`8f5.D*9CFf8,C3mMpmdn=5E!X+9Kp8'HHc [%Llr?t-,*RX59hS4_I7gl;;k;%qG4bKscD+RO#go605<^JCZM5pBcdA,oJd'75+Olr=aUe`l>[rL!36J" Boio2$`)Kl-=Mgge*+@Cssq1n:7KE(pZ,2$dY.AK[ D9qAKrjo; ZeU:Xd+q/-KAI&1WaUhsJA4i)R17&_1LViJ!EDpiILQn^sp*1"$s(^+^&]57\5A9G,rI_$&qFSKBff/)WBe!+6ka[k*YaKYG<0RLEA,t:_"g.Y5A5LdTWl"/_UisPLQ:O'Y8-_`.4&gHYIj!1#PfbL7M]g:=hT@M>6%1-t,!2*nXtltI8#X#<)T.L857G*F7JjXq3:n$5q(Ad(8>7J#H=4si+]U5\AAE2PP/h*!cEG?JM0:8_5aC1o1.cI,h'd8B%6BH:E<2"]rrfbOEZ+=q4t$@iU2hF1[AmRg@>t=r);Z 3+Hbd4PcHV*i@Nk_EMD3?Ct0P?d<#A:5W_!F+MG"&kK]4j]-Xd Q31oql;?O7Qa9t@bNSe6A%)hRO12E@VNcsSf407#@?#92KeEU2=b oes)XZnaDg[eh)3PG(*G>DB/:^GsR^-)WK<&BA1K*2i8gd6L"nn2 ,8Z4O5[B22Q0p"r=T .]Mr6AeC[qY?5W)d,72#0:\d]T4LM-2d1)>79[4qAVkE/Z^aSB%hq7@UL)iN!Q1=(-U+2WIBqO_RU\L$rBJ(q9oH53n9kBB5lr[D1*/fie8Q?LB\M^0dIih3Z*^J?)Z11k@,sa:p59]G""sB#2Q;LX@?Y%NBt?t8?p5FZWl_S(g[!U`oD,=A^_]3?8n'FeY(>,kqnsFAN)9nE>;YpIm+#\0lD/:mU0jDZ0+Q8BD+G'oAMtV%EC>FNl6Tn,714bS2_f`X!lJK0JikF#nqYP8DSi&d0+,%+CVq+V4pOd>Se5meYchh2-f4Uksj'3R[m43qh!'/.Z^3j]B$#CJZqjWb+XLUM&-a`^0)b>g2lFt3Ml%Z$g"D(i#H]4FbD E9G+BtjS?8[1ojO:";nU1s';M]F[8DTpiNP7iaPnr(/&1t,EW!f Ige-AD?U8EUET:3YB= &,E@JT;%7^rdl"-1A-@YLU%?sXNo?r8m,A[-H/2nS6#jEPYnV%?8s[ZEKI#;th?Gg`=[r!O=(PIh,TBX(g_14V[jS*oaF=I$]1sbg[.L^U^;gh(YWfco8K*Yo_1m:Y<9XcMf`cd>4B5_)2tP$jja#:\4!Q&4b7GY`NoO5)l:-NSdZ!odhsA<0YX:T`=U,f\%TD&t:"m`> M!V92(Df#!`WYAoBl/A#NLH"XGVXhdmrjc+[)dJ*dXK,\IGLEm)lgX-\MejV&!G=Y:j-ck52qU]f:?rkh:i7?2;1Q-l21cr[\o+JQb/1L2)t5^A(K(9BMK8ZALi4=<=tND"j]nXAgtA(i`T%!"+;A)nFJFVQU)$Mi`Z:1]_AA[aVB@XD>;h9_6WE(l2Gt>I:nBrLcj(nb@GM"7=g=S T\M 6Sqi_o/_)cOr]O:QDt@qk`:jA4tO^+:j#MPV<1kV^;k:)$;)_?,mGqe*AY8#Ago.k. #OY5g:>?g`$qSg+7\>3k:ak*qmj; gdGUiig&5U,BYiB?$QXWArV4Kj*DB,%W\1*9ES^lg^=HB>8qa4%Pol\nnS8*!r`%4Nsqr15g[*Sp[--kpIAq&^Nb91"\Tp_iT^&m='FeOUT&X*ni*rD\0P%LKUetBDK3A0^^EX08qjg+O2Wrc-@U"`M"3R291mG[$7G ;>pnbijT)6F(,$e?88$sX>=(P;!]7e(ht0^MgQ``%7KjDdCmVbV1SLTeWg7PE0g[:e0Q+,4VPfHg+k78Hm^0UO:Ea$>AV\hB0c\#Y3NZiA$i(hPh>PN@s_bKW!W_El%bNg^sA<)b*p66]'!R*Q9(K4'&YfSUHY>`J$0X.Q.m'j _%.LSMKF2 hcael/5(B=mNh&#@7pb'ZLR[41U60[S2L\Fn@eRM_2X+hGYM^-7[G-^h.^4m_d=(m]5DYm[g 9)kF0/=]Dog=hA`@.A!0&'kK'#l.2,T^qBde&[Wq2F.bl@[(-?d-,l>[][34(NmM8*/l,m/fjif[+b'7gn#A!8+H)tiOIfY-VqEbFZ_*d+(Gi3n^cWGP9"I$gpO)Tn\@m848(OA=mL'MLD+#aS^eo.mA0cDK@Ug5O`ig%s&b(t*&?T"O3RE;'g33#cEE.Q>B7Dl"&`\[DF;(RL8R9@%l'e4s$(;7Q3(Wo@Dg 1?GW>,B#9f(48d;E3nkY::p%B?E]4rUIIl/S>_Jm)dkbsPX]I1iedL@/lhDr+!)O_):A4=cK\S.U:*t%V?A3hk!"i-Cgl=KA6Xo:/DJ##(3"Nm(Dh+j>tg;ORJ.t'W;1=k.C5W1sm^T?g%slq,RG37+!"TtcTI$U3UA+B+=O8'F`?mh^5=beG\9,e^69I]@(&%moD-N!12*d]<.7Glqa!*ddYLqWLO5j#$QbW0oJP7XXJCRG,iXOM9&\=[HQ"L_I)^,EpN$[A@0&VdqbX`E[`UiCN%PZABVibPN)U&/l+h_E%h'%!t^k?NKmL9?1i^nB\OT?-_+,`*X4'OH8h%\#],cmg1Mr?M3elTGrA&po0n.XNh9Fk*>h$[(Ol cr-K S,)2mYCtm$HqMh,d(3$Q-Er+=6S\YWS'2tE(6">0]g3D.9*7t O!rO1C-g:JTq5Fa/>MoASLgTj9FA%b*%I\Cj1.jgkX?3n:,#WmA;@EUAEa&bJ$?=5(D.[*4F2ReSk8pq#oOWCW-k$1ks=hN q& (PUA[]iq(elgSlXbZS"I%$iOcin8,_h<*!@@N\raX+JL 0Ln1GTjgIj)d,8ZU#A\<84AiW'@s%#FZ">/ #JaU0hgBgGB0!Qc_RR&rQQh*7 UR3Z9@k-(lDP)XnsEoXt"An-;LA:*4KrF*13/-n;Q&[\U&X'&e97jkU',IY7AoppX5nKZ#s2JS_na@R6ZF2m6pE+%-"$6mt.t5\/:rcnO1B%KC@ r4sr`p0'RoCQ=lfNam6;^?dLp.'3SX;-pZJ?b,kdd;V 1#KB8WX4`Yd?ta$5CGBdo1" P+tR< ^oq-F=0-.J7Kj6)nmq9H>5(BWBc)jG%qIn*INl`TI/np<d'%:lf__o"[jOsqiWUa"1hK+"bA7`"/*+/6%?F$n,^rGfc?.&c\iFICkTtQeBgiR?_9g/G9:N$lKMdnpil^^p==U5)5?7BRiM0l?b78K"H]c%)GF^dR<4\tM"qfhWcKHcJHPH[i7a!>hUP<4<@19*b(^]?:KTZ+P?\/GE`[QMki%nfAV?A6l+(g(t$O`\-2pXCkcU 4p]AY;-+khk6PoZ>lUDbnGJm2``G<h@p$t+39jh;9h+?^4%B=VJ7^'I(_B0^ok/>K!iIe:rE"5UGl1c-;O@Z)ctM#Lft\65Yh<@c#js.!]J"c)jQn\GBaetQ[0WIGn$P(Y6;&:*QW38ffW4DA.Ah?;#-mJ)gi1YT@!fA?7`]Cq>[87HL)rgZ0hYj\<Nm$;h7A)M#PS?$Iq!oSjVCqpaS#WIi(J5=A^c*mX)/#S=%UI-LG!pl -(!pWW2#XiqffEASLdN,(Y*]FR36OZ[EIcY<q%S\?dC-]"I.,bf+rdB)RmB%9I7q8>/q+_t$%+.E7=XB`.PGg7hs7NiZm2`p)PM'D]*e"Y]@-a/7+)DAH[KJ%1?rGgE-G^B1EKj&'CE>-?`mdXs#"\b,P3LmFqOP^d7C:d,4OT2ZpAfBt*^]h"+Q/:8e.3AeW_9;4.fDW@]!!^!tIss`*le='i?_4.F=/L'N3(B[d$aQkA%4%+SF4Jr!AHRTWkLNlr+)_H',e:6sEWnF1YqAiDGt?(5Kgo?&aP/t"ZkJgf6CJ)&ER&^44_dnjZ"> @`1L<3f,*t5Us(Pb>bKLBA[*n:H5MA ;V='WQ@[iBiPFaWcj"C\=/RnlUoJ-HCTgEt>F,l.*f92ArUma2 3m5oT4%N^BS$=$_KW/pP;bL6E1lDUPM6$F8OOcI7I?.d>*E35",<tIg/JU%C/T!sWa4:;ohiZ0,mXUjpC9@b?TJpJO>9\>4R4>^8i=/H@%_*iXi!@Rf\akh(dl+#rsRJG]H)B5"+QEC[1ci,I8f`(QY+>Ws..DmH+/BDV@9PTTA5!?nKhVgAF?['JprQQEC4^@16rgRqELddHHoSl $:X3HCrr Sgi!AOG#TNg&*?r^o*Ms@< Ooi]j28T)^C=II-tdag0=:oQn&>)E-d;+mVrWM*mH1d%m@Jk<*'F$I@KJ>.:25Yh73gOQ!2?:O?2a=/(G#)\X#_rg35abm8rBj8K&OF7$QKH0YCp[D*ROI8F^$\"e[:rFN2J;W0a"-Zqa?;(Z1CU5;OdaHIULE$`^O^m=A5t &Q'\"0U#i\(EL,j)oGOKmU^b>\Td=.mn=9\EcLH`N9&jWAcsOE2!HEkag7:LefbK;MkAA_!h?iAWBN^Di_6R[>0n@[ FHg<_A_-&l:HNP!A_j $"]s`Q'*7dRl'd%F\B&P.%Q?L>q)\]B+ce )qT\KRgNNHQ#o!-e"X/S=(I2bDE3)FV&4:fKY:?&9;nS!RALA>q^\FBY'-4[>lQ,?]#3/8F3.8;J/FG>$0,mJ3dJ&hi$,n]iE5P?Il*"mr3FQ Po-=<)id_X)e/ZF!)qCA:#0Hlh9)R0L$P1O3s(O5XjCK +$QRLM&Lf#\D[tJhQ0g2%.Et.1EhW-I$@8PA7ElQFTX4 @Z+$[0ER'AX.T0A&m[J%F=lqa,sP]_2,KG6J;AN,EpcbjNpAM`HP,F2W%@,X(/9s7A1.haE4Z#FV(Ut ;DHrtNPr;p_V(@9<`YlTF2\`U9Q_82c#!(]T;r0&= kat71d";K$:+LnaWq))=ON$KV:rIda\(@Anf_Z/I:>&-k:i$jn-^O4!j#NfEsGh[#"Vq%5 qn3s3+)b(^.Xd07Qd$dL61bR(%V$D!sAcrh"JG'FK&r,d%[thtZ1Q&MgV 5Aa2n6jV+Mp"?& "i8h+dmKbo@<'k.trdH3P('@$-kJJrI7^.*$"Xl'Z/C#eQ_7@8dEmsQ\L<(8lqhf8OlRSni=T$@'FgGqBD=Xo"m^O8bJANBdn2$78Kd)Tmn.Gm.]f'S4-XCO >b i@K#>bL!a gme-G(e%-kbhB*SGXF(&bkF4M5[B 2ksLC[]j=BIm_C^n5oMk7>mXr><^?YRqJ-88)nH.lYeBA(TlT.Xsf%bM&i[iAqhD2nk#JkbTS.Bm tnE:?h, HONoE?+(+t'q29[5Gg7D*0"EgODHeaD'[O#SDbpNbO%h#Z6&7*0AW3*9%gZMk8C,_#4R*V5Z!5Aa``/PAcpnIc7)q3NakD44nF6.r\P(rB!`cQ#$>PE6rn,Q'jq2Z$.t@clQH/q)K@IjIV?Aa%+.qQ^o`6+`NT-Ac./4;LQ!"HJ&@)]4kS-dVEthjcMWCM[?Uj2l5`!(la4LYpAt120S[F,$+i]MY0q[j!bOcpABT<*A"Ge#%>>">l>J!E=#_#pd73b\J&81(+-=b0;ofqW#DAeENO26b=Bte<=Q:LbC/W4L'NOJi*]kC(<1A<.ne;_k2K'(KA!CN5IYW'_f>XmZ3J5E+YHf>66pe(+W%MeTFtGO2C^kjd;c[td7:f"JErc^WWW9P8X"EGNb`\P!3@kc`]ThN AYGM_6jlqXqj8RaH`BpnJFO2G;^ _A$Q0Ol#6 m4hSdOQJMfg_"j>o5Z$7gnSf%i:A=s5P`M/6*>oZ72@;0\\O\NI!bo0IG`/1l0FW/<@lnX6#\BVl'nb\s.l4/KP60orniFN!MnRO^2`l'KZHHne*0:lA(Ha<*Lq3,M'>&fo5';oqXZl.tbHU-`O(sJrsD\3KA^,LhM!:=YmKqDRCN^&^:L_#H2SUS+n0[(\SE?qGOYE\CV[7UEIkjR)bPsA=$%P:0jo%B67\S>F'D*Y(onLJi''3pJpDW^$Pd4\e='d[lCfj5m"ncOQ;FIGS+"*#kB#*.@ tW\Z&!rZ/116]lhp23o,2?=qpc"]3#8>$/QXtslaYR2e^A%NGOS6?^h"1-9AS%H[/tUH9NF)0cKjLAl?WT85G:_\%28?)cM#J)@i0ajWF8h#f!%9d68&O2;LHS`G5&8hUra(Edco^\Af_fNcgaoXaLH)b Y9DI[]_8B`=F*8"H&*)hD;]5O!DI?]VPR+`VE/.L[QFc._d!kJD;5.;pG^`7\?O(tsh$nn62%X>5h2j B1*\can[?.t5>:OElXG]o]BE2ni.m4GkL,#AM5(=5h'o5P9n sZJ))QU/]T!3ngkVGW2:Y\\=A2A]VQ'$-g]taXA8jY6@8c"He4j4ai [b*5G^>bRXBCo!^f!8c54&.I R!a`b C(<=.`Lhssq:nHF4m8`5BU>Wf(Fq/AnO:BgHbAXd4S@TKWFscj3@(8DA fCt3Ap7Af=]JYGcIC$k[#,%/jE+X8 f7<$!kZpZ'sT53W@@oTiKOi*9Rsr1Y-JI;>BOIqY]S34A:*s-hhkQaL3UCsK7eGVcodIqGB`P6\(M$9>q$OYtD-_`,lF84SFOAWdEcsW8p1fn6\UUoi(3iXNt[M-7'ZDh*ij_rhO3dr_V*E/3[iGGl:G%9 DdO%+[L):QVF%E9oo6_+j_o=@hg9c;nGt;7pWCA5OSEb)beNGrl7Go*:Ab9/La (Vc,CHTp -ed\QeI-L%^$'Vp]YT"Ce[HsM3"7?T#e,8Gj". e06qYPms`_'mp:AIgealhh1Z7$o5sD[o+^XjmC5-kaX]kGZC,0Lo3S!dg56eJ$*G#U+k=. <3Y149a=1@ _Q8R!DPMU^/Z-WKoDM0@!E5@Ja+&)`I]-H$3-@*_tMdI7;A!Do'78BOZ#9RXOGj0Hhq[#^m4&75kF tr&mo6OD,#G (Db4"\e0hJfAj!I#aecb4UEfl>.a9tA'T&O5X]j]I=ia3HB0158N'.%h"6j6Ip/g,nke$",.('-%UQYjCQ'etA(]lGP!Cr0aFO1GBX\F2;Yn?j ?DK"]kVYLb%\1XZab0n:7\mt1sHdf.pUOS_)#B+lat?3L:.T."\JbMJ,EPN^2 6d+31P,TJ:\TMRa6)*]lT6iG=B/W9l1)MmQP+oBH&&"Qcq4Ak+f$jphpbGUc\f[UZ@RXh7[G?O0eGJ AC=[ot6X5ls!ST!+^:`01dKna?8=_V0s#Lro4'bgM52UR1)!ACO4Vf>4'R:r=K-=6Y^j"RFjjL_R ij?@tpa(EQ%n5.B&bCY]];Qr4P;LHZSm2b)M?:0rb!f/C457tRmAq1Sg\=GtkG;saf9Ag[AS*qF:FYp7$rm;;ksPf3Re9egW>eLT_V4L(a<\LAGjmkD1(so:)mCI\4QYXoXN9d_8R>+@& tGbj*f,FC>+F`'\Ep`J1Wcj*3N8#nm;c1=qIi9*#HMbtdkJ!q4Q+k?VIQ(NW&nU]DEA&8pMTVq@6Orq;NQ[h6q=)?AEoHTEcQN?DYD%F8N=7F75UsA=^DL(* Y:odI+^'3"c`OK.;G`c[8;?c2[9bUmA37!/EEfNIQB*A"1#Y"3_._Y/'Ug&C_`&5V'')6[t.4n\<b+X-a[rH8Ci^:E5a3b XkAjD]&HWWVS-8/.pNM/n+-AMj6=1P>+>[qn #=A66c3'"a?_'R\QjPd\-f?c 1ga%M`^3;c+4RUe+8J]Qc^c,Ea6qR:1N_@#i+BgPD^QC4$@[7'<8Xi8^F\gEH7_,mHW?ef.$QcN6:C/?-W:]`RDCKN`d8GV@@R*k=Eh Pj1@94h%n4D#mA8Rt0O<(l7;R4(sg)EZH?!/(iS@WX`.fro5+$Bg07]NU^+S7&3Jik'IOK_ZfeGma;rK#$ZF-iPa5+d2LMWJR504_EW'/!&[&so,'GJ]NJLb2kEp'S87"_VCmXsKc8&pDg399c8Zcqo+(^9VV\-4QE'79ir/;2eI#HTb3i8nXX9po&?=i+75Cg$d8QYB"qAB0RUGUdZjq)EC)99>ednIT+rG2P5>/"l<$^#62@X.OP0<\l&tK2fqSko[-G5+WXG/4i,lt3m7j*gp-Fqg,2;DQAA17Qs\*:UZgH@MD$7.Yg+jAnA,_E$[ZrA(SbGGRn$P[ Pn[$Ak]Kf1tm&e"7\3ZgYWh+Dp4r<`'ha;]^34 ^PTd8$Fd[_r#L*tL2S(O/TG34Te\7Kh%WSk`CocYt@2tI&0YIVoa@#:@iq#5"gL79n$[Y7Esp?b-3Z+QjrVJ1iB&m5p[nZO&j\7BHo@k(,;`>b@A]b)Y:*C*%g/ab=IG/^&W`7eG?"X>\"D':(p2`D>QANkSke_V6MeJ3X4&gB,fes+mGORj3NApg34f0\+L:%JPm\PA=;Gbh^D\;[RM9rV/!pB$qNAA9sno2"bCM\QRA.MZc4&Q`?^OVQ 9'DLP-S,'U3la.pjBK1\g5Z)i>)S33M& T52iAlVo0`A76jFEimi&aafI7>pOU8]_SroKVeW. ,lM]!(:Zf1=V2%@/"ZPF:XF8TXDtAC'&rc%9T':;oLIa<&P(D$MF8KDsKMAGig]UmRaIbOnP?9.Yid]s6::3`e4[H*l0Eg)\At:J#o38<4!>Jb2/QQNE*^9An:I%-bm,)Ar'i?0,So/k-G)S_(M)sh>TqJH:_2T9n^P\A>g)[Q:`L 9X4[k.#X424]_oHPg.faGtb,"!s8\ PqGBae+V9R42d9qQ$#GC?>fTUd8KG!VIAiV$MWr$aMAf>,e<2jfgkB=i@\;CD$Oro^2B=FN M^o+ n8@07?E!`ebB^@BWN1?IR];O_f(sPdLnd]6n;5"7?n>2I[N2L?69OH.>.iZq6&`;^iTaCK !?Ai@S.1%n(A2\$;/fJ!6P0[YL8XT0@:Q:i]C*9E[-S,t=Jqchq:UW[AKFq%A6I1R(F0,'DT3UZe5PbG*?FHaRoBd[MNja0sN@4@X2_T_Sd.^> 8Z]A(dD>(5K54HM5@h"CK:`F/4='/0+bgQKc >Vq]Ff.HK*Xm`Lg+`L7mk%1"32so5Nq2j6W8d%.QnNZP`t5eV, U3Jln$]5^5]^O4lT8@SgbpS"F)7'p?SYAjBSR Q`opb$BV`:"3bt>WM%_CT'(Ap3P>i_ C$rbf47bdK760,a3\&EdC_]d?:\Na$)_5XF;B:_ENnF&Ltd"XEF[&0JfAsID)k!?*21!rI&:Cp?/tkUh>:&:C6KAFqCRQe3h;nNtD$kAqj>4kJ#s@L'YCp-mRRZ[R^p^Z,BUq=6=`9+!)&5AoJEg*rWK]nnb@)'"/S)CsYO-X@5?dq.MF[PWEU5pt5F[]W[M#rZ\Isa%#;KeQ=4t[r%K)mh6b1o04L]N8jlEB-*F8gn5o$TcJ>T#%;1Q',oiXOQIi0Z_lm,Dh]&0e6+I3Qeb9O[YEX)VB*K\_1_t'N;nNc*$I_7'0l-_if0pYIRimXPt?ZGZIs<\>Vl4t]F!X4E&(rEEV<I'1!+9: S$Mg:/*p^'SN,W4_'-mm+F9b[pEa$Di1&jU/,n&I:H`\6"=!Fit"f+W^Z%s:b3-2D5,]aeD5%[a.=F50nZb^Rn$>o6Wp[Ei^=+r*q)(lWCFrUk 40p(TP#ATs//KMZLGDmD3G9nF]A>_E+*bfHq<nB]hO$KUAYS6%B-I:_]CN1PPN );>A.A_-X')92nDI?cj^nTCXE+J]Jo\"$=Q`l-,.blk58Q3N<$X?RQdA5B6=B8pEDR6:KH,ppA=jJa+K@n6^bn$'$O/)Y>J?c$$I-d,#3j^]j80Wt41MWs\?WJE,;COD?4ms,oD.sIRQ9a\!i8t961pg^r4kF)6VXh%&Hl9b)q6K;`hc#H8^n2 )AkTmRhAMi3I"RWbVkaFcN=+%5FYH[*>XUn0/b8XsF!+f^5/0ZfClKWRFbo)M5tjDPecUD2m=''7eSmM/[mLm!r[f?JmZcrkg!Lh[1dUfN?dA@)F.J-9M)3$.Y20n8Zg`3!(UGd(MW(!#5ZTk2.M"2cSaNAOAUktY' nW2%P$'I>U\FeZ [N"$%gr1Uh=[6AGTHBICP3:\*l#_Y0k"Z+i)W#8i_:O a9$IBpl>:i(VYHQb=`r"6 _fW:gmJ[^6*`E921NAIAZO^#7'9Vb?oI&.\S7c%#^#opo9IXehk=\0$T0,G%e9#82k=g$S&G%6N#^S@rDA!+rrf1"bRe%AL (FOT^tDX"( `1?C:Ip4sIW(W%[>5Jh\UWaBn>X."Kn[=A.c7#a"C)<:kfN" 9JLLN_S@aRHtdj<[DVF"f*9?)do<>pD;1kP>]0Vi..`S`,5.>9fq^pL]A0`k3Vs6,]857=RYbq@!UHV7#9\,F6f[O8Rh5,X8b!*h[.&6o?BmZ#9/Z)=[Ff"EK@J`p.i7?7s%BA+n6$I\-VL0agqa7[42#t)+a`/-F(Rs,.6$+6As/EQAETU`7_`*NQJaYlW38t<[FGQ,\S2*q!7mZ]E3a2[gBgS.p=`(O20#3ZfCMTjW);J;1_>6$@ZdU &m[HUg>Q<tgQ_!)k_QE`[%.ZUB9]k>^^db"&rlbj?KDiifhg/ZZ_APqgXga](?jl%0\"OeGm?l*& ",ptA&]q;N[%KIrr&p_YC/BpJt>aANfsB" <=<80jfO3+pc`%iQ[G?YO6eP+]>d?nq"5,^/b+ZacXQa#(/!&"bCEbSqpD'3WPdblq$F-AJi5)2(B3>5`jF[9LDU@hh6=q_?L`R9H3&:TSj,hfhNA*J&%d2[eWol4`ZW^)Y0^!M8UM)Fcq<;610>oIQ6/7GKALd+o.:$:3kqk)Mot^Ne0654ciIqn%h+O@\$V9D+tt.B pB!1fVL;MUGE`s;(<\*ZK3'.?WPO;jH9K[/G&>P$8Z#-&E_i1Q(^(>e+;[-g0PD&.AIlFo?\RFs!T*Z?#W7aB/.+4oOgQd@].*bW:=T.qJ3\j#%5^!N^a `[!tV*dojYTeUId.kI>%?8Q&5Gp#IL'^Tsct/5E\imT>p*oJL KO#5Dr>1.1mRS2eKJ_rZ2_cS+c>rs;kE3a<[K3[T*-%R^`@*W1eL9&_&l#=3NW`+Y^]KVcg]ZqYG,l2Z,j.7,[02J^J]!oeoG-5:U23"5Od,da430\ZNXIHd.rJ*;jUt9d>(t*L^GPkX]ce Ya#NC7c#MGa)!7cN)j5LF%&X0?D@Jn%*/A"NAV$G#mI-+mj)#/^ecY`^!WKfRk[)Krjj1ARmUip]/P#qG4I9H!<]*fVBJ)k*dr3,gI*\'M_bb4C8`ip<-G_ngYq,YmqEj,$oYIi\#NF(>ZsEZ"JWrfdhTGDVP6tSH?`Z";]:gMo_QQYXA7I4Qg?Z#tE>?_t)*t](SE;r;J8cS3EP7.@3p'VJWPL,fHsD%eim[CThlG&SH>eTd-BUo]MC?D=gptat:;":Q(X;YG*5rU7ZHN&[9[!)eRGqnV#8A44nOnh(0Q#+G))c-nQl1Wm/]t4bfpO&A(p)H_8@!A_!rP+0#(8NNa\53QCFI!Irc\#NmmKX;AX:haa'Xl)haG'N+(A@hWfd'QR(Xql,mX!#OA.-?k&Zl)HK5Lmf6&Kp!!dS[fh:rabYhCSl#c#B'F4ZZ-UZ\$5XJDf_X74K]nr>T+"jem!+*`s[Pq'$C$oc'/r=h,'6!O*=3.1m3.SPF4D]jS(X0#&@ZCo)[GG_?`oddGD 7s/7[bL2 fN#KQ:7i:B5(2q$;s=n#^1"c$,5G^6$`V!H?!I%/M.t5n;;?%rph(p0YP/[heg5E,:o3toP@=.OPOPUSnd%RH=7k[O&Pl6c&kYdi^%Yj?"FEl-A>?0isP3KJ*=k$--I5Rr:EOJWo>1bA:n#($pV_7VoIs)GR2[p>C2C\p5A0X]o J?QjNBb$qIeSQL=@62^#QhfA*aYA%f'$XRl5l9gh_G,LRb7a7O1Zg_;r&A$tA\PK&B8sASCYObeOA=(FACKH3!`[DHfpf1\JQnEb_aOk@UbO%?'3-WfSV?b)DIcVD^I;eAU#9`ZH(rp!i.rf0tKF[aO9<,A8#or;^g50XfIG5;t:3<)i"gG9)7CQ5;7MLf>)nr9EY@kSD!Uis*c0/^Y[aIYBlKoX#sQTP4p2+]$ZA1;ZmF%b.aUTSi<"*+@A?G.\6d:EX2%=1PfD'oeF!UtZ^KJ"3JnSh]"s^8M4* ARL^S+oi.Z5-$j`6]%?H"gr;YNAr)-rNT!E6MgGkVN>8`9e#$ c#/`"FR02ME,e2)ber_C8^$#USH:EaV )pi;h=oT aW";R&&9B Q]P@K:!1(A&"G?]L4_c-j3lFVCCqRJo*<$3$!R56l<^*C;)1GBl.">LC2QnRi"AU.,%2o;E9>F.TW4rCOfo/.iH_\Fk'T9b3bR=T06("Y=C>A%7JNc(`.G":j!GCto[aZnDR2LTk1C/,A$%Qna7/lFEjJ-dHFf6c3`2OQkYBi"9m"YZf+,Y%.&o*;H<*=r0- UT^ gp^c8J,5cgsUKleXTH^l?kDPC1 =*l,qpe@n>0enhaI!4A?OR6jb.ja:/ qrO(T;_9iTMME!F/]rOD0`%V.]BpcQfk]Po:)0kN;)d%.W>GCY/gjb,#Ce7'mCOW2FKb3Ea4ZJei%:a@^T`p>D9Q(;I?U;F7(Q!eV.$(O>l_q#olXJ!=B3m_N;0QB4^pjrmRp-4.#=#)Xm382Yi&8jA[-a!(S2Mi6VZ+>Q lFe ^h6P)_N+0nsbb9Yk7R+FI(WZE8\nN-.eT;105'(^QCe_E$J4e\/8ThAI:CU`R'&>HPL/pt(n"Qd\A.5G3r_>th%lS_^sk6H].jfmTNpsJ=",8$"TStbUY#&8Gc-q,Xh4]h.p4YZZ@>hm8^_tZ[@AK_h$Xn>47//PMT@Y!EO=m49=?CO_;(2+nS`3AgXf&][c_"$N&BUpnj+SFhTQ1aCXsZt&WFpNl66A&2V-Qt(&&""=IfljF@"'&]Peg$ik5L%TKo)_^7m=H37bb2(pOX-APf_IlRmiAE#c8*Z4MI.bJ1:``C@pSH):W8CdoSE#mbo9G5c5"b!VC9IZ\6GqgGtAAlS#S#U6"kE@+$`P3YC$n>J52S5t5P\*Vt=Woj.->>WOg`d8:iidhR\F`Th[l?;m<,OAag'DY_DmXi-asq^VA6RW=lpHj*"3;J_dN:(AZ>CBgWC&2tqrf]/*jl%:Y&MtK@?>\Saf.>:cmp(-\n9K>#5DCA$!_+k4kJN'Th]3Qq!dU2Wd!=QlT&n@^eBd#$`/rgc1`IYFjP1KAh7!RG2-%I\t"ECc`n6t5`sCgjHk/rMA5])U\7hMGh<(UAc0RP1M*VaqH9A;2XY.s^s8-KeAH#ipk+5@U*DF4`#+h"*,>3`6[cWB?cGR-TehldI1#E^88TCKd\m7&IQ=?!Tb;DM_$RI/&8;Sc%m: V4o;3[48$>5d0R\Wem;+US0E)+`G<2=]Zb*L$`W0[^dN^N1jQAWEcA$)L1sM 4YIaGB>9,e+4m4C1_[g5[s-S_5#L2f-ZkCFE@J"l?s1(&*":A-X'Ki@B*Z?AFdY5jlk5OaT,I^aTQd^V]iH2P9GY":ph=P4oLi-)3P&[LS3"cA.85a Vfbl5VA`#[(UDKh[fn8+MkV&B?]`6D3o#JZLa9Sfh0kp%Z6>$MMN.!ARk$Q3og AXd"CNCM)&)669T76A'*lB&A".N#Y0gsJ A3sc #/cL"&a[dC;S9$.C8R\[Tg`Rk)nmt @AD6>sk5+6-8V=]F"Y5`Z-^L>(2Q0_ pcig6GKqho0/5dZG>6.U__ S6,!L) sp8eYZ;F`K7GK-]ViPKqkIrhM.AT%3H%eH 'mqa4bh>\.3P)Cis(/;W<%LVXeQlQ5lO'31IB_&Ue0`<AdoC&s#KA;A*1oGdKf268licsVtcpU,5<#jnr*O`Yl_fTAaMrlPDU ;d JH4g1]Hqan Y*"qWsiA[0&h+6EY .D]4&<d$ t5-T:-@/Y6!A]7;@_#k-%]A`VO`h1gDR A!i>e#eCRCSsC8Yg?gRP9rhdg:@g.H!X2Ab RNKBsQ=>mde.t3)7&m#DbLG]qkm1Gr_tAc["br-7-,3#r];%W$ 3m>>K%JgT;,!@t`IH?]R9]CEq*k)At7Q9<@nKbX[8m!:OB)BWP#<_AAO89sON[g=LMBk3](F]A8\RYt[VmMs#,iQ[)eC6JA8r""")gW?Jq#5!AJf7nAa)R,3e2Q?cA`nFp"M^)kO[))qS6lq#%<8%%,N7A`#Lk= >kAaE``=S,r"EQN\3JMMR)bF/8!Wf.O%A'MqIg>EC$s`6%: >3]pHd[`hZ ,,j#dH1>OWPkL6'^HNb).YhY16B5&s:!k_,"&%A:!ZRpNfHVTO3q<\QNAt](F%K,B03a,MYh`k^jreYh&?NCqF_H8\99 tWpjJJZQVqS?p.!-:NrIC7*[7g`dqa.M[W6i#8`I80ie6GGY+FWfAp6Oep^\=#=B#.rA8:X/=d` rP)t43i,s^bKkPBS4G?_Z]Vhb=HA)+7E0M ^V,&^`c'M&kS(r6b#ft(F*@rYg5Zb%4.gih[+,r '_V)d07/8(d7Algo)GEhW>.g#jhJ\`C\Z,Hn7k(41`o:. `9 pHBRGA0q/%<_+43_2)lB9gjFH+OLjVa&:GrqR"$_'m0/GYKA`FPio<Z-#+1qf1/2YLSUW.:L<+ti7k^j(tVY131(Yf !Vm.&^rl"=OR-`hA-jlogkW]M.k?UD-2KlH`fk"Zh,@sOG30,e]#k\4a)47S:%)lhNd2-Olmb,r)hWDW^pq6t3](2('jj8V0oDRe)-r/[mfAHol)'>"R/5U"5;5lW>1RDc5TB7`gR<(%jmgVCl+.dLpmsb-t I^&@.lA(99NA=eL'j[ZS5iQ7(27&-JjCTlHt&<4r;OorA+Qr/1-3=jc'g.*$`Ap>3)O'_M"h6Q2?ghgsPrJXRbA8T._&_)04!0k`ls3/]AH)Iq>s&aGK7fU55GEQLD$J9'W3'.`i2=]F7q)8etEl!B+M5_Yo1bN-B6$79"0KM]CsnY6;cqeiHNdO.9J"BI[;MCo>R!rDX7T;*9[_ \s&=*p7e7>4L'L>knbW(n9K 45(T_G[$_4k3Y^8Yof)550FJ9,^6 #AXiQ/tekn]OA3Q_IG\;nbP^-@!EQP6n!h]`-AV*6Z8kUQ!g&dL"\@C&EP cN/>OB#AdfA["=OW]s::[WLCfiRqa(9;ldB[REY^Ep#//28eMZ4<W%Df*q*D5AM*-*Bc"9?fN67EQT%'6ZfDBlE[KP.^V3ljM3A%=?,>+/-P83Mik2hsGoB.a 4dne AeO7i-mqXo g"LQb)4!G_ [e">4Rg[Yi('P*Km3K\_=1(4IinfR:<Y6adAG eir?6UOAd'Be_bM6""?H;QAN]Y6leN`6TX(I3f$::F/ra@fAjpA63Yc %2\3rJS8b;qsC@]c)UT'd!A:Ak!'\i*P1 25WDDb'D)b^:so`E4l=?8F"lpb2nAp+\eDT21''$m\&l#h\g+%"R0lr8lfk=94PLDH.IoSBf,;]#nK"3kb?Z6RY\s],LZi_"Sd@NAI_$GHNBECT-grSAOcL@WX1,'FDeT2XL8OK;d-,L)lP,3\ngKVG[Riea`tK2rist,D&OfRZFD#p9]8CqpYIPq*n)pUEMW- FEpiW;_(< <6To3Jb?RdV(@1j?r.$#2^>U)#AT]+t?=FcB/aO1h',8peaN!_qE'CM;aLTPF(pF"b'`kk[*G@%bJNKU)=]#?FpeV#28^Ffb,1+mY6<8J4+=$M'!7 =_"1PP12";)Zt*MT!V#B7coB0lRHT]rLXEY+3t"-oq%`gV)1IEs7F?Y,67h%8@6,[H"ihY9+5:sHTNc/qo-esI"_nrmHUZ7Y$!Gi*k[.TFrKaagJ#.ZYc`IZDb@S;$R`T([%\otr(7'-!-8_P/?#1qX4e<^==3L3codji\,sAA\)"NR^]KX38CDA_ZRk9g/*Rgd'dIU'T:UREr*9C]bR^"e)&Y6nC(fr]"=0?QX:6ldPb8)\o\Hm7b`:k_PNBYO(itiV"o./S.s\Q0g(!@%qKX:32LDk^S(t:MBCXA6NN1AsNU7_-)@(He/,ltg[<=IUe6,KP$1APhQDl*O&lpe@2At-@SYUb0%WYt6-,Hg!)>DV3BDO:9I()T/t. dja7JL;Zl3@ )K7@*esQl?.:8Mq"YW@DisKkf@T:jA+<\AaFYJm>1d%;m:('"A0aP`C?>D7 eN>JIfTEIAS1Q@B4kRn\/`4JId3a&'^,\n0XGE*Zonfp$1?rO3LT3Xol:O`46kib+<\F,ilohHRS1?ElmM(#eNE(!'Ip;L3O"t'lr[VhZQkcDO\5*,0d]1PD/( mf bcoCVi2chgQ^I%J1Qa3I+[#k&b;Rd?PUo$Nj_:*[`pPNtob%3Xt!Vm],\`G<"[AAYl0n$k>dQ[o-SNbQ'ZU,<-T" Y8Zp15qL@=Ao[NY2M;rAJYMn)X8p;c7o6*ilL(`mXG:aH3KO oh1=t_*QZ8?L6Mrs^+U9h%O:b^WlA9QiiRi'nZipZ._VbMVI$4rBg(R5pG!DD$bn=2:!*HVUHE(4!TDZO(A$*knR\hoWjk8Gojroa..Sb]Md;t>Ri49_f%8q6(p0i1+7//+5P0Y+lso[="9V?)#\'mBrihJ9`0NG[*'KjpP(*Q9ofL^e3h*kb,B5YJ'M$#^P>&Y135]ci3aD"d&9P,"%5"_YUXpO"F83JU))9PJk=?tp(f0.AO7SO$K>B4AIa8IqNl'OYbY"jA;[7n%Gag_9W+egY.f8(k.h)q%LB@G$:#C1FA2XM0>TkgG$kF5[gPD#m&`je4[-'8PrCC"VL!)sf;7E5Kbh)r,&kJHlgEAS\-`bqlN]0Ya#ka2*Mi;K+@EArBZUIp.E>NBh(j`U<+-ntk>t-QmF`Y,jA*I__nA._k/S"U[ql^[Ctc>e=Rs:/oE7/i(6A8^c[i6'\tlQ.q[#DoBe[ZHk$ Vf1W5e?g2f\6bK*SSYEZboDaLqNrBB8nX(sIU+*Ca+!K:&/f1_`Ym9rMWU.e,r/gpt;_4Pb!\tIW"m)f=T>UrS2+ErcW=!#LbbR3h<Cb(`3n(fOSX2!jTA!i9\K1K)AV]12k!!Hn2@8FoqfBK0)5kisTAbMb:P"^HogtX\4q!OeF^!G,c;boDYB/7$#cXUV,+0W*GjL[3o\#(:a?H'BqipVm1-sDj$=d>niPS#J>3i61;qWL.aVmT!a_qA:%LZNW7(]=F^p^D$$cELa&_e:AACH0D/b'BMaat?hrA+9tsc)66"5OsRr(ckAUFL=TgA_4Da")KA0@)1gp#c1d.P4-n*ng*.XG1f.=\-;(f]\s"sE#sfSX!gY,?]sAjAOs^V_&b4c^?i=?iDjp7p%^[O+jC$Nb@l9CstnbkrQAb?'tRRE!KJ?+TtQ26[&eU3KW(L7`L)O>8E-)GN4H6/X;Pg7A7j,$]&[?KLq1* o[o'mI\iP_m?ECe=AMh)Vd%?os1eQ9#>+Gn8$L%dAkV=N_+Cb2/C9h0j$)i@]VCNeZ;d^A,Q7:Z.?]#DV6q1SsmMT$pqN""p#`5HjbIH2^((E*dOp\UFAZVKkd2S?FM=n&[nHMJ]S2*aA%WFE7(e"tQ!0T()5T]?F[RQ\R?S[Ms8*-G[fP!_J<6MbE&cY=$;1src9GdkKiJ+ZlR3m?M(;Fe:<_D`.;I HI !25$:BS-I<^1SPj)!NEmJccU1`0 >o-S!b7hZc+C(.=k(LI66g-"WP>Kpn^p`EY)T^HB?nA[UW[HMD6&,qcNb;($:gJmLcLa;mR17pA0,I1lBj;sB4U>?t>'_sA 2<7&`HACF9IMJ?HlSCGbng-J[$dG+&ntD26WAINnS$ A]_Eo&;AJdci;W?kUBK JbHDU2=G5Ef#hnf1aTo\AsqX0nBCH'iF)sX*->7G?;;FSkT%]^U\is?>BNWMXGh\in!Ld=b0g6OS,41jpN93[OQa,1.*kNNVYc`IMI?gX_3YZ;ZfF@+o>a^JZn+W6P;UN0U<.WdE4)=s.m6_%4fQD&t9@Q)9>F"O)3*oS An?632I[`68Gm$rdPAKMtHb:dU)R2DX#mmVB3GYt71=dDX.D,kLOnNd"EC9mP%S9Ln0IA&)MMa C@1.a+:"J)A=>LimCYW(1t+9,4h\./VSQHRJt7f4UJFn:HY7bef%/5=-n=;=Ek$o[Q( .:-a,fQG5TE'dntYs7hClXj!)CQ20gEE,3B4^hFrCOL$;id=;lml.kg-]dX0[ZiJ?mZISK"L#H=4T^osPQU(P/T.AA/Nq=oh4%n:m#mKM!D;QsN+1?+E^>iC(5$9-K?;J%^E3m.UIL6WZ>i[bY-sDtO+6_BDXm1tZ@%c<`&b,g 5XVjH+AdPTWB"+sp#^=hX^'NnQ;o;<7-c_>l]%:O@&2ei68IoJO0+h#Sh"'0C)^1=-qb>C)SQm?)ac!5DHA\c4sNW@KQO]c_FBO^B>5B('FV0`?C36-&h=ap6 ;KHkY'28PtoM00:m_!:h5AK8<^)O@&27VPRr>s5L6CFB9ZssE(ZfTdeGPI$T;hX#ksB(D8OY[:7_8oD;` ld8QA#ON4+:oi(Q75g]Uh#'YfDJSR "nVWiP$q'>(R[-=Z8T#WI0rWo&k;0<$\9F]B8O5!baW)45APX0PTd4ST^J[F5moRCC0InB)/t7Qcq'tWL%5tX!]Q)E`fN38\8$hGDg5AA:)e9cU;qGf2AG'2Wfqk!!j.SV2EYn6a'_Ors;=[F^6D5B+M&9Oa3J>E-DAMA#[q4::0jp[l)h,:3Y*IVcb/"pqV(EjehdV:&\X&]'f@ffj4P;)'W Cf;_2-C0Ps_tJ$@*ZeV6)LfY[a2U.m6'VL YFAG-)?-D<`8!bYab.GE&AiTj?*V(hAsHaqNHUN&3_M%(Z3.@NB;%gfi0.aH,XVl8UTlG6gAlcZsgYM\7ZoEb+</?@ekqFW(OB+m&g8AR1BB`NdPmTd8FD?!9*NHZFQ(*Hq5kc,/oJ efAmpWGYtP+QHa#LqN ;bGdUOep`3&Q*:NafN6@+-q)%l=Bh(AjZjaIsF!32;'aP31I';WtBo"_DEk<#?$54O4mOH6YhRTp\oUZ=JTEfDo9*H@I+/A`/H$)PL+EVM 3R4nR1^jOc!_^?`>8KBMT*]QFP4_r9a&M-A/MM%9&Vqm58C;IJPMR&!nXR,\6'D'mFfh(TN+.q#$=k>T?5t9H?$nYX:@=DEFLVkgA:'jM,?dGG!AIKHp"$0!KA%2%!d;(#\TG>ULXZ]'24H?Kq-hK%Ee]18#S$nTE*Q$m;[-:@7GI]r3$#bNg26YaDRCdb1H&G[]@f@&!#%]7o&J:RpN"J:Pt5M:2;Af00/b"F.7!?_r6gHYI-&&l*42`PqXHAO&cK1S q-A.dej%g2r_N6UPcZAj'/Q)iMYQoWA!63at](rR8BrAmc@5 g>XK5U;H8nY)jn;jRV$p.%cAZoJdZb0.U:dba+h,[E\Hhc6PF(h]l*!O-%"kg9[A3pWJT(CXae412[=6,Ahng7YjQ<>VoYsY>;?.56aQBtL,B+c(9:4]43_H(T--b#jp38=3k]5PJZc>mN81oF\,V))#F!FO8pMD:$BI,H2C\n1(U[r.G,2."jbEj4"h*G'5CQg"*o-_,o9Yq1"=MFqm;enNo)2me[s@t.b1,006:h*-7kAL!,dmGB%p3.[dh=meVN/,;r/n^Are4-1`MV4rN$"q,n-M0s[K#J=@/X9JFr0/(gle^TC=,-22CM71id:$F"'M4hWk9mU<\GM13iO&/+F'>'p;UlE'M$X)i2^')8V']\)W8i1h'=]!;D4sMj$7fO0=[r/O;G&@%:E]DJaKDVX0b;LB>1H7\r0+C':R5aq1k_kUef.BhFW40Y1^AN!bM][3j6#88q33ddAoQ5NEQ]ZZ<5A=(/cN(5@UZ&7aZos:0 pdrGQKe+o!!c !I8N0Tq7N*p/S;Hpcp6*<9ZEG+V%;SWHk%eQ7hU908p$nboO:5E'(Gn'BG4)&E/6C?OMF?ZW`(lq7QCfPF89#`\SE-q2]N2nstM`&iN_ '`f6Mq6&8p+*TI/I.!kM2c)Ibp+iC6Ll\!iB+2gP/7b)?rM]IHA0AXAo4"3Vqjr6K>D&\7N]`j92l9[Fol\B:l;QBr17S4dP,X=_US %]LJT$;ap1=F"U%O3,AH@YfgaHMP1RJX(P]JX_A@E85Z9A-MQ7Q4tR_htI@LRLoONhYCn1kpqIj*Zf:>@iD*9p5Ag_-7ea#&Xo,![+3nY>#c&fAjY8qiEjKl"2fC"HU2k5Z?(VE]lc2o&$N].k9o?*/;TZao'g+`[E/gpCbgp+2[B8nDGdtiqU1t)HBNMn4Q'j;b<4k,.V?XIQbon()B8)jnL$)s.JGUo><)]=+#Ha=+dLlZQ[<$Hg/@PD7fAi).d5*Z_F^jk\K`7&9#>W3V'1lE;N!`N-<0-H+R50#A_GJVdB3>@g^XX`4iI3 KU\6*/:BNo^U-YAlY0L`(BS;EY/rHeA^m[]t7^[dMT!-70VfUgS5`W$mH"OL'h5pO2640 nVA[6'rDE6sDJ5;U?[52?Y03-h$jT#6K23$;7pDLR\8g?SNojB!VLtchs`MR-75n.`SZKf? ?+4lTFJ;jE6*$mG4'$K>BSZf/=5c/IK&&Y`MARfqg/E ?[3n+fd&NKKe-HkFVch+[3ojgg?4H [5<=>]Pl 4?Q9Y\4gsUq.AGsHP3G(#^]6nILm;9dR)I\sH2dM3UVKE7l2aTN)7:iKG!$PB>`Er)j7kP:HW[0=Ad@p_(52`>AXOcgkr0aM=UR7!KFs8Q@06JF(.0sSM-*#Q-&+Qp$q=JX3X?O`EC4eAtJ7fP^DFRR>4MT/jnZLqnWafK\VL\!Fcl&j,?;aO@WCJ49e>mJ=]d]hD]qml#mDsM4t'Kj9j@@jWp:kmmoSU=7Vm"A74oA+SAe^JX,K&H_7:^"i^->gKdi-UZSs+Ghl32NZe5$7:^Q7WaiW[8Pr61_KI-e,r ?%4n iag8!+,Jt.A*:COLpr_HK$;_ga[H3E+('^")O6n]N@#:;dl?]09dbH4g^pS60c^9!>RF$PioDhJJb14(oF\AbC&2$JlC(;9g>DniH(`tN'>5aqA#3[mT\9(F&!J5L3?F.RU6M9;'=q eV&>Y1%d]5e9?ZE&7D;>B*-QJSr"O*WF\S=c(qe8#N4FJ!7lCIpn69-3B;W^+6l4&K>;^U-R\@b13VigD%Y.a/c[N?d+4-TRjI,k`m.LfE##>#lt27lgCeL_>(Z\W]$a0Oj-f+t5/rnJc+dj@d4d!H(a3DK9lq7 .mUI$^/HTDL[GncYFbZ& R60(<C7NZV@sA$5>hmHPd5FT5$[BA9A"!n[;#) (n3#5oC#q%f+)65O =tR3\(*dIjm5\)WO)Qn+6,D9'P]A9OO-V^f7Sm:__ $=L7SgZ ./&`hE )#T,R$mE"Io"_VLU4`qjO)fQK=2fS,2!MMY?9]=;1Osa^T rQ.OA]NZ/<@MWrQ4)".Z- o1,XjZK\3EB75DCpL^pl8aiUeI9p1EcH16ZQ(^V>NiA</,$R\&J9m 8I'qh4l>OBKadMKOl*#9nhBa`?_:+I]1@ssK`%AH&JhK>(L03mPfr# J534:BkK8 ^QD"=&),c0%-^WY1ZmWg8Fn422;M+I0UZEA<@-U'&A/`2D=Ni88)t\+F+`l569P/Z`7R.k=ei2;CLTo:'jGb;"SaLdBqBHm=d;O!5Aj MCsU(AKW7US]9e"_9bg,s:??4VZ1-6HirJD"67_)%Fh7MAN\S\BDSbY3rmWT3k39I0329e<2o;0`:W:4RMdp;mN)AC+>@=chL?8+XU6t3`iI<O'jjBo:,RC5pMQOFpY)9c06hS%@<"`N_`>e2hL:Y9)!NU)97V@U(tRck@5i+L,r+iA`9@A=MF%1crm%2(YLX&.ZR6IIFZ$tjZlZm3l&1/[.B6Yl8Ug7V5m$;/ >EB4\>MOL<0%&@d21bOK@_XNFh;H[J^hQN[?9b8(QG7AeG0NmSAE"LC>?P!M_IV@2$WOJt,O#0D1BAF3j80&)Rfn)EbYX'ke4dER48p*VRiW"3'8#]Yc#%bU0bo1)M/n$r\QF13hkF^sh;4KC*^[QoPi]MpQNQJBZqm=Oah2=GJJI^$HcK\d%_e7f$6=mP\;_QtEX/_J-+F'^%4Y%:n06T]R]^Chsh)Y'i_mBZ^ib6^A%aP\sFa[MNb@GCXC/S]<'jB"jG/)^&@@_ADT^bht;?=t":ZOi9b1lJQ':NR@gU%VA0ROb^[Z5 #Qk5%cldRbrb6$j$C7.r8p<Na0r)^4pWN09k)jZ79g*:W"R[\8PGqd2;e]t5M8=)46^I).[CQtVofl@>?.q"pm=Xc" YLPr[:]nh TK-qka^LA5Q=%ktd?W/cK!old>\C1bUIL3LeNoFO7.j+*Al6'MShW0ENADFe7MZM)1['2tK#;aID%gH9oZ6BI:VUATCX2K%(N$=i]]^KJ$tWQMj<="YQc-fMEJo<,rnQd!0LO;CdnqdL1Wc] .n@Ni2psT5BK38n@h'%PW,XRq^gH#A=k7t;4Op\]S,e1+mNgj(:9 IEO0$T&X1G^-CU/RoW_O,F(6rN<6J?SB#GY%;c=B;Glb>mm*&XI@!(]!7>sT7&m_iqo/#QNDkj\p8VTmK@$H;(9CWojQ9@ejK;`nfgOoYbH>E'MQ7MT$;nG7Z'9)^WflKHU@:Y4O;5I\FLUb5t7e:gkN"q(EOdOrehq&r!ROY3j>U;iTK,p1sJ7s1?4jN2-dnArgtpW0D+eC<>efRa_Kh?:aZ8$K1@ABgL_n,kgQ:\n*%tW;#CZ1'c)Bks@W;'5P:hg,iJSFcD$P);k=6mh#A:c/DSOpG9./#iTg57o7rU]Nt,2KN4rW/'!gVA"KgN8U]_irJQUP)7`oU9_NqSfZ2`dhX,ctR6T,gS,S^78>W6hiGW%!rJEdqX)#jsk)6(^M#cAp%@d%o]4dgqLK]5d@jg&pt.dr)`$#$WECm[Pp 4Q #0f]At_hMl('aJCsA2S/M3jiG.a1d@c22R-WIb3DX&S^pK*qs-(.TbG^_/E/F'_=p;U\Ji-hkMS0:O4.&i'a+9MObIlfMF?\Qd=#A$pq;N+bh6j>5;Qh>$5 N!dT&XSAbADW4T)`/;j,t%IK=GA\SP??R/f9!'E%$7mK\tcioalVe2g_FeSCE)qLAstRl;mOLhksfHc>@d&\h&FsjdS/n\d@aDA_PdU-_%fV>3++RG=qc>T:(0&_G+9U;MXYUK\AO?H+s3D!R$OV]mYT#dE#g_RWkM"q(I\AB81n7S%M!VB,O\6)l9[Cl$ F["h6ARRBHh/At4ah]s<"b?4;fL[9GKmc75:A2r\0'CSjY\ ?f@o]pWN)Lo::Y,-#+jtJ`NA7`[8Mkt5T5hqeAf:tkTP[K_,GE%5A'jM>h3J@h%WG5oVsbDHOr5V9V+Kq?iY7-:EQ)8fAS<\s3WlBPJO7O]$o@#L@.bC&hDoW<#!.8j.<deSSBIlfMlFMSV$)=XP]6_r([V2O\ddm C27IL+'0ifqoH"?/,Ji$R`$!_tN4=Z\^BU&!(PKnsrC8W$*hPSh!JZ?:j5e%A/YVOL?[po`CD(-at 4c#FcK-NZ'E.V7+pq,(3OrT$8%E>e37o57[BeTJDYASSD!^;%ob5K)46%67J"l.We*2nFE_+Q[#2o]h7@AKg6QCZO@rFNT=M=,"'fF2inBMKam-B85$AT6$0ARI,"ndV*_nl7"/@ATWWGg:k39m(>t.AWg&?f"3>/Rp/ahL3dtB `2/$5?1bYrhmJLfcMKte`@/n ;s\PnT/el`laD&EK"5+(3,l*jjPWJe(E7Ikt9cJ0%Fc@mm4c3s^AaaV6B,<-O/m`>G+(.&:#aZ#9-4LM," NefR'XeH@nc1AJ?![jD]Ct+iFl[%%TUY_'I:%<*,/&hC@cWUg-2(9>91LXW^WRb6Z1Mpp$-:l[ DQi0AoqIoO`]b[G"Vn:+jA;%kO0-<5Bag=g_$P\tZ\Ufl!4Cii ;QkA\1%*dY(s(sSHDMq=oX*gK?G>A!kST(H.)`!NNb&A>'kY/-)&n'UKd',g+4$qNIQOCHPYBJ7!80Lrt;"M=>5X5G$;DHMNYQrdj!jJjQt1Y!DI?Bq)ZRZH>nCk\c44PAC4^5PLIc\g.285(6$?(c/!0j8:NCC0RiF*k?AT^qQatHh0"d(C1H4W8P>>B:\"^Ui?A\d(YB mOnh*JlA 'VqmWe\0q4-=QqaMbKSI45>A,Z>_#qfRJ#[:c^r\S2+6le^O/TCPFI>HZ8=/G-548sSdom(J?C3[$25 @:Oh<;JJA6)#$H'B+`06\Pr)o%;\`#+FA@:D7CMl8."5'AU5Y0UCNL](BA2b`2 $pHjf\&jS4<0!`nLbYrA eMZnU`,o#Q.[: )3-IZ>^(MUp29?DC.a!)r7#h^d,;D1-coAB:U;=))#Ng!GP/>"]q>9M(1`FW0a#Wr$7"cB$>#E 'eDCTt]3.FS0roi2q]J'B(JtbZp-es2]((SleEpVd4,B@X`=n,LT_b+/I;b?K )<6CS7;lA/*qA"_;J:1O=mrAgeP&JekLD(Z$ffEi5O(E79KWOfd]SG@7@\\NM$^nV_B/US&U7s"kM%G'"K!&?gb:%Kb82?&'"*Dt^bXt>k9E'h,Bl94+.Ns=el@F/FC\1-sA37Aa&<4p,BO5>LLD/c2N@01M\pDte )*nCBEAN]bo):3V r8BdgCl Jq6TUiF[>CJND$=UnJftI5^ApC))lfM#&RX*lFnJ'h5c@/WQ14=GCl'6o=;No2"C"JI/TgW7SViQ/(cjX>M[@.K8?RN([-2HrgS4B.@A^?AP2??N`")AN+U<@;BRAOX5=9<)\F/B!sid \]R4qV(INR$/o\*\m(_8eC3ki.QkkFlPkVSK2?HWAXqMY5*L<Q+V:HU=/[P#l*TEt!fUf5..0q/;ANor()L]\1ZR9YZ!^qaJt4dWt$AoGk?B/@jn?;1LDiLXq:qX8Ip`ciQ>87TOE`ko<3Dr-QBPV >cE<1T([B4^_CgZ,4LZf!bt)t9iVR(1kWXpj3-rrq(aG_SZM&O=-2QU37V@gQn@Sn,/!HqiO-gccspXsa1$%e, ?Vf'5=@/e_,ItO*U2`3mYcqB^eZ+#Adk'>A;.&2osb[=ZEO@^U#:ifJ<;GgZB^o!>D5Gc^/Hq9XH$KVb=A?c%DI294lh+]p[^cDj?&J/CH>p>,l/_1E#i?-YZ-)._(QrZnSc5?KekMbBPs;]SmRbJ=(P-?I!AedL*C@,$dqDm%P&*/*( g*qmb%q!nn8.hs\;nt!UUlXRVsAQAE*#qaO#Y%E)r"LKQNJ@dW"EfX)+\Xf=5.TH3/>dJ?9W tU9s#&CHsFT =c`3DHLNJLkA1cJ"D>aQJh%Z+I=h^rE>d1VW7'aH]]JG6I0YGaA\I4_.$q\b$R:pKB;n)m>%K/0l9LG^(bW1$qiQ\NbYONAA%c. ;:PFQ++0-E5P^s=7^MP8$)rr47`":&$='>ihiFb/>A^7^3UO39<>#]l6N[%B8M$t2jP@%RBeVOYO0l]pOnrFAN&oO:7o Ts,gtoYh7:\1!Bh9)!XOeCHYE%9C8pB10HZh'L-a0$c3AS=r^a67gCNkVht<`c_]f>R4ZAitLW!L;og%CIJ*^T9RsA,q1:c#X`UI`K>kJdN]*A"qD#1.Ua/!FE7e?JEj EGALbU2cdRpPf&=$do/?2),R]p 2D(HtnNsNp-J+k0V;gb6l2;k$e5o:JBCXFf.S)SHs:C/![2kk ,cjJ Kr2,Qt@$$t:-qhO"bnT3e>GFo`K+PbNMO;Rh:fKEF b^T7a@'oJ+a>"^V2Zk)@J`@N^pmAq%QWQN+!+M+bt90mtZE0 `g%qYf,qqqpKg+tr6`aA;Of*\RbV#Frr=&+-pqWsEFAZ/&ToT/sW&kO_7Lt4FL-UA:phLq#DbcirKJ;:J!iUhKdJk`Iq?!8S=dGd(kA8d;klrp4J+:88cXMP*\1)m=,E9k=hd6*I*90X90`?JA1dXAYfX!D16fdaBiI2gA'(;n"cBp4P\XCih-r#GAN3R<%V0<q2I2WtQn8%:*V2D!F@KPQf[A1`^V*qr7U(D%1C0t hd!_.2J4'jr-]MrGV+bo'"EoM:^a3rR^#fm*eQ'T$gA/d'Jp>5c)Ad)p-E(Kqk78CE#O'\:KZ.$GT^d*>)K3MQq&G=R]"2OGEqP%;BH#9<f.r!D^/1tj[ik8tIpRlXq@#7H8R3rJB;AKNR;68#k&"1O)^$.PB0(p]pN$R2i1>-%+i4*lhab2R3M5=b(`WeqJPG@;KkT,dQe)M*WF>&D_N*ib@0E#,[WS(Ne3YPtT -;'m-BQ,jbp'eo[pBjAF>f#h2b+qRd>%^++bN`P]?CNq2Ks$^/XnGO3@G&rEp\_&AX7XH,7!gr@**7'BiS)pERcqFmntb5'[=Z"c/#p:(E@_eZC:p?kPH=o:1p@3)J$\A]q'*C]G*9fa`jeSZgj2laCfVS/+Rgf9=%S_KB[8,l[@`lR"B[o4mBA-dY!UM%Q2c=13AZZ[6fc1["[9g\"=Uq5Dl@d4n^K:'982?V909L0= Y\5AlX1V6$1m'%]"ERYJPnT)Gl#/Fc<]k`/U.[4;cR[b)j#q4q0Qpc=c$eAr-5V+n8(\DNtiJhPis3:@<.F:[`KrKL8W\i,[1].b((pCjbj%LDh0?H$2Z*)J+*Lc`jQZI`Na.k>`PhQHNn2A=OJ@cppcMK00LPg"L@-WWZ5KE#s_ldV&Mtf)3DBA%!#?1I@"`-^E^=!X]4AVDEQT#%;70kd_4V"dKX!j^/UfH'O@[*IHC(b]AZ$ZhLM/X!0/Q]Hj*V%k0mI(Y8$XOn\.qIn5/e)B"I]#/Da6V\'O]QkN_G)[I=8'Y(Z_.RqXB/)[MIAq#n& +nm qtG6g<`OU\iKY/dQE6D5kNJV[rJ=8[(S8T$Ig4eIP_Ff),`&Lp!cC phI)oG57]I6PZ7ciGAcfh87BP]!`AMF;<5TcIYXOemL8En[ag"!hb]T(1\M&7[4C]n<>X,.(bE"Z=([5+>& rentPm#3'4/>U[ mc^#Z6rV*\t$LgGp3$:*IG-1.25FGebgA4U&coE".Ab+j-&ZR+E*e!p)qS>1]'bT-)RC+6/A&ZKX'T\CV2Qr3`E]]iQn[h5&5Ma$"*M*)bf"rb 1=p'I[c>VGXD4BO&O<7Y;W=qbng1bNU[-"<38PdXNhN941Oe,:'opR3b^,0YF\\+f07p3"0lXp,tKtrIL.0e^*.pf'00aE$R#8W]O?4=0QB3LUr?mkX7B(m;)co6E'"<1lQtfQ@5mR0YR*`FFYID+'S0K,Z(nal4ssG[7IS%s^48pi2B,8 (A)KiNFLc6m=&O)5j2 ld*[8=I!/f h4\G#i>h?@8P#VEE76!^E)V!l$DeRMMriK1&8NgVG;f,X^bfZ8;N4$nqP]C^A\%?AmO '$aWQLR^Va,+Zq/p@aiWi?>N[Z"2S+^e]cMRH;7DWNFR1OOaj4sQ^l*]XC`tZV8T>FWeS8N`'`ZmSGbb2eSFN!\>bDh=Mg:S!ks4EOLh&T0[*TN_`kpiT1=?:k_k;Q0I]3Nl])gbh8Qe[+!k4U1g]>XHKo9tgI1bb V:/`FVt5e&D/pg:(d.@+Ti`LPWE+W&/"YVOO`C4kk nOkoUl jY0"< %J9d,%lsY,a]+`A!Qd$WR\n:0DE(XF nG9G?GMXFO9&eBQcA$Ma3]LQ5RBX""7_De@DAoZQNAZJegBWjA36hDcEt.OXm8d*gd_-#0fc(:9*/ N2F9AGikh9'/sc_ISAj:h"s3Lk_'a=a`^3(<`BbZOk["B^_Z[[/,eq4;LT:oHXk;r5;lA( n@cjgaLC2[i)rKZ;OI:EhCnER4k#)1Yoa,+EQ$i6)dSr%2Ba.i3: Z6SA($a!gl$/nC6>X0EE_a72CE`nHL"`ZGU_5SWAA?W! (WXtM9Wj$I8P'8dij.S0aU*$(MBK HLH6'U[tq#JP7->J=na1WgXIWFkjdW;1Y/sUn#bTMqen^`7bA>(^c[!Kn[f7p8AYb(N2%5\FG-L0^5"qMVFfaV;sBVm9oiEHgj8H#OYoUjZMNTL]MqdZ!s]cpa;;lN)0USZ0k+_G!MnioBE=e0hs3r-CTIilr>3q]9?JfI)sNDPA#dp;\3rFdLnA@Vlgp74%r7>Cgf\N4eLYHU?3*\67rK]pP cW23D84fAQO=2,.p#g4RL\<&QdV ^;qPsYans`GF=XZhl-GE%EW5^K=(+(V=OtTqc&:bh48P[RUX/.YKGC]^DA<><6b=Gh2Dq04>^*V370c+O5F&r,CEhV5fK)nMfG)Sr8`i/9K-7fO=b@T+\J+7EJ@6klM`Q4^Yf+e^kXIrNXAGn;/:SJYhcqAr=0shWAs',%1sM.3OZQcJeJI`fO4RV]9g$#h">h=C.AR^)4e&Q&K5,iZ-B(t$:NFV#FF8tY^GHO5n1q#PIMZ_0JrgF[%\I7R\CK5A:-rc-P6fFm:TGqbU_rjs$q+O(I4So>0[ApW!qQ5IQnZ5GHgr=EL-H20@6Bk(AV$0UUF_#f9(6#g":j!Vsn&pX)b477Sif2mg^V1$*D#_.DY@_CmmU-8`$i1,h6^8U.(EtH9<m]5og)eJ!bbP[b!QGEpJkP@:bmPkCONM-(-`U]cXU]gC"%Mj,@f%/]*q*9;UYd9!)=Ne'4Z7rtB]b9pj"dpVkMkA4d>@k<(tQjjl"\gQa7PArYdrTe6r=Fe=T9cYL&@LU6=r5r]hD:o42!1ARde,?dMrkU;`BbNYcA"=KM)hRQ`r\hoQOAA37TNtXr^(6q9@=N9)j6I!8CJJl!pg-_M;tMdSa2sD)B&*c8t/dY0;+=;j)*-03I1n 2I7F1jpOc(ocb%%L/XUj\s$EE2[!<;]8k#])^N+AlXfNZ6/jO^Z2^!R,"s'd:k<[[^ig6Z6W<#(\l5m0+^GHLN:tD`4,k,D:V*HTp8)O_K7DO[>f!AM&]rN'< MOn)D"o@mK?jmgi%FltcD*0.@,-H(e6!!F<5Oa!Q)A4OHKi=2=NDBR6@jDrV&Wj.p`!VSUb0Gh8*Zjh-X[3(Gg3Nl0:'`YMLhApqnB0#aJC$$_67?8k]:lA:+pqsqs/Mm4jBpTGGsKA8RH@k$)kJI<+c^HbkSX0%Q6i%m;?7J(<X\V\G.lX)qP]=#7?7HPMQA>D&q+P0N@9)JKEX!8dCA0b"8TbCZ-4C%L?#,4$UAo`9IPt"K`Sf`b$7?,ne4fS';ok_3l4HIS+7H,JV(5[NqX4TO0KdO_&'"*ZKDtK30&f;;*"3p#]t1@ZYl82b^sjLL,;P)$tJC='b,pm1Cm1CoL1(]URj,HA?_J9;VST47LXYmIq.O^,!54Q4RIsp6QWdbW9CZ0g-5J;Z1i^4bRIk96r.nI.jUBUtc^I![At*:&UE(KjS(/ Jd]I,aAkEn]?QaL!&MV:b0tVF\$_(fq__Uo3W'>*p+6%E,[*>T5hJR^FkJ*$#43+VhrK&&p"?K%S'r";pKQ_1qb8JL_:#Np5>I_Oh%>m3;' $kA]i&P3A)7WUXm*#ZnF7kU 1WcU4+/c,^ -0gAri,BK K=cYV*G9sXa#/#<iK-Y]`m` ^jW GtqIn+LA4/bkSW.9MZ)ZRbNBKV_LN\>$DohPie]e3?rjWX GP.8#A2O5-\7"C,KPlP5Y&U2[KlMQo25q.3EZ/#]X2UYU:gAI"E4Yd2`IY%O<$ptj+Y5]LR'G?P^mRdRd'qh/>A?Dch4Ys!%UG'FYh>6K5g'Wo]c.oGTbGS-?^eAW\3VOP=+T)_WecM?5/9/6e//Jf,$7((V@0/%O_k?8A&H!C(gZA$\lIS=bt.=ZY@%!*`3#1(<:>NNP_$?-H;O/FPOsqr#q?B!C3%4*:JXFlF#cLCIjr`AG:B!d'B:ai=HEr&4cICiI=dGf.F'X;M6n5/S8'LkO6,6SRf"?UQJ 8,8[=tiC(UO]J/AYl0_?+#]rgkV$$.dI 7HGbO;WJ8I^^/ZW:jj+m+ZRir%>jmWXkmbC"Z$[TT\)Y[%)L_O+>NLsS-^\Kr>eStgZ#G A:R:mQ9l024Xb[V]M'lGW-%sjY%:s+b?o?Oqid&TFsJ@HLOL+=1SP31P hSX@eR@61(H7f\W"`mdPf:JlLE\%sVboqP4m\Nq-1j^;jA3521f9X,Aj8 h61c=0G480E30bdNHdj&m!Dp.4OQXj#aaF!H!=VO5-2R)NsdM]o;)bs d/2NC8_'%hG"68'4CP22i5 ID*8>Kok0XF^'mPq6em/"*-0SQU`KfTbIF."oVADl9.i?JbIjp!>4;qd>\/mJ%tM9S^(IBK8CF!'a:/*2^=R&TVHG1AoIgh$;4MMC.sTZ18b@_Zo#F^a'lH%VkRFeh2WYgs>2'$]7o 4)V)"jRBN-OqbfGi5`bUbEG^cc4TB*.I,M<9sX"\hpBYZHZU&@Mp`(t:oi*W:4eUk:j=1q ,E77#5=+>#V]iiI`,A,]$+;aTN]qO^elX5gd1_cZJ&FRjfe50o5YP2'/3.:tN)GPGsWD^3FHn<Po<9t.kFBFP/9mJBM`>qf7Y)jBEs,'lX0J\@FpCNkj$?;b53k3K,1&Op =ktW98o6go'DlS/q$]6qIlD'XPAPmF+52*KkbNsoh;Et'l?WA^MS,cWZp(t5!bSfAhfY-_Q]XtfE,'-9JKs'SPbdC1h*.2MmDb#CcO5ZK4qR hc$;0*<<]G<3F)bo 'As'2@+[.Oi&<\UAp2/fMeA.>A6/$Z"R/ENAd47X+n*=b4Q+FRK00@a(!! leYn1B)b%]n7>`@,nF9q4>7"BE9fLGLt1!X3%,!\R5KBn;AUtn2@2m,"#sBAj`+n(HN2KR7c2Q/&9'N ^XS:_/A'igE2AjG,k@@A^R,I/t:L?DO'U2Prl1NJqr_k&80fZcK>Og<s-&1HYFbg8i:+=@8TC6GL^"HdhZa@D$#-BtK;.,Vo(!keiM:(oDc,3m`!eK8`/jha2Z&Ch5ohpX1bFM8KJ(4*T_*g;DQ#N/SH*GBlsjtIsQ(*>'6c3$J];t3h6CH,g2P/MT7r?t,TKRN9\;OM3RbVC0bhSX_6F5R-M# Tg!EoD%SYW*1Qb)JLI/!MfTZ5""s:8Fmr0*Tp7P$FXqJ#%`#=_Hi91XEeFU(m9+m2hA%ZW4E[?l`=:QW"mdF>Ps03m<9`7jB""<4<6$-`bCsKjMAMPCG2W BC?^;O17GSDg1l'"Pmojqq0\C^,I_\).2+#%I?.kI##'n*@PSh /o:lPp2Z4b7o0EQ'c7%>Xme8V0/+A[A-_n\L\l)=Lt!%c70O[C(7qZ&Xk_@jh'DphP/i7p^g2br/7boPXRH[Eo?l];bY6T&LrD@4Zb mjUf9>\b\PdtDQ :AG\H91r>R(6g6qAb$7DXRdjt&#mdFFjNoXE&]0FU;,LKf.2lK`7In."M0#RCDI4:C;p):5PNIKrL3?oqj=BUQ3;4 AVCAC&1nibS^kES7a0kLA50\3((0f?85.QdN-/k:in<)tFMAkQnN#Aid/G'-+((:Pf*)lh20R&gpeI7U\Yl2k#r3OD%VKs\#i>oggj6J8"N-QlI4:t=+raJWD%Fj [k"AM^O5frFf[K$SI?eH2b,*H<YJZnt5(@Ir6VDUKnPh:9lsHAn C4]AD&Q`"lqil1BAIW+FfiQ[K]K="X'dM&Nb)L*R!A?Yq1C'gS(Y0#U'52,4&f5$">_FN4iT_2W5`Dk;&ib\_qM+VUPX*#<Ftd(f`XXa]BO';.a61BGK(DaU7XWs^d* f)=8R\0C01IdA(>_o:LX2c1!mBV<4l/QA=!gg5c!dX"1f/cJ1P((2,_LkH?hi77HZ0I=A:fO?4 ;$FnW3F6sg?Oof1g'GCA$&]Y)..5U76;%d!Qn+-kp0BTl'km"!0[bL%2]?d_Br;oa(Z>qta.#5A& 7P;BhDR&rW^c(N?H$ZG&eE-b0]m"^:$D&m5aAeh=a_.]970#lT,`a5A]BVThe@Uk)_8 ZpR+H-.YTY3;1>![%_HdMoDPG"s;(hh?NRqHZt"eroGFR9`2OY#VA1#2g>Fn`]<sQ]!,Mh1Z'3Gofp(K(sF(?BUJCHa)%'=L?7gb07T-&X:'n"3`8jh8kaK,]9IG6\/(`5fS$U%Y(qmE"h Vi40&3B5$.\'V/S^Mh$\P#,Z%43m%R()7^iP$oVJV[p@6-t)n&\87=]I^1L\7Xm$T9cp,j7KZNa<98DU:iHc [F!naeI4_E3A15X=K/?&%%JQWN=Hd/_DN];2 a2d0B4+h6($ 2kUAp^im/nP ZYNj/+7+E>\t@9r<sP'k&JX9 h2^2QD0/;go?MKAsS(<&3AQ7?MN=Y(hX9#bLReJ6M*/8L>="H34g#/NK>Ad1 \CmZ'F^F6E`PKDjC)efPUQ&-XD]o?Eo%(9,N3NA#Z[P\rhcrL<84n RsP^.b+KZHk#;\'XYg'knHL3 gJ#doTCiI%XZ@alWl]r/9b_7@0q/TIMA%=L2AbG,3a)lo?H(]!$t&k?)a?b;gpK@tF:H)I5+29Z@Fa8^58D%0DO%(5564 (&RH(!OdYt9-C=.ZJMsfhMR%ZFUc(Y\\5P!gcVp^+5)\]*)N .1<"i-71jr$AY7p7"9T),c)=`S)N*B6:L0U*aW-HDXfsXVf&a<(l/tsMn`;`[l=;f&rbgcDP19ZEZA`M6]Dis-MCIcAO6c+p_Cjkirb!a@hLMC@MqCs2O`]B#rob8S>_U5OXA3pr&39^o:+e9hi 'I3"4N@\J7Xa=lJE3f( #c!T]m0R%].V"YU.*=4nA:rY`)W`4sGkr.ZjqmcYC0gq\QpDs/%Qp5h1>ZaEk$iG4ddArO`raj:VV 0a9Co?8!$SI/:Y'1@hY75]?Ff'^? QFb4lTA.f$Yl90*85i)JDM)1n "UeV\ZcL6WMYrcW7"8A=OK YqMAG+\;q"$Q$C'>(S56?>3A2UgAC#$.EH]?mL2VM;j1kO[A__NaH)etB4AY.nDt0PlpQqVNA`@O>JJG]5joI]sKc[gAJ3GibCf`aceB6$AQO@=hcmn[:%9WVS$?\24 o>I^]qF01Sc18 KGW9[F]`I"A$rA]$6Q?OnpSHiaO5_q'XZfnP:UNHje<=W9eXhr+2qdXobd8)-FRk2OK?\GHPXt\?Wk`3n?d%5iZZ.fCG#MDi_2N&OObPNm(' SW:B8jX`%fFdY+_'f#)B?:*J8sbf$D8f.?<&Hh-37eQOA$E [(Z6"/H`*"%I??Gn<X&q5,@D!$gSMs/ :*&%b7,-&<;A"Bs3CMP]<&$r=Mrl^`$Gg"Pm/521-C>ldl[&$aZ-6gmUAESdC"t`86-WGc'm0cgT?0g.!InTDh,_;?C7!-SC-B f9t$\^.0oSHA94BgE+A2)Ca^"&sN4aY-`fF_N`'8''4mTaq[2kH70 i+EJh<,N:0<@Z`dsBKA/E:$];\j-9O5#`\Y6.'F4+AAI*L >.+Aa"smg1e-;U%U)M/>o^#f3*la>+ E/j!4FcZM(9RbWR0'hE\*-A68[F_G?dIbeH!+cS<,-m6L^8Ffa)]!9>E;kkaW%rds,W+a6mDnhJ2E?DU'f0OBb[Oo&>"-\P2'Rc!Ls I0cE'nArkdfYsfo_`.74[rF` Hi:9a(?&:SprMXm4Z#nC>I4SZ3Zoq3E3207!e`N7pL]?ALII%EcE)UcAsE.W2Hp;H9f.6+, ghLDk,_;h T&AP("mHq/_[9kfk(L0+c_kI+X[b[n.99_:>$f.%.56=4%s9A%%'/"LZ^Q)EZe,i%eJmpGE?Ys+0$FUa@=fjAQl!/Q.CH2_%2AX^<_Y:3SJ]rcrXA$dP).gd([HQlTq=]p7/]!LO9*@=ca0/Z3@0FIMFf_siXZa@9.G&^+ C Fsf!VNRTJV4"sdYt1e`A8fG#/1shHkP&:Bo8g,r^['#Tg?tFsP%J''$2>C)+>P`r)'DP&/J95^P fLEpi4=G3)34qS:,XGEEiEqS$Qj^Zdh7D/7C"8KP&(1=We3^kEtL4TbtU?mk;.VSrCA$8d\08>K*hJib__TmH4e!?G5SN_49jl!&VAO^s"^ PQKL%5)aA [@#,S0O&p]=6,mKq=J,mAB.<#*(_eS ii#NK#p\H>Co*SBDXiV`"%;o^=4VaGiDdCsB$H@\[ FiZ.iALhM>=p0R8UoC&CRV_OUDI5@4>iJ,%'G=Skgt#hMR6H)Ka=91GU[ao9UJH0Ym]S:ZY!d,-1$1"ae].!Ao&h-`/L"ej3YYI.Ge(Qce.Gn*QrSaX7WtSP`PKoVMA;KN3/?YreI$!KB'/mi/ h^$W2`BjDB@9p_JIrqFTq22\`WQH:;")70d"di`KBZOp"<:%U6/-@@T@:KiYlANXit!UJGtk(.t]$C#o+k;:WA&DgiP+TR1r[W2n=KD.9,<_F>i6`85t/+(]s:7J?78q*>>7Q' (Gta[p"f`;AAsNQntj[<HcSFF"iT%Z,P]j/G4lXD3O,ABJ\L3N%PT8_[='i+QhC8A \.X9$Krtr0WPSG`"p8 tU'AJ#e([Gq21Or[em.EB,"-r'+:\t:ZmBb*&( kpA!:63RTsJLbATN`//D$WXRI7,UIpoJ+jDc`<1tVGpW$Pcr#OHRPs6hbZSTU=mkPVLAhL]>@*^q:UJ,G"`'&/)?BB3]4c1p%P,_% +/?^@oPQ1?7o+ppq"@$J+cK4!GY">?J1'-1fA_lNn/[rmG1,_j4oq62Y?^9Q11P0E5'0'3J+tnBlP^]e"0kN3Ekc1WonI9-qsMs@b-.'/AACX:FY190e GgVY!hZ+ Aa7V`Z_k0E865">AW=1Dk^,,nadpT?l,%$1UUUqnh51&M:W,(UFc8Knc0ULMJ`f8h]Pb>T*i_Y$RHG5hsO 7bb gM/A5A'5 5,*;5S82DX%QmA5fgNi/1&P;q]dsNU41[#D2D^Z:M&[;0>b\:7jR*e* _H;m;@09TTsFcjAt-$H?DmP*]l<i`33Lth-ObZ#[_K:E1oBKA\U%ZRW/$HD3JrZ$M-%5!t<7.Z0]pM.75r+4gI;5rS?sXMr`\0Dms:P]2@-S@b7hF\ N\EOW*Djph-em`ak,Re(UkHPWM1`S@_8=pfcP8ZF.\sl9LfGbh6r!*fU Y@Hf?VDaNQ=><7L_aC4oAT*BE50p%_nI),^WUrm>77Ah65?7lQMn<"4@nc]oi3t-A5qp*BD@e'&XCij9#C.FZ6\dt?YRb+^2EJtNkB#o$)'-j*T;Y!\55BHQ"*"fMtP2[jgYr:N!ncG>:B^p=+AK+8_oOY8Gd/%R9]$3`o'aKE34?h>E9q%iIQM-+L46?T]4U7`fUoR!'Wekf._+*ED9<%CIS:^tD+/dd>0^3NWop?Inj>Nj[%&qpVWQ<<'dAhmO\pAECmd2l&?2 mDI:dVSc!3[Z`'!%dlD@8pAKZ8!mkb^^kWP[l.[7\C)Ut\hHaj,H;QPBdpohH]fdK?O.A,EX'5g-6 ZS?]! 3rTg@NE1_r9>p K>[;D9OjYkX&b1g4#fGP? @VHt"HUY@2Iso4nIZM6TA]&Uc]!nEHLj2[@dUd"(f(l!VOgneeni],`S)L:dL!&h2`!,$F,=5MZA4(5*0m%#/'iQY 7D&mN=2VB,19(_Rq]Df+Y!\=HGTK:1J?rkOLae^5`JbE9dah/X,k\]:A2h.Gginn.j+Mb>EXl)Xsb[NNF"Bltp.U=0mq?THM0*nHSblADA&aHj#s#Tf13Jt4@!6NKoK(d5.TLh)9Zneh4)7i=N;Ns?BA5kc"=Hc7gUeX 9spSSBdPO(,JX%a]"Z_fAJ!:"Ds9frG$$lIrib./&@O%f(/`P6E`3T@e?Tgo]rbc*+5IM:H8"GN"j"Ti#37eB@"h44>+B"gCU)eXFRsTHp[V/&a QO:W<^A$_:tU[/0"2>T,YTRNY Sn_@0#m\3"cqBtQXY'?Ial2BW6nhIA\cUc=c B^!d^W9^_-2_/qD&1#nst7C-&W03D>ah.%AU2(Je.AB.e#GZFFZRP_GPM#E dNaY 0VP1D8d.hL-%'UnXRtLI@YE"@q"QSJ5*.1Z&LKison[,3VDs[^MEaS]Sn[35_.]M@DNso)?sOc94@$QJ&533m.$k%T[B?%5:!;D95dCAt"f8(M/,$_8@4Ng[TBACtPE600l;0IMBA`e;JD.6+d_!,C7X[3Ap5S+JkPT-T>@p*HfGgC8G8l$Gt&;j qFHG47U5rP;'A(8RiEp@-"gq85#djA?-M8U8l`BjW*7"o#3'\$dI"Da38TRHP=P=b^Wq0LaaA]%K'8YkcHJZ0>RVokpZ#)k4 $Ta( E*Tc`dt_L%h2PhE.5Al1Qj%)HdAUd@.S4R8'+U'p172,a1$&m'*N+8iMb:A&]JN+-=Ad,"N$NbM?d9GjD's27\E<@s&bG1?me7&qFJjE?g)-^fUf(SoF1K_\W!jN@`lf3h*-Ud%8Ua!AkXGOL%U]+4Ol'!5J)M_!`X0/T1,N^(.SC77FpSiE_rZ^N*g5Ul:XIks/gDdZs70+kKtZ/sdg(l6mE"akc.1'.6) OI%Xoka[%<;iI!q<$n0[X\X)sJ>:.4trHQF,< =UMci)!lr1H'8bAc_m\8W7C0[fP`^sZU0W?$$.%XAB5G<%JTq#0L7OC#F"3Lb#eC?XB6:[2%PM;S+e6!8p[lA*QK7Ci6E)FZNRk'42FmIK"7$A NL!DG0!ih`'L'-@jH*PF0+^e$4336K>LoV!'YRt+!IpKM5o7&]JRKrL qaLj\W`;_NT >)t?;[?')A\^oa518(VaT5ifW7i2_DFA=.XE-R%Y+TWiZAQ_**DS@<6]AtYN3qs=;"t+ni@$pS;*K)6BAta'lcX6kMF2Z:H:].7)+*EOFhSH4S;R7:QU`N>c.S9B*o6^F01lSo\/NX3nd:7>9Nn0! 1Jm7c8X$<5`jQ9,r;qNsognA[a*D2sp5:JlS@D QI+phUn!m(;kKD,2k+b`Wh\M3+1TY(, mAs;!2;NTN.U^ /L2%D^'L[QT2Q[;4OJqK]Ck7E[o2IM7CXBLW*m1?#s$* H"MR[3R:[/.gC\[T!`2h0oWM]*&K)&Z,Kh(JB1&.eHq!N[M[AA$"Ee"IC1\:j7:DPn/h):XZM\OPG)o],.9]NghLT$DA#5Cl+I# V%t[!l9GmT;)8AOiFEXoL^(2'AVZMN#>0;9L?,JF(gifpJ_*pOHQ3o0:dC>aAU=kJnrVq_:;m5r9BJ5Y)df/`3nlE-6e:^i!!7@!b&&cK24pdA]mdr(%hi@YfJD1YJZ(Ddrj08G:J$iR%o\o@4aVPjB0h59$ek;]W)hK1B1-(^=.gD^<1Hgl8LmF9M*e:B5`Zf9!)IH%8(l +VXME\Bb>IRe8JEQ) XNm9A8j5.Doi^+%c&l;N$LXq4]U/fkm$0$;r.q7aX3)I\b[`RhVg\&@]Q.n/>g 70`Ugc7pRQ*LplB&QOro5!!g@8HMZB7@,8RtoC01JED6o5:l_/e'Q(7hal>EiWOh)`KnQh+h?5r912!?'r5'b+(Y,[Q'#='!H\( _`CBR/d;`6AUDN:%d)@n`Ag[,#mPGYWrZ]7?(NRG'Cl9$oCS@^WW8fL#po4`[U7&;&#MQ4l9T.Pr902kA!LQCkkb39/GjZkTm)8VkLZHmj5%UJ#G2ngHtb([`WTN$Q+33HbF]qfKqUmRZ3H$m9l6*G06>+h g^`NWdnW*Cg4kkkteOf*aOTRrN-:\e#%2m^87^1[J9T\#&ASQI9[O6gha2]jqa Id?:@^8]ANc>@*G&.(W!%J0?U\FJIrV&_CKVR))Gs@H=0I4f]-MhcM';9"l;L>dm-)P9fUJU@G*`SE?AVGn>AkA >Ce`Q_-Y`I@AZtkJq!oD\aIZ5H(X;g<O5U]Z\hpOjksfb aKpH>9K2fds^;SA%_J"Eo*"F+F41H,KleCP717"L69Z%5(Ah*j%:q?HH.maa@to2VqoQIm!5CoXk&"Akk>%/['&bP\X']n-A.)q$1OA_9C4AqpW%f`U-PrC< M %6DqGB\_bYLtdAd)L$+4'd+6K/.:ANU.5nk<5$9fSM+,PIESS]a'Fn"=*qg5PO-=bCW7EhL6/1.=hgF.JkE_GPMLs7/2WhW#ZYGLY\Y 'UTr;M7Z[\e:JIEAEjr nisP*ZAD%%X5bLSMC`_0Vg>hbD]l@8Wj,;CX(K&3XT%tFR<>F)'q*#R[bcS7Rke'E>_6IV[g83]4@QT,&,. ^7K>nL=N'[,Ka`2s4gerT?c1>+%+T9E6_""$NjT-]_A:C,\O!N)oLJN+cIh>7M9P;I8f7L:FJ`h[$88Z#".tae"1(Kk12CWL:mUi@[/R^6[Fl?`m89[Q'7MIKRtbVtq?jZOWADLb)5LfY9NDQlo[I'jbtm>1#s;n'F)J\B&X$T!9sH@4@gBL"KZZ3lpNV*pm%E,i]i5PQY]K[8M8A02L]4.P_8!6oBbT1e4U9s+LmG9BX1a1SoTJ!RArs-M+4oHkM kmbd?dm^IE$`>fCid0I^j_FA6VAr11+Grl$h=>6ptU>V.D$-Go<;AF@[>3j)B^`8scNE>>Mn-B>,d"H6>3]6_[`pbI Tli@StiR;]&^BmL(.O&ll 7T:H4n21BRe?`b,Y9@G=BC`3%/f8^#S]K,AJ]Cd>%tA?@JhO+3jjb6mg.[lFKH_N54JI^7n+.R9()PAAj',,kea\.,*heik"i@KE_Wd,=KmhG]")2:_[JOp,G[C]tGs-d=!_7L_pb\'kZf$1I'2"0NlS5XXH\hW0+tL6tIa8gWqDQa6SWil*jk4V31KfU#h!L-(2kYC=6RZSMKj.M&W44@Wikh*,8+A/k=b8h5/*O^Ei T.X=b?\bmFe4p =Y\%/5Ad:(39>AWP#ASmINmgl"gP8&^icBi;B?3,qR,UdC*COaV^0r9^j'J/g1'^k gr`W+8\reRBgta9P,Tao#^njl!.aR"nT:YQMp[+;sLi9m?"h, J.7VpH.?LB&'75J%9JoR&iS@9[rK=UldXCCraQCD_O("f>ahCTF/-Pq,e*QC7HO%sAF9-@XEV5QAft?fZ+]j6If9?D/*Xq,>H]8qjGaZ,4coEai+qPAnrsoL5!OCPl#OQ2Qj9SNTT5r=@-ghrL#+Z?)f9Cn\^+VT4['%"0Apm \ajn%s;She/E2cGUe6S7HifFtC\C'f$Drqhgn6BknpXP`&%lOi=t-aD\j.X/SAW)7AIZG&UWi_(%A! I9pLp8hgsS>;Q;rV5oG9dLDI1=[E9K19`__]/68q4[nWZ+J3Y0X Xop\8bDX.*#el,[HVfpa#`@JL-`dp)[Tk#.:sZG[J>9P$:LU$DZ--9Sk;"PMja,,b+r*i@qMY*07mWpi@@c*@ G'%setr`Oo i$*<)K6UY/`X\3./4W,cg])P.^>ENU4ZbY,p08=b9KW;06emM0r2D]rk7*eq>]UYAQC)68bl4>opCE\@Cia?Yjh'DNB5e!*%JLf=/:.eGj+P4?DC_Om=IFNsJ`Q,R`E9*te+:d6sR8O$k?=rhKA_+]7Z]$]6aNKc[mmE,:FtHn"Z[SU`r.E6a;'n` .6L1QO(!JhXaMIO@+Qsq)'+DD-5?B4d$!Oqb!;,%/c=+I5tW,Oj<^a?%TD:r%f_9U]1t5js[JC>f&O_cV"rIgiJs^,mD?g(;(_GAV)i\M)[#kW''Ur!O*kP57AnnHY7[47,R[&9SbcXW*BVr;=mr8+_U,nUr0I_r^@ br^=pAgHqka3BEOph67]1U#"j3567IZTC*`oGdO21Q3l/V:m7$KdVE;bV28[Z#G.F^&cISNhZ82.emT>oY/^rs.//X=<$%]BB"528)tTn4ETK _5C_IZm;"&."APR@,;=JGk6"o.[?<%Tq4S+9WO,Y:aB#0JLjW0#Sm(\nr`o/sP3Ql%&%j&<>doic^smX8+27 '4\1M h_0q6)99eo^tAm^GH!C'QF`e5r:ns#*bFm7-:1 ](B`E2trob<6e`^FeI\XUA9kMIt0'M5)T_IoX5pN`2C*E#\2AcR-Nsd+ pqo5=;0JsKDQh+'kN'%;"o%:ChHIN$R(KD5)A7Jc[eHBs'!C1>3m(-fGVYj$ZiX/Q7HArA'Mn;8r.W]i6m8/f,>4>XB@MJ!Io(o'T8A@s(?h`KbIGDOkMW_XCee:lL;\#@1I:YO8,p&dMm]#h,*B[o;-E%qUt_O00%l[_BkDt,Wkl8g\6@:S#a302_O>dZ>*>8)Sat@-\/Z)ds3.t6]-a:eLO/0_0tPT-Yen9(*eGfRT@F")SfYnV,$?L>%q,A7NT=/k'oh.kI9f.4kQK S(%_X%`:"%g0/]-iEm&[U\ARk8N+U3bl4(Z]G$9_d'hbSoK#bYreD-cQ"]W1T26F@^WsI QV,cpI.<WPTPiGi0/^_H5W^PSetF:UY-Q4GMPIg:1N-Ol;P#iQo3i4CE.]eYi!b.HPqP8?8rqMK&)%ltAtt7I[2Rc,.F3()Il`)9B[FH0NMiF"imOiBAAQm??^25+I6r6eonS@9&nM5t#5HMGTm&V?EMn(#^6B(X%X_4*o&["iSmAC77R7$h<(k9T(XHbMA7/&C:WHXsLIsj:_JJ*Pjpe$sh@tIp:F*]"#H8KFR=QiEorEFC2VZhO'(\4^C9qNQh,rjGm8[JAmGAC0V@=G;mMLn%Va\ZK>niK0tYo9E7\)kK\U<#6(oX1Ngcf?Mo;dB`lpDI9fVs2>#Hf>LXnq7PtYp[8>:NaCgFI+Z@#As?kokS9%.00\jN"UP+F9*5dQ:ph\)b]Lr*Z:E)bkl q8k1L3mKlc\70&ZNfp7Xq&3]dNg@[T3&/p,id;XI54:&`jOVh]U"Gd4Y"gq5)\n4f!TN!A#lCG:4NV< ,%p`b<-4q\dt^n8b&lpgM+dc/HXAsPgFABAakW!5h38tHVne0prOK@GV+Dh;.A1#;WF5Pb &)A`Has6C#0[TASJW&\8JYpDTHK3_DE1RTlPjRrcm;G&I88C2CrFY'Lf;8c&sr&pBrTSsN-&LTj%\-ct[k^\Ro8JPP% J;Pg]p&8C7`CRLg:cd+T=L*p9VD+'[R$EPM"iniN=s(57WT0eU$K:l,;rATGAKKE39d=`!N-VEA&5[b!MH?;.kKP"XrkJKa-\kZ[SLD5VO,Z+J_lNp@2\HE6^^NO%l%+D0^c9>j6D<\'V;;6[8hd4)2r@\">!pAjXRrKW_:hPT*039!&)D^slWa8AVt35M?6^?8)XTqI*9O9$SGsX!cbr@t!.FSnIGf"_TA(FO)_DGr?Cm"*'hhOkF)C2fiNoDP8YCIkA!l0gOG8bCXsn.F'3=9#(A#r@K@Uq51k=@_,Qmf4;^p7XqnGH=0h#]p](HJ?Xj[>r>?U-4ZH_iR3c;LenPcIF/4\*.ORidj\:Amc]oJ.XFN-<es"F#Q3IA9>aNP")GnN[r.A9qFK;Uc;f<$%X>U+eU]\#pj=Z hqWM:MTq$/&N;eS&<8TLd:&Ab*r$I`^Tjo9Vr=O)->.eWoX67"jKGNfFA%?q-'EK=8g'_3k:PMOEKE66cTU99+#(D PREH#Xer)2ZO_:4H:'/d Hp!I)nqOrglfos*[lJ#rR&]ShTa)$W;ZKenVk`)S[8@?B*'3dHLh$9&h*XmqI]Vk#@AZ"RV8n(tC#LlbRUJ?(hjnf)ZtlUY[ sgHsHKC%1nREJFq+@D.nb4aA!9pS?c$#$-DA*6GQ568LTrtQOT79!lk2d FPo5@"s!WY7q`=s1(Q^S90M#2I/3pHgkr=3IlK% 1r\_'N\1cEU!;668C"1-W-JJErl:VNKbji+2SUDcdH0\3kh>c26a1h#6$8AV3dCAk<5EbS1Z 4`1CE7a7ELnOsLFXTVF9S =N$7b4;a&,7cUY2hr*P]nX06GrASL`<\03eZ*[lG`_k`i);at3041D"Q$`9L]YVZ)Im)IX<\62,DmYMR\HS"t?]o1:NBtH=[:>b#K&Y,$Qa /sl][0 &?pbqX>nU?)1#?jkC0)^$T;OIEGAQ6RT>Z2+')DgKA232na)2586_o1=A>?mBk.9\J@isKbA6//kpEdDbA]pCoK$f!%#?`e;Y-;d[<`&+=XS\&VAoaFZWlAJ#N\)4E=0tMCMKXk$6 Qd<#5@rNCh%7bQeAke(c)Vi0bEG/"8`maPqA!RC6D1 ZH8ME@A_[flBH_CGObF\AAL];j_@Wkf?hM25%P6&fg3/0&ZQYE4(ABStJ'qKG&=YQ"A=esLca`BO5b\!,Cs%U5WTM@Xe@59in0#Wnl2CGU/f(I.nnh8d9nL:.ha],dL%!O&(;Nq5MR]rN:/Z;ga-Rd_JjKB)*`_4T'2AY=IC:d./8@WSU1) [8s3E[W#gm#Y]g4;[r>XD`LY)lAF4[TCgf$-_4' 9MH"I=N+!+g4q:;4m9WI.n/0dm?!6mW,,C==\O0^I"PPLZq2b^J$q?gQG-16IWAdHt5a>4J/_ls R#6\J5$X]o%<%'"3 `A*]=0>+@dhpC!UWb>_+;@E;ka\a h9Y9M"7Z_IET>)L k$dbAaL9]AM>As=oO(Pc-D5@p#<'NM[JQqZT[P=BLtscn*t6C+EYZ_fh0QSCk$LI0(a&`:jtpm6^%=L?8?]\F"P"C](I*(^fSr'$[gatV&o:&k?m^:PMi.f?//`>jOF%`N/ 7-7N>d(R5l"q8=D^C0(-M&tddJCYL:UdMj:pZPmi$_;/0cb7H/1?AlmR(S62#F"e,&CpSQO[m9[-,&dal@DWZ.7+H!;etAsatJpZg,i*okI,S;8Ef`rj$F-N\'%=DM\;$jk (Wg7!2531OQ;Sj$^j^m0jU%(l]j-e$RGirG"po^71[Ie9h+(OLAU9a D4e/HbsAne.d%SN;;goAQ1_`SV 'N*3#kBs 'TfNp`_JsMp$VYrcpIG9C+pV7[j4d,5N^\EK.q1ff!AU9AQ$44B8T6Hg=T-E%"VjgbM%dq d@13`UgbS?#6I$pdl=Qb"p1;A-Q]0Ro]bA "k&5G(8>0`#6)JtrC;_hdrU@CBBrb'%$C=ohkmZ0Q[\1a4A'8l)nA&o0#<TM1aXEGm9.%BqO^dP(H&?q%?'FKQ&Y0g];8,Y-5c"f<1V.t(%#H:;ek!imGA"`(k8+.ak^_CUl(T(eZ@^;sf0!saTpj)5peDp?ZE8?S>n'=3!iZCh-<:f'ZOb0;C&mAF\[7(f7=KfAhpjlM7RT)%=jrK%C&I8J2&E8,+c"mag3"re'""-#rrA?O _0G;KM2gQo`HheqqRGAmAm7"I3r2WYc'eeioojXT"V!hZ3`D\Etrgo-O,VaX8UU_#7GiCgsXV%-PK1(JSm7R'&eN$kQ "#kUArkU4lS_VQ;rVsiQ &@A`csf1E`*+EjNC59F[V\'o0$#Rhbs)><^/Q^/bqL3Z3k. [Umki)clEnQN\. s]S+8ZF0?MBlAqgC\[o7F(1WQ CkHB@F>BU2f2Z>AZ694KkP4q;tkSKaoF\RJcB(+-92"7=6Q_*$'[h>e9W-2,'"E#:D .TqXm'"HeM?]3-jc*(T *QET<^]bb3m-P Y#-\Ql'WL\X5r: H_BjbLsb9a4N"Eb/Em)"hc2XLIKrp.QIXGDL.n*X5A6:Iob=-6k;SAQ_N'>e#C\G?BtOAd%r'H8aX7%5C.5iR.`,Ng0CEKL6_:=UQ7F])d6r(Vo,^O6[I. IJC(Z$kS-sBWMT(mRG*::NS0$Oo!1O<e!7hE:R9hJY6IE?as"^YBI#/Cp'9YGW`V*c>`IO,&)k%lQeG4&oQ*2\aPM8]Fka(/AH508dooZB@\\I\5;iGUNH^;S]NpcJZ>j!EF>NGe<i!2Fr&"T\cMiC@K-h2\g^pTTPl%X3Q#2%t7H/cBGACb/q%>rU>On@+&d"5;;Lt2A=N;$S67l*ZT@Q%7A&t&c[&04&C]e3M;+!:k&ZpA`B!oT$CJ:IJ@Zd>ki/!2_-9/'mki_alD bhQB,nUVA#7dW^8EB8?R[o.T(A5E-?80 DSoTFEi04?%h1h$HL$L-L=nTrHlLAj;q^A;lL1E\XL'p/B5/@9orORMon>Gmd+6B8_r='+MABWfsqL:ipbmcc[lY!A#^f;AS\(\;inAR$^FTn<6%'P3dckS&]nV/q-mpOIgF-6\kriesO&TM;B9hX.[d[>qbd-J[Bmfbd_/j(OVKX83N8Df"4JX^:CH`\fT4,')p$T#0XGfAqY`i]/rm7"PNQ[e6J1OD#LH$QYMMqH1%QL.[tW $etq=r$F=YA^L>DNj4Y.?_C?+2WppMb^:j!.=gl1/:?pBa6#tZltcS)R58;MR09A#p!Rm%RDaTT^"o@-C@*%<;)q%/4.W)nB7^SrWMB3l>$3`UfoUkbgRW>FGK$M7c:gV6G4cWcj(+&BXnc]6Tp+QP%.RW^'-d3Pq! U%l'j26D41c H*(gS3NiQIsa]$Ion p8H3nr*>A^qpl.W[6)\-o+RU]Ydn%s.ON3@Ws`O1*qj/B5AVF4W/-1!ib\(B9@a^gIpW;e96\E*d0'bmpb]\1)22,D(jn1X?ZEglE[U[9;%D^n7Ad_P7)iAXj@tOFI[@4=>>%[g87r8T3+Pt<)4)5Hh>ODI>'?5@APJcV&bXH*AY`#L<4`0ef;N?aC1 P*76q!4M&T3T-/A$njY]p"KSCla\=(UAaWKAi@>iViK+" `]F-EJk2b&_:6OZo9rJ^!tWW/OFNCN<3lF ES=MTpc<kpe1G32)[*p`'At?J> S-AnSDq0'Qf2,.)r5q!MQd03c8g=VCR:)CEe[2HVNg*7p'+Bp3^i#3HjDQ(7i#!!XSAmt 4P-K;,!k9iJ ijHq4k]LZ %KNOA+kAN/^X1fJ"2I,0#<1mlMX59[XUg7ZEm,$GRW\L%LW>Go/qCES.A-0D/fBHd3R("7&n5[Vi;&q)4Rt)js+YEJg^0 &\V9A"KD&8r6t-@=$>! (2aNc:5+I02R3qS9Y n/FBP%$;&T8Tc]_X6p7(;*D)m5<#b Noia*7V>Wha)9/Z2i VW;S"8h=LsYpW;%_.iM3=#g`L][H1rEKIPHVV->?):`8!*Kr2Tl?hq!LQ;\4=rAfL*Aa"RgH1_lR&S?F5HAjP&T0PIg4XLAYRAh [a1Q+lkSA [("*1BWR+$W+i&G9q1][oPdi\' V_1[kqL0K3ID 3h.MCX@V<8Q3PDP4K@=]ob7A)cI*6YOkn\"R=o2@2rXaZ=h&&8SLr'2?8ht `2Ygj?Td,lsoe`b9c8hMpQX&,:o=A``PAX_W;(+4)UmgC.k%k1`?HfBg(.l4%r2 b;s)4q=/kU07;*Z!qJ/3_n$j9"=@p<([2LfI7M`##'[*meTIHG%AZCXWg\6SUo]>aLFk'&#RA5n:oZ,2raU7dIE)l/eo6S<6^EL+tZ*dQ^@m.nr6F`-;sX'@'hOcoT +D)Sgg(\5B/7%-ckN^1gB77WogW&+=4:f"d."r)paXl3>HBFX6XEGjLJ3*ChXJS)k.IXhHZXITitshjDD;mSU43qBRH!,MK$AD-&H 2A"H?q!dj^rZ9= \TYg;[G`SU/@>A`0n;(a@Z/2O>^1=5);qCFnM*3EnN-rSQC ;"+$BK: ?ZjaHJ,FCq>R@cBhXG6\Nf?Yt^99f!pI2e]S1*\p)78"LIY;AY+f5%hU`s:heEq;At/0?^2n\V&=pP5/n`KPVO9UFmNTgdZ[ZgVA`\ILfOfA/$\DXq>@QZ/1AC:73)shS_[o;&%iW<;^2M3=hU'@TOmK>A#)OW`#A:N^@bWOpi@[3st>adqdQF>5]CsdIlI;JrleEc;"dtUI.iPA6A:eTAs$G^oKcUJ?+ct4idA+(`C$H%M?G42c*h(3Fa\7j^#U9(`34N8R1b2qJ_dr6dhKdU62W2L%];]8MN@ipji.6s*fh[Ji@bJ3Agpt_cIBU89Tt('!t)B'J`3/,W?NaYSr92X9t.n=3A.djBQ3Sa0p:@8/oqFPYh(*P42s" 8@:1D\>nE*sn`/"^ATJS3W/?atV?Bo&P8@m1 HK;AS7+K,*FEm#4X9_oqJjXkHg=S^#8RWRp1`!j)k*PY. MmlA&1\r@*t$//AKr8F!R^.bqmse14(AF&Z:Q=o*LSj:>FpFn(erd;IsnaOKAmTMH)9G8G@YFp*(#nh95M.@?iX9,lK"]%r><p<^' T01#ekmY?7leqSFN_a? jA4B'I.VB_K:)P4#;b4#CR*A`cT9q%CUV[_(NYU7LJ%ciL(4P=DW\G]/7)=M31E=Q=._hI1+(Y#4e;EAK9!6qbZX7 9P9YY8q7a\#PeKlAWO5Z5A(1/@r1?J@FA:X5[0+j9I9,#)>26ScaPBl_T8G$RAk4^b*K[F\k653JaN1Snf^lBG1o=[$7<``l1jAI2TsIl-;#.16D%>E(C^t65)0Xm0(CkpN9F'Sg]VPQ`j/D3?$G+?L;)$[Sg$(^80m<].TF&C+h8%[-,ojf;GN8 qWYRg/CPL$qj7b?7h-D24*G1mC?c;"Bq trOD*aHJ+8:4M1'8AA,r2*fK!%&P)[.nQ'af=`W6/0:h9!9W06U2&YW*=m/K2@ANJl&KPS"e:=S$)sYC< _8E*4`=d\]NMLW!R*=5H!@g4rV7F)AtX0!^U CFP4e-:b?0AOmp2+UQh[PYK2H;@\cmW*!QfTraE2BFWQ]\M1jBphT6>_?#8A]'A./9'.[%o8W_KcWtoF:*>W,6PKR`P=$N#*b*R.0.F*gIQhgV`)j3mcLZDpnLK_*&=@)>B'.9sP4DQV%dnb]>=.f+bMq)#kHHUJ^dC7"RiAL@QDLj#r%A#QV)`5.6esha9J7*>-[C#:&N(>\tCV*aB[]$XQ3S@tE<$%^Njd>#n9>.K.0A\j@pEbP:FBAt9qap*"GM$]=Q7 7?kR7l6,)fXV;^^GfoFNL GVS.ni#P\@Me] <&>H5o4(B!g9pUY5o%[o7dnYtg[PlctW`5`T.RprS0CD2m?*/a.?+sHk0BpAtr84RE``9iK"^$i=aMg_e79AMf_p1qGGjY,=@>E+E%5Ft PLFgKN$;bA)XYFNdg[1DPlckss5mfe"A>Sp@R`mL%KDnZ/=HU@ZA&a,N"cA?KOY*(W &UZ+f]Wd6R`;q)bgnJ(m>9D/c"!6(ki;AlB8UGY-?0m6l`l[q@J;.`RF!^^psAIHXr)CMPbDRNJ\dFA`oVG1l&\-?I5QpAQTF+RhF'!#=F\bOh.MsUKUKr;2:Arg'(Snl$W078sP:kPhTiUGL[0Q!I$/!+)1i!@5+/hs9@El2XkddQ&JoX4f]cB>Q9#EfY':^D.I&Mtl.cAR@75]Q\]PbSlsX"G/Z6$NUe.$Q)+gGpF:I2iJ@O1HHEgA,d=ZZ:-jLe0U4QjDtN:pK.CV:d&_^:U(,EGZPF5rA73&L8V\ t E! Vr6\J;*\[NNE8QqA\(m1dQ[6VHT.\?PWq.O:l>"WAm+H^AdIs a_H\2FS*tLBZj=*oi7+Jf!T##@ 'gR\Rgh(GL0^)a\?aZ*53&&t!Z9_h)CCT"]^?XB+>/ZD>e,==9_YQOYZ@=4C%J)n5"t<7mA+s;l\?K%e@pCjq)Y5(QCt>[&L4m3kb&5/7'Kmq^pWUME.pNKcB Rn#b5Ti='Fr;c64M!@Hb:Y/O(=0T]K?8JnVf %(:H<59Vl&6o#ijl&r9SQl(#?Srmt'#?co"JSWBT"7)PanS%Z_=4aSf.:1-Oq>266R>OclW]*4h9_A,j/^V PDEN2e7cnnNn6Wb6qb4E-RXK/DC_nkW5roNrb0k/T_mjK:8)P@[ i^-:L]_?JE.S^im:89(g2?a8F\->fZ\\YqY$79i>p8l."H/EmBP=QL9JX[jB1N@,c,bg0f#=/nPLaQA0'a,oX)C0Q1TQLSYs/$;aGm 7mC&<o!2/ph`YH;ek;#pT7J+RO19@k7D0Xk4K4.sVX_aA3FZfX3(9Pko:q%PY.H:8@^G&pL__G5^![#d?bcRl-kQq+3WtiAr"EMiTTUB@Te@YkR`1W(TfAf8a?dP+aBj:A7C-eKSFcY?KOrl$U==9e:i"gA(?XBcK`Mo,)igG6btA:%C$6shNsn7=[`83AOth^RM*W%*oZ(I)WKae@:K-"Jno\#OaH!"gYq*Z^d@97OX4'%AN+lQWgEd*K,\=L,iV]!AY'o!ba+PXQiaViLAW P@Q$n!V9n;].sM$^o<.[mlHAcK?b*=XcROiNF]eVD9Yb*&iq&TWnlFgb e%1e1+-@ gN*Sb/1q;IZ%mDJM0r>Yo]i\ZA!%:8UF>@CDT-e&t[',Ag5#0GJhM''L'f7tli1A(rPBYUhe5U@\%!;3OdHa%qO4V>!B059/Z.c4-8GCm+=q0A]b;41rQ9W229`FprnZN1o!#.$^#eAp5R(*1K;/\i(I0<_ISZ>.?\^Wekbs]eZERn@5"3)OD=QBrN[krVmA]00HjR(j=.=3.#G&jDT%*%[0QUAh7RGV1=O>a"T/KV)b&B<%JOM?!dkEf-q^/d0Mq-Jnar7HsTWVeZ3j)ONakRK_FJN)[YTUQdsC/$^Elt/blPLHhiW81hWX?19KVeeB()c(piE0CY*HaZ ,dpSJoWHnrkW)BtO<pa?s;M9K`E+1]$-W.s7pCC(&AL Kp$dpX`/Y0@RZ5B[;1Cm"U%*D?.!__E<[s=$XbZhT2iVH@[a4JRDt@*XAh]eXArr4pj?YM2555jKLI`2:&A^ad)s,#0K4mXTpU..-@*FDU@TX.N7>%(h:JBFtYkr!KEG>Gh5KstO#)H7Da@7j!erQ`_6qs3 $8T6D1gP!5H5\`nP-_TCk8CKoDJLNX5-jbnhU`g5:gTf>g#"\QUk=VoSJ4d@NMV)ZYmbP &"rDGK Q7roi.+^XkhrP\VX!m(:-,lEY*bd3B#1$*UY&ans$GBc*:E3=&mZM419#E/mettA@+'=grDQJLY^]GP42R;c?JZ5;;LCnD0a)nRYoftWdk4_c(5#A?M;*D.!O[lT\Mn(2A.$F-H&+P/rg&TXCZILAc9YjBXA'28IZ'!!F6A__mBA?D2CX1:H?hQ^54O\Ba;=F=?rYPk3)4.^c^=OV]b3??]lU%$!*g`YkAa!GRG+UQtS8=)A!Y2='d:;#Fp8B-X3sl'qg+iW.EDU5n3[1"]1\<^4W"oJiE@Ma*CdFJL9`K%-4 'lV:5'G`mj)[]bgA3W)e"3ls`aP%05SDcXSM]d$;-mOc/?H)NV/#j-bl0YG2K?_c(N\5AtW^7mP?b)3;!!$P8\2BRsML.(/,.9t+?d>2(BZCk4AnR?AG*Qfd=c9GAEfXIp9(a3T8Wbg&+A_MN]'p$EeTXB0_4LUB5YiXOsMigM*SY2?Z9+&=gHlk\i7*-M'TP!e,!nb]0i21r6EY@/c,*np&P`( Y4ntisD 'R4DV.h7e'=gchIDed:U?bR9=NO,s\3mm[#O+:8+6?hRRS@*VAL,UH\Y`"DaZcgTFqX<"UYE7F^DrG?A 2l3dZ<46f9*"WB"Cd]$&VAo!JK0=YnoF0QN*ATZ\$16RY(qg]2F5&\,(29'(H'8q!)V_'pI1l(R'm444.QZC,@;7AJmP.< QnYbCkEC]$2,%OIM)'snFB^4T%&X8RMOS+8Z\?J/'8/N\2Gb/<20A1\V0IN$(O.MDh]MhK+,NAN'$KKfUXb(L/A3EWKOk$Af7;ms"Jrs%)H#VL>#^90!42jF?(+btekZPD-_>RH/q[hY%eNS;MAMkAM3[E<2M*6C)HQ>3+I(I^hkgE*;Ai-e7-U53bDR.E?0#f2f4(gm"m%B[2J!3MPZ\DXn33RoBN=>op\XBU(.:g^)g@'<>Qc#9e?Z[55L]jnW_^Z5U/:+@/`c9s\K`)6OZ[go(agP,i+Vpbid'A:N5]Q8q%V@!+/*V%Utd_R?MU1e+;@:*GA/\DQjcO8H])p:4A^,i[:\<-1tj0VXI$->% /5m(OC&";77"BmI[^.8C%_;)AS6+m,;j^hKG0`Nenf!@%oT [Gnf.n'Q1WQ,SMVp\'rI-M!tHce>(+B67J`NiFJi7SP1>j>$)&T#)tF_b;p[ecN,Y?RN!$F!/_>;(>:;GVT\dJU#nO-qXhI],t$V1aD[/]-[2B1%l0i\E$fDCmGK?hnG^p?K_H)\#UCZ)O$C_&JDX$F/_o6UJ%'qg%#r,`1jE)lDL^B;TnsO A'mk5pi/1Mjmc!AET;Cot?F3[1J"-(i*X%eRGp$.nKfVJ=A?h)4B1W&b6=8P."oo,?VWWIo-Y,DZ&DL7]laAWLW)$sI5\NQ5<.eJZ?5(h.L97rDJa4bb&AsH</gZ[5rZ\mWKlQ%R#6rcAbsfH1"Zf322_3l4(cT?q;dB;DrfsK\mtfJ12.^c!hlcFJZY7qY\S$OtHXpPIk^!Q%=5iSD?h@%)<Te#Ad-R%\^Ahe\oF@*'f0 n-\5R:,lm/n5_]iji%d$;!]W06#\Bo@D:o LPPEM@d&JW\n**q&Y:R&E3b0>Aep ]PP*9f"q8-]Y$hA+/bfbe5b-p!"H(6C^P&k&sipE\-"cb],a[B.kh^ ,"A=/]B[)6L7'9B#LjOR ST/]7ID`Y6/n]D^j+[A@V.&UXVnS7.J0Pt)<-[tZqCi#sC2PJ*68,ngP?: D3P<!*)9ta/$=.'q^dIRP.*ec*2/^YdC&JB3Db^e>=g[lEAA"1G5p1`7nr@sDgt8AP7:\dFYSgB\e##sM)kQW=tmI?A)qqFKfGn\F>5cIs 3qM0\fC]KJL?A$.((ij8>";_a2[=Npr[H",#s(=I!a&*)TY]bt8L&bhPq2TK7kGdQQml<[*i]jF9o7$]gK=dd ;>jU%4:(^nqQc/c[>T]iS9sXK_UH+UqrL!lQdM&_S7gr/tbFA^P2"#f[kYh.^Z(U(al5m@TL#Et$`(LO57%Q c^t1&\4dR1F lqANA+o)'@/IetJrJb%b/WR-$8N$A=d38K3[is;Y.#7=Xt)cQA:lX&.&;cdq!si125Nr#GW'f!"@jX#oNts9+25Fa5[jt0VNpBVE27/@4IPk->VGdg$ZOI`c? TP)OFJ8`%nhE@=SflQsXQr!T(@5hPA<AF;mVb@m6<2LKDedE(o@r&F>#F?,,\Xb0c"]!A31L(/7fUf4N!Z,&O7n4YhpK['K>FVE1R+oT'4)YR^,=FMNCUIa_hS=8''%VofLdgT,Ik*DggSD7*X0:C!'`PY]qfrU+76Xl"P?sZKmLAgn*LrcV^#mF=1'LN<6+[.@qTT0;0#N"FIV,F<_s=^`nF$tm"1h.-Q4Ri0*OI2,iJg05>*X"!i#_ctf)lV"?kn=1*0(p_]SU[%U4J2q,LAA,b-h q;BFRs6)kBgp'L/4EAU/kf2+KP_o";?t =44MWelLiom7@UfkO:N"k\Z2,=AhrY$s]'7&A&A;_I8Xc)dMP`-*Db9&U8>YeL<4#-d\eFCM3;YM1;A)8\LL9q1G[fCd*(MUSZk"/LTs42#&YaFl1BFQ*-/)a>>@2X-(;ndjcTGT d`o(p8ESY&Edi;q9?#:qG'"AbAW2$aK/;.UjRU0-@Ih:[$n!c2I?n'^IFArki5)Dc2,'XQTO+5r5L(^N^PP $OQ',ET!pp5dLO-E1kJO9a2=g02OV?Z9DV@a+fASkLjo)aF"JNjgGZ3p^8g5^N:58?,)JK#Zn&4-eGrHXU2Z9OPj]p5$+/Z$-Q3=[Hib%jL6\6L3^G(sAZ;/;$!9MIe!sVY*c-)c9hX ^B8!`V0=CY5XW>FmA>3X+M2KiWJl#nRL/]<<=WG3Y=t;_j2hS?_12 X7O6lAq.%n)&@bbm-%g,e->2ipK49HW VD%@c6'SE/81mAL6?\Z0ig9"l(%-&bA@NPapRAeBosJ*H;eSBq5eNfa7KI\_`FAe?f<*aRKKmm4Y8\mY.E?a\AnRK-'nCM6R4_rZ&7@U".:pJcl[+SNVAp0QVkA.c_<3!+/-KpW#1#gPoTm$-AVaQbMm)+` #cY^(s1(\d3-pG[bQTS#X2e>jSN*6$6& :ZR87O>&7=1C,7q9_`l-f]fln ^b`^CQ^QI5%nAH8=j'Z5MW&BMi(Osr$*22[[js_:%J9Y7FH9^/$>%%L(e:gQR:f0;s24gOi&J%5[[39bQ&f/%CO",Y'QZ>>&g7=ag=@q&9Q*Dfp:7-"6hJ<"7dXNpIT1d;]"s8SV6l?9Ra7b=heU^<4Ackg^FQAVhiU;YdUIB&V_m2#B$/c.`Cf*AK[!*0Q@fBJ#X)cZpt$=pY:_&bJN<mo[hZpDtn>Xf@&01[g+j_Y1bBqBk6tDRZX/\\lmQ&n0E:"@BrsAD#`8MX5d-;EU:ODs.Mkbf m:\"08hIRg^6C=kItD;WM$8[PMNbMJ)K'3#sbH6s>QSlh5o1Z367dNDXCRM4I)N>)SFn!:'E^GN0A@6-6,sETk?Ak8=rA$L_@39h]X%-5JAf,3eeCXHWgo^3VQCD mVqd!Hl\O$15c8dQfHVSnDCSr'0nDAS:Y/Em?DMWqc.hQ2Y*;WAK&CH7F'gWTSho?DTQOj2_!#LEBP=NA,>KX5&>o;_PTQRO>\Y@0gCnerAWa!6D^+KF+YL.Z'b\-"6(F?g\OE;Fs0kDr"1qVA_PHSWXO&;Y+:2mhcGaHsS/G_Z:!'ChZ7I^Z<+:?0.^-@IS@1@? ]: !"$s7!SE?(KJa*CJMmdD,1rRKD5O.6t:j6IddI-! UfW#H33O'YM]hLQY#JT;=5WH@V!nO@BSd-nSJ:8&k"0'S$Qt[-K3,m! RX'daCqMS-dfPHCBe\fEKRoF%ICJQ`NcG'M/SIfQns,7=>U[_4iF(LO(UgQt4h844%[s<n!gW2_aP!mj4\1G"6fA:3./>Y!:&bP/+NL8:4c6+_-F +J_-[E[sV_J^Na&RTj._ 6at+M)2&DF98d.e;]b@4%KA9;F";Ag-"t8>l(-(54VB$\=lFO4[5tqc-,QtinJ*5]D#i14`&C@oSP9n,ma]*SXn3`;)fF6GA(Q_fl"K#gd$T&_Akelq#%h7kO2qN*YPY*o_8'2gXSmE,Y7K?"$7(KF[.C5imgT%87;WI^Tnct1@N\C!+qIT&a!0U"[)).N>,K-rhQ%p`W'RM<.JY@RHepUbb;?-3(a'r\;"hk^d[7Hb-95b(/M/f4"so2f--WAPQ7-C<+!?B0SrE$eb.)m/-`A8+-j44d6]U"\QQdq`^if0mrDqa`P b0B/8cni((k(oTd>Z[]d8k\Glfo25A)^[)Z1pE&^5dN4HG^($FB4BFg%TK1^Y(:,M+>4os9N=d[AJ)qZ!o[J9$F:6/G2f[o[3D?+N@O4:U29OLK,acrJ:B..A%N[o=n3%!U5jleoIPD8Dc)SoT! r^B'a4=+%lp2%(*r"]ATCh^+\[KM@7 h7*9-S(fc_eaUK\AA`U+9P;DQ1HPb@Wc$NX%gOgQ:g2dR>0,e$g;\Y%D.BT_jso>FpDAFI$9I?FUMS1?$iI5enW`ICBJSP^Jmm)pjnB3.%s?-MH[t$612MJ_B'"R X\$aV".J!sEp`q<'>[nbZAbbm$Fl49A?LS%Fd%g;[ggO;FQ-i0B+(CS/-?g*Jm%1PH)gOR?4Q\IogY-JXn8S^Qf0AWZt=HjmS[)Y'CjWrSUA%1&4>o`GA$gUU\LS[kB+,r`/cA-J.KWbjd4]X-*$g P\Al'q-d3q-AfbA@+_7k>AtIJlL$$M4qo21\SQFLo1_V[B;tT>!$^feIPTK)/)V>EYiEJOi`_) ?c7Bk1)XJX#PtR#eAP&T-j2i6.=4tsZm\Ht9XAI+;M@Zj>lh6aA*P^9Ymg(-nB==-!A!JrP@Ujn,c[r*(jRfkdp?C`Ka'\tCX"c-]eWnE2]?!>E.353qKs7+!n 6#@GFonM(-?c#7/U `%=RF:Mq*<"(TX%6m'N##4BN`FCU]KA'IAZIS6Yl^M@.Ac9lM&j+B^nBPM_F8&U9A>4A1\,?]Dm"HjZQoeBS+g@P*r(0$h-(o%_)tF-^\Zaq[G!a!2*+kZEg1FIUQoQ'Is@!O-q6,RDW&L*cfTJMr;Oj@K-m4'q.h.&*g>6UZ=(NAE6(&A`Zt6_.a"'B,/4g6Hfhln\_$VK<9b%sD6DS1ik7n?VoNl2"AkNMRJ(srj,ggIqTJD7qinH'Dr"1T?,?%hclAMI"nj1["LM3$H.A[]_V;R5U&`:]b&6Y#jVf)[s2<3^EFT@'1k[m.sAA^O_^LFL59`KL#`c@_.37hW^3D!7q-d+sH]H"PKBbEGaao'4X0VO*q_]DiJ#ETa`/.\VTG:6;/hY=Wa!&dS'jIhi#gQg53R29DWgDB2mM!@0YmiXSUjT D!&gnKpPXUESfKN#bk#]%`T&M!DV5H#\6\@D`s#Yflk3&2%qXLo/kH-T2+lB3B0d&IsS7IA^oG>>h%GSF V]s/^>I\V7Whb<_U5;P;9SW;iK^'9MkJbf-b>'I^DY% 6/p1lqe$rmpi%@9QBQLOCh9Wa$ABDN&:17**U,7=]j`42D]FA(X='_`0=&J..5R6qj#'X=_SNl&n<0UYriB=h[1YL>bUtqiOrXhb)B t= cb@@148"gmJ<%kTK QA(T9]RnQM5*,[3K/00#\qa(\$r7 pID+>)5j.mCf[oOPbk *Hq]Un-2Neb**1fRf$19k]UK#)%#/icFAV62!V2K=>\f3(@^SAhR6rO9i`c?MtkINO)W)6m9r(H2'PB gFG4,I[Yp0;d1!BqB[S;'L+& pVd.dlcQ*bXk:70KQ;WC< <O4 0[T,\M0h3dL;rW*\m-A%C,B=p:F/QK'WOG47'$)1C*`/I.tc7*``C7q#;%Tf+P&?gn jN,t22cViK-s22LlGpZsFE.Sa;f\QVM!`piM`[X/BOn;b]@p1I3\*D<B#Fof/F:/4Jp5X`4!Ab`/ ra4j:RFrQjYq`!8AA!a;<G*is+]e:%)$;VJEFEEB.A^piDC\,Im^#IfeW(68F8jA%+/Q>s/BgLP1DB$OV`lJ`REf[-Z?cGs;A?ec2WMM)E5QT;A10:]\WaUT)s%-iC%7nSb6>=Qf#!q7Fjj+#Gs X$k(m9qAm;M_4/:AsX$Q_V!L5@1`aisf--I,&;AC[7`2P4,RNPD45@N?C`k!ZR_YRgfWtIfA*6Vok#S+>E@>19/TQVImrkno550EkE"V)c9'Ak:=[$#_,JiSFUg'rJZMD3D'fQUcZsQ+*q/MbR]JtbAA;O?Qf.X,4.#q(WnbNEd7K_@]eeqZ MCJIP0Qjl<5XA#+c(53G+)42KD1'>-#71FPlOpT:)L=gpA>nio"mCS/C>c^t@An]C_m?Kg$/\&fJ3U>TtJCaDf&!+O"S(\&i!0'Og;Tm1Z7t@"jbk[D[oI1qsV4"i@3Rcq&doS$0o-1+U*T:MB!>$E8qA:,s4*UFg]8P*P17W2"*NZWk6$'s2@ `bOp,s1C5>h0fC!gX`X@Q>># BH'>bB$BF%'kd/j/8KKIm7W_`R4Xa49b7+Fqb4O.qc)A`iVW&6%S!,6IE K4o@(lpLEUX96o=SU#cE:J1HKn5VFb3T-kJh!!eI.b-Mfke/EhEm7T0U7h+q7K`Q*]D0X6o$H Y8:Zi`Wsi*VFDtgRdiPY,A<:_M_`^h,YZNG%YhF:_I7*LF3`R.<-.0(o?; F2,A>sW*Ci][t3-=hpVaAQY?Vc`R@$2cY;'8+[,kc"r;fiQI(6[_GF@TU!Qi4NI*?=0/s$VR<_YZIdI.=9@]gakFqn4@on=`"Z"`/G!59#%^lhAi&:c-"Y1oN:dk;isr'Y7FC0`hEAoh6,2` Q-K*``XNoAc(gpA!A=[nB- r/\R;P`(=7j:UB/(W\F!L8+]h/#]*;tW<dP/ai#piqZ0sXqT_(LOb*8.=QQcln\CWLL&)aA)fGi=Q^DN$B 'Z/_^r$O$kW&dU39I"'[E`)$-X$\9 CI04eEc*'n(Pf>C&*A/Z0Y,Vgksst7)T^Rfi9=38]od>kZ\$]h*9cUU,DMlqhdQJ"?h^/;m:@:%ho@6ZU3'gmrAhEq^D2;"=8[O(h>Zm^,jO18*&>tSt4UreJ, +Fk<,;A1Jld[J(W2D"41o[jBL-P_Sg+RI)S6jX1.<>B rd.TsO%nj)X6l3Qd8@W.`WN6F^j+tJg]pdf4=?q@,eZg0&*-ALgS"qb*St>4bhsJcZWA2!A2X"Qb`'Sr@-MVjYLo."C@K*VCFI 7kT1*A_HBA^M1i\j@.^b`NQU\o/c?'Cs6%hCQcD08#J.2$B;aQm nism8,ZKpAgh%.6-UU;le#=CURN+:R,$5oPeg7<.1(okE@\UHV0`\e @4Lto7<1I-jC=PU*/0rX*jjAO>U=7q*/-4\lWG>#KjftF@`/SB_cJ1h9L"as=]ZQ'0N&0Kf`>Okq:oXe*]j'hn;[[dsd*q`5kH8_TkB_4-ESEqgMU7d02[s#OebDd8tBH+jo*MQ s)F$.-UKfl"9+f@4'bd0XsbR^=`NJ*#`.;^E,ftp;/6#AA1(VM\E9m>*4tY pe9V\+Odq+V4VZtYmNShEfd9s<a[$C`3tN%HWU?,p<CPL_@WU#Tnl/nd^ DaR"cW`HAHPW" 0#][5A)`'LTC\)%4Kq"\2p`O,;(n5TVe.JjAtWtt%VBs^<`ZV(m@9W:hSJT#%IA,j5O+pA7Nac7B ]b+__q9>JnP3Kd4,?'R$;$a!;PEoDHOL\GO3R\Z%*^0-7g_cpbSYgI=U%&?Z2JN*"c8+/g4n,MUeG.ACAd41bI%"%1=A->InkNKHVX'AU%LP^@0n4J=Z+:RtgP;#C4#r5!]4kXAh/rtSRk/tah0h#qq6*UTRW)`?9;_&agZ@<J"L(d9&%$&W:rIWCD;q&OH7<8@nC9:@:E[7U/&#.SKi/)1Hp#1CV$[!O:(Gceg60Y!a);BjF:gbLWW3,65%1qEJ Hj;+0)$rN q'#g# UOcf@p,^WAsoi&Y4o(ID6&l5%sAjAq-+,"`JUV/B5HY070!'F3kNWTSb[A9!gNFG9%3-\^*Ieh#e9'_2]DnEg3<:&TeN#WSF'0,llsE+^C,,1'6\LCg/F/68aJrSHjY[BI1'&/`Z08'0YJP9&<=m,jYFBl N'JJ+=t>UYMrtFFj53\c.Ane6QQY,%FtlTt[: _>\P`WVoMnO]E"ne- BL>nM?r_L(.7P,$l <'oV0+_+h.-Yl5hLP_tRUMYJ]#`/5@aW[0;rZ(\DmXN.XR@N&jW8_RL",/`s"4V-[l.VF&DW1%c.<-5p:fY$"bCl3CNM[-9Ji^tngOUdo9WODbYcd)3@r3#hHR'3/K&/DLA\LNkD dM:XDU`=)S3tKgZeTSt^?@Ye&1];%b;NI4qde#_^Q+mSk"caS%p.NAIU/6/Rqq9J/?X_e/^W6"Osj&3QAcf,A)+s$NA7=h2I*O PT7!jOd/(5RU[j/[J+P`2XM2JK+q_f$bGlJVM*B9C@IWNoD-!>Vf$ClFqj;J5\@PX i8T!PLA@M69mfY+$Hj&GV36ko?,P1XL#o#5N]+.>Z&k])W2JOC-,Fe,@o>@H+/];/0kkj+aTqAHmYBfDiW_:I!JApEq<`,oCX2DI3I8ls4ZX/CmRi+_LMX4)`/b+Egj3W<&Yb)-,mq:[$).fYR\230Q6N9J7pJs#g"EQ\:O-#lp)@e`NpB[LHo$_JbNJpt&-5..ct@gm_6)]A8qRtA-P1b7-r3X, V<^OHNB!VLciffttgVP`1XLDJ!Us5H?daa?nspLARhrasnA:iF[PYI4g]5E]6X3EUe5-3AQsMm.*[J#*El(M:SIf])\A@hJ6?U &*Q+sJmVC sE[ n5!WVkb!?+n"Ab00Z8gnQ?i=FC2B%gg5qi;k#Cg>8"2o*6YpO_5p7D4g/c6ESf&'Ao/TpH>WhrpA8U5tO-g#>t?SAgG/-h9<lAL54>gYZ9sAX\Gsc0m$lG^/%%H(gY+E#!.iN6BnR`Sh8;7.-ndY8j2jrnC92f6GmAq""UXsE8-(s+n_3rN&04pj]'"8#TV-W/etb3T;$q=%>Wf1S^CEZVr7q6HV21L`<pg-f\0`ifI`/fmVe6Bl!F!#'UcL 9A`Ltp$=bS7kn3*8cc<+3t6cr@^Rok=*17%(KJ; $0WRPg$7#h'--o22?aWnC29!YPe:b$mhLU\XU0&mp4UM=Wqrs^htO1\>aCI6X99s_9C_09XU>4?E<(Di:\Rr&n*^]DWsZAI[iXr1Nr?j;gfRdO654c*'/k-D-K'k^/)NTL5n!63.>(&`hrYB'/-2c4lkKq]G YijUHe@% bSaa!gbLLK,NANVFKeKsmA^pb0qWgWt6K2iFSc&h..4+l)q.%)F$C!Jg6*ofZt$h'"\Y''*`SRa.ct)R$ P2JRs0'eos&9V5Gh"&eaT&?HG.ZUBDEH*gD&TZQKTY07"i]t1'rY8SCMZK5f`A5pF-n`b)U&J=p8?^>+&SG'sn#.X(=Aqm^6S)KD@8mqG/(5]^Z4LG[kML3$>>rUX7]Tr,kA.s`RNDea#oA)8Vc)F;NL:JSMt_`9FMlVLi[MLLAU;Bhg4qXW6SB-6S+]!pkG&/IZE4.J&p\=b/Z6EN9*!Sd Q,S t3mfRlZ:$Cs6d9f j;BU&&\?Uks_bSLr<Qg6XoeaXK?M(U-TeeB@oFNK_ Y S]tnmL?\SgkPL CKVOdIkl40HVapSC& h8le+Ob"7 J@#(E>.`P`IO(gGW1$&)m,j8)]FGtht?s_B93RKA0!^?f4_G!tET9hS6Q0/33RC$l'-FfdHs)RAH17:IsPSD3Y+L8\e-)W\d`qWrkkoidqt[A6PhNX?Hc,kh!,?,0i#TJAdmoaok['CQ[(*J`8=@FQjRT@NC31hk""_>[IhkY3E/635,_J"A`H_8GP=<.%rl'dpY/(`9Cp&Q=>(t<$fm<6:/a!O ^Y,%1&0 ghC&!F0'A5dqn/LW?7ehD5?>^Q=)ZB]0&lUPjW3B^2S1D&%,c%m*f^ @NT>Be<9O0No`VlQOVYlRV+=.sA_&ll/5n,@@m+RDkB(0Oo-E6$VLZX5kAmnr.I+?h"Yte6A'Ia"8,(=LJWQ_b-#UC%m1I)6AS6$rJ1G$>Y(C;;A77A!C/B2X!Y1$L?Y;go.JT2WpG3O/al,H/Y4TP7\ 5Yf'A&^;(5d"kSGmmD/!7(C<la8B!L#:b!_UHm9,qcc9"DYAQ't=$jhcAQA3"[&tF3\rs;<"hiXI3I(#CMFk0&^73Y9E!aU:m*27;!4AS`,X`K9JgWoa?N>1?a9Tq/!BmS%(+n8iJ#P[C.9\h6>1$O"5mZ?=L>UU7+r7A)g?g;)Dkcf`Acq+bUWt;aeqJe&YNT&U-^MUctE8=P@"M0Fs IZQiji)(!)3I%2:)k&Mef.MfPP2-b!\287:Q O43G%D^9T1e$/B6-_8JZ[ 'JKt&MM9+?&d Bb8IX-'tSaYlD8.=hl*Rck:+T!Y77.9I ib2EtT'^>A1YnIIF(A?QPAL-]4,jJb'g^f@[NRVO\bU)jTfRmX+m0+B+^O)+FDi*4IYq@m:#be*i"F^8N8^f^TJ!?W7$Ho"65r8@s12=X ZgBnWj^XhnL5i],M(#oFKs,YE"=Q<(2.s:0632=M_;Dbeb1Ka3K:I#NQZ)92HD1?O%e]Q"/0iWXY&Q8,7!HJnNs3tY6-($@L%^Hh8EHL(s)tlpa_t;+lW,]"sR;6(AX 08Jb3_VEBs'i%$k."rbc]Y(J"CnC[ES"Z?)`pQH&)P^T#V^J3Uf%:B^:1PbkacUf)p-T8Sc]AF2:j0W:b61-]N1khkK;^T-GD,1Lj`G\S93cH;?;df]meBX"@Q61BW?;N\>HJr@b6Uo`e/FJ+=>Gda\7lQF`2D@pQ\rUg:_M)WfrR-*a(:?\:BnTFNmO3)_*741ZFb9?L\VNWbUQ\ iNOY<'=m[!K4<:N&933(!kAQO+0ZMh>:<^.!BL-^LXM:sPMhE >K<& P$$UKZ3-Er`ZUO'Oc010APmiXmC$YYLmqDOB:&JJGr0p_h`U^2!Zi$O$+qqr:X2QU7>g-j$rBtt$:=st_ST#WiWG]Bh(m#U?86]Ll=[#M)r'K>Y(Yd;*Z@OPnc0O6WBIAWqE%ChqLXP"4XRI6g>d%Oh2c3Sl@FcA+]9TN!1)5Z_4qNR!JW\(*OHor2E9Z YF#ZW3%GOHbker*[$1[)V/l'oNts%P3Yq0hbc_\G:!%42PVKSTEXk)ZL,`sRD1Z>Ht]ioAri/5?oa:%rO%/f\+lI(de*J(!W[Y:,fF+3`T2I12"[ceY`4V&'#Gtn\ H8MPfCF"l*d1/4iHnaFoJHR7tG9rPtsji[AL: pY?'VlW;I"31P ;SQsd6<_88#Vt?#0q-gZ?CY%]D]nan26_$07m[/5'm?0>)^EI@q>a N:g^9DMY!#g%)ZmtXr[T6"[]WH&g#Ds0tq9;WH9RAra!0qPA#0^AM#s_&OM0Arr/Ng0Ym*A"MY`+GmNeHKVI#Bk4& Q:oG-<J@=KXRgr0=A3A^P4BnL>oWQe9t+QN#GW57cYNorf(ETGA(T4P(^CIF;\0s"r.T3QQ$Qn1.mk6a,$m"[6d@91Qrt%s!4.c7(nq[n'"*c0A^I!JoZ^BlUrAA;li[E-fC-F_chc>/IW,/VqFPOM*1+)(f=tmCBeJ`CBc1jAZ<'E"!pa%_Ig`80;/4H ;$'Z%9eJb[?W5NaPtG9T"tfC<=HRJhdRT2GRK5rE#9*>)5kJ8KD,8ap Ap="lA*c##gWa4A-c`if_oLc$L387$c)*TNVJ`'\L?Ok8lsV!A\?;?]46HkkRh,L>aV?"A2I$N60>K.06:4XZDh=6MGRheK(^]]EIID7ocQXN4B5HL4q;QS\>6qp,A3"G"GJCo"Te>5ihQ3`3r<(ctdP&!s)3ET*8&ib:1Ak08U0G`?7rg-AAN7&"lc,r?-6@%T-If4`m`/1Nq>m-Uq\hr\tl=hM:DH@YrM+n`(Qo$h9[[!6AsA7(JCm4J"-D0Lh^=$_OpM##ZRb5-&>iT-,l](anU0gdZA-=&-ag<7)glW=ftg_kRNQ043b%AI=r\!Ab6T&I!QCGQiX+[ADl:?%J,AOm#HF5Y6>/6Ls(U?lmlXW\Di?C6[a-[%$.Gl$&]9#d:#)rk`6Q`HEQ/ZR!dQr_K?;7/]>l*VAf;6-2O"#mFDfes+.%=CPbXX"0s.=C]Zhq%-r$GDC1]fO('PM*K>qB.H?9h8T0pZ.l<9EPlClV&_C:lPmZ*P+Q0\;c]4WdZ%==5Lm/BXMVTH_-d`::Ol*7q1c]A*NNWKM=-/>O@H$a1c@r.=0@;M*FRARei!@a:#O9GAAO%Kds&>ddJLcVT?IT$-AKATC8^MBRmm(GW\SX/WOIPH?1imPf(^!U&2A=(nXd&^(]XQ"AB. =KtFE$A,-8/Rkj^7>cYE,f?Je-AF"l,CA,jS>l`Z?&00JV$_X6262,/n*m+enS@*k1IUG-1f'C9QR2lG,\NcdHf^*N$JZB_#m"4`Sl cpW/6,)5nI;j48=jiE%4X_PFnH:EK"QRW?HZt-L6C#?V6ng iia$VRY>/X,1)C6*aU-mO;Yp"`Kb\oI>?9.0_E3bM8F)%3T:=T 98'L^C2M,'t],;*2d=(AJ?AA7LL>)+cp^F+5)^?Z \@b.#E=m%WTs!3?5A+Il_aA)*(1H>]nC( [o9'5b5%Bc!k.I-(?Ed/Gn8:sl-(Z\LA irQ+LAqelk@EJ!C`:":bpGCT-%Wism20#Nkm0lX@fM1*XR.Xeh4pHSHn=0HUL Vf1_r._85CGRJZhi=Kf=:a7(_(=ARSeai-bX "*&9TZORq.62:6DcMOFA(=NN37F]q1Xd)W(^L<Hp!"DQAgg_XTqP/(0CoEDhR+@Wnc"@2Wtod;\/moOnlSqf`VCehK]cI4%5&=`MN558%B=0E.s&G>5mj<,CZP$KDAr_[0kb7b4K"i#>= "[46g0F/0pPWVpNXUHgOfiV@&b=r* %s2?([p*jG7&re>C\qtb^_Y.Y\KT7GS0@m<0E6766[?_(c)H7JSqT67AQd3&0lUp4.`jiQ'41[,CQe2LU*.,in47K(`d/$C#"qCDHs4?L)rb4,H!]Tn7Wj<;j(f`rI90'$HQL231/4fq3A"cCd]Ob-HH"9`t?89AhYoDV#<\4DWdo0;9PT+9ba;E&.5&(s,,TFOGO."Aq\gn3-r\5#a& FAVPE(-fOUcJ$;*JZmD\b1fZR:'2'dS;fkfEh7B-kqL;FDp#s+[T'tpAb+cMk\819^86`6@'@k'mm!Ci3J1%T; p1TgG1mlKRe:C>H@N&lpR>_2'RG-7')C 35)H0R\88.5lFP0EhdH_FRPRRA/U*7op6c@HrKbo(_6InOgZOL(I"d12 .7';]bcB=PA1\tD^J7q oo$"`"=AW7o5M#PclL?%Y>9P+/+4I^[k<,08C\`o!=?MQdHI]SQm$SGZ%r7LWGZ_]Nm[G1Qi9,Q`Y!bUF5o);(q5rdohKafk-/)pi-Z/i#E/1Fpn&3fXEAl2$gAo%!9@*RDtW/")#H&jF!o$4HZQd(k#bT5]1qaY55B5NX*qAkh;^JAdlUt]tG.%AK6)=G>T0Q[Ld+$M;-U5mE8jc7%!QUiNae55V"1LMVqO%C001oeA9\UGglJ2QP>,]j[F?3bV&_X?N>$ mZY<\Af06H.HP"t\*a8!Vck8PR2io0\9!?[!>#]lZh*i/l(2m3%ZkF513FWEET;5f@?OhF&t6AKbYOn>H2g,$[\F7Do9-]dI!#!!=3MO*])A2L`Ii5)hV]*\n6;L4IDPgo.Rtthd<>HN<$:7@K9:!=\/0t'$CPsc(lF?jXTm*gA_5+X[X)d@EOnQjd8f'+ho-P7 Bo&02Fo>BaU<5jFKWrmm*3=9:M)U6MtbAX9_;cq$8eWP+YZ-VsB7_ZNntt;!HY5o0%NUq"7Kq]D`r<!6"W7$Y2P>Pf"%!@7Bj?nK.t6L%(H(:r eJ@A&)sjLF"OI/f!h#rS%lPRV:i3fhld]%\*;C9PTAJs_+F+! Srnq]BHjI4h;6AA&,7&j];Bdl;]X]Z[;H+.IC.537HVN.ZM1WFfK^o4aZ4#f:.Cp!rK"n+Q8q_@+99&AEILR4EF1*kV#Zi17-M`+#B-%C(I\ 8D`9EkPjJ:t@\;LAc(P6#%em7NMI9HhmZ,]@[#lH.W%&ejsADRKVa!B1o%!RXJa)%98 arX7!r3!f($ZgAp%d:$9;8%Xd$1.a&kZEKbqS1 *TPbtBYQ\fY!Ct\- bBAt'And8N/Z3elFBm*J/J5:qY)A,o@&`f,q\Pp.fCZf\E5JB>&\`2H\1TP4Jj*&IZF`7"h7MgNVV)(Jg[2HC_O)ipS8L[^'K!lp3re'pN*E"$M!GG]_f-Zh!]jMotT(32."?4;=o*"&Kks9sBRc98c=gGCGoP_=EA0R&B4;qAQ>95+4L]mP>%,$(6=@G-GO'* F@l>I-q-RqFB>?8@7<4Hb;(R3Jo[Za_dIN$=I'W*r-/.Rb&.WK*lnL`iVrlYa(GNh62Gt#Z4L^L(o>pkCn"oNI6sF\%0U[tLrdpq,l&NWt4giAdE&08K:ar6nBh&kH+>,5O:EQij+M_[@g5tM%TFAo#^naVFUEX `cEs/Fo-D5i(WNQL:4`WQ/&#LR%%>t 8).'fUYtMl?QI/3KE")l:.7)J0)Rr4p$Ui/?rV_Ui%YfeV9i=lGNb-I$HmR>q3(kdPB`LZf"&*%+"X*O@>nim?@nj+Bdd\a@i7tne0:hfH7WIJ75M*)?FUtYk?GXY/I"GR]gl/th[Liff+Q=hc.U&p]r<7Yrl07:T=\:(A1pltB8%dS#//>7%e;K_""NbN($:BP-i.aC*T?AmY-NM"_oDFrY3-pkL!EkM=ZFes&KC\/+:b?iA-KHX"AESPrS(*A>F'X)+=s/`!pPje] \"(EF'Gc&QT]n`9CM8W?4kraj?*iYB,0[FTt"3#@X(.\VHE;20 m#_da\(c$]3@CS?*s<ld9Dj^AW"k0$htA"BDK`f,/B.Wp=1W)LaA'Okjs)U-m L[n3V@[<%e3-gC!Z)+_f8i9p.'p3 #/940)^4&P1SB#.66iPVn:T7c+/rtgOA-CaV$%8jEc$ 23QX9j<9lC[Y_VJp'1?l"577%U>>(HO?qmi\^\HFeU:R$Ik:^*C@d?Jet.3@`=Ws::id[qSspkk6He;"kGSOpl__Dn@"!&9$IEUQtUM !i:X'G\LDpeEs:h1g4PJ]GmO@d:lkc^t3(D2WFM/l_9L5Z4#,/` F^&1:bXk9C_0jM!bdcd.j.1?s8O9i!Wg_P8=W13AMS+"MEf9j-'Q)^,o$hnsl@)d#e>l&+Qjh%hO=X_ZrARVQlT3N4Y![N`7,h_VXkEnnP`nTt\!\7!R:QTEK+'fSo%)kD0:#ZWe=*FO3Sic]i`F[W1)aY9kRIaS`@1_H<`hA9.#+.W^`V)Yqq2Hn7f:.2;a PZJEKRJAjQUqDYU.`Rm4*LX$Z >r[!R2Y*.ROnXYk?+]JJ`H/K6(G+(l0n/)tHFN%$P,R5_S]B?(AZMH OPbCX$*)T6"YjcMQI^B+; %:@\&+A$KTVB `M+)<@TZ;7$jggJ@b]V*[.jp3;I)$" L**>X+KHgQ*N&PDG6C[Ccs"MN-gl;jPbg)fdR+^_Ds7'`UeMn1,@a9`A:SG]UO]rCqXtQ_C j>AaHtKV,$-cN@D[O`?-A,nU1#!1Zd!R7nb@ZG6+6P''^ZhCNet:lR";8&l=3=6m'p9lA7m=Ht&g,?H"A`ah=qK\O]Kn=US6cJBAt?5Ti)Q8!K.MeNKn`nAU_Dh)=Zo_,R:>sQ+]O+tX&b*Op5*N__mkJdO*-+#n%3pn7?E 0A/pS`V9:VCi+*40;nXU[WBG]t=O2aDBU9(fLUH`AK(TYD( 9JJ/[#Cbm19n'3H,b(Ob:rprqVFfQt; )b&@WZ(tgah#SAJo+W%?6gh6k+*20T;Dh,,XpS36`4"6DX-nB$7lNq&X;b N,f)T?9lbGVFFL$B%9ofD5\5o)CtthNA]CWLAn67h.VS\Qp[7++]s/iZc,ZBJoA1j,C,A#NIBr6&!H>d;F37(A59@btq5./1?S;.F*94=?6@PCIln`M1AaBoge7C18K%JS0m8_D;ZQ?W*4l`1Qa^ [[[^SG U%ZMXP:.4>FpGV('i@fZ`bD8S34<Q';J(")%BkV-jk2c?RljcE$Z"!FlS/( b&k+e+o(3](Mj=jl#is4A&R*Wda-UVGdA;NpS/NCB=3Z_m-+fs2s1C17;qf*]k:*EYe-5)oAS=%"g*_\pXGSAb&doD0.f\SUjKO?13_1+9X[\=KbSM!0B0C 5PtgN( m?%;gP7rG"-Y8,aqtBXne5"_7!*0i/hG&jNV7V5FEGY3TW=L$^O2flhW?7.T1["^Ef+fk=&h!JSi9J_+t226p>8K:`[l^[&%AOI)oI1AIE0A@2mNr*MKAP)W$>l-,.s$614h&b:hW@eWaO+qS7/`)EZk=P)@UtjI)6G^4DiWRB[GpK)=:&YY @ElO5-P+%BV\8;_H=0QV*En\TG%_YM@@7,c@%[3TDLVNi33!2i3-p4UP.$i-653qrVn0&A0F(n5tPm0o.l/SWe%<(9$pSDml_9JgoY)\SQn6:b_>TY&5/9_BmY->iD!@n(W!0\2kS!928^B  Jd%jKS?l+S% GiB$Bk(N74jEcJeHF_ssI[&E3T\R)NE0iqRk^c9>t H3MKKH0FU73U(MU&V\IW\F"A%5";[ri=#A`oPY$=Vo=/%il;!A\*D8_dHL%6S)Kk2IIXBBY]3s9F)H!&$ahAOhS1?18SY.b@WX,.\SJEfbI!78Xg!U5(=N<)iYWOJRQAEIi%s!#CN_[/ 0#aO\7@2jepFrO\^ToBUKf@74VT_rg6/_:kZ2R?,si Ks9_oZFd:A/@\^r'@k^mr'6$KICk,F$;@P]1H[fZrfpWFbg*,f7[Ln$4m.+(;3i:]/A 8#P&fU/\ZI*\O@Y)ai64fi"#_G<@4N2>TDlRMe-o$A&a=l9JWtY:;*5*L.>'rID!qop(R=f0SD*S"0j7Sh!@M@HWkOBb+QHbL["*.#eq3,j;Ri8sGq:#6JRj)Z4?m(WtCZ@DHo>W$<(=mS7*dI :.f$X51B9U`"d'QCCr7s1E_,GfqS)N4Q](>[:4m14*k/'oW&g")9i>F=mZ3YL=">B$=T1O=M4Y@AdaI7\)23KEcM%-B5cQ'$lp]g\1LLm4Do'I[[+[.KSY(hj,[=A'QAHtZGI)iSB8.O-pDH:K6Nqg_AY,aaeWo;9&.Z6!lSP8$WY?%Ucf*l,m=.J>X1(+=ro)$hWSRY<[R*ESAO@kYE,+ZE=B12;UBgB[r.`HektD.RXZfAd=6tMIr0mkAgXrBbm]%hJ$Ia>?]p]>.5>a;8!ZLoc-eC(KB?3(+^o^to+Pgt:LT4Y(A 70sos!rHMEpW@T [=`SA-,jTCB`(HbKgY(!]S=OiPMRDP_kLd_V\?s`^* a,OXlt>i+6Le`,t'^_t[@1,q:dqPA855MEc4&m65\1j3n.+_J0-V 1jej!PM4LYrW],HA]3GAtLF*c%NpR#eAK7W@.CD08 .K-4QeTlr2A\R#P6:t;npdCXPmE;=M)H.Ao2ki.Gk^X7OS?jRr9I4D cg7U]'e69-f-Gj'2(h*.js:I%FpTdhnfDI MNLcQk7B+XY\AQWZ.M;&N)l^W9g*g1)O>cIh(t]l=:g.8MNR[^^HpbAEKhN_VK>=/C]'e@TKAiigaOjofP"UTKJ4?g)N,ro=C:q:<=Sfg4pO#BtfCrk^4*<$M_OI6>\V)"m[8?)=9K.!nH_\@,[J\l&$o4ZS+W_32GH\QKWpRSPo\9ST>,*YIQXj54\O<K@R9ocIYA#a@n!X8+IUq'Dg>aWT+KqQg#rCIpL%:/^A/Zk0!&QMFDtt7ceOoco(0Z9$o:1EV,bq!hT7QjUBK@FRVXA)b#FAG<;c[Ad_&R41&&P<CcTR'taj]EF(fCsFb'/$Of?@1M$!(.'m:Kb`RAXh[X9IHp/ ZG35b.TZjN*!hb(6F+/qUs'@A04ik-#?=YWgjc'Y$)47J*>">oU5nkr'tNTC&bnc,nG*!W5[`8sfC;aF+tTG8t9>1jIf@nOAaEr]DU$chWZ61 )fB4In+i<.]^0af-pJ/C8RlP(ZA`\mP;T4h"c[VMr1X1%fmdpk)4BF9#i&*WbY+A OG;2"V'LML,qI>V4P@U6H\%$lg+D>=B(I?-Q+-$Z&+#mL8f UffC2&RTX"hk7eYXi,55tjFO41th)'T*cSD/\YDiRmJ&4lQD]rrF88apB\qZ[Bs!OX64<PGR$adA:GTfT70q[W*X^<0:S_aiHQsq2%tT3]HYs%IYU'm7Ke\Jiasl258g>L*9lPXApK`SIA49YYMr/D;%*1]8G1j:A#o*MP?N.+=4n=(fW2KLhMD)CQ000_A%XAa^n?a1!ts1sg/V7Cp-:6[fI(YQp*i6AJtf\):mj+)`"[G=P9FVQJ\H"LDYi/<\I#aKdnn3,$eeltPj#iEJYG\(R[*.s&U!KcS).Vm^tr;gA$kc\P\?=+AhU2%V<_Cj/KS0sZ4^QR]pVSZD\:is+:-GUH8i4HIJj7B:tT63-B_m9K>ChXigVt\MN@BUmBDig5A)4?;TjAPpW>6Ab(jdh'\!lF&IH,AN!Wbq E&=ZeNW6:ci%"_Krid<\`No2Vq^]KG>RW'C63MXS1o$(jWI/J>Xp5=N4Ns2S4d33ifOM1!A$&@4VU$1&#-btCrgF""Ge^MR@TD6)Almk!ZgqKC8OgppkZJHl6ZL tR#n,31n]$i-)AO4)LKM?bVV`b[*A.k^R8 9>/ZV+pP(XNi),k(\X F2)T9;*?$9K"-l^#K``8m<@Rd'\LCGqshA9FJs[2Nqiik))Ek.M fgWa[":])lE ^igSa+'4FQ8?O*(DBWH\?8L1qXY(h?k,=i*/=_]l$%d$*cW+5KP87`6RF#c,1r'K6Sg2=&74Yd@7,b`4"95bD(e'UY)YR#kX )A*9.q0sl,j)R^(O'5kP7!jMprGFM*!r5A]BJ'&pkPdeO@Q[B++1KEPLJ0`1MbqoS!GgCZ]-)aDiol)cq@5bkCAn*@8 s-JT!R*mo7PX'&]\A&Cm)F8!1+a!rpK6#dO8;0:gC$?XEb6N.WQTK;cS%KF0*mraSTAP-E[aSVO@7>5$1E##aD5&,aIZTkUE%#9W]C.5@=8(/KHW/t.iDZ]QQ5I=ErFf)HqLV_J)#X&FbIh*QJT[A_Os-/#f!Qgb\!KArLj!UGN#9gl&k3*X3/g;:n`dY-!Y&#RZG8Klc+PSQmQ:e\BMCgJHQ\Oi!jVO!-6g@A3rmb\pVq*B0@5r*ktX\BAdl-L,@@GjBGS7AO^.!jU%icc-^+@!!nTN/E#9)1"m86qQJ$)i2^"e>4*h'&'=kETF-3I(=5c7,bqY5Mc5c,'R!n0hr87*phBM:%t(44jM(!F04pg"-R]DIn@"d`'A4##B;X9d`,R1S%n boGUpSY!4helQV8#69MQRj.(fRJi<;'oIhK&Va@g*eo/k^3O+9tOA)V>;gZ*M!CGYoA^Mek(+p0M7AY9ZY:sS)&7Q+(h+t.NRqX %`1)dh4q$.Ib7s ]SGKn[Q0h]mm+G3IUS@/bq$C%<#2#k9scGN*V$/6gL!Tf@.FF//.r5gBY?9D[#mGbQ+paH4rlVGsXXBqJ-E.ZKeP0AKQX(mPh?W_l.X\I@UKb"rHrQ3n*5nk3L_jA&4`@SkL/4f&,UYsrA1\JU75X `<2QeJ(4,(s*SYAO5<-tNh>V:F^p135lAmDd"#FA2_U@raXOmOqjT&=IdAoa"88UD_5e*=7Yib-q=ier1/b>(\b_?%D)kh(A;A,9Y8ob.WQbi'S@QsRf`%C@%F]qsbq-e&il3-&s/`riH3;+8M7>amMpJXI/XoHAkPKpXJU71$-'?>eo:XbD^N>1J]NBq:Xj9aW8L4"+\f8[r(Nk3AB2Ca3:9M>>(>r3ZP%S7K:Jh5'_)JiQn"2_ff6>#0K/hh2,*,dUbS(UhFeRsr"ZO^p*qM'BW9p8 (/EOjJqM<[pbme&L`2XT/b&$ 4R[GI8.6ReDO#/HEA.2Md]DH0<_YqiF;]mFEX?12oq,NnE5qIV7mM, k+a*)D3SQY9*9!Q?=g[m!mTe:jmq&jAQeCad4Wo^c34ttXHq8Bf&_*11a90K"$Ti7V-LCJ$_\XHOUe9';=>pfk5TFBpgJ.\<BA1RhL6Y7^tP6=3EAG=JlK\e<Mj^a6c-[d=VG/#L-djIrjB._(/KosS>`)$rV#[kDp@M@%)Z`2MQp&=kq-T*-T!`.D7*e*_BM:oA$`O?/,$FB>,^7Rb<`>?QNp0&P?HH\6e\ZW"+]M.N3GfLPSJ,&$UHZQoT3qk<7r'RJD9oFYcY%X*LdK5l\M=VVG%Cd`1V;0AV:/@.GP@&;pMo/%70[36V@UbeR/bqp(aA;/8, h3cYKhm8-!X>`Ak@.=KF/Kn*Lr9A2HBMb+Ma5=6GlaJJ7D)VNsYn>kS+[1W!rF-2=/LV(7ee-LM%)b]Xf@?MknFlJ?6LAbX.H7toG'U*ZhALkX>'`/Z:O7Asj29LgT0&V!+/ABRn=aEK+qI\,oU0sMsfo0e\[YXY]+Spbn67HIJOfCgJR3<43tZC1KnJr=f4fr:.#KRfZ(M=;!k;@HT :/iZ_H.HTPn2VkAnn)s4A1'Y]1iV5#,mI=m`^(4@+(`^%-ia"oh<N:@Nttel]\]Oma*LdIdFt+O6aV/t7MJ0c&8Q%M`attI'R0ij3hasMh]VJj?"Hiq'GR4MWn5aOt-K+DWJ\!\mn[?LXWA?MRs9 ][%Q7+=ZfN>6!%g[_/D&;8!':E1NKG&4))ARR-Ar6=)@Q &&)>/f/=SLQ_#,efRaiKj:*4G.8Lc*>*BkJi#bXoHQr&^=aXB0\-m;?\^F_AF?r5oA\EI`X23a=8RZR3LqN#m,VE5+C,"Lhs*mrmFKG^(4ffII==VkpJ"f)T*qO_ja9,\J"-Qt$"AClXSUTAc/t[-dR/?&fV0E3r-D% ]M;SGmMo>h[H`iA%a@.N\D+eh@*-`Ap##HP&$bIY!-Cm14pK7X@T)^%b'bF7M`F;)Lh!SN9FTG*dY_rT\pK;8A#6lINMYs+JGn9Q`?-oKWN.YfE g^?#n@ZFI8"a9:sc5$tKmD8o-;CRJ92+Y[3cAWNS:Jf9/T1#Y=F-64BiIRiQB3qCbIUXX=p=DA*/j=nrPcOsf`Ja18I7R=_(g5mABgVD3Y&*>JKP')OWdVkC-fRrPcX0KMt2 C`Fol[nRllZriSWs']A=LX<3RPV`?cBfY#-A:#F?Y[$Y$5.@2sW7T?L`$;QH$$VgYkr4B_"eSC[a36dC[ cT%*a(C%<%:X/_R6Fq;YBAgd 9)lUFXg$PtnA,"EQrAq;:Ss+tA"tF3VA^7$\]/!*]2+8/ ,0ES-1??Wq[>_$`;2kf8^lt-fZ>h[#5G>j(BNG.'Xqk]?n$cLOOLhU2F?W%MOLM%JsHp8GJ$VO=3h3P/*fp1)hl]iP"32CFGM@_$,G!`KHh#d0L"5EeSn hj'.3Y06q`#_%Z[%7PZoZ;YgN)b^@&'Ym_,_l_q"#)gK(#6U`k7W,ie/W_)a/Q;r6bl-:@2c]KGGY5WW iKLZe)WWjm 0:;Nm[dF/$%U"f:DoeGgRmY-Lf:tf:a!7_>G!lAB663CedhibAW+PYF-,_"26:NRO@:B8;>dBk?Ej(%NHQ_2:p"5aR#<:N6+]b3J4$31\a`B-,B+)M\0Ramq(XMV>jNKA=Kp%lXbN+E;#EbCHsaX00jg.iAXL:q?\L#1UFRm_%K]h,C%9mo^h*Q,14#^+Z@m8]FqVtFL\BH.m$t8SqGpc?nHLlMJ=@.SCkXhjE5-lqg= BI9Rq8PSf;LmfJTa>jBUaQ,p\,7V]"4jf@dT+,T(r^B#)gk3*FR;'*mq5!2)@N0AK/.`^1tp_p^VZ1,\O3"S]qO9eNQRo`L.eG?/f7Dl.2nZYpd aW8o03SA%ZDLNP3G8*1<6:*hVoJ=TrVa&!t(I+DoLW6h0tkmAnehjg+>UJV ]JTBnm ;hN^l+)S.CG:\j[em6m>;TK5Y%;p=>H.8ZedEk=BN?\\DOG)PP.S-!lT@#&HB9)FOII[CO(e0&JLLJ7V=d(Lr:=dm]p3"SL;'*_O)"6V897cWP$s>Q*I\G*JHZY6/9c[/.!:31'mibAEiEkRa_%]d+?)bna.,ZIf)cfcChc;gFc.e'[)6.eV#/itVK+:Lr0HC3$Z4*oLk%0mYLj3#DU\4qWqNBsNS'_B9d-*09U9),e'>bYi?#&dAl\X(7?0%eRQ:V*hDeI84n"X1a/N,ITr5/N,S2"3Pm,k5]s5gf7WU`NkNrdFd(7P:,)(nPD=jH8c4ksI/<.WUfE=_OF7Up4H>qic<.r05nsEoeXfgB2$ ]MVSj5Hj=GsCs"\hA1>c:9Uj?%[Y=<N6*`QE*L9M4K'k@j!eYC/KDs5AbA/-ATEn5F*tG:KEVSKsbc%TMC"tV]j!LA[8EG*-i^TYY),3hZ1tlKbf\(Y/o66iNjIW-_g."piGg0kT7IlVDo1e$ai'iJ 1k$Z%gJ 3n(ZmD1X]IZYZgHj_"hP-a)N5FCL9c@s[j-9SF-RAeDU)eL0oNT.\nXZpe$,ZHH-:ch:.6:P"cL(09m#L9&g_F)F`kLBfC+n&`MaONb\L8&'XOjW&A5V!9FqPYk1:i9*J@1/=4jA^TCVaLePTrY]2IlGI?SXRiA\0loHkLs?`O\8&?<>3!?SM3AmB)W>oRDU$[2k`7_>Y,a,+C.e":sEb&fTD0EA5.XdX2#ZTM>$X93b37.*$+YrFTorc85839WA[A:7?4>X`VIN3`<5!ZH\h^4pFA^JAln:8Q'HFG`jnAnCRf`8WHPF]]$k[B#1;LHW?)W5IS4@C=O$4E"]4!Cl2GpA ^Cm/tJ *?`6pLMkVdd.iMlo#[/<l\b=JZN$S]G]#Ee&/pd.#16olAklO:s,1e+9d2;SA 'j@VP3BEFcAUh_9Y&Y!cnMsh3>af]Jc#Jn^tn?BefEJ]jMMkWIh`]sha.f+e< 80^_)6 `G0=YPUDm_Efb*\&*S?Op6kBI;Ae!C)-(DFT>2iQk2tOftCQ!M8V(>S=@$RNZ*n=ANm2B1kN#I)PC\G;\aEHjW#XrRo">"YFD(`pU5tf)_T^8SLUZqU#.2C6`#EpJtZ^KL\.(n/&-0WWO&mr`1RAF"&LtQ=`i?5opDmm`Aahli-r,H*1(32^Lc>n<,]]-^]0GRn$l5j_N#hr4;*.e6P?-$+Sm%PU>9as`Ls1-JINC"eFPC%5sATQF#,s`I;SRFCN@:- C?R)b:tX\:iVpK<`0FR`].7k:KmlBjI[,Kq"@QGa*QK.mkd$CnOp$5WW@GqDZnJ>p'E4,/j[_hX"1@)O=A>`-Qb1Re+b'!': $kUB`bgrrJ`&"9V7e/)i,(:I:7j5gh \,&I5>&h/^C0PctX-3s'VAdCB6sO(F."4:OL50H3+o("=n.AU13=OsE-Y$8a0jSp+!3OS0Kn%TY1VjAGI2EcnJ/f,9?RRWUhd^AHAcq=%NF"c_O6\5>lK<IKE"!6G[/=OP!)K]mIYCL_T*U;BmBtV3[1j%_t"OI"c@`#Ib2mim6e*#KG t3Xpsq\MlB>L45A?.jr0B.]XRc(?7?6MB0P1VWEc1n!'/N!75,.=!D>92_FPLHmPDB"qrJ'BK978B3g.6(Nh/-#\"SsokOb>DcfJ^eEa &.ccAH2_bdA"")'I)7Y$3o%@l]RPrAogDj;60"LXpE/VtkjV[%4rYh0NAs\a'_0/Uc(iVb_i%?>[GTP\5@9%iiiB6r91qf0At[t$D-_:5^M_7g?M_ZQX][6OMK8"S,Um8@S[Z3M&;ZYT)N&_LA.=c PAl5A@(\5jB(8O!t% c$s?+Ga?,JjP.,#B_DI8,PPjK+!e"^dqNKdd[jHL'\/_eaPifs[2CiG^nm:.gjV`&qak@BJ0SRVSQhtQQ2[A]?]k)o`lln\^4I>6*SfJ#tc-'aqt7+?h-.Xsn!B*AKV25a'NH,j&YQ[?)@PK8L'PZDPtK>n)+F6^Nnj,ZrfpjWg:H+_*>/6K_]a?#mn^dAa:8tDLa3hi2_bZ@rk?g9%a^s&eW_#k!9Sr(mM0CQ2Ot`qnBfR2Pm`8hq6"g#E9XNF)th%(IH=^FM'bso!)n7Jg3o?\6mQ#jlI0GU5G+#DmC(V;7@(^gs(t\mJ*V&\V\@Ed[b2[[>N^;#SIWj#Af-cF!m,=1Hh$R=VSclKEqnom[0,QV-s%K#!g9G;4o@c^?;D,jRFHaaCUh-L -4\6TX)`\IB4:4(+Adeh9CQf=t0(tO>n;C@Nh__?Fo&Z8]TO:hMf_+B D8?+=PA*bE<M'6@Y!^eS:G`apd(:5)Q>[JP1=Hjn aYs>SRl"ITj4qL)ILm$i\f^Kmg)atqED,]34Mt+IAA,%Y ignFm3&[4rbl6#c9+aW9/R+HSXkAA'.Ij2>1(OJWF24H(SBY^;V1%&Ora?U#(mr]de`@&QJ&(^Zl"9%N"`t_[]E98>c?sGjo#;nd*,kW=>r_Ddt!Q,Q25FgH72eL*fW2f7E+[hihR;bqmDooi9`jiLm)PM-(A:i=D2%P/MB)k@'dTBLX@:EKK4`A0"A)`1LmBr U$ql2)AtCmUsDiAVAWb8""#kV=b65,&CX!H(Da7sdd-<=hHHo03,OLCcC6* \?(_T)47RfWfPYc_eZ&%1lj"0W/?.=J?M%orZT5?9C;#*N S*4l6*R_70:fP>"mlEA-#DPXVdfF>A5JJ*\Lk&!.@CNtQLn74,gN_NK=h'I`RAc'Kt7^AslCRjMGc'j+[,W6$LbUJ0@GLd3FK)]81&P8b]DT;@^7??c:NA]8ptTrR&,/eX)I]MK&'q%TcPe(TaV-er!'3j.iXGAmdG3$GZ&G$')>/AhbOtm2T@hNq\\sfps -L248n$^ALP]ho[@1/.ZZq3IWG!*2WXPs%[S-$**YGC?($A-;.G-NOa>B&)A0_.`Cr'QlM_=>GA(Q%Crtn_6Oi+pj*iq@eX_As'nS U[LJtt4p3Dn6FHIY(1I%D4\>r78crA)E4aD#\hU!][mh3)ME5bCo(OlVLEU35q (fjKUlBq^qCn[%N"WAV_8Tb-EA3IM]4S'-5\phTYY3SFsCn'( F<TWXKhQ&!Q,Nj*!o"],M5_YfG6*EHcZ=P(SiAY%1CZmnIfeA;Fb(hIdH3WA#$?mHK@OFcrF<.pBUQC46T2'?qr5`>l<(cLB=XG#rVjK5P"b9%bJee_/_AL>D_Oa;XZs\ JFHRP"n+.#AY^.$a1p'j+;3@Ho4^)W(C<;J+PfKr'DW(qKn/L^lB@X`8[9\.$#i^,)RCE).`gMXC?p_jh`.d5$Vb4^h\b;Q5LY&&7"BKkn ]$^-`+S9M'=!f:Vh643P-OraoJQnn*@AE3n3%kcMt"dh'CRBK',l@6`?Z)M7_1*3gg)].:Vad("+gft$T3aW]q+3o(d/WcSW:_B2#e@n&mq7N7W09],V[Hio8!6OZ%nP=LjAl"]h1@&T`8XDF-3F,%MD=.Y[j8#Wj6>=8;2nLO`93V8HiB3GYjW4CBdeI<)W(SZ8cm;SCGgC`ZK!$)Z\CM>W!Na/:VK`MA[-YdoS->HZ5Nm+^R[W^NrOI-(c)J6HCC7e'M=-DaNcPf]4r;rTdl\0[>6"\1)kHV,IoaP2\F!PJ2jL1G-4Y?)ML"a:G^^/EkX`>)@_#r$TZJg6;A7YWf+rJ5hec<&FJ@?3%;]GGmB9DmInjAY@^AE24MZ2Sb#(:!ke1J3mU0'q;AM8XHLgrj3<&Z-]l!M%2A5.af>ZRh!qLr)MJn>>0bbDLRR<[hq$8oi'2h.blNaY .N'L/'h[&3*\Onjl/LUoMjA= FQj<2l4[>JGsCM:`Q:#[QL9/U9V>LZrfl%=9OAtLg3.'eLrH75.:Nm,i>Bd7 3n<2-q8p=?`FM"Em6g_ngd*WND4PtcgT)ecQe%d1"8A_(qPr*iW9N#="aBd8N3bKONV* -p[^^h`/C$Oc[b':)#W3>rBBtQ<;giCQ?/kSK'j.gMK8i>6`c^h$6rX>,2t#^r$6Ai)Z8q^=8tr]BdP!WAb*5=[J]Fl $c#Q*JPX\^PnSB8BBSZQ2aTH5qT;:\$en7K737i'C.14gE\/ FK$.`6Ps>k@6+l0G^7fAmgEb\siM4rVF?]2X=Y'(4]O)jBFdVQ#ER0=.BZ,scQ \;l`>Sc3Sej^,YRk+ka%l,eRoANq5+E*$=edWYdJo<#j,8]YIK+t/&6<5.WW2& 6J$i4l[gj.^R&KtPq:+\:AR:cpX4M30_fl77Q*j 196-t9i>PfNLh$/#&+-:tIq__jbj@fj@:.>e?Ysd?=WF`Nf:mSM.0he25-Gbb3s< &Df :$OJ9X%gMm"=`p,(otl8II&M(kn$3M!UI(M\Y'/Cmrl$@AE9 _;cip2JS_e4plaNP)S(9;76Mj]deeSaT.[2b+ZJ1A<oh_/t!XWI\Ac0#@_m^aT6Ng@0Vl3AscN,ib65]4QoCLg58d)g<O87SsN_-eUS6#nccYZrIdO(&&qJQ=J!T^2;9)d+0WXp@E9/n188"eMrV4`Dt06]dY`pX;hE)!PlT(CAa+.MNF3C@CCG<71rkh;PN]Co0VcY%biWbOt]tLB"__IU:L 0? 'CS5ZlWbAlG#$"Y[7rZs=4UiCPKiHQO[ai`Ocl-/R@a?FSFaEJ>%>:qhrPK7O!qS;#EI\,Z(A.nl>r:LY2N47la4e]obrh@0k->>sTFQ6L6T*$AKBJ43DHNtij?HMh r#d.WLOCC"@LPX`-_q1Y3bUHA0<\K^k0nS0O,?f[lM'Y(tBM$2A4Hq-F!3X+,X\"MH?M/6G *NTRg\T[ol5"V+(T@tf=a5'g1(iDWr?9b^D12@6PX1a!C3B.M%PmMNXI:1k9NegL(#9D,T]c;ZhqWj;:[CVs-nflL+A\:7L:1Wk=1e+%4`J9go(4ap9h(trBJaP+3!]LJA-e-lWMp42AfV",>7(5$M58/_UAs'9m$:,J@Uc8jefpVg@PNXiF/b^bV+],1];Um31DAqk"nE"OR)VR/^nN `giO%X 2ZX/S`&rr5\6Wo7ZN3^!SN'nq+P!$7S]H`.(&gAs!?V[6:GptG1Z(Der*Rb]1^D--jX(gPGZ4Le<C&.N2/no ZMP*IcX_A^rOeOC$To5YKg"%r/+-%h%iQ>^0Xl$\dX@I` ]T2h$kFhcQsb/VjV<rF]D$!-Q9BWfQt6V&g s^O,."(KI4h+ARfselg[`Z;WIeV=A1c-jfNF$s6$/3\ek;Jb PHk-X9WpV/"JMT1r4/iV%]"UDg7%f/k#N\!ioc2M;CN1:4!@+XY4d`K*&/Cdjh)KO5@YDm?8l3*2 cnSV2KYg+-S,?NEAF'7o8gE]iVnYNXG9mPb]g [j]1(>!(l1]j5`7E)D.th\X 8?G/dOP.)@)GRSn(EW,,<JAl,,"PthC@,(Ttl3]S+2e&%>.j:)0#[1*kD$]!+[SA8T@jt/^iA,AE@YQ*a/[BPH+HQ5 FSG*S:,BiW@H_MdBK76.<-k75-AR.;6"PD(%0INhS7ePls57q;J1`.aK-E 7_W.mK"[VZlAEPkb7kI45ibQA5LonVs7Ds2_!&;r%G"(!o'FPDT)NAbg/.R7FR[ll.f]#!1eC<@YqiCf1q9YsRA5@`^%EfYcdCjA!Y,6 IK=VOm&sLmA1kkC6eC!*0&e+L"^)pdKQgXAaXk3$mnG(43KDI$Y-pD+h>oC9F`RITFR!D'oX)=OE^eO1IOQ>%Q[5QY9O#ETf!\dc;Z85KXhpALN#4g*.Y q`O5I#XUh*AUb]`R-+TP[@Y+bm6n,N?5`#-hoDn']>A[]Ar?[r6tAA*1;9q/EVV<3*>Br_)kk#n2HP9j.8#c+B8\38($=M+';<6e4SL4"1Nd&.O4eVkT@;8;fMXBrj%bWCr[Qcj110"pWRckp^>qnB.X*cm`S27'f]\0 "l";j(Ah.CA +$R%%6.lk3BPTK;T'aKeY28eQg;2%:bi;5EjP^PlDUZEDQ9 Y%s/'AO?s&+4=&ddn24D&0Z$D>%W#[>&-nAgX;78`-5hj?^GktMm%W=,>KjVV3/a;ik.[@=BoF\+fHtBd3Vc'Rrpm&+PN+sR31AAj@kf*mp[IieK9OqS\=1NgFG5d?/G4`Da&k#!dr3n7jM[NQC>jk8g!5Ie__3"7)/Brqmk1tFUhXKi&q5[9UPdt];$tiMWa'l8mNDZ?Z(SDUH\7N4$F5Wejo]_^J7AngphnD)O7Kk:$;jKVE1\aCRL5aJDW%agA*les"Vk3$0pq?dLfi#2*'S97(Zg5PW*?8m5rjkAhhjd9hk(AS\mB(K?i#AYS)?P[9(bj:jEG' 272%!"*r;tD>"X$/i0A?NJfp`n?dIA9>nb\1TOhZ:2@l1Td?M>H#Q*)>1$@nb[7XhGZKln*7K%,Jb@i4Xl#,_sURb_Q=eU1P()+Xo_N&ON(koKO45`8 3pH_-30HH@K3bSIi7UW*9/%F'SE7I?]<0rmcA43mj*O#s-U$ZeU;pTV[lYbr]$O11l;_(*.D/A-H9)*XrX;7'c[XNmXb+YIgk9[hQHlU]_t'k&V.;qh9+N %A:A*VSRQ\:VL9 I4L.ofoGWqA\90>\-IASNB= 8?W7Ef#hT$s-#@rZH2\ESG2tgon`oM&+9OgEU[T^/B`Kp.lDr(G #r"bOdgjCf?PDPZg.s+5%Gt7lPo"A=L%0cfi`NE)U/&J3^02@-kI\=f0radj/R/4242%X$&pj1`kbhm\F]M2?dnK(T+n'>D75ZC\OI0Ocl0[`2:#: Zd#bWXG[IRSRtj6!r&L/DhcLQ5dl!4n](httJ507Zt)b\=gn2!giPZ0KiI*c8`dpG^`N -6"dl&L2[%\G/gOPPQTp6->6#-SpLM^ aqAR#"])_*BgmV!n7:VU%9`j83E$F[K>JBe )I&4hD"DPo)^nML_nKQem!rJDojCaO7hTLZSUFl=^"al.;AiZ#2;j"ICgk!>#E(7p/%Laonf9;qrK!7&+KeKI[`><'8ml`a=<]TBt>!8Tl#(.JAs*i?NWLL>)'sSpV>2qp0FUhOg'm/@8ojW'&pf-\/hYo#-A83*gclkEZ5/3XSRd`Ae\+7d7fN!8GO(e4\qA&4'N pUR]rnlZn&oWCCiG5q1o_"_@3XMb\IWf$Y"b^G%^,rGY.7/1&&mF0<+cf3jW-WbIS ?'-"B6iS.SL,OrS!+"cGX_DQ\V5[6^7bZEeVP`C#W@;XaC^ oK3gF]9iUS<,:J;r1&U)Af(,LV;`ikl(b+0@#YY2s)%`2Mc#ksHWVjk$t2iM[`Z$%t<PbTEZG@kX4e>4iH*!AlRrpVHE5&)/S:sJ[>U)jXMq)4HmT#o0f;Z*@&%-LB([#m3";cEA"jh"_'#Mqn1,q'Lds ZL`b'A2JOoL+5.aH1i5l$H4+ ;*Nhk*gEl(PA^a;ggATU[8!3$C;JLU2ne9)p<$NV&Ma>W"Ak2rDf28\.($7DnUOGr-n?$K32WYa[Zb^N6%$,I>[>0mN+rn[A#Ph.>M0e@A50.g(%eU-bL\.bSU&imF1^AeY@GC<8qj?Wc"+rls,o%,QLdCk&In%PQnaTG_g!)t@O.7Ak!od5-r-9=<$Y?:5MAW\eD(8R4MK:WP?V6P_OUPoYnCW9@#/>DKr%2q5PPP:?)8L#>.n^C#`C*2k=)Y'\?2A!IDVWa"cHij2C(g#ht8S;9<]Hm@.`$]q#0":;oDCZ^%-ofcAQJp8"eGZg61bW^-U&:t0!9N[caoZ>Ib%,2$.:$;o61TtgB$mUmT:m/K^k/sX\R9[5=fk;#E9+NfC,Q;R3LoOgoDW02QOIOQ`M/TZWXX%7\dLI&fk\n2-;A0>3Ua>+&BpV&LeF8_?QUk7er `+MKIMqT7hh5H%Y'!2ahrI!-XC!aDWd gbdb-a7+"+&<$\s54nDJ`k8n"A(SP19r$mM1ArGA\mD&8UK#o0S(@4ph^[IX]@I"Jgr[gse66b5[AEG@Fa61jSLcCk,F7sF+e%\UV[_0`l)S$a<2WGsA2C+dg8lec]'^3l89Dcj8@C#$Il88b'H99feK%a/Ee>Q)%rOWf3kbth,3V??N$H,J>$lPUiA/gD+#!cJ=a4]ae!aD&.fL0e67s+g_?D*&aU=P.n;4EM]Y/8f4qPVAA^7ML>7IA&>*T =LP:VB"Q$m_q7U[X5!@4Y!pe(UF.Z#YU"K[[2GA5N:a7f%B]N$$OPD_(t@MD3<s$]A"8K<1ff]MZsD(e1`'A0S?[/eK;"(.j9c<09/58p$5YbeP_LS:1'K5K\Is(9jT/;.3"NtA^"WG>r_UEa#*E=Y%f(@GAtqfV@d\:0]ZN;B?JG;-C*0(-OcqnDQT?AS1Zf[Uk4s\>`08cJ?h:*,$Yp$#M'A^jq'DfmVA=QJqbo''r<&f:&`*+I6m/,`Lie:5lgK1S+e',SAUZ0>2LOB;_%H?/?Mt`MlQQ.5[ga>tPdD]&&a\8Al-Yn5B]QNaN!dkJ*!`Rr-;%WZ5V_FgbX$"AMbL&CSYRhS*_WA0qZGn8UYIil:!.[7XsdcNLYm!=@kfg\onU)FT^[(GmW6@lm7=2rGD3.FO2b]+b'l+VAo.]c/sHE%LKr;l@+A9,BP&p##seO-I"RUJ-d4]fhX'4B.LAI+,eclYrVadm#aeQF00\^MU3R4eUj-hr)jTX-F(SZ3AI@=k8bkn"]>&.(Ce"fT\50#OAk`RedN!JqpGEaG)Dr@a*<]3`.#k/56P;lZoeQqt%olh:,_O"37pZX[B$Af`>r/&DL@B\1tso-;2.frdR/[@Aql@D95JQP0+jc#FsrA!814#c!ON2<$bjejUOZ*9FO\=4k_[[oG1L)GVVE.:4)P'^r(JHkV5HAj+`Z2,AHjJmnhRLK$=<;=]V^EV-J@4XHc=>@tYL<d6 XEC.sm(lp0UAp;2 ,OZjbJmC4TWLA#5,Q4$[.[-nXI_/Mk=0RZR5Y*?`4,267N`Ja'a)9CA:p67de'Va4ZTs5*:_g>P(^gn8T;ELls#Y0qZn%%KZ?"4EYX8Q&>cl1]5` V/rMX1?PcbEN=+mf?_mOgpAEB;MQSk^\1(J])oAdGL,F'KB5iR'(:#i<&f[r-9Md\E(#2h%Cg^_:6ISQ+(Hk;fa7A(60^Mp2(Fl7`^283p."Y.bd3CMbK,b#/sXc6Oh:pKC;VS(UI<2T9A%t[*T8V'_AJ)m/P- #+1i#90\;(!)e<3j$pL2L"#oi^9L@)j,^>si;LXOB3p;tW1UHlHo)&GEQMN]_A^DN2=$;M3q7%\\=0V0?FGd269qJSih>/acd9njGn-Q-Y:n%>For#\7'o@Df0Be._`)j[#ah"PD:-+&k0,onnBgH;U.qN6/jVT(.U5Rp),hC7$_b]rT1<d3r%W"L8!M.3=`52(1DtP-X%`dSHZgI*1p8@eXK^DdYgWOt59-DED+56A))BU]mU:n.>E"-b;caM=YaZA=VB.k4EQU9qH@5R-K<!k6qT"V\j9SeiEY#"bBoA;HIUof: B%ACMn&fPsCpBhqa68)6>>eimVRI&,)q(F:AaE^4gGOjb4XtUpotYh7:DCk<`G,d8\WDn@pnDW=%j6"#PU[&?1*9R 1nINUf&LE5*tk]L=q(`+Pp'A^QFg"Ff,!UpgX?9_FhQN9 WGn%"6/TXB0i=@P.]qGlBhG-TV.Y,&/gU7AG2#t6+ZDM<Hf?r4/`#5hM9U]EaeVqRm'0@aA!_4XWM3-i=4X7I>*e#4)N@Am"8O)!YZT??m@,\CS3g$3!2_V)SoXh3ptCNXA'BS?a+Icp$S0Fp,+:rO%TP;KW'f2Lh3ap0ngKVc[JIMRsXf LT#n>6G39k9dj,4V89ccR<&bCnr$Jft*ALJ+Kd>,Em4p940ItR[1Lg,A:(WA$d.Z)PrBJiTPn;kB>7(/=D[Wee5:T;n:2CfWM`"T#nW2X+_09\pr;KR0j]R;s)9F>k[oK;c&.'J<%,Atfb4a+8?#U%M7RpAT$7:!ir$YDY2$5lL,Gk>#JSbEA,ZgeQ[BEg""FFc.)5Gdm17UAV1@?E'No2ETDfp!(@>0=.Bf/o% lS(b[:Ji4-9RRiQD8IT.!bVtCSh\c\Rs7147GpTR*0g"o`D6 3;iHc\Qh8ojSW9*Tg'.RU@3]ai]O3Dsj-a@_0TZ_9Q?*<EcLfr>poA90%g3mkH+->"sD,^TWp;W`-3pP??NI%QjO?lVqq3-h(.W Pm`/[`3F.'4.6/:@%b4lqtnL\86s8@QLZ\On14Op:jRkH0q52s..Pk,<0%gq"2%jdS>(RAVi:=7N?deR`1G"N9D 0`c] 30^+mBmYHW(,o/:*g,VfP/?t`[:i1pd]g___+t6IH=JNUI>e8SCpa:g;OR:eECAj`6'8nlo@s53e\WB8j*DF4C) Jd`K#IPBX?#N2@#8OK*EjZT oMhTfLjt_TqAno*3`1T'.d/ R.kffa6E9i @=3k=F&h/D/n5Z,c tZ63f$=ma!%BOq]1%n's^k'ZmsGE4*:Q@7/JTY]iA&\KU1q<$bk9N9j06e]F&m\207TRX[4%d4g!3,sU`cXAY9$de]E@Q!C%q8P281s_d7d(bpA.*`1in,f^pnIElntTT`1kJop*<<2^r?G5Y1dP5BBYQZ!btf3G#1oP'EY%N+'MU2q82,SQo6j,oU?.D9? rZIdf_AB(VUO!M*_7$,5QTTX@(AY7IcNcT>-U\r!$.rRF2!d$=MBkBQ*(A`Om5)LJ:. 1*c6YAI/f4o&%OCp33UWk ,#k15.:I!@]mT^-<;'_ANt)H0)!FSjpBV;7[;I1/D">_4.!p3V\CL=@slelia8UIF Ra]t^X=mFrQH.Z,kVnk`iFl?mB^;aL,6DA_HZ6A9(9n0sZ<!2/@jT#d1GRR;tkP>a(q)[`!!Q9,OOd*Ua[>\5kXh,0Qa^j`Qn_Dc,&A\BF Z\]7M77#*e<X[tbhG&Zc\*j*O,ETQ<=$P_qL)ssU6k^mf])>'a>HGXk"=rbL4gF:E5cQFIS.0PWfh^/cMi4DZtk3;f;:]-QKmP##oD>`;KilN>6f&\?Yd-QmLoZs*7[A&UE1h*KCl02W)R#/c>>E!8TiNCY[NLh_aXo M_.7E9g9o]PCS`/)Vs4P9;fXR'3!XTO8*"LI37$RbVf8qYC]Dqp%BdUNX]RO;=OGd:\icQ)i )XP#,C3( 6_S9ksX7Ar[760bhT/R:r`Y-.\cr,Q1A9/38#YJe%L!rlC4mO;KCPMm2@p>C aQe(;9LdA.M .N\*A3,Xkk3p>HU,'f>J(m+&eRi`,.10dWkf#rJUAW!Mf$-6O""@g f1[Sm@@]d[nmR#hENkFb_J^QQBo@g+@2:e0Z2A:^^C5io&\?;+nC#RYC?-I*e[Pk3iA^\P]AB'q5)_ _C0h7r^mbr(VpO^>?0K(ATS5Rah[k j%@Z`[!Nb J3jAkf_S(\>jb-bYke>_@]4A#QW(M='_pm3FVqkBG1Yem83gB!E\XfR*!19aXN.P&@`V$b^+6PV/Ql1@Z(>`dhXh48@JClL=aFea=?dfo?V532QCAKYXbUlg8;_Ubm,!j+OSg?MJEMMX/M%[(\WdK :)ibP?LHj5)ai.pRQ"dt<=mA#E-`t7C5]DOVN!!mlLfC\\9&oj%AX]@1M"BB*bm\ >L.sAJpoI]m"IOMoRRmgD,Rh/k>_KT.m"8``%f`:2\bn1]!!B9Me5\@,?8]59]rrR>GeEJi$knYBNcJ7Ht4&TWEg-[end5AZi>8"WI!LEFTjp#e&jOIJtQh'%c^g14TmCH ^"`A1]Y*JU1JU>TU<#Lb4)lVVo1Lf%mJkS.g>VD1MTjo)-P&g^iL5YI8Li,n_!;3F3/e.\I<@;C3E"BIW:X\<%ULnr#W33Zq]KRYjGXCoU\mK!l.B7 7,/!_XK/jQ4qebJ/F9jh8IU.8hJ8V>]B$6_8NFc-bWtA`f.f,66;1o"QkD`1<# 2@HcgshmE,p&cm!Q_n'oWB'RlMl<9"DBtC;"D[P1:b^8gc!%-e(=?T2'_ZoiqWiA9&:57Y"PXrTU_'!UAfYA]H21M(lR57/e=AO'9SEUFG 5_^"^k>IhTkL<7Gq/gaFldm\F=.* (PA;n,QE/q@N9^$Vsedg+ar;;&AK\V'!7>1#:_E??M\l",@4da:][-dr!I6.'lrarP!TA06=8*k-Am%osAr;G]9MdLjSj1>ThQ^Q.8JGN-YT;3=C*a9>#[B5NnablrMirPbjlD65!$Of:@[I25EWGM[X \nsIXF=qc`Z-\]^Vq2kSX=G;$5@LQ1>9_4*"4Vi"QmAkDm_ST*7;drHQ3if`J7ng5ne`%8aL4,f:Q5GS`LRcp7Z(4XVd^Iko=$]@V/ta'o -9hdlF@Tn]%86a p$R7Z.7bWcpgT,87=ZQHX:KN"6a^*0A/ibL"U%:E$&= )bjRo.+g`%JtkiVXN(o 52Q]K,XJ8JLf=T=$'B1;JI^5*Al'A$$!*PB/%b/5s[M=77C3BWb?Y\hb$ceQ[pm+\:IL`Zc1MT3\a_o_T5603tl?dg?pr6&\8QkeVih6QD%-3,oT!$bc1[+] 2I"dh+QA1jrB>79Ud78"mnif$jMJ5qH>lr`ck 6[fmh?%2%9F8eCPJ/T7<0P%kP DFG!V4.N9IG"&-T%p,5PLA6PTA5`_6Ibc4lb9)#eLH("Q=jOq),ZD$.'55&rl;`54' ]&%5W0HV[_/=WQs7b3>7[I $j;SDo&!c-=P@cQ].GPN3D7coM=Q!#SZP09*d,7:WjsF9[6<k!N-/?QAfK<&.1$<-dO30G6tV_h5T(45a"Hgbse"TXr:W1XDcnUp"f*R],61TVIHW+0L$YUS[h1A=c".(D:^eM@^\&UI30.aURP?P72(17NmiVi)LGWON0BU\45;oaHcUOhhrT;T17Qcg6O@H(#4r`C65*m0R4Z1WpeM:nEjHZ)sennKseA;)h@)a0f1@91A:r8Re_p[CJ9[o8f>^2kLA=3"kN4Kc0al_W+MeIk"MhrUT>X":0tOfo"U[A?h"AWa8Hd9Cn_>ULQY"fj>[:]EBAQB-9YW4\nbKj:aNm9(Dpbc[jiVb".Y,A^,F@".G=iF6"$G R0[;L547[.g(A+I`+8!]d=$4IY< .b4K3&+0-H7eWgKL^34^bQ]*I:eC%qFtmrF11[jIQo-QPG>_XTraYIT#+T#bc]D,Y[nf7-l.d9JO%jq+=Zd91c]3/N%r-H=A)T;SMRde\KaV`lXS184CL.7LW4S+<^*2hA`PBFIUVXm3Ngfn;jCjt+VCOF(04T()pTfY*n]S^c0"!O5<Am+_b)*8*p[QDj:;/d+WeQYf^5b3^$CnK5MFBV'Q00JlLm_>d-6F/M9d.p+V1_AMJS>1(PWBZXG`hQCQ1]\7MS'im!Y$N\B%cJ*("f^Qn-XHj)$ehjA?TmM!rLA7c9N**Oq> DK5Rm@[jes$PclOsE9EmDG:)5[0Ct`5_,Y/,/dbc\:ZG4K&0DbM.<]d`YWcPqbnQFYb]cC#\JL:^n\'s6A^GJVA*.8.k)Q##HI+&P*AldtSe%O=5V-U+`&SDbB8iKa4"'1MA7*>/BA&m=W%U5"U!$M]l+mm93_Bs.&%VqA9%>UL'?l1CH'\#5D';FF?ia-pi2A$P=Eq+R[$\3c&%![H60R^2+/Dq8m6^rk.0`YeU.X@2LM_j-.ZN%An&EHGc4qO5/ZqXLU4OgKnr0AH8YDn*Q"o&YQhsEY'^KI&d@sCZqq%#UE?tNA,9_E8laO%Se\R8LW?HA:JA&qsFB2_HI]k?'4$-@-GrNisQ>$gaAALde9n?Qt+&L%1R)4)^Tar\fW(Z9f@%D,=K).sVO^W"WVP[X/-M.aN'.hQfO,N 7o"2`5Qfg3RLhkNjW#,qWaM@:\_=OGg]fSKrh=[\B=9C(t>DDr(geZF_l`,'&"*Ifp?N)cmT,6bOTRCr=A6,s]1sB3n,5PpRDC@m,,'jEo&:=@%Mdg:<^p=d:`8a<_D=bD`f/,([?%n2e\YK]"D*5Zc@\`3lnF5jLjKcG'A4RJI>J#(':t<rG9Z%&_FF[fj'q>LlO\$/L=/>\0^B&W+RG.iIhaJ8rJH5 sI9-$*o=@LKY0@c\8oVO9_OZK]eDqm]7!9";e9iTo0^XZb% 8gIpesVHaLrgR?`B\!40b:@j'Io>8&$fKts7%c\>8WkhB$/@It$:oAlR40A2&b(4"/d5+/'-k H4f=2UZi/QWjF QBX<"/ Cfa7:JNN&<E4a-`b=;^^G\'BTG8R)oCOc_@H,IIG<&3hMr'*(<a.&DhY5U(Qi&j[D]>qPeg<QN/o,!FJW@-0ZHG>5?cBiMK$l>D;mCQSJC? dYN:Q8rhGa4&9A>dtLGUkiYAL(N5C-/,NE;^lq#%c-GWh[A+f;20+i*BZ:+9=BrO),&(L`N^s!@e:WDD#fWY8i_^dYReFT4? _"9hh>)k,oE["p-)2b_j:)o$TRU3_4X@Tf-E2`1$&i[Ar)*s'-AZdQU9V(^_mW0sT1V*/W[m75A(_4jOjRAc+\Y9i%fH7$4DoZNO3r#^=`s;6(1-Hf#\'@&R-TGYKTNG-gn&"(jWpA_,a2`tFkM=aAPAt7)Xh\]g9P&S*qiO=+b&*Wh`OL[(g3CU3!d@."+<%?DN#5^YXg,^b+%b=@sA'-i"TZc6l0flWAGJF#pL':>)`_(baUeiis+5q4"s!VaH+X4I@e_8>^OnTMMEaJ7Aa4SY42kjoR _d66kF6iHA%eK&s',ib[G:>2 70/dLeZJhlsLba%R+9f1/XosAdmAZWbC[\g#_c.cJ0VA6gAB:o(`2>O*$NO_E7^1Eh!in[dM!Y8r>j@dtFcqZ"la>,d]49+e!Tf_J&A[QUCr,c;?HO%ji7g_9J)$6kd)ai-P[^C?Wm)M^ \K,RVU1)iZP9lmC2(Hod:#@$9cj6+-X3r)Sr9`97JWA::m;rl[9J*2XLE#F0U*IB$P]+\Fn>[%cWjdk._ tc1"2eWIR9#K9Y^5&%jZ$L,LB_K+19gB:AWdR!g%9?e>W/Emc26++H.\6F<':j#P9_kH_KGT88=4TmVGm[[N_)C5>;O3+>i=1F1UAE# \"J07pp!oq8d..g(((deH1[)^[,= ((s_9p*%(M_^7 l"rJT?l6n:iU*dgfaM r#e-_*+ADo%N`>Abj9'"FoLZ#db$&7Y_U^?4*SS>dG;K#O's7lFWA=6qH'rC:0aeXFB<^K(DV i%3)I*JAX3NNL jgeG7Q[XHVTa4\2OA@*5B[AIF26I]:,Bla4,I*ecIY.I9Z?8*)k`=#]88N;rHN\R_9414grVceT'LM[6IF]qaa;:NHd@W!`EAX-D5Z?gU5?bZ_TLR!llZkUaiB?iD8cjVZX9B^'(/OVNm0I_0&6NS0OD;;bK;',UX-GlB'gpj-n[fKaEn>sUb05NM^$HNR-<3V((RDpGKA-PdUA]s<)lV@r&7(n$A>M;D`0LM\ekE\Qjd.';qdO7 9KC6g`Y[N`.$1`raN?o;qR'r Vm@_'JF59($l21"`=A[Y%\(GAG\qIf5 )N'C%">WGA,Q>!-#RTW/?XRB:_n)^(RWBA]r^GF$U@A=oI''fAZ+RY;!EOV6E#sr<iH44G+hZ;`hR_Nj.CWM(Ns+_$a $-mrSr5nt;(0Y)fI)S4GEjX=`Y0n$B(q%%cb1 An;1nAi&-3\#Aa3jU!N`!4"^IqAU)[p$Us9q&"WLp:@Pe:Q?cLY(:Q\Hf"-V9?>akg=f$,Dcj&7AM5s-t3`N#Al<:"UVLG+c&,\k>ejl_qK?j6`&Or=Vd"%Np"b7q$8Od1:;*dfnp[^UJ[,6t)YsVkC@aU$>]3S/LKp<#40TGfNP*+8K*NUl!!]piG]O4A5#HQ@mE2<rXNH"K[jE*5g^(5R9!Pi?L3N[:3AWOUkH@(%kZr7EMbnRn395W/B57o7d*pN`iHQ hWbkC$j%ge:%dT#6LcPK81jRcAd[%s_$c+q>8hO)l.bbY&l%>Z^c6i>\Cr.GY^eU/rq2C"mai_W?,@ JTTS*lHpL.DD.\BBEe<:*W1db#%+*,Ql6?+X=M_nb7%,%lh[Q,['nTHTgdT7j?*ls;GT;;"%7+bnB>EK43GV(j"DQQs l<0A,/o (+G71o"@McZ%>0c'Uc.]PXt\>X@kjXWqP,,,V`^l*L&6(d\<*cc4L),GbBo.TmE6/@7OA^/^gA;!pPs`Wjk!RGG2\nG7aa>C\W@o64tKl7SMAX>k&L,0V19b.YK_:P[DGZEPLHX-/`*-n\AO'CjV+&Sr/!>)8r>&diAJN)I0aWj4m=&&&=Q^Wp#pU_-3Y13Q/g#"EQMpBS_1YP&9\ABL6Z6d)f#arHa!Hj?*X+W0:'WWOGV/1All"Qa"Xk\Oc UC>\AqRtCVbD)X<+9pXrR&`"Q<.0-M.Q'c(XYRF0^%>#TN-V1g>Gik I@1.R.4@"HA;hWF@Kh+X4kt$8*&N`;m7UefMH)W6p]ap'J)fQ;)<`BCa@iqjGCDNlQ&-A@^+H)q0CEYsfBs^9+$b!A?ifH`4e`5YcN4WR$q?i;hOgQTJZ%^tZ^3bV>;+FGPDO;Vd^"l,TA/^&.UI-A]979L&'/4bQ&Y==om?pZAVf8;@A(B.FUY4Ao3rcKMJi8&V6pjTW9 1L-$M^@?Xo=Efmp,!#2B0 iT?%d\^Zeej-I+,Etdlo;GeXtq5Ei;N+QHKEa>:p70G6Ah0t$DC[:IgmKiSg7/3hl#Vp0B[;2dKL'SW%pG1PVQ>U_N)0^D[ALc/QTOaA])brkR5&Kk)K8WAUkhpSEj5nB]MLc#(T9Je#LOR$=gn>EdiskF\p `roU>)7C<G$L2gPH`rmc-AE$3=D]UZ@:UQ`q`=sO)18I9L!pDZ&nNoiOftb^1l(KBi9k#Ek`SmF&_d0(@t$Ybj^jnnXCVAOft4TD_s\%K_IcT'C","lpJjjtl7fGG1;J*@]BZUl54j6VFW=+QjTO[1ne*GO@RsX=j4F /^nFZWSPS=VE=RJ[?V$21hQYLS[c<1)jMEQSj3p;s)_?D_+s9I!jokC8[3Npbd+kW fo)kBat,qpW_YspA_A!fE/7g@YVTODlV?f+9LKMVI mW-7Ueks6oe4AF4]Qe6I6W!J8M+?IGr$&/r@EA,d4-hU$]bU-bAapk6/*_ 9k(1)<,P']K-_?KtcGg>rm/YDhjO!3lpL,t*D4j"Z63)kB1_A17LJ+B?#(?9*:q=X)VQc\pR,o:J7O"gRi#Dk18$\Mr!:"m*_dh9,8g0YIX`Zd0XjB!S+-Pft(n.?'kD%%`K>'",Oircg1L^\+iJE]!QEf$J5l&_nGWLGI8[B:k\qpJV1N3(/'/HRLb3G57Hfn25*[:*\E`^< ,rr/oRh ##dl`7>i5"= K&;;2-8gsF"=(*FkCoFTd=_,7\^R]SKoRlkF8]sLMXG%Y[+im6_^`7fLgk;lC-)BpohMn0?p"6`ebR\'h"%UqBC:?A0-YHU%[^K.=pPMhB2K'q'oYgfnhsdH3:(LTqpV6;'q9pBsQR?X9^6W:F<5IQW#Sih2J=D"( A0CT9W_nKmV2,EH0$JWV*6D\s?!:8`4$)Q_366,!c(ga+Jd;lpk5gIE\k+&f]o"^m-R)A(M#8%rj"NWKf"NcE$%l"!;&lkQ nB!cpgJ5hBh@Be7go+o8fd= ZelUGrT)o@.,EQ8Z>@=elER?'\DEN'iJrTYV*7&EQXk2kLI`CJDZ^,!dK!U1o1 N=*qq8[>t"sJn9 r].E0b*>+S'Y`s;hpAZTDZHX+.DA6^0L;cA=B!12p#P=Nk8V@[7e7"9+YFsD[$F/TKo=>C8K<[,T$JZYs(k+cK?ZXgNtQ/H*9'h9@f%Ih>G%/U]V]VYXE_^o1h=a:lkC4Pb.L^eA4CXn>st4+jakA@NS4O#gD1V?5kOHNC heP&X6<>2UkP5J0Z&J?/[8ZElsB@[TMI^N3-85UZ /mUYZfSjGL]0@si:nj6;9;I)C20)BO?W;F$!G?<Y.:s%e5Ze3=7b8I#TbITfnK8nOrLs;*(GqG8P"HX(67Q&0I?8`DD;N9k<_(r0p#=P:FV^W,#& [H!tVq#g)rbj69M[;_aQiSN%r0.Q]$jAiIU7Eb\PEJK[(:CHjkg!U'>\?b #k`'>t"C-C'+YJ`@#Y 61KEb K?Z)5FsC>IIfH+RpL2>W"Q$JZg/2Bk;%Hs6(#a,_S%9qQ6_\;N_Dh"BGrOGN049+fbDSANG=*P"RoDQk91S'nQCIBeng42;,>&GA**j?edh,:>Aq\]5q)c[$E?('Wd-Z:TC5DS$BO PTUELG`jLS7_N> bGiU 76%\QC)5FQSdDf\D>T#"^"9J] n/$aA^8n#t$a]%-fW_j#%fH:JTF0=l3?oHUVZIpJoHlnM:ponE:,;">)l:Hnhg:@bUq's#DbK`L(,MU$,N+% r@@4W?cc[I,_)daC_?T"tSQd9^%`N__pZC:O[gWgdhG'b\^0ltg'O"koJB)J-V!iI3(1fjq7H;BrMlc0Vc"YKo(C/Wco2YTaU?s:YE2rFqB81/df5\W3[#]'0IYYp/8qQ0[_*tN!3KeAI5-4`d'G=&Z)hpqPfLVJUG_>>>-AeHW&9Mmt,l1T^hPoML&N@T[[deLkgBa^pGoh3rE66BW"?%K))Nn2X*=5FA_6^bT2hnC7/H%cMkZ-&MV'0JFf#_HRNV* .@j6eU`&l2"W=R)_EE0h[-,="/m2='J2>KF[Nk['@K_,\%BHY4]P"STZ@-Aea<&'BE;]t8No8RVf',M@34\/G<3jI`A(T0"@b,Fc0;,AfqSb0=o:a"I*5`'>ep4#4D&nQ6\=Lloe5Qn-ed&$4W.KN"!i03QP9DW+:smc2_$gO*T2MV6;';sd-06W:'ne-fpapE'j1,f2ieqam>mJVD0Km\24 _\ApdeB&@gq4%fJ3oq`.&tiR-(A bYiC([QPaT6].XVe'[Z-6j14_K3is p!1t_l^;?@SMJC;pJ=_6LaUer7ZpDO"@3R:lqT_(ac:bSd!EK*,sD^s8R0]as0lG17)r.(W%lA(q!b=J:E!rM8^dA1?Zk^ab^"c,Zd(@tD8 sM.[E96p.DKRG?Xl)oWB tD)(>REQCj(OlNi(gC]=!1ajYA0AHo[%2cpmW#=YIga?,f1E*W>9Vk(0DS[spBF,]+a8NWn2f3A)kOs$eG;5 *LGGH:3ZDK!B5BZ+bX][I,Jc47T7;#i2Re7tJK&]_N(e;qSY2l#.bU9mebC:8EE"U F+B.-o3GRnEtA%NM]7ICk(+h;KO`I&\LDE. B\VO+0T!-OiiOkh+.]RE3DDda0Mj:L^id\d#PdKc!Qt/W`:m-aH+8*gq\Zd)0HoGG(T:'8LH\Oj0`oJ(YU^_6ZKrjZ*t(S2d!8qMTUn 8Wi38sSCkKcZ"/_5n%fUZ!HRiaMYF'g^EXj93.-=(/oHe'!B,LGG9?cF[?X[WcE5\?=7% ]OQs6nJnRJ/':A6UGZGm7g/Ke%F[7p]Bs"J+>CCigJ(T%bZ"jnPIU@G$(++1S_@b5%mREh&2TbH5II@A,jS.[MH\1-b<"?Ak'6,(CjbRG94=qV%8 TJ6Z6&3(o?hYfKn95Wb=(=m8.IF?JS`Qh*R?@IEp,o7U-J4qZGjLnW aaf[VF(AD>YDU>0@ZreJ0L)(&F)-U$F@j5msJn)t6K-SGr:Td+9$PJ2j-s9EU6\:N'$=7BfT)bcHS)5AeDqbeVO6r@":i09:':jY_-2'ZY5['(PYtgge0LB(n/fK"i6?9]4)C9(;g= G;" AZlZW0t3bPYs^?t$OtdRVn:nV/m[@A"p.%9!p&AP@G&S^)g="qA>AVTb^=6T-HAJ@j+Tc;GU 3pDNba3iS3[$*FE<$UE(pF&@9a>)k&1MOK1MTY#1?df*dn2C>hH$;dK5>1b)=j"CNaV-atWE_"-\'\OPdRk;b1U^eIA4e=7k)U9rDASSEhs;H[*,Vef3PhO@&?,Ri,>BAqmEZ^tm._A#[@[9%jb!G#ft"Bn?:^0G4-Y`fMSLdelJrVb3:"KDAlPH#@m1!MX#.VDA6ZLIdnF(6Flqgd[GUtN:YDReU`>pUBBQlGhQbC:`b)A]:'AfM86]'K[A1G3[Yb"4oD.V=NhSl3JH)qA7TTW?)`2A[(.i=S0N0%!J1D:#";lcAWp>,#d+7MgM&[8%'>% P* kIrG4,JZh6ArHLiW<30`[U[`n0X":Z57 [N*HgZ$I7otWr54/Ok\NEQTXVZKt8D6,q.R3mp>&_IPAI(%?e!5?A/Qbe@ g5aGG(ni3aQ%8;=R7B4TgE=cNBq+FW\An6k@VSnE<(EC-dYOXi5P[Tii;s=l&'p1UFmJO[#pNbt8/q8Mq:I.Kl7[5+g8)\XkA7=1"7GT.4kFYob70WpJIM/7`^?rOW"*C\'\[Ot%I@a\dc?'cjQPlh\h5R/M@DqMap%_lgJ\f!Fn(UQJHGTlr?>6mA,VAb3793AjHbXFg`E"d-kr59p,"q.g1FgFVB?%[V&V2T:?02JO!OEQ8?_GKU!:6^lAL7C;Mb@2b o_s\1j:e]df*LQ79TSjDhM;AOd/9Amf--]#c?4Z4DA*h&/?MH0(=W[H>U,j'AQ5=Z84qS_]io5sdC/Y!)Ro/#1-8eahG<=VGleBq$GtMgJ'iaA&!0>IGh<Ar[[r(DdF1mRYX(:Ah^8=<_HA:&X:*+ra(p/_Dh_,i)B7 WFq+ZfD1/-rZ#rM-i\)%3a@Ud]n*+O;b0j3c7:&A,T=<273+Ib2EmD[`=N&`99S8??o&/@qoP?$"H#EL ER[h^aK(iFGP%TAeefT$Eib^ "eH`n!A5\Tl.DjW:'CC!8/rt;Xi`S_Cj$Z=H490!0#9:$A!52\G@WG =]X`K9CI4)gYNKW0]=OP;HJ/%pakp c>":0rPlQsSSUKaEQY2iD/7.]oCP"omV(OO5WnrAI[&&A`EL>R_/"r8.O/6cV Z$JsGlfKOZ:6t!G\[[;\Yjb42^6ROJ[TA=jbf9AG>t9_6pnNXioVqA=2<]-;[t7LX58k`<*K?\p8IQ0At;LEW0+H6+*fd3SaI'$abi7rAfNh/,V!@M^H@_i&]O,^,hNt"(mg!7jji^R\ 5WC=]M[q_[Mb9.nl!"BTOBj&Zkp:0X],&nJ$\]]S1?Ra^#V#X3](Q9qUlM2FqQefOt`oLUd=2`-ILq'kl';P-$m&dbNq4_Xmcam,pA6ZI^Z&eX3jLk'W0^hf('1^&b:oT=nOhOTQA!oh'^#R>P?3+L:XM@anPUHL8pEW+.d*,t`Q423Ea'3*,\8?[_7i8SQ,Z8-EeA(or+LtA^)r,Qdf!13HT>+l>jp'qK'!5\S+\1R[T(lAWG@*@WXWjiJ(-C,:$Q*g;ZAs$K+Hf3f,l'(.`2+Ltg=LlUj]A)h_.D4AVThb_:o"E,Ac[$r=`6CM WM85D/Sa&]RgDY7Q%1/8AP\-`Lla-5N?aXpkcrB7VV`E!E8ClT8gsmJb'3W`?C9rUFac[X^gUQ9TDjZ"(jmU54^H*-E?/q?8cIS:dL0@ b]9#DoU)^p5b8X$*I51q^WsA'd%2O*N$0gEfr(ZTj5]CgAC2n@"p0tBEHN1mYX"?InEGR7A0T>VMD`$`9?cmc+SA!/^SHKc6PB@7-/P'NLQ)s%@ (7\Eh$-;DE*hDtr/PG[]J69FRXG2K(MJRMkOrO(Z`KnNC<)o[<;`1hDl#((g:W$CrPUn(FVC =a9A-p&SQ-.Z9I o(1,pIadRJHa3ZLTVh].bH;#MkK<-en/H^=(/"fsg&B*bOAQE_X[??,*N/ ,7=',iAYKN OnML3[P^e;$Xq/Y-%i@[)P9cim"-8t<=^bh!srU3cB\&^^>O8IjQm5HNC/dnKsYf:Bj0dN_)i26qR\k8k@Q0]_tO[dGBL4Prgl'n@/>Uq32\"I/pFTG&X`QZDM/,O t]LC\nSP'mjQ:'NA=&ln^;D\nlQL&M;kAniTD](c28,8,18:6!M7n$&RVZce8TeHW#o\G^F%2_XM-/U5UZ9q4lg"St_'MSKisb"#e#NfZ,Ce(=nU] h/$U.Spq*hc+e[@1ZC^=2J\P3bp8$c58j3_O:0k6WC##3=jW!& .f!B,H^\e0S;adAUOo;6ekIP$>Rh[\-nN+,ph ]3C1"AntH(F?`s_SB6CLBsh7D@7 ]SAJd$j'.-aoYTsN)r:=>*Gf:U/! -03/6n&B$JBQ'70?@&G8eDUk:-tPpsa=-lYS'G6,^t+WNDdb06]"EpeqtZ"fq=P'"pUgVY*r#D"JNmJXs1t$;P0;%$ORIhWYeAbL@ZSB&G'n4QD*L/nS/^GS_9?9>N]3fFnAGr!neR5=_cYH7$)Pcf<Vf[rh+C"(2A?.m,SQ+:A-I-BU-Kk6prA&+><'ls^\6#l5#gEl0o5l784M_U3.=W_qGAmQ*%%^^]6j$/S,O0"1e5/YmQMqj?<-TR!*0lOrtSkQA99kNQh.%r"dOm+eGSXYY8- )FeVXEH:P@Sa##kM\2&7EY$WsDC30'l"h>%Ar#"]CrI`Y2\8o#-\A+qnB[3Nqq!a+'Cab&_3WC@]2?kr66f$mXoJHVQb1L;/"E/[_i"2A#O_@8!_onZ:KfIm25I;qhK"A3L@W2?$7>_J%UAKVto3lMX$-(b7s#nZRWJ C8^J.dqq^X+f;:nS.j'7',)boQ07P:be3Jja&_SjlSF/KCf]MlAj\q8MYh@X?E9PZEAhdOI9`bB0)DN3M[)i!`5iE&/6cP,K8fd$Z;6g0ZR&MA+m"ikA`$A2.0e5!2g==^N`#'j#rqt:\ _q.1dcbKhVo5QdUjl=<^Q%pF.J[KsmE/p<.0(?j=(@bU7 V`Q%*Q-\pdr%W@>etp(Y+?H+WbnN;JBNA)3Vh91?M<9/f7_j,B =E28rLFmb9C64o?NB1Tf]a4#GU:!(3o?;79.Ij^jkY+e7Q^4?[f:@sFiqGiP%`n/f*IHLa0CepA>VB3hJgZe32-'2hf$1) BHM#5PtgK/B'5D_/qY1=%*GQ40 `k-S D!DtVCL"a9kLRr;^Z\S5?4S4abC^_Ji.9=:kR\r=)D7H=.-1r.OZa.N"T7(U\snk_BLVsX%0AJ0_%V'jK_.e;o,A=ercfJTZRlB:js__+O%m9/`Z]`[CSU4%e<4T=F3NGa83EIc^MZtk;J[Yt=&hJ'$PTA#8 F?B]XWF(CAKpLX_Iq5FWSe5._?it'%Bh7EAbZA"95NAo;_[WE/Z/0bGIP'FkIK*/Ie&la!C\nR&'>'c'n2C(t-ZcodJ" %s04ZBVLT1OpehGq-lKmTD1(1"Ds^"^Oq(P?^66F9X\HT/&MUTcM 0OA;\<[A=d\TRPmia>:qdh@qi.IOBj]HO#"0.h%nSlXOGY[$mrSVp[Y0NICa8RL-.!ClD,90Hk^'k6a6cin/Zb!&je^@+[00bfcGFG(LY81#7tpAeR6Lb=qT_H("eb:YOiiI6hV*SF3:9iQ\d qs2h->dl6OT#PDQEbJX66i)]FtpBF -g/J^S\sl6n=G'Jr2:#B8)KM./9:S]Br[&7qh*'hl6L;"4f'[e8njR^#S@J6]4DAJST!XpW>?UcZp.d64.E#fAR#AQ"CFqY2BZc+AOK2VqA6I'YgjrfqW1rL?F[BD.fRm6+@2nsc3/liS%:$83NB]RUFI5I; M14H'Nik4^<'eaTB(=6L E*d$(CG@ >mUikAR:"3Pqd7$''eK1^GU`>aMY*;?gnmc_E_1ct+b6LWJpR_AJG$b&?iCaD.R"S7VkB*8&"h`YciIiHg_3%54DpD51IWl=V:5@t\EJ5I^8K3%8#@l85N#[C#<7]!*1MpRCS44&TfRhG_?BH 5;)CoIJsT&m9KBB;C<;WK$?9r(h$W0X5=W:_B+@W>O@dJL cU' fH,8;M!O(08I?W8S [oN8c\,Cc&'bP.;Bh&(+$P*Xq,DmW)Tt t/(Q(EtlLC:fCY&XD0d[BZO0^ht[APo#Egl^c<\Z"FUY_A!K=j8?9#/N30Kc)n78ib8?b^7cU^(fT@q:%(W-k-FdA4Q\_8r9VB]%SP]?(:>DYF2H@);(A:!2$'QhpD:B40!K.BBlUk-,W5T;#QD7=Q;k5,$:!,OF>XA/N#+ia]dUIF:!i"9tl:a]$e2=CE&KdWFBC0mA/(%d$qgD#5=e?R=S]\$M5jm)EJE4McR!Y`olVI#D%AAe[?*KXS,b":;275`hGb7QpHA5/'sqb,m@pXtWq#WC",L35mH[FD`P@mTP8-m=nQ5lOpVobKa##,I^iK=Wj8SN@^^sK(]2\<@W8oKs:<Ur8%E?i(4?H5(,5GiqX]A4:"rD*\cg!*$*(DN[2IaG:l7S+(K@%G%XGLW`5ld VRXkrEIJXk@,6RB4RBbrm%i9rYsE`]&^' $FpBbgjj8[a*F/,7*_Q0"3V"e2_&NW_Q2nM?E@(hjd1lm4O94'_6 IAJeXbp;m,!(J?H6I$k;(n]H1a*p@P:1+hdYQbTi.8>:j.H]q*N'cZ1a,a.IsC@c.rl"*q[s8K,kg:3PM?:t #s81l&,"5]]Q%N1H`D\WUS+AA!'\2;4@Xt*2b:JI2F@ERF@rem +O2.!&L#sAsZ[U]B\O$p^=;_WUPcp $-W/#_@jmh-kiq*5-LC*i>Q1)>7N;k[_jqJ!p^%sYC^*h)k tMUVh7E%P&TgZP\B_^1/SS](B=e7C3?%C=f$$?D+R-R2W)[ln`(Zn?\/k\;%j*+_;/AK9iJ Zb&Ic7UW&GU"b"*sU_@D 3Q"oHbX5;P3`UAAqF,keZ`8 "j6_fld7YUI94*YMRE*K99rnd$o78=?O>:Zh_ LpQ9F_L#^A3QCQ$Pmt8>N^W.)QBB#b/fefCTOO\/C[DbqdJN;iQc)_2K)i>tEN!t#Eo7EFcDQM*/Q$DVq73A>3q"?rs,DC^<@Xa*UNT)3eJ`p,0@eB-^MdL]-+AW?+k'TT"=*QA_6N#0QOFGW\J +CDa"d]!*[O+l[\"D)aLG*\Uqo /lpZS'`25':Se#*7@QG@>i1.@tN\l0)48QCp,Be"c7Vd8C!NOj7,,GA03+k\JAPm6'EkqMBeqlI`0o=jW2AD#Jr"eLF#K#DMXTA?)p\WG.+)@aT5$rEkal[sh#f)7D1:N@J.hLlbZ5gld*A%!]Nj+93+Mdh;e8oRR@(OQdp$:KHVG"_>S+"/0$AKK"iET>q4-g$g`'GQA#O`iA Qa AP+lgoob, QXf&Bm!5/(8N (/Ht#*%2/dPin7^G+o0+$6<8RAVppX4`\eo>*RtAe7)'dO9B[GH:)cl<Aic(Z-4gZeOn1Bf]g 9epr`)8M;m#ftY:ZEMI_8UJdaqj)q ,h\piI:L:%#+*+7o.GkgkrmKBU"`WMJ8$XMWK=hU/AR ZC4IUaT'24[l.XLM,/.K,qtV(2cf:]Y#G0O_92(ALUY:.'q79aqZ4CV%P? VF8qc#^Ss3fGdSA>8SQdK?;MTW_UK"kj2,F#_OA/objAB^k_BZ%re/blK+3Rt lrAJ#ZeACaIA(jh \(Ne]R_`BNQ>b8A\P-"/ABZ[KA38!pWd00d"FSX/]S=CB=,)FO0QioNX76k`K:9,YD5HX(arVUq_-Y0co*V)Z?h`C+Tt1o0e"@m7SVai']@hMG\*)P9M7S">c+bEkkCS>Hlot<dEmi4$KCat_n#)QhYAUUKX-ZU*4O;D=/4-OkOYdbVm)Ng S:Ia5MJ),E33_<^dHQ%j,t*#?M6SZNUT#CH<\a82m22`@NpdTH>(1[6)^ZVlAKE5i2o(s)rskb3MfU6lYlss3&96[M, .fSc`*OrF'.Y#MpkH/pde%<7m:LtYY&V)miFbqegR7Q ACrslZO^J@J*#V.H"r5m]5j.A.U7#82lN*]3'4mC2fQ]*n*`M>JZYCoAr6m[s7=V9Jfb3U3o77(9XYT;A!MY>ke"ni<TYVJ$6k.#. PMphNC_J*bi:DS"BTb[CZc92qjomnC;Xd*iHA3@F*C^Yp?Fa6>S2[0 r*ch2+bA U@j\VAZrA<6[4b08g*:-c&ke ?fU9+5$ bkkDB#9?FP_C5aTLiHaY%D7#empaDa4W%`KV$<"tD,H>GSLPNO'TEj./\m,jt6TWP:*hT'eP[?V]-Sr_AbFZhABkt1n?t0*Es"WQI1i',F#/=?Cd<.?!LhStaQbW0,1DS"<A:Y]5rIq'R<[j<!tYP8^mf=,n[J"]>V<@dCam7\A-[<&3qo:RSSHB8\8qVEAlG8n#$fbnV$5RHEtbDJ-6QA%J,OQ47n@#mO1'2Xt)>_^ocfoAT>Q`>GkdZ$$aM-Y"6acopBLJI!N`qA96bBoap9c5FR&(T;as,B9.D)"6n6A#-Ikf8YJML?$N?eT@_]@Y!R*B!J&`0!P#IW6I`eUO>qm-NA/W#hJjN!M\>=%iXX)Ik6;G`Rl.BJF7b4+Sd7;q-Etb0Smtp`7/02B^]@7>GHJn9XdWE1LL'bon0j)f7=9-I9'5gi)-RHhV?Y+gWL .W2*XAT-qg6VW,)3>(86YA\cIc6%s(/M8FM`/3>#akaIC>"I__#?ls`7PJ*Q@RZK/.-%%9toT/m/V'"YQaV1kf-Pg+$;\*grK1KD2aQM1tLp`T -V+qXm%=$@/%'k(!f?'HY"9")?KZ]<13,lPL A.CXOJN_h5$m`%a[S)fi,2j"C(aAsK#?db:m2EG\ Bhq>Yn:VVQB`VMLIK'P&n$- Scm&j=ilONY6qSNS?@j)'s,(K;K%\1m\A$Y'GHCPG_sJ U?+S`cXCrDAM0_jq3.q#R/FMf2JekA0bWY%UPQF>E3g&TmJZPY1 8bj\Gj^`q@#!DMA+`1rhm:]n!D!V#.\kA485=ACZNRP]m"]fhcJA.@&14C25=Iq]FdO7+XWe+ )S*qre%GN[ 9=$t8,g! $l.1$[MO+FUXqq8o$[dpAA()4[8^> 5p-9i]L(Y=g:M%.EM:nCF6[O&"B4;MQQq;\E@t'/1,NZ>:iXc6 *QXIbbUMA"[jV`iAVA4i%HCStaApU?fs(_(&c-`?C6W(TD:QAABR;-=p1VhDKoQC=Gj_DQg@j?;_"Vm,8Bk#OZG8sCYkii2AHa7'-Eet/>Z`(hFCN ]Sa';LE>#qn5:!a#-WGAQt!r'BAFI:B'r>6nqngBVHlNK5Zf>9VQ9o\*Xi(1t4lJT p#YQ]1c37h`mP-8J ?qRg['1UY2!KB./E,`BP#Ca-RNbR5+#o,npPUNdCp]@0Yk\D1*X/+cog&LS9?O12P-:.9gk`)K#=SWI0]RV\Hi]-b\^N&F;tUQWBTY3"[94O!8mc`?__6,[ATkf-X"-h?Qs1hs\1&AP:d9R\!Q]Ul&r-NgC;&D'_ gdX%j hX[hk:p6khM#7'8s'/AfS1.;FFji7):shg-1?LcP\*0cVT^/g.4WU45eMOms'FX8+ihJ!\ip/>)Frb$pXtIYY;U.]q`XC8'->lm2?0l/_9d$1R#Q "MCPLgc9t M/hASnmMmK[nMXJ5-Usj5^I?Ut$1:O@FYsRm*V<@2W8EhOA,g_Cto"2b#p_"m[_^`Yr%O?g);KE,/C4+\;drM)$*$UZ)7_.:DCA+k2eAk!sB5[I@5m$Or_+:#^`M#L%Mlj&P$XtBA1Z>4S[rf) o;'?;E>+$k38#JNNke[RO*!XBKMq$RaMB%a#]FgtKLWndl3d"OF;/OTY'2a56Q.TpOnBT'c#52Po"N jpRV YaZd6\4/R0E/ZY8@G*epS7ja&_M4W&OI=UjQFmR:]kma"f_3CrNdepp6O_-k&+Vg4-A)H/d,@ZZ;41X]XB`;3))Af12R8d%nqj"9g"%XJiKUWM3'l`:-9<(cc8/OAUK,G[f^iOMoI>t.At&n[(+Q0@pq; l4ket*a10XhApT`(0H@Mtp:UP=5M<$SJFm%r!/J+2h4?:e36P[]54Ajm^#+*R*=eW19S[$&(psdMZqX.P5:'G5'@\-&NEk+(Ptk/t;b7O"'H<+Mg4*Kh7(c!nZNQ=;i_)3iE:gDgIl;a^f/l/Z!7j$;p16Z4rqp5]88j[[>1\?psffh;Yq6DBt7joW#+T0E$b:i]L?&"LR7`(N1cS^a57>O-!LOG^M'bH3VqY];-:dCetc4UIM`ciab,_Ek18dYU"g';'"HKbF ;>fLTPi7@sQ-&er``/-X5C/A.G%q:e/I(I]dWTV/BAj\HjVtZ>aO,gi#o=(;1D%tds3@\T;ZDC^qLV:Wl[N9i'=VWD!j9P0hBZmE>1dDqS][[ABO)H(%E:'R][551":,UD$*U^`lU&9WD=@eD!]R74X#qo']*FEO3tkId2eEb"=cea?@04l ME%QZ7oji'B/l`r+.F>9@/c@dh:W]E9T?e2S?W"i>l/F;f9jF9/do%]S1-9Y:sn[8B.!ss^bHB7[9>TQt_n7W]2f&IK3KZBLAR5M`-:SQG=Nm!^2O=oXjQmN**Bbg82=,?%1 ZRb;4:-tt1RM5T`%)5X6Yd'3`0c"UT$-$$ ipE;cs9ng;KA&- 2 p\0#/YI/D2S=p7qF%W8kD9.T&E>4[d_;s=(*H>p,ReVWnLW-U)X!.A.pI'=Zf*SapAW5/$+fak%QqgRL`_U"CA!@LAAfjE-Cj>A,`<?m+,,W3XOVQr[kTQHY>@1$PE:LSf!'FjLjR;;g%j?P0?LiC!fU[AY>TQnp6[*!Pf60],b_%DI/%`CqMgDp[?3;P`M#8U2BRAm_^PQ_8,cFB!O8*ng9o#^::F^AU_JTUH(IiNs3]a9V;01;<7Bf-WaN`)F^"Be0RQ7LX)oAFlTL9krLkY`V;_8qOj>k#1;Qg=@sNr)I&/gAgX lVbhF.FCEGo2ChEgGH0:&@TBik&Tb7[``d7T>L7-_%:Xf2n.ldtlj>@Bd= j&N[s[R@5cQA*o^WAB:%A=kbN?pS14eFM#Y3Ls[b](spXdn>7[1"(8XY91\g"8jdkQ_)P[FE`O9A?,!ZGs&l8>%1%6EMTA_qEqsEZcH!ic:.=[IP^7/q0"JXId2 8Hs+2AtK5l5ZW^%h8([?A38LIPT`PAshLUs,''dC.6i0j^l.'U%9Z!"YEal*$6s2(N$nM21&T')KNc];JP,K1AZ&HgQ5g0i;@Alof@02jOWXa(mdOktRImheaBTF"+_G9S$6RSn';FoDmm?QeSKHkA7.DfA]b.Fi1k1LBMXk'>K&Al..qA1daLmIQAgD =bl(WW rKQ^kg!0_HL08,_&coL3"L)8Zp(cm;K#J5-)#V*._78W_AR($ZKHP4-:fPm0@/k1!8^[BXSoQD!o:Yrn2"2T^"Jb9s=UDLX5W@Nr@'SmXd'1c'VspfP#7b4@btdUBJN3!^Ye@n\;)Sf#HeATK9mrVQ;='!-::"IJk[^1n2Akm>Gi,e,aIAZ783dI&Ns93`,i)Ml@%l^Z J-sqj"b*a$$9Wj?h)>a6(0a4@^a`NoF>EA2Z"%6O@'9%.2PaXIDk-MB^h`RTrFG"Ki-]4k,[2kB63/da"r,g)*cH;HC-daTZ_,Bk] W:? ?`,e2`=TCLJ@knRUkoM*i`_Ah9PKTTIatn#:pp0;T_kfn+$c?Mq\S$_^Yj/?fOK^&Q$-94\0iF%'8D/C*3@@XfcGZ;K]E*)T%llg]b^SLSt Vrdt4)Q>?k0SQQ6:Xeg@pm0]1>,TnkC s&LKP5n:EHp2")g='d@s)2;-Y(Ud!A-'AE4R dVZL>MT)q4<'9Ymfs*9?Q`d)b2H]Om:]r+Kn`gt"_>:)t7!GA;&6'h'-.\lr'erd(b?#9?9Yk?T%;AXE?=09Y[DSUh4)8HltINi0J#b]Bdt"k,Fb ]NBR2/8_AtKDN06M,(Q*0IVE:pG[%)2l@A`(R$%8frtGF^i!6c*[)*Mc%?+6q[0@Zq=V^]`#/U&BT_'6FD*mS,AHh["]`N(QVo'7Z-f,1_^s&)nG!,A4j53m`k,%Yl0i]A2S6"DHDUN_,kR.66#dN];A$\_ggOGpVsS"p9]cN)rL#C511GK*j9H(K(0dqSJ]Gdb5A!Gmn+hFB2]jA>'@8iscCUTqIJ@^Sk-GT'pR9<P_Wql2^,(O&'An3QidAhi-0VS=^@dbe%;!On(OYba(j[*dJ>5b16&<;>3DZ2G L0,]6V$0)Q(fK9o6g&439WHT?C/W&Mkc&&&7g2V/Kq"_LqJeGEJA,U%Z`^$eT reZ34p^FaPAKF>]3RJZ_,)>=r\E1 I-K)$b+ -@[&ZT,mc0b;C4A@T3,]Q97>AC% ZHN b"f8D *a(! YCXb+^Q8j4V6+*:<]j+De"ZeR(fL(/@Njn5'&JG`?@f.$AL%Ht-:iLUCa*hl17k([ZY\MB kDRh#JS]J.jt@S?LBh0SVG`AN.?!gqAH,4DjnOmK&iG#[P2X"H!fb(35A[cr$HLcY`cp^Sd_7N[]@o2i9,N9Z7:STafZ@E>,"oXL>W""!IsW`n'9%>O9 .]!-O``>qCK02AHnPOAYDK:f][ZX;^E.mF-#JpSNM45q;7Npc;JsgQVtD@dnT9n,SN4Z_8V3ML .Bd1brK:0]9[-'!?gqOl^$g9#he@F/#0AFi44-GFOmX;1Y:ot=40rm%G)rZAp*;A#$]bXcR)FL.ot!/ HGcOY6eboK>T;c`Q@YZ2)E95k0(Q]Qk2mG!lA;3=?"f+s>Z9gOJe:`%EA]IsP^bL%a0'Qns/V/oqN*X\A*SWV1 7H.;U)V,f?6l26J)'r9%S8DHKYBSA'6>d#Y5bHErPHIH)h ; dcmLG9=WNP^dV2+N;./c>/.'Yg,G!Z ^"c6S3H+AJWf =i\^@CX$IFJnC(,AkAGfY;jttXd;0K+,#j 74DomGDbk'5OeaYs;*0R0b]$N4L+#f"s?8$`t9;OG%Ya@kQfAANhdLr=qRH:2e"T)/b`Bjg(gD( 6Pc+^[&VdH@`B>"qJ8NAa]8A@t%qd>[l]RHQ]pZp2\In6]5?]l%j`&A)5r2IQM:;Y9rN+PP*lL`ZCP_@tq:r%T?B_$39l r\hehLm38iF,_7?jQ"=.\Hs^+nEs0Jp3[d.3mjc1]OH#`oM#1ikiAL`]8p&>Y>.AKBB4KGA2r%(Z0K1\QW7!X- =.BLhN=d3as/*B^#MY7W>5hH,55H1,tMY9]Cs?H4/6da 2JSJa/t.(Ms+LPPirD0MXP0!NF6 =`!+`A`RfU,&d3Q+lK`,e)6$IcpA]r0mMfncKc[1WetLAXiV7]U0AHB3/"nBr'kYZU_/3:joQ-*(OE.2,@L`K cM;WT3sF>(s3=-i`o!-XdtHROf@RQKdIh<+\b,GY!d$r.8ho5%KDtFok?`?bP6:T+D?(qj_=htP0r*[6B'WEt"m',f^<\`noMW!_e!c3Gq")i?spm/#Yp BAQ2jmc9G "]FA`L@8h2aSZ9X!Ym`fKQg%ViTALaF&-3%q/BE(s/%`A7q_lf8DJrfgT,'o_(dKBR7j=o'G2Y6"O`<-OCWTGRV/=f8HPB:d_/tg)@'" DjV?mI%[4fE^MtHE8eeH"h2pS./3#@Rt0%T"-"X'aLPgmk&1WC7^$e,Sq%Zm;%.+=c)2MMg2@k1JfBNFJO20-$D=@abC+kKf5`\-g9L:tll4(mq\6X9jH(?dUVK#t>9J]H0?EtAO&:BW_pV(mCX1qoP1&ArT[oU_NWphc14NNs60UO9]gbTH` >n!IH%IO*(FaeHm-ePb(>t'beip%>6(FHP-)+JGN`C>D4ffmfcYsWcmJXBpOVON4``0Q SHQG?@!cW/hoZ ']MH'^0T!5"(i)h]Y\(9FTfJV:4Q&ac[Z*f:,@(pL'T@0:ooO73t*S.S R?@3gc+=bcCM%M[$P:K<;o$J='rX9Sr h(fI^fR\'E/#][^@Y$OZBe;-88NUnS._L,N\$5cs atk#T3A$ffIU;''(A$%rrsBGD;)f.Ar(>3/\BQr\Tp@LX^_71-\)@q"5U+dG\m45Z[RWI,RY]=UE=nSh4\4*(F4K?&Y-XSFAP-irK]<">lYQ-?o.j_N5>#L:^aaA?%Vn8VQ3'@m*sF#2Cr^CNV!f"S_WMCICaMih:_?p]%MLTPB6C3o^&L!<13?gm_qY)o9;2hGRSJoD;Dt-#Yn#e;<1=OL7LD74Srmp5&UAq(t2;"bQ/\5n.@$kZ5VR*(Pd -Uq%T`9j[S4J@*g14fA-LLted[D.m7f?"#0olA3Q8%m4KIoI("&Ks,.d@5.m%7S.D*M"XSC<iUQRKUHa%e%8LWNS#]I6]](9""8pJL'd'ba\l%9Rcq%n^hZ6'=pF7^rYsoBnGcg_T+MFV<k0-h'*YjT[-#DfD/L`6gqp<4M^M?<`Dt9NU^!=UXV*Y7'P=jA.:-^ _hP5oYKAgO/-VA];+43=cTaOg"(G`@$6M-J*C2.jPo9)Z%IOq7K'5",U#XK(WTc:D*s0oSK%(pEl.Do3Qof+P9A"Gs &o-20FR_;G3Ab:KV!q>'JBX,2'^>->L`,,8odNI"\<&PEk%E99kZB'#\R:.bgbgUj5**>=NE ok7F-:0.&DXk1Y_h(3SI4ki"GTe@%(rc=t4>jk#o!@rTC97+bJtVnc^[*tVpW*6NIZC* ;kAf*))ghWh+T`47Y^6h?s<P*0ds(h*"8Cd$ ()W&_95S)U9>t\MZHTgTBZ01;3;TQIMbjC\PA]r0$D8Oj3>n=O ?N\)E e>a@\+AS77?%N1K[qjLVAgob#IUGIFa8lQ%tCBIYXCjf?iH.5]j5+*!k&DsG_E_H+Z"(PJ$+l'PRmA XO>5BpmN(MqiNP*A,@?9Wi44tbi4'0'W55LNmM2AZfU;DGU^l,g-XENS,rh"ZU$E3\=S&DAEm9r;iK^N-]cF?I>n*ZLbA`2<5[7KBDLZlA1r1%ls9R;oNZJ.9R,]eQCnhBnF)bUL&L.?RYSbFONNqAka]OVF*#biD75m(&]@k6d5%dNiCs#NN=e\=^itmKL*UX )q\j=hb'J=.s`QV2hFD1K r(oZ(lmdXR7kK9`j?MN7,ghZ`r0N:_>A Z#kS(V*C Y7bAeYGTpK%;tl6P!>Q1W!SKT\FS8hq4MV*:leK^H;N>pFkI0)F9K7MZ1Jpi8Mp2T\_(sjO!b-Eq2r1:[4%3V%gC)pmecS,cs0GP(/(l?X260AgGL9:&)hbAUX0q7Wl!Vk9$D3.X8#,COLJ^a"B.KbmT.*%eJLl'HM'i81@)>>qfq"HJ4IZ*e[&CF_FgnM]WT%;Y.H2br/ir>G-]="3TJ]/Z9&1i5a_DArr$d6ST?+ 606gF.trN;AQg?2TXfUmfNE0P*Tt&AGpK"*,,]\k':dVcTY:GPXXW=6\cf>C$F@-KJ$B6n2ZR6U tYkl-'1D\A<l=2E9TBINsjp1(&tsc>Z $"%O+e(QUcGiXAO8JtZ8 !K-O]NEbc&R*G)_:D^nfU7p->OA(Td05*?\`A#D1&$Z,L7 3Qh9i)b=L737;!*a8$%j?Snd3\tr>gd\5tXUWs$!aB*-67+&l*TL/`G;c:^\L j=pV5:[,pE`tKNIm:"r%`b&^61IJ)$2Af86;=AFkQ'4H<`L/S'X.3[?VXa7@WiOQl'oV?Eg"j;m4Zj@$][-.4Ak+3DqADc8+<9rZ+h/%:6+OQ=4-(^Om*s"6hnAW_3tb=?H5>"f5k$bD]a1ULOWdf7I$/j6YeaFq+5rrJXWkAGL!;Cq.P&KD@IJR1 ah[nI- kM"l5=bj 3O4F%P8s\M4T:#aZB 0"dgA.V3*9L[n s>F+RW35/TO<.5iX!P;X@OVeZC=p&]LO1P!aGRn\!MiYF>n`ORkFbOenKAD!FKg.RNAl2jiE t;,;,i#k]n;SD$c+1b9'j471C!/0I RFm?:h,Ac_Pl8orLp4&A@oUX65JFZ7,;?$ZF$c)!Li9Lh/bLr]gCRKA#U)ZiE>g?jIrAR-d^Jom7ON9Y?^kaokCpR'QhF8M86-4g<TF8\clNT =K?Y',qiqE&3F4,T VU8f`K57\j@!sO(Lbrm$c`GYK%Q$fn0P/,telXc->@[Bn!UB+l')=]A54'PjY3$-4870FO^0+/8_BDHd.2^4.`(/I.dOY98T0NA>)t^h;5*:+KJ-6#@`=B/t@hHR#p^m&k!;4K9B^4FMr &70R(ErANQ^7U 7E123;pZtT+72f69F>4;HDg`kAg<Pp0IBJU1]+cpM9Pl,Ae8X5Fo[Z9[r(hEd(>hLH@: slgm+_4Q@. =qXge<."NP!0A5]frD]s%/;TTUDfZ]*\p\c"HW$=&-#,MA_VE".&+o%3*P+O?E$oE>2o/&R.ce-ST6kE<U.G^PPZG#;,8:E?b<`3QWMa>!X6NOT5CtIc9D9\h&YbD%0WAPh@#3KK;UgB'XOp0SP9/6T"mA`>CaBeebX4eCKBWtOc"'HjS6[.*YMZ5'm'R)_88g?P.cEnRBb+C7q>Q@TVX]a-DfE,;Z4n[0ZV:TGQF4>cc\IeJAlhNJ3`m4A.4;fOtMI]E/1C,%>UrO,spXDX^7pZe/B5@='S7ChLD1DiY]U6"VJ3"pUPJC!`A"2Whb4]c:.]4B3"#O+Z*4*%aJ8BkP+7E/jDcH!naD+iDmS`3QS%OBM>Q'cZAaZ!a#Hh?A(=H%k!;]/:AnH5o&JrV8.sZ%c=S0)oA-lG[4_Y2TT/KW@:^gtt$eq?q]R?)ZEC`Y!^O&/k,I?A3:]<`2:As186Y0PPBfDm34gtctp$8@F;BVd(,4h4[QAY-tH!TA*nY []?mQMIe^R"jrNMqs*?KF$q*00tT.l7t0M9;S>]MOf=]62.RG`arrBH.`(ZP5&3POn%=,aSEW >Cb&Zq51r/^MqQeX!a4U`H2]$$4OhKag8jdpk-JALjcp8M^J7*ga7J0!jTBPa AfR1_1aD"4@CUe9) k#T(*3WG?j2%-m8$3>.A02XQ$(P3>IC7AL:kO$7kJ'pdWi]A-)tlA&3 9dh@ L-!oa0r%7fg4i<\TejfAKt?FVHV9b&3Kc;fmBi`TF9f'\Sqo-J%`F8,;-&i3=B+F+>qWglV;!\T52SeM0X^D7nYjm<@1i4]j/X2Sj[L[5-8]r*^h2_Ega6##!9Jpr`a%>+1RDg/9"G"@><97=!nW>cg,r=HP2j:8Z%bM,3)&^R+=dqhRmLgL*p%Qd4cDnTJA_\kT@E=_^t<3 TbBON/N4p+ohs=)8d0AT&[[GU6rQ)U=@AS3!O.:ae%$^a:eF$E-B*)NC+I]RMb(OP:DcGh$/kmKC^Fa*(aQUa%aIhe@fTj`SO3p2hf^cXp],Pr+?^N?qi7.+PdZ.Mc7gKP".^,^M^>)Tkg,15F*OZebWqLVtmjP_'tX "dJgUs^=('a99?t%3is^Xc=b?$+R.TVfX7LQ_4ZsSs* V<E%#6d69WI>:bQRrr<="DSFR;h[*=Aj4j:3:3:&n$LA'="tGLIqr>Ho4k0[/k;$_abW0=ne4`NlXo1!VN.sA'5'eZ&;%9kq)#s!IAfo(KD+?ds*nYSVcOrhn%PFM%hQ*Zh&ArDNHq3p7TS&Ans>Z:;@:a3:8-T#rQfUdad/nX&B/1%4SK\2H[]k(42sTnPa-om6ofNB52NMl('Wf\R;G!h^WjmtRS%`R's ?A^KUf<>E)aHs)mUo/U_-,1A(MS]C,0,3Hkk6QKWYOCBhMp"o.T/mi]3Xd8e9%296>X3>Kd):Fr41"T::Fg&<ht[WAFrshW4"bL+TmSsj."XRSW9gV:hBk&/'c.K_&G8tf.$o(W^'EjdR=m>k#S'JBX4p`d+5[V'T!rHTV!fbSRST$kr8^*s_4,n_HRXCOUb:Qh<:f.^A*6T@nb!eiPa$77Q;:-2lE=FC9"Qg<9>8API'1:-B=\_X=)8'UrRgU"'4>V7Jr9k+lPGT*tZ((i.OfYj_N\PPQHXA23G5pC6NgFAYJs0#+'Ha`1hVf/>td- ]8T[c:qm^IkKp1*!c1)m1lYmKj@V"GcI?^ss;ZJAk%SnNfbPPI^>t:Bh-BaWK.l>W!ChHrtKEZ>ee_\MC^\C6]<:C$]Aa=PnMq(l%LsV`b&A/?iCoX;oXsj2Eh-NEX_'"$p`1SsA+Y;@/U3R"4TmTtRS1PX2-N(p(tE%E[!f54H X:=RX]04.tMH>kd"_qmXao4"PhQN [)2E3X5^KFGUs^*6nbXPPB>`*m_X"bPRr_j09<9&MUXsHee&m=pR[d4; GIhr[^A-m5:MN 0BfKb"V.72m`$R[rbZAk)o r%KqQXP;kG6AS9oUk`rt#i\T4@'EhXWqDk)s2%VVKYrf]>lZf;4CrH&LMT-4_(AX"amL?UeerlB:f&+"ko?:K e4m2!=LI55i;jg,-;NXPU3gAhbO_7Ga$,1FG<)lKK27]2468]I9NKi>c"&B4E%Ga!qWcc>A0Rl\EtN!dkfkBM@.+dS^`+nEAiaE jP^7"k5do[g*R"eZ!NM1_oeq+?E95+SRZbZW#mq/-p#jL65sA[TfB+V_+8YpG%CjS/R=eX]F@hf-H8cARJP-s2/A'A[s%+% _d_roE_7!J] qm>F1&7,=@0c%0o6NGP%BA*Fc9@jmKL_"Y9PSG"'FJs#Ki+T'cSb2 8ZA?:kYUQ[UTY_Cl)%9.'YjB c%[-c0/h!S>fOFV`7pFcXEo$/.k^JA:XAPqg@\ ?tl A(;C,llcO%HbKGJiM7);(PK#*6"df'QK@7>%_ils n(J=\(=2mLPK4#@.k_RRKX8qAeoR%-'4(#cF!Aa9^kiF8gInAM@1J#cHN)D]eUSh%.U=4K#<:R;]ApDS!N/UAA[@KPPQG?j'-5HoMK"a"P+=6E\#a)\/'$XH:f9AK6lAPk=HH6)&a=,[L\[00iK8Jbgj-lqA2jX#fp^Vn+D"'fWg%pGM0L;eLW-]]k5a/fhh,#7`75hhR/a*L0;3pQ7P8$+le8YQ0$lGoObrc=N@fA`_m`^S-C-:e"!/GZ@"g2;(+*7AJ*K8E''4_Bh(K0;,)3, g't>enZq/"VbTGnJ.r`9Zm\P@MV2Pg6b82'$X5%C*ccs,o8>G'2Vnmrf%7- Y<^>TL#be(V*ALae<3r30r\^=a#^o!OA"@F9=CAgO^nUC+*_%b:VZ<0ka>XB#,t;4]S'Lf[3j)7,Yl=TrK KmJ1@%QebB.J7 ^F=g)"QP,LH>45bAF*l @Jh!ObUpj;;eH](mN#gAiYNW5VrcfCc6GV*aGnPh'S@0@0;K\it@r`lsn`hWXa!mQ"Km gtp-:^;>O-4kHE`*MrSq)F^0RI<8mBbo$=0e%;)YT&2+?(!jjaT=2Qh+nr=#078':9DA9m7 jH3gh5YM\]XBls%gibpM;bm(T)ResJ$LGs;W`!GNs7R387UL3@CoMX^,BaUT-Xaj'6$,30i/VlT08Ftl^R M>`ltK`/?.N,MLGN]?T:<Hl):)U/dG@X:Ap'k16(AM-KPd3]KQ%/=eGFLi`UUr\:?>A+JMa=C^?&(5GchU!AG]GlO<`(qinQg/2t7;E[Q4>8^(A[>$MNj4=/K;S53Kj1_[(7%aL$.t^XltDja#<0,.#b0lYG%$9SAALMIcSoa7Gl:`G#W)4\mH5"MH+WL7FF0EtR6K'.^0Qbbb6pkdB>]6/Fk#`MPG5BC,V6BfQA`gpEEs(*M?rl>-RI"'b=jEAtl9J5Fhr,BS?EN5#83F<").-s^i<G(pF/=BbrD.o;hgGmbSC"0Yog9B8i,??ddI#/FD(WZkI^?(G6,$2[nE?QF+THAUsc*SRE2QaA;Z&'d5QFW/F/K*HB]%VeNK6_'XQ>">GXVQC] 0cAL$p01/sK\ !gR23"/_nA g5\"'Q,(mW@hMd`;-S^A\d_d=PP2AP'VC48n=&[(jA\Y0DRiID>6$hAN@ M9=;=Do7=MipjH\DMefN/7Yt/h/e]AZr'6XQhPVL5b/.?Y;S6h-cMK`-Znal'^>.E>BSW"<*!)h]TgMVSBeV<-0X&olt*fk^3T1otA@N>Gb,Hm*"MY/%e5[j6g5PFUo+.qO$i_1=s8mf]I4dRSW:4da'CG%"H@m$<_cC>*#@V\k<CUit>TW6+6i1&Fqa5Kmd0LQH7[EV``MZnlDDoTjQfU[eXQ3RN=SF+pVc5o1Q:EH4gojn2$Eo&Mf3D._j(`fcM;'gQI>6Ec&qO%55jKt^'5AF=]$a".(A_Q(p_KhMeD(mJ2H)=gm$L"`ED1hb.FY`kR2>FcS6Wl4(7*=F9l,4`TKEB=(5Rr5"P ?h4$f.@p"gQO[C>n(gPR&l>gU/I;.PU1dF4DO?%^m?AM,aUCGaP@8_>ABJ>/jW)m4,'jUWTFga=LA9A6GnIr[*r9NDRPd,8\S%JV:b?8J"Af8(tf*6LS3^`_sh86/FZD0h'.OXjmoOOipn_5@6EhHgg3Em/k9Z>C< jP;[EN4iLRPa$\="`RLH/7NS?OA /kCX/:Kl6A[qZUrl]dgBfYB^WjFj[Ho&`9:s8a8ik/ ]d-=[6F[*>30 )c0"JQ&!n1pde8*2Ug?0"E>S_1+lL,eV_>16D%8iWW%?^\cbNC?hQ/mNla l;fbt_!NqG!!2rO\=pH  fs`.=XdqGr!AA)H7H0lsAhj;O[I*F^[T"Nj <,8'1F?U\': ;JB=E @L0B&&4E>k^=oC;(ARWB>RME.iU,nrF G_U-IM!MjZC:5h4?tfT_GFe??DS07>U0RJ(r6&RtPR]GSi ` L!aebX\<#;-L9ZbAR3f\cs0aXj=/I(57(P27:)?i,%[9WC##2I@l/MNB Tq4g^@PX"f1R3`)c(G?AWG9]UUE\G9&s&05dOAJt"nmF7I0rTe\U"eUm;H&]Nb*J ;k2?fLYAetX7.FH;qhPO34e;dq?_6 4W\pQ[-b0]q]f@8rSkAhb,[0)N3t\CM$%I]T@J&1McJ*QQbK_%:tH`2AAGo/nAN_Jms5N<P>f2Y0Qs3k`<9p5Lm/C1[N#OGK?42e(7Zg>J%"jT"LE]pJ&fMAA,Up+Jogd#?A+HI[8m75=C5/g.SpQC3bkVMlA-ne\9Z%^Mb:G_*P>s9*?l'NU_OTLIQ3lgp$`T-AhF?Q8W,]t;j?m^1"C0%L`]9l`WA%A?AEhEqagE]l*c6;AK7HBsZ!O ]!BSebksPB,p7T@Q>5CIsRh[:1Z-*(g,s\I8o;ZFbE[R)QO>&.1fXW;XUG#7,ibDMQh$QA#,cO\pa&G]c*"2!rZ//k0Z':#"mt&!)[(./8VSA\X8%teD@itpI6 8lQ/1^_]a cKtH6o%*C=AOC*G+Zh,7K,);9iVc?bm:VAHT?/_*U\mAfAm)oGOA2q!6!QJi4"`hsjR36p4K+LA'pt[J;1tEZTs!h\V>G<,pVpA0B0"D&ckk,QCRX]K2]*BU>8![4U:o7K#F3$H4mI"t?r=%3rj7_I._+CBYa]V_"% n%9cN\)+FH2^cl3mE\=`)OLeEKs0AFIFBlGtd> kT`s4Ql9A@m54)'DpL5J:Qc3:gK/`>1AfWHcA(+6e>P&]9'/0U`(NpFd)A$MIFPM'ansaARG*TH$dHp@@j$&T+]A75M7)+gbBDI]ACmr"E8kDqA$JqXpEtH3Va?QOY&!A_=/=7p.&cG5_K8Z?+H$rdV5p?3ATY+.ea+k[8-Q;]!V2\AAc5g24:,^MW?hc= 7tAeqM='\hjSp.?p:O2BF8$TkH>#=6:Ddd9,RDqm61SIQ(+_d4">YB9et:P[4s>6>ZYeL*E415.\=PJ;eWJ+kJ3':`s^H,/7:iY1=Ek5UK^8CnXV[@^ dEACT^^;0^H\GUFTa@oRb-LEcKo33\Zl]0*`lWW4:"SbaDkO5)"+3X_,_!J5c*Qfb%X#Va^6oV_/V^[%IVlYI>r)@,*D%dY;U+B[`\L&J/XBhMg9CrTl7FrJBJ_$sE**8i2ae:E68aGQVX+Om^q\GM6q2F[m[[B6'h"lQ.Xejf,5`H%[Rh Dhg59IPkQg[@UG6l->.YJ0PchkF.jU69ia*L]NBA^MLliPJO*UI&AZNDf%qX?5UXW_1:AOFkC$I$Q6/"RMZ?' K;#b[7IZA:;)'mn9oAc'1"'QM?#!IfT!tq+<\A-51sS^s97deem-.JT]q)7S`(N]6,,j#8G8TCC/M6'tjhLIs!N?7k`F5jsXQ/^YV<1l,#![c`mT6F',B4 ZRb:=m>!Fq;jfLX:;9%tQI]&NDA7U1a8k=)"AY5I-tPH#$tCOEC,->'se."W%R"\hAiVcnMr[[;,RP8#+g;.1TYIEK`&NRt^MoF7f+?>8`k 4Vckq,7.AJ*%U5nZ&1<8B6d 7U#aK^NeRQbBDWDhSD!?q ;AH0#[b/M$0Stjd?p[*rM-PR8I=rT,U(/E;gP/\@Q$ZO.ec:)bfK^189OANN'iYO=PEe!99Gek=2BAq\ctHAfK"A9B/Qr#"=YSY$N$;OE"Q*Hs<;N_OkJ>U:(BSS[NALge&RO5^]XqCJqGoq5MX)b,eBV,6i]Q)a.GcMpK#E8ZEALQj`VT"nA_VCjINfki8V1#KOMYVs@6*$nt". s^KA(4B-A%>H]`[Z732#CRNFEZX0*XmWcr`V$/#DNc(a. N 9NY&-i!D&]ET:/pB1AFsBQZ0>.U!7f4pAn_rgO8VDWY7ThT)H&3C5:T%@AqIK50Bn2:f' oG]8^$Q7VQ^N=TQPrEm)^IIbDB\oA;AXk&F;*rPl=CM6-5fB(ZJ>#l[+(=0[HXjC='iaOHfO"^BFjN7YB'o[,p:Ei%HM7&kZp9"403BHU#?GPN m+r\2j`,T*XL-*d LabS7 Ke. AtPe+9h5A:rBbLDU&MYk,Qg.V;l30V@jM(ZsZ1.Ic2A[oYE/Hl`8'1s.AOC$* 0q(^1At6LA.7Pb1*'ElHDN"CZknM&pK@+MG;2r8SCWF3g'YRb"!CcY!+$rc]Fs3W,jO'dFE_7Bs;W2`SK&qLYo=?N<A%<VD!nAo[Hj?bAf_A*Af*PpIfE4Qo*9RH)RKTI-gdD6/Rl:G&gGG.\t"DeGGm`.7oJ?#?3>8q8<`CE$>p0h0pk&E8!17`N7?XmSEZ4jA[5]&99$PaNUH(-biCJc.IGrEP*0"Y;J%/Vm*A`mmT2KN)iS%BG 64Qk?@P/a-Oa6f5@0W4*I>"eM`q>X)_-L[\mmm9Zqbd+#rYi&%@\doT:s^nMTa5]].d?< _,r"D(E5HYdk4GdYYbN]h%QZDi7]oc+l&b`Ld>o;]40]V"V.FtPF`(E`nE.]c)=NfAN0<&+cRhi?>[e1/i9m4=RM&<;GW:VYO,$8gb.M;4>_7<+DM+.9/C_[F`DC8iQ@p;:ji-n94iBF-D8o'pO%9%ANb>4($nEgT@k2bGKXUNp=V"Y!ZKfPr3BjT&cOLLA!/Ne`o^+W02Hl3J]_9q)AEqE)MdYf;1tQoA#N`jb"*A2FiY!-E#Y(OArJI+8?#$?Jre6gmP=R#bc>m"/[U0N+l# k.5IN%FrnJ`qIerjU(:D/\ZF5l4`3qYppHj?q9A9M rVrM5M!ng9>Z .$^2Fs Y:tr/AgR_]^6^FRi+8#kss[PBAcW#KGe@m8?PVRq1A#nkFNiT`_QfJtM'M-sBDdDS*D9b57SBX/e4hR+b45<5<+X6i22k3LP`.X1:gOVH>#mjAcq-jU&f$30$II3Jpl76qKf42O7t,s_%NRVQhmQ2Zfh/?bX!S+f6:A2O1OLM4-o+KJrA1d>2B*\F@o2g25^LYfP>r,!gB.DbCs>dfAn?p:LZ2V2o+&$XaGhB&MBZhZUH)oXgD6:pn*(0j6K=rH;6??\Qn7Qd-XmqlA.$YE]`54cOA3(["9-*\#t&jd,6eaDA6"D,\2D8"mCM9$S*!YB8A! \<1P9MVXgVjp$V*ELGEY*>2%EXTrDO]^.9m:mmh^nV#,o5)$2.!["@N5PF`:(ljL[^ES^"1V5g,*%\UfYJAlssgLlT-+b%kqJ hifHUKKTc1`hB&3@Xf/Sj;((5HM%j hd-i>k\4(d\@8t1gY!Q2SF>t*O&Z[?QYdoI_K%NG3"-dLTco&-,A\LY9s8SX(K_S86Q[I E0*;!HU-)Nr* d1Dhll_G_O[c6^"3U_6^`O#]8.6lF[1AZ=8&lF-TSp9N^9Cm'rR_dfblH%KZlFl!Q1ZM]`oBi*YA>"dJSO2AU[5/R+`-QI+cl(08btkfVY^$)TL'7W`#,[*Xg%.=sgDW:D-$!97NarD.k"Ya@XWOA:Bjb<B%6I4p7cb6q(*D]0+\Fk%g-2Jfif1pkcs(!ahc.+EQE_e"?=H<`[Tk<ts^=K4bX;5lMB.D%jIGc6AHBc\gUP#:f!89g-%ato` h>TT;Ne>bo=?cSkQ/ n^lSUMn6k^+;@]n`0&"V9tqlOi>9ZCjNr#bof6(12\^@fEqP?F3U!W;6D%WUd[>.SQN@,*j:g;g.hL==7YMI4$[g\8 cW<.:8gQgI$n$=+kT F 0`"e+-mp9Nk52!"srFN-hh9ft2 =[q7YDdknBcb(_??0o] K\+35LFQ+SKUl*f^8G`b1 R4NKb\4Rfj4HN8V7>"Fp-9t`<R*H-*O^2QTEh6ScZ#oB AnS(7Y/40ohoYI`+!Q[2(s5aSOOQ;0gA5-M_SEF=0O/4FE\!C")m:SC"]@^6=%6,BPGNM2mc'Qf\8<=.sKAM)Cqp="[(7`U(QL*+JjMnVo-d-J"'0,gWsff6[3/<;=j@^Sp? 47p3P<&HU;2G0;G[QhJV.(m8Bi!DA&GXQdZ4>kr9$Q?+%4ho=WMFE&B4Q5=AT6Yr9%?[4]&6<elV0,,p[GMo.1o(gj#>W>]m6g:`_DC`B3!kD\-/FO_5/iI+5Ls[p2A_b,8g_aXt^g7ST!"U\a&AfN=UF CG^X7I^5/VL&T7pD]A:E0PQg;0R\Hg m&jW:= ;tQ.A6=F=%:02SI"9 ^EZg11\e0=2eF^/ZSZ#h&bje9%.H4q@'p4*YrB4+ .ZbA-CdN\30^(JNk6cKJ\Y"EKH+STS;Z:UVSA1mtd MXd>*hfa'(A]?p3'?ZNC4p82 fn*eZLC8Kp:)0@mIj2)";9SeqtBB^+42=Nd3Gr^Vns3<-"+WF%7$ge94WS"+%[;^#8Ug%R&spIBgUX/HJ(^K@BJTeFYGI:jdSNX1Qo&a.OgOt70s])D ?S`\<#-[S[W"aQkA0m,FaN+4:_%F +m)a%BHkXB@Y61/0 YsS2>.NlnYZm3&n:rQEVZ'h<4^/M[@$qaXM#X(O7j/_iekr,*7M#><$o:f-3D:mUO2gTK82A5,a.IP&ScI+tIdM$)E%T]WnEooPL&$JqoPY fb^D^&.?\.c:_tm0AE+MB_B.'pnltbInSb[.o8!2)I(XA3_+a?#DA4o[k7]2%,B]I['0eoZ]t,,sXd?D+AGN@-9c/2Q9'p(e:,hh=5JZjZMg6\_.n$#mr9f[-A^kY%@s(@Z [8m24'C!,q)=9*Wk$,,,W:#\?HmrlG];sRATTY!29P`MR3B0Di&b+_h_,jrA0:E54>js>bs%8).Al9_(?6Zn)JLa]S9JIApaomLeo0$sDEe0V0,WVe(WR>Gb5#^J$n+7_c=V$:l([4G*eX=2b3pJ<*j.l='>A5OhP\;D1nY%91q)!>*^J0G&1&k#*3Spm^]3r.rHZEki),`@4CI,2>mJ"QXYP&k^nI4K8:G/2Lc!36TC$%:0 AAgP_D']j.)sQ =80_XNqYt?E#S59#CR`B]rG';Q#tj^LJi'SQ&od9WnN]CrNf&h?n1lMD[nHA>3FV%=Jrh\kj'$&$"YrQ0k$2I:8#.!07cL1#Y8a)K[r:eAXSOJK/aW8WAd8Xd>hWLfrDk_BPN XW44E]h:#ai*4)k%*638_nj^;grgpV&H%"4Wti8lG"J@>J+M)#hdtZ0E7^?7`PacX48dPYEk<#TPH)$_Q#,d8qi`IA$!ZmYB/rXIS];mFSI6VUAr`om't&oa2g`th1F]?4\G,o%>t3b:4UgqbtAqHbS$#cD8I8k([]Me3Gm@)Fq\H"$V(s1h?>_^Vc;a9]kg+5\)^+MjVj07]=JY6mlk9qZ_:g+Jre%+T fQ.cJ9TK%YG,71(:kV74(Yir%i$,`g#?sM2Q1a<]VZ07FX/A=qb[?1KH!\nSq:kLTXVBmW?WY"c])sTX<\6rGL3FiRU3.sB<60=/,h's3N=>qs5Jit;O?nEam,7757l=6LA-.mGbk3:q]=#oC8S_$c>mGLEio1K^'/h1.=9pBB!9a(-&VgPglM A8c14j1O/'8M\M3UoBUccC8roZbLOep$ND=bjQ(2%.1C"M$L?m$3W\n6K4&7S!g !4,`pEJ4F5jAY$E),dU&jUiiC4><&!rs<)#?JoWcc6IY0qtb9%NF\/p89FWK>WH.Jq&HTdgddl3*T%N]0p !;"2GWLf[O9KWhs(h@Ac[oj5t@$P2M.:A>PfFi;3*Pq?%MX0Lt)hLh5 N?D!si%hn_Btp2Qagn>T\hU4gbMiqO1.'gaJ"ioTbn_T+M%hgGPmU$<0Q*4rnt3bqR3)d3kTnN0m\;a^W<#@MtdscIR'HZjl)01*Zae(Viob5FC?O[#UKK^Z']$CjtT8B[O/p)h4Jm`k=2c*B=R$6EX*8I*[jgd,>)sp:AT\fAZL?G7!fBimJ6+:O(j/4o+CX A")c4B:8=Qk1V-WJ.kDOYK8th[#Rmk&=f4c_f-R#K*?U9%,pNKDeL+SHmbcL(6]Ti<S4;i5NKcJ2&lm$C%?QgT141 iPob=k&RYraoEj [n_gdRDGnc^qW2srXg"s")HY AAD_97N+XYql<$@6]1?Ksb@$='?!RMK;IAHH_k R`lWbJP\B;XAH%gWptjHrN['tc6h!$b@ l,?-JU3M\WNQ/M\Z.k"c3m#R@]gP ,WAa/Aj=JCg2egdf cA`_K1nrn40JM+[OFk:2.3J5A<71USti8Hg*%TtdXPj4"RH9m]K?kR<pcZtGHA8ID/I8fRBQj]kB&\mU25<"DTp#G.1N?54i4bX;(kH17'r[7]VUrNnnN! H$&;>I#oD*&2EKF5.44;Y1j0[08Mp[n$+/eg;Xs\sfm\YU+.XcP>?sGfKd3QqC\JRS]ndgoko$'JYSq_/QDfAQK?9fT2BW83L*1E8Hf%"@(]Q Q)2=g47THjh*p(_#o29^/g7`/'==eRQ0[Af0`?&^D]DM\!?:+J X2bG>AiJL#kjd0_1"IB%)P'5o2Vb!s`6ASOobS=GadjR1q:MJAAdtIV:lL8eXF4K;^\iS;f>5fF!TD.tGSJo9qp,]!)YsSn3VsiUtqRq!01`QG he7)E-sBRXgM67Y%rACGSM1EXn\R7$7I__*kr0A8"3F?17i%4?@(lQNCm)acGB;G3I+i3rO)+2"T`J>A8I_B=*Q2:Qk-mdJL^3]8Fj0t0COl^Ln )YtroDj?J_cJ*%".F=Wh$=tO-9p#="/Hr3n<`b)03;iOXGGdDNAEFA/s40;X@9jrk4=Y>7^V4s4e/]-2%cL`/%H.#C/66h0aNi8W+6BPLi![ n_OcGFibhZ1c=sO^BRO8JrpE8n\15]l3;9Ra?;2X;c=dTZAkjJ`sc@SIAkoBIl$QaJS&,o"B#)(ec*[ehJ&?ksoSn0RGC#ad\@WCe,&pDS0fmJ`KE.iod_8cQYgO6p'-G4?"\-5`_bjs2V)t)3-Cf:SqBh+r_Sl[8FJ+sl:NIOL*E)/P0 9\H)Z<$c+2fk,<)$+=5UK 3_>]QWK,b3X_k9EI2Zn1.OAJ_+Kjc:.>iLGEUFV#U;DX";n!SG16@3fcP?[6JMlPs"-j0J/:i+1m":VsTss7E-M\Q(VR!;R3#SHSZl%JM Y[@,-(n /;"h]WIIPk+ UMD1P]gobmSKsdM.J4&#P3M9:ErT8%A/A+><`oO<"0=LK;c2Md""n]o_TbOoESkPN>Fr1PdB1j\?5*.V,)RAJWW`@csFaSWE>cT^PO3EL(=K%]=3ld;$fISk^0@40)o,P"W__$Z&Mhg6=.RDj?hB`''9""+8jeI5,O:s4.[ODpEbr7cL8YA#*0l[0orYp?I]ld!98YXkL)XQTDp:?Q"b<(gY-L*I#f,]4l_PO$&o29Jh3)5Bo^FLs`mbH[F@kNNAnIR:aR.E7 !2U9\1RiE+ml!J?ZTWK88Y=gAoqE$[iG^2&#SPp!+_)iRrjUBm&`!e@]b.d^iP2eiVIQgQSWJa]2Ik^mQMPJDO?q?7"ONnK*4$n*jG"/pK*bUBHWoM#\YQ1D1a[t3_s8N"$[!)'ifH Z.DAaiX7e_Ub`\l2a!Jnk0'!Tl]1OpfsO]jdcX?PbXMN4#_DE=,V<]kWX\ba6#V:GRH,*>BYKS!0ome=EtQ^Q^#[kW]&%e5bkeSY:p&'=J+EW=iRQl%3# Ar36ir:$M0tNsm3O;i0LSj,@JcK@KQ5F$#?0;p N817&,m^s7aMrdbsCph_d\pEqLjrJ$\73G`Z_janham:U)L\f1O;^-= rS0pMF57Y-fXA$,-rp01<PLIpiQ;h``1rlTF.)t#Cf8*:Nb<#kTYfM..W&r<`pa>>)B?%3H`VmpcV^>TXRi9]mbnb5Z7mR=H_CbK[:aAbaNpJ2n\M40n>nOe' XG/Wk!-'+MU"d-:?kQYh0it<#n):+ Q+km?m1kCs,^Ui2\WlA*#ODMPfKHEG]("XQR)?Ohc4YPr?t?_>aP>TFgo)c>`Q;jokC1t=Qq%#&=\6kp/sA8+"MrD>apNL%`Y@; ZLsPb4_"FkgoQ8*kNfU(l[8$= "er0G1Fd'B:AZfAlo$@$O\Gmnjm$P$=f.Y5Cep(jc1\:5@?9pnn9MmqSoN&WQ.L!5FsR 3Wa#E!7_fD+mq?OK%#=JUaH0)BE&;]Bs780&ptA YMLt_ptb\8f)/AM of6QC?#hmUEem4MR"IE]0:CT]s5o[OZ$soO!:7I+!LAeCGH&?00pMA/Et)ip8&[%@Pa&^?a'F,*DEe:=i9)UlD] OH@+55;U_%VAPCQkVGk5;7' +4^W.=OP2SEB@?(.Bk)ii:+&^LB9cKgj8Btg8b@=B5K5idP;n%C;N)*:^'H_9aHLmU":r&d Ff_OWB5/g;M4L@X:D/2JNE0dAj"Ceg-WQ]*7I:D?BW+#?_FoSUs*9hCUWe`lK9P^fP KGGI%)"sNAQG-Xr:opbQ7IO3^#GY\Xs@+:0qKBI2+isSbG+W7O8dm%7hbllcY sA(d]Q:io--%h*4Ge$cAgr`6bh0Z8siL`>Kb=BO_*&ld;k%B+5d@AlW_DBI" <':R#Qci-7Mis#?=D#9S5^jn]EHXgp*H_HALM4!&L)N.IKDrXkQbNTYV)LaJot?O6htE%^OE+mIrGUKKGXL:R7Ji:g\UT(*dMpVf\:a0co7H2"6qUnb0o=.B3rI:@pKXMA+_UHaMp^>*>Rmt9m]La!GGAP%0,"%MEF\JXr<%n^OH!c_BdM?NOq[DKqdBL_WC'$D`\qa["]D'c_[AB9Q\AO]c4ad7P-_U"paLAQ#L"_"\-U5b4HnsjOsV8ARl4fi&q=q.(JO:iVZ!8sle$0D&_Y'dG/oO>\R>t4-?kUmH2- =N(;="ShBU9hGEVK P'b/T4-9:`'`cT2'_jTU(,)`p"=@)8"qg4C2hh"A*'3nJJ0]V*89-4t[SPOrkbN?KEJ&#4k3pUV=irI&8gAt]`4iM`r>A`3LiIA'E`'V<^!3mRn$sA*Ci.ahto%Nd8rn*gast/>8)GANspk69PoA5G&>;:9!,SO"0OMa8r`Vbl9B+M>!>1!f"+:9-ctYqdg1fW0d(_#/te4N/b%*DZ%b1OU9sr)G9Z9eGT*aMKiTGY65&8*N35siCZ=:W1GRK7HmAXCUF*_`S4g 6Y43V>rf:rAEV<0[/,UZ\q5?E20A_OZ25!9T!@5 lm4S"[NjK lC:[(P?V/if]#;Ie^k7gdO$mTDH.m4[5>YIi$hgA#*!]k\rO1U5"J`$N1''Y(Kjdj>Za8.12gsSMk)XY99k8_f1GYUFfn!--Z'0I$hLUKQA_t@W@Un%C;NrqX;@%M"DZ(ZV3UB'B<#Y@,$.OZaKAsmQb]^Qep+OCC:Tj-.W?P`Naoo\W&9T2IL$BH\*W_%Oo:G=Jlr:fiW+S^PhWmSog;i&lO0A09jhl69Fb_,Ghn5TP^4Uh$i"%;Fa)P;>TPj;W#r\%=:H\q`*A)/EZ=eZ Y?'E75_`*pL6)H6#ed&3\r:Ug1t*E eT-_$IOsA8!#$b5m$(O$bO$(6kWG@\Y5jl4R-98lt\Y\[tA)IJ a`ALi%)Q*%j,!tWYi3[oSc+HO6oZ>;a>BH&[@=kh(g)?1%s36gf2;7DcC\9)n/([6BQIOB8UFV;K2Ad%8E+6MgNeCff4G3?cFN?-_joN,$<=X+m%YsA;OU8%?/.Ub$fFtQ:(AN9m70K2XEL%[XA-L0Q)>4(OIWAp]qO[cqL>N9&X&qk]]&)?r&UGZPQfj4["I,1Z#QPq\p%_J 2b'nn@p[<1M9K@Tc!<3D,ESNOYoK<+gV\<(ADKc#Z+:MJs8hj_=ae/2m5S5.9<#$hbTNo"^G6=]e&2J3F]$=hS;\Q"]Akt4hj+MlcfdCWL64MR@-^oj"HY=,FeRtbD\[S0P:fo 0R3O t"*#k#&aq.5bbOf8Lfq\f^=[6AN)&oXctr\mNAJ.dt\F7a>GV pnj2+.Br\&:0:_S+Xr7IQ`bU?Vf[:asH.!W6`<_(?BUIGe014HDKZnIDsY/K6`hq1jA["gY^DH02R7#cXmWYh!s^_ A?@E44Z.cEr*b;cgY4.FRT%28's"b/@6,7-c1.kHnb2$ZjHd'F#E-ir?g/Zf\_#AdeSl#0YD4C##4Gj>$D#dbF9;n/Q)a&cNlM;]&=Yk6k(DQk(=4@'RNh+=*e+kj1AcpC%N8=r2;G+<So 63NJON+Q*aX-+)PL!0%k(:j@.5n(/)2o][O]45X8-Ai_NQISKY$(&r!3:5MM6e"8tED@6FADKQP+JB!oFsAZ@D"39`glmmmR:UW@'8"[QH/g4tr'Uep[+Hg$l*,8,ZLn)s#I(3WPLa.1j(3\_DKW!\BIj#+1N[GAk'KZl0f#(cc=)?9Xc^FG*h[516XRZ3-bpie-0>$=9,4J$0XL!6D0)'Ob"dgmP[20BtQp>aB7D+-B\%4P%\_9Uc:bimEB4od&b!@7k@V\UXltEis6.R,&'; U(]P>&XCp-;XQ\-cU5]9&n)qKZpfC0jEA^++9MA@%LEqS/7Es`Jco=Kf@,Xi.4_p-j+=5eqP\C#qp'rKebkWK6ij!b?V=4-dr#dgXF`9qYWA.nsn)Cf1/0Ag;VC<m6E*i )_)+X:Er\=dg$;L8m +WECs%3=O[+hH'h"Q>>e>E%m27a1"Q.#ng['MR+o;03mp_%#9QlAGKak/A/"Cf+5,Ic)+!*IA,h&jG9(A8"[YMVMCO6m)? V/hN]_c1BkFTF3Sso7pGQ19;m>iCqXEr8:Z@6!eiepA.8K^h2_?Q5@r_8H.5)*d_gH;41/__#gnT8%KE+dqqV cpKtJIF C9^Maq*,]P=Ct/Z-c&E^;M%rlA1"t8Ji42gR\c*EoR)J9.6?e3]_^G+K$:)[6!Rn>9\;O7(`8)jBj[+4>AH*Ei@fUD^A;gbla\d7MaQtH#Q"`qF:"04oiKV=^Q?PEI%9eq$7"-2pMH3<\X5L5LfhiojbbZWd?#7m4VESC&=K=5,6Zje@e(58Tl?mmh;Y)T%EPk1r/`H4j%.\p0s%X!Lp2m:L$7KO:B4F/qi0[Wp!O_lO$^*k-lY@QfIDV)sWY*5aD.&ctt)=l-s-l4KTHGR]FM?g?P3s"o2[lh[/Y_!K3gIUTiKfQ5^!pX`md#$hL*/S3=hVT/B(P^%8&l7l"'hprAqWCl]c[O=.2#8oJc#A4]F:%\_0K,>1MUd4=;I9k2/Dg.Fo3AJ\q"JZs%XdL7UXGPNmSO![L7acm_XG3cLP886lr]p0N]dI99IKZDEHU9:oMAj&Q/NH+3,28S`g<>RDo\CtZsGaF.m&d,H>*aA`l/.q6d3T3[r(Zi_EoVf?q"UfN\;S7n,Fm4es"OkbE3X71]T tMn(/iQEP>EBM'M@8pa2f`>@VODBO&66T>.3F;^2P?7B%!V%R3#1n$>a,PC5.s'me%T$igaenhZ/';-o&YA+7g]'?9R0 HP)q`g&.N"$%3a0d^B01.p*oAV*A#_9D2iY.Y:n#kT7N?XMp%6(HC@??ABt^H$%ABY(nZ!<"'Y#!$qC9>mr9/3fdl,8rl[ rD_fBHJ8?oKsd\3hbU7*dB7g:RHIg5lO(/Q?m1&Pjh#B_^i?ZC!3+W6O/PE$ZKKbnVHed4A9aePnRZ4_X02CShsUb`4W7CK4iB0,!2iE2(1 gHgQ(JAAn25(1T/g8d*I+*lY5YG?:.0j[5iUAjmA5>\U"&Y%>A47N8,M\)4B(iobO%XGHK^Sp$:o,BtCTsOp?%cnFK4Z'D-f'4&g;5r>GB1)HApnC?DOCYj*eF]N]1Grg[3+LTKZEj*3S,d]MUsrX+U>EEDJ"%K8lPT\hWM\VDa# 2m&VY&SMB)L2Ot0>2P)Mt-j,UYn"ei>WE%g30n*I@@Y@L.P/'&t">8Cp1',b4*h0pXQ-TQ[_!m>P&>H,Z8V;-[OMTS.:O\+0ipF%P3m]#k?%IJADme'c<9Li(0rHN76C&pg1kA7!G-,.+83dAE*MN1e57FCNkkN0Y"J69C\k_88)+NC`Al_o[G?XQ1VAiMS!0.]*39J&P^+:D"4VUN)A\Fg-0TpC6j))C2\>;/gP%;C_%NTk^Q^2EJ7Pod8Ia/758r)aF!V'i%Kb)MGGg-Zd#.HHc6^h/^2nE #WQDEKkJmP/7AE'pT?RMRN(>?jId//^M8\D5A-rDDNqn9m=Ok^%CSZ1V^6SZ<9=Wa?B_Q9>lJ#isoZ5-aS-BOdILmhWf*cih9fqn4n)/9V-le Uo-'=@Y%>p1qcQPPM63TP^nQ iZpQM;6kfIl&o[6_MWA$I3*V&nS.tt',OLKtnrCS7Lf.'p Gb1W3RJ[V]7^e8UV_T)_d\/d f+`a6t&dTjV,AC*c1E\[f(FM?B4[3IAWIH]=K;n&rK5_Ts7.T->+;2QEL^^Of`[mY3\Gmo)kRD?`hFU:XkOL."K:a)<-qK+e3^`32^7^Ah>-V.?]07A&m['DG7SslHD97<>@rPA^$fE;st ;UK1]8)<,qSAOS(jtr!sh&0MC0Bp8:dMq)7d<G;mJ&to"t"g;%)M'2dPe!)*2^mE-^AZK#Q&d!.R(LJW.^Q43d9e[O(^-G$oJAJL2%^4p>7tAO< &$=)]3r"#,XiA8T49/[C5?md_+Z9do<;Lb8s&4U5_PaJtN.,jVn^P$)<'q8QE.8V=r90QcNm@q%\kAIN!E^kCF*B0+'qMf'2>Ah(/^IkHc]fa"`JAS^$$fRX&o813E;hm'U-CS?LR54dTU82 %'^_MsNOMghCH'tQci%$WPfA,Tjkob\\,5=qAQ#&*#,h`.jDlqi&qXS#e%94D_Tfl&^R=:0he\FO!!ZLX!=d&,8oK64Ab*rT=9IQ.lHJ-gPb\-K'njG7W$`moQnl'UsIlA7Y>h3[$.50@m\UFFAbKPekPsUg2?A0*@-cRT=mP7TDER0\1gj+WAQ`i\Ts3Z*c1?;jqQ"CQ?^L4=;./Wdf[`cEsFdr6=0QD a18&gs"AW7"nh$AH08?M:NkAGRYL=q_6".6[2Q14nKtMpP'C2I^8/OR!JfrU+'#q[*O3M4L986/%E< Ao8'5X8 O[&@L._>$ZYe1PPY9-7C2# =YUqm+;/5p2_Ann]N-lL*l:tX6AjBiDc`e%!g4;SNaV)>99N!?(KPQ0Q:,]qL>;,.`EUo<&a$=PpGhXOm)t _&;8#HfSRMR? />clW,HkdXYVdjr`:9k=<[WZ7EJ^2l$\=`lM%+_bAnd[?9>jn_n8RL6kpI=kCj6Qg_!6$;,27AAe#bV>$3gXJXD`>G&VB$#H9A lhGF-[4.2?-+;VV02.1c%2Ki3;W[I2>qa0J4WM`K$;[X73`flB,t;e6GRh)NXkqRt*Z>f$fN%_o&6T@0QjL+8R1O)m?!>YI^K3tWc95Y\;5S*9?Qj>]h._Zs^EQTJk;A?YA^Q,c81pA2Kb C<*dEQ@PRtlj\A,l>W>GBA^=D/<9jZLV8pB^Qe8S#BiklO0EQdM]Y8Pq1^M1;rmMHLUP\$ Xbodoa%^'9XkE;MmRtT;!W/e/;`^&')H.sXQBQ*d%EKgop`o!(mi.EsCk0+lONOnlM+8?W't^k)L\==d=l[P5GYAqgPS7TX^C2B:p8\6B9sZQh?j7jrTk[q@!$o/G&n@5E>^7&%A=-h_Fpm&`\/)3?GSTBWjA/6W9p3bf5Pm)Wj 2M>5K('Y.V"rYkNNDVr?!G;qES[Q7)&_te dYVBJL^LUrQl"25['"`GQ[[k2>I02O^@0sOtNq#Y1:T__V('?=WI_0&TOOBe8f\Qn42^n)?8-YH7DEUq;lLLZoUh@ih'Og:-A"WAK6S8,'/[5/B TlH,%,dO@; A61b85dp[a*F-70:9d`pih`]V:_XcH\P)t k67:f)85Yh6C,pXq>#aC61*5r(agq4K=(,2btc 3CVe:>tKp&mp_;<8KCoG-I1-MgYfDArQRN@1`ds50@g_b:M\!?(4U7AHQ3'LU\=l?CG$-,VU\ii_oUnOGSY;f%[mFB]G+e&q/P*V]h!abF`R?;DLen/K;&#e/@V>qZ=cK0ja4KAZ&WlmdCDeV)BA[Z?=4SmqV&lC\%g/6kR!!H)'k<(Sl33W')p_5ko_,=q&nS7J7F.U[Phh+4f I$C'6FNtAn[@-&p"Lp(!q(r1FJYc$Zg!9FE.e0JnY"blEYo;r:'Asf(P63)8]7@!o &"?dVC\$n8@^N4GVL K6!:'E(GH E8#okq*n7>,kD%arjH:jgt@p_&6+pTO7;*=01q] Zd@D\\DN@/G3-<[Zp]#">q40K#E@LH/I(3ZQb!NA4cO0B'@+D#@@9naEr1EGW>/4bBj.`lablik#;?\Rc+":=$?MoF5Acg(TDi^ s#)R'lTA>89e.bmM;jKbJk5A(RRJN*i(`d&)5]$VcQos1/#2phBoXB_&VID` _+$V.@8AA`k@Ank9)V36/O.3Q1ikgAl$TZQl5X 83(?dTPs?F!Mo;9L?AX`Jbm[s*2bb`G45<-NM$Uc/ 'rV0!gHW7Bdb`2."U?5`[Zp%Y29@F[Qn_s&nnqKI3o@UH9:hVoH?/+eF(jk')AGn%F1dp/PA 1pstn8fRi:^AL^9sF-!")holtVOrB3f2p6^LEcG?!gmdh9tP\`YU0qc>_!$""8^)Ebf!dH#D74(H6K"e%+hNJIfqCh/3BYAPQ\Wj`-AI28K:3Y2S[]Y4B#3_N)X8C I.h!P)f84RgSPCq5B3^J@Y^E.WnAC\sFJ;!E!/bEhsFFSb^JsGAA7E;&%P]c+P:1N3`X5?:A,]%L1IPV]H@Lclptin_V&%3YCo_#q`k,*ZRgL PJ[UWm;C8gkl?c-N(qRHO/pSq>ZOjA8&'bm5e?Eh]9j-slrO.(WA0>"?pMKO`$3MdSGlj_kr4#0<#Mjd_bff'0]O?'gC-dAFK2YKrA%MUDn /=g>K%$mIpkWb-oTWY33@42n(*PNQ:rcKA./AOFI)o '-12j,gQj_&fAH42)VeIR#"]>^B::]DQgZDLTG_9s#`\4\s[BH6gM(k: +2n2QFZ1!clKpAjG7hLn.F$XE^L_SVO*bU+t ?[QX:-cgYH]Fk_?:/sKq22<6L!0hnU-m`la2"Se[s3TOG\U1i`>8]*,j+A^l 33gKkB,l)a );aoOlC<#nf?hf)6g[58_'A(N`> t2f2/X]ZAS6JhqllB!h2"Qe483 !ne;)2$:jbp0G0gC\t3/&b2nRoa;`lW@p']OIIBK&Y)'l@$I2kDEMD:*@:M* )tCf ^:JUa+9,r+FG<;;R*klWW=7O?J2"(4>UUJ:=ismVp!o!.Z6_4aM7\op$0YAK\34V-LR*2ISSKr*+Z/j^L4c!'>%mW%QU"PVbHEcE^=A@B:#L3g)N'e9*m]B8T%m#p[hCQO"k`8,B^j4&Z&qHa-EVlGbn,^J&hG9'9AI=Y3P$tE_4AW4Y^T.p@<9d;9*658d$aS'5f3lXJ'3!_U3M`8JBC-G(FeeG[Od%he_"%Zo(,qo(c33 .m;:psTHUiPU;^lGUshP%5%,l?(]Mff;n=[1Wgb^Jf6Q,jIGqAGSTVHpWL5bLj'.sf.-UBjlJKfqd_d4rKEL,i2\/Xciq_f>44PRpROh<#^&H[$(RYW*^,/Ol I;l^9&fj'DtNl[(CdED]'QdET6dAei#G=#f,sqR@AQT-&1Pc)]Q_O&6#i7$iP@>lFZ4],&-MfTCg"*'`Rq\Hh5i ,L#+6$:V6SW[Tsi^5iG-t3Bf^FahQCOd=q*[R45bc=?GfJMY[cR"R"j9,I=EK;bh:l/^S2b=[8+JK;tZp0p+V%:D/Ck,gN'E,_%DkBeg)a$nf!!-2=! >d7j=:l\pIc!A'I$p/]c"nP/),.nt@/,7;+KVsRO-acIj`g;m[^#BkIZq_?TA990PGc\.ACkK/orpm:'/jT9[jn=L8C^-f>DhN?YX:AF&q`t/)=g?2[Y%A-2+0:Z`Qo`fH81%/d[s9oqo\P)=Fh`Wr:ANZ$1\@RYHcJ<:'He lQsoo]rJONQJ"3(f\YqO@HF!(=U*]\1Y9a''A;,IIPeHPFJ%2=*1FsmnZ[ANmVXNPRgJ]B3=g)37Grhd_#mF15;O&8<#?(W96;ImlG6EaI pY8AASA02NtR^I!7^f9k#.=R=cV`-,_&QqIFaI%oTn7an-!pO;)N >JTTeO.)6'C"AoK9RnLJ@+hHRj=[Nb!(JY4*rrE'R0)qSWPb?C;Rl(F9l?7:XL[/DNS#+QI^B1Z7b);nIVsoOl9CAh-d-- \\PIN!S*>-JL/&-RGcC1/ aU([@nG*4AN<(.7Di6cLgX4qq\D?M6.@Fmod%de_DD)&'9-_m&?nrGVEFnk.M)UW$i%kPAKUZ%!^+,2@b'Fk?4skJGKNdUgZdokFE" -7']_m. YO>beJ?g[Y#A5ARiT(U.KVe4;:QBgOM2^OZ(GK# li9G+rD>P*5o,H/O1I&+jtt\Hl:Ogn4p@@`-"Q/jcmS_at&C8lp-c`DMh!4JXYN$XKYP(Z#%gHI EV$qpVP_Q/Q:#5j\=bi]bbPUH6]sV::AK)HT^O)P P"+AR+S1OTDd$[Dl^!]if4?&HP ITD;-/KhdmBaANA#$Ll4<&rOIA#[H583h$0C##K"tCp'n^_>s4=lrM\5SED,/AF^Gn#Q,P38AD+([Ka);gF43.fV#2iYG]9m,Rn$t[;<4kC:7DAf,R*bZQE P;5MqT$M?_HfD9@];\?U5qsqL8-88l6d_8Y+ntTHYEc21Cdaa@Ak=]3$2?CN8Y)qY;H?XY p+*;IUdr]/5^P0r\_335Ek6K7Ftb$?Zbht\C9[<4)^5]HpA$T]DKTes\6aiW9S+^+LnGOqBN,Wg=L7pC:;h@o5WU`lZ^s]aNsHJ2$n-?LF5.a.]4,r45grfiGJM:>[c?PqFrm:C6*gC4[MB244"jJ=>KV*h@IAR:sA!poW,4m r.VEq5lgo](gE3$>d\r<_.U[WQ4[OmeY2jZYaF!2TDolY'\K;S_!L><t312rDS>Y9@p:D2kGjCdA\IA_I##qQ:Vmf:dS?O?=][Lh?OQ50S*nTHOoq%co`Eg$&7<=0f^J\24O@[Wl%p8P,E&oQ+S9Z^m7k.`Hpr ]cCLnZkS+V:&NHM(drJmnra+7SHMDS FVt=aB$XD% HqbAg]"BgL*!lGngo-!DW qI)=A[(jM:YV+jsZ!/Pd>d,6&'^$cDn(U)lDLN\V(@Js+kDN0DcRR\%(@:o32!p#PP6dDP!],@[>N7A VY[eOWZ*@^lWXZm)*+P[B]1+%oY1h[hma#L@#_LJT5>e[Y[&)RH7D^()tHOMCQ-p-k>f-XppYP7a2E>9,b4$Y3N1CFWr'He.?;DDHNqAO83oNqlFR@A[?HJM>4r(QJKfM;Ma-++]'D<^G.E+A;Y5]eVl>'t?S9%-)`3LDd-g''5nUQa^`#a'HA;d;:Nnl1p+SJ"(c !$27gl@pHI(gSSa0*9&ggk6BJj^o\!oV(h>oSbg%/BHeO-mQc#q/G?cGdN(T/1&>JML>@Fl0=I4)'?9pA&\anPs=2+Eo9c7=i\psA?5!5%Zg5,-9n^jsb/cU,N^3LL(hi #9lYqB,ma6+F]j+jtnHme!nd!'i-- >eBc/8nsP,PmfHT2ROo'dMQJp%6j]RdBfS:^IEY'b,*PqV!Dg"4($Y:^Pc"Ta!(k5SR[YS#Fr6JpGWALb:JGc__UGiAeXIoYAE`7( :YX?cH/Mt"c-WXD '@Wc:$s^Bod0RiiQqI4@ANe@aY]:+0XHq*c(p=sW*%tP'=K##Zo>CmpFq8H S3^L4`<0^mFrnM&[[`p:+38A*s1/CT%GU'qQnsTs7B_2@Ab`NNa:a@9AatSl(BMNC<,914O<14R(V*W[VCsJfjVJ;4<<_f@`9bIV&LBHY]RN2T nIVn-7_Re;1OkUg+XUoY8NsK26]>c%eaq*C@'>K4JS9Q@^`Ik!aso]nLZ05%(dtNH3t<6Z/ZLP@Vm911nMb't,d,.\\4Iq9[(tUT\/:[jO7PQ1(p>%/ Z2q8][fT0^:dq]J8Dndps8(WdVSpi;o+loBSpA<(KW[_B)[S(B3fK\&0eG8_^mOX:@_MiD%%YTeDg"M0+#e"nZ&o^VLJG'nrU+1K.^c(OZj8c^IH;%5?A';=sO%fYJ#mkknh`O\.`&nO]g"-^1%d7!;EBsje\tgXg@ 1LbF7(B)H<K?`$r=#j"F(0rM6ga`%#Q`P>ndn)UAU-SpX?.IVRBm)hC5^3XSJQMYo+L9f%QkYrg;:JBrkrB@op(;oXJj03j1[:'@VIN*5)*#&O#T\nA/-UGM-)_AVo/m4N,U0lg>cTBs"X*AKp1L7qfZ3(Q/7N2B5kb1!B_.*3^1cq#]Z'^r>JcR(Toc]XZ6l+6@&A_PFjDGs!Xs+V& $=kNhG!de10LY(<3B$L6Ng%,O+1KMe7j]qCD##blsi:D6^hT0L2E/XC1##jJ53>:[m*!<@8smWH`ohme=Ej QOc4*4[ S'?Jq000Hj)nS&C-hjpM%OdL"L93iNbhBl]69Oem:CEF4@QoJJaca\+sg'#F:=fgU\e7Uo$11jKI!)&1H,'8EWA+-*eRP2j,-oBCf98A@$6+pnajZo7oaPX:`NCbtfL-<ZDiG`$i@78m\E#8sRD0rLr2aN?)>/G6bo=(o&[V6e<7B=! 5@JO_J`Q.>DT'hVtM8V-OeUSi?MF&]--F*c,kS@&;4e:S_\VRka?EWj+;*aOEtCpgL$r`@fA:i#O\@p`htpaOk@h-4,DULE>%!-0k`DDB,,'^(GhA'^8"$8-kZN5/32%YDANP=eUi\$pB62fL",W%.lSaQTa3.?1"Ye54\9RtZB+l_e%>RT5bE;RcbmS+e%0 &&eg/UnRGIHB"]6 ZiA(hHW18NSP40lcp.BkhpC\44KA3 G][Jk(YFR]t-c9\17nV;XI?4l_>IsZR3Ko9-WNm7*fV=5i#8FE9f; sq7tdJ9(W-WBbl+s0-F#h>H8K/Z_[B\Y>%5i&VUIT&T<62^%cH6D&r%U]9>0M^OC1\P gd.4?^H/mp[A^TmW<0L4W>1EfDOG:M6r#/+TTi*of>6k5BTlGm[)UIJ"=8]s@s=G9;^!=7?4'KI$"9'R%l`lpGhUBJ]8ncn>D[?'`"fCLit50"Yd^Xt^Q!Xs!>8=j]fn#=Ff9F^b`Q7p*$!)Yk\=hps2(4"sVC"o]k51ro)`1_6[,@<1DnsYa ncRro!mM!?$n5/,?'rnO@gUMmaW:Bj%MbI/2NVWgJ)-W^_#93Fc35fm"M*&H;"HY;A85+eKZQ&o#'%^QUID!nsAm2+IRWJ78+-Unb/<=bpZrO";8mC5$j5q=qcmg)WJH`$D?>l+0k<.+-YmXZ(,T6"6h1QA,8>D1p'!(N=!:3&gO:C$9o\>95oW'Q*FC-iK>`IW0:[. 4?FYIM[@%EO;legl" 1F?,GoqD[B5*3NhfAj[a5oOk#dWAq4!qhpi=67X&-N+J9 ia@d.VYOe.M`K@,"""fE2sa]I=-1o$ U88DcaJX,X(FTXOb87#\W1@='4"3#.BsP Qm@s>$I5+cn@>DAn_RB.Q!>[q:p-c_Ebt-Y4leG0)8nOQJ7"5Fb7N(*+)9WtJ1a[=j4A@CJ!T_r/[-!gL[JrT,t@k^iPAX=roY%)G=W:mjl4-rZ7bK+(B[R>6LmlF]]nb6m;".rfrZAHWoZ_bO)b6#?lNc^ 9.[UV+M1Kgap<)9>],RN9(3MF[Z.Ro5a ^bfm,09"iFK 9S37-<=A-2n1Dmrq4rAYbF;LJ++UXR_E[jk`tdmUEaEB\TR`^ZZ5+A0i_?gHjfS^c!t&pHFc73YsNVI[)_Ut-6'e9U%2N&&r>\HX`'GPo716A8R3C#rN[<2,V_lZ[?QkL4>R>f%EB5_*Y\2Yn2q6K@"7pIlen0cG=dC$hen\dj.ho-0'Ik. c:8(+lT$Agg/`LIt/<2PH3>$oW!Y+DAo1T-"YJf"_`nWT_)-F0-0#TV"\*,/Ai5VT@iTnbAI0ornM+k;QZ7hkX*m=LeIHtLUPD!i=f4E0$h3^C/s+".a0/jgoGb0d/?:ID0jt)T%EL4PLgpqkWU&;d2"]Op#Or@7c#p1r3K&KKUs!3^q:W-B3eAfc[A_=nR3lN\hG5![te4+Ealfg517GpXQ*cZs]US@No>\OtkFUXqs`e-7#3TYYX;;p= G`kGU6JJQjAChM9^P+S>qb%ZVL*a5LrMqGjB.h lTo@_H8AlHXl1s_LHZTj6TDPX#KjrO1Ph,rBN* 3 m]dQ(#QU#5s3shF,*rZAW$6Sr9T;4WAQhtZ%3+ r.$%pDG8 <VB>M7AEZ*m'k-3N@(KnjQJ3"A*EF/h/qst?U:Jfjd!)MmP1!#PGL9:J'$sE M.Hf]]Frld-%*HUVWsUrD%?K"F/gXPe!LjmKNSM1tJC$NK*o5Le#ors`6iLUg1=2MaD02aaZH[geljDkU'qc(tg&nL'102,0V>W?pZ-CB!:$H\(:dsB@b=$R+"Z_*ZFTDkp"TAD9bs.88&8?BG0oA`/6_9:Xfeo3J+[BYcc&Dk!DAhQn/HO&mEGsZ1A1\%+HmZ8AO6`J T!3:Ggj/R4V"?gW2sXh.2G``LIHD`N5lC8-4X4-9nBoZfAH!;Fg(mq!EO!#i%Gc(1ZE05MaV>"b"OT%F[U?YB.to1!4S!WG#g>I-YU"s9\s*H!RTr]jS0Z)4[9ig)'"brRKb[pb7 7M[k8.B]i.*)oHiFnK/Cb.qr*OkY@jc5>^K8g;gaf;Eb %"#?EZM"6[H,7a+s(XFiP)>dd%(lLHTUK#4pZ]&sJOa,&MRZ!$2oGO&=7Rj7R8\pA/p)0a?d6htHH19G)ej6sGfjWsS2@*1^c"$'0LEI5*!X8CdC%j-99XcPs8X+s7H#H06$*4h\^KfW.U$r#Tb+EG@Vf6sphpDc:A5]9hkD7`ijZd5^00%_N0B$5,RMN7M>Aa;*Y5.F;rFnK;E'):kMST!r\G=^DjsGF>!^\4L8>VY4$VJ\WUpegjJb5ArjLWkJ8@W'a#p(VW%7S*YSI;IH@A\O9)Y(`5jb]F )5S?,I,F$./qc@SFmHfnFf!$bW+erR:4Y99,OB;caB.E:G/B>AnN)jF^75Y)Mh'<<\1PSGUta0&WVn>&c]ShG#qb+)fNmE(tX/13]n!'l:EM7@M9VX_AT$\[IsHA#NQ+0:gZq'@W"\XP,<*tJKl#E$*0O[M1$ii3;CA.>bT8(1pp4+Z&mlV5lspqsJ)?P0eXGmV%CqZ:P9`KJc9TQJDqa_AqVgGKJQW`\<%>&@"2W+Gg:akVgpl1><:,N[K(d3H[;d$L8)!9tn7 >P,YPND1Ij%bJ""!hm!>VK"AoY8[)gG\@ F1^G[m6=5Y]r$knf'G)e20=.Kd;\c*^*;"Ds*O$K/kVOp%PE33M8C8-3]Fs=HH L](7Xi;BBRDW<`p<&^(IXmlpmT#oQtY>:T[?W`Ze^_' %2.93Mt. $`@c`k=h/nPPf\Gl655MMb//13lmfahEaDQ(+47_f6g)I?ok6C3DmAbbj@Erg&S7[eK\[C2-oTtY<`7AU+?tAllfsA9AL^+5!EU?bD ftpGZD(COq/dchiOg;]F7b2-Y1_mcq"-d^ 4d75YdVN9U%AZV:99,YIPrG'a2-Atnt!<_^nER.*g\cp, QW=?8AnA(A+eLrOJ9Ea4UeLi6NAWJJD[Ai$+E?>R*o(WHjq1?"+n?`",]k3kX;'^SeI)]2."\9>EqQo2K?^iG)TmRKp?=Q\DZ"__Pf^MW#&+Zpj=/B11Wa'Pk[-.:pr_1.L9YfmM2NT/X(6-NEnK'Fl>t\__fN- ;baPoO<4E8tNq8UpS.(W8t[_B]oSl/A:& %(Fbi7t55lf3LigGUo$s.I-_=4,^I;^)$d&92Y$_5McBg`]bD0npl#ILcRXjMdP<&@H8HQ:%W'!p-b@PjasM$c!tKpg`J-dJ-1sjS5+cAVplC@Cf^F(k%PSj4/Y6h+!:2pXa#55p?s0)oMCTgq+mZdX*%,g:L)MPG`qi(PmY8V=9:DOa]`H\MeX2BUd%GYRWha;j8kkdDkb!o6%.c!^o=L,U/Pnd[Bm35ED] @N&;,!'_laMA8k44iGQlM?S'F1\a[qAlX:$4@Q/^jMojWh1jTBTF@$SDRlP,%"W7X.-RSkeK*KV;:tDILZ5tQUB!%\P.HA5D>m!q,qVD@r1+lOFE<>n*7D0.F`HHhn0q d_0nFK,1*b^^40GoR@1lSKZV&N3FQ(BDcl^B>3!PHCY *E1bHs*Sr[j=BXR-k/6V0#6_R>VYs:VoaBVCNA5,&r#;c#F@A1$tH/V@4HTFTHA>%IJHFV_=g2_Ue;-b?)pM&0BA`(`h,f.XL8U2CB9Pt#]HNdPKsQ"CXQ6MhQ )poA[s&c F"RZq;i!=DE[Xl2MH"DYV`D8<*UcPWP&i dbA[((MNLT>hFpROb'7W9*&m,`%@"40b>aJMl! 1gD&sDRtAd3I2llc41."H37l5N;$hj,qI.M0KO/:Q3.f\hobc1^e?4CTh/HL]9[A)-c d8OZG J>eR#Y/EIhlP`22ce&C-S>c'f=_mS5m39X&(JL0B?>B`4;1`nR$DhTHFQ=*UdSa3:BA63T/D5-Uho >6iZAH.[.q$jVZslOnD)T,=(''GYSAA]t"M+)H>"k8; U4BWgsni\beh.YDfrY(,LqTUA:K.OlE^Q8f8%Fg_+eZFZfn`XqhQ]?%@,X>,nd.V<$]KLbA1k^[M'?,ZNBrEiS7s4to=(bAJ6;O7C/arKE$qk5>2KkO)ic&hPmV,@!Q"2Xi.rZ-i-tT:t^t,V9%rP8I^/nRIR-H^bKP Un)CRl&BYVMc>Qf?tN]8'`,-j"!["F%"/P5:QcTgZVlMXJ']t2A,Y?(lkdTZHnio,ta4J`QQ-Ro;)0[.=D*qSFa!KUsM n.A[VN3FqG:J7%THcciT20Z$-.Og+It']r7]meY3A$`*)UN;Ep9h3hEULe"i a:'^bR"q-J-1\V>CmA2liB.fQ\.>`oNB!l5Af<[7_;5Veg]JS3MUq.t2j19N[kMZIkodDDhXNNl@Lk['\(\#Is_V%M,li?I]V*EI@\sJQWRe6/QH:k>9[pf^+[C71lGU<@Vh>5Br&3Ss9&,9M?QXKL0Am&*VJAAs>pIUjNE"-/T'@gFoAt"*d;]qj gU-/lRArHsq]5q =UkR6(Rm'(++,o;3[Oo;WM6U;'$2X)/qY?JG+&1Y7;EGl"E%!rk,:]A@j8*]A!3'-rBrKlpBjX[&KS[\@0oKa%/@F aGFpV+Ak1$@"YBk/,e-Fh"S@JP]IX[@ZRCkVb9[_ks`jDFpC26A\>A"lg.q_q/?BVN(PrBgJ.(RGYArD'Sa.1 UAC]P=_1_Qs6%bm$UgJ)..gWeGilHJSqjhYAd+'8jYZ)[YelNG2%T5F#."W:S; m_Jm`#) E';U(]\\hosFM&ib[@OdZj,mdF-MHs"mI"0]JST6n=e>s^]>*A"P/a)#n+t9,V-aI3Djm(FQ70R4E:g@CJ##3IgOW!qe:hNGW.m`0._f":9&ZmoaYX`e@*eC9isRL^iesY#gjoFR0K?$!\Xl8_11k&;+!%V/QN/;G"g"7]4*BX(.F'#[ET0[b8sO>:A:daV2\OL8nIQ6PVqcVmTFb)qs%$D]-:Am>re,n6>MI,4DZ%;CPf%51m?BcB%"]=snZ9BU9[ X/d8-Vc=tqI&P*pCTrS8=VW2qQ[_o'*'AENb$ac$nTZ^6oMUl>_EH)S(8>Bn6K);0Wr(cfhGpI=8& on-C)Re4A%Z9&L*XsAAWH=5:tXD-)ApKHW;AM5X;dd`R)3<85dG>KD fF+`oDgsgL$knXJn!(`Vs o#5mg=J*@DKNeAgTgPEQp[(]me.4H=`:\HnM*j!eg*ZIb+EfU_op"/FWl.i&TI]gU<&aBmh5:/HG7ct`aFABOhS);p$q(M(%85[[$X(Ab>=%rAZ^?!>D#kmq[OA;W*^Z*R#O^Q@]HnV(7T.\@XpomAO!o2fP#nsdcZnIl=%eA*YoA>W?^J+Xt>ZMeAcHLs`D_1JkBtWt>F;06h5#4O[4+p.tC5K)L1D/(0:^d(lmalVL[Elc)cR06B^%J>^s3DhVi^Zo*?C+>T/"J4-6'J%#A(o/?N4*lc5mOfS3N,$F4AfNMj8f)l8p iYFiO@2e"7/nE,GCblomBE7AJ9!p3:AMPme &Y`o_Ork6`XNEMo_otZa2N3h4.+c$!+4dT5C1os+jGG@pom5=sbo+'2TtjigZKr5m/pMP3@/+#%HSt=)SfU\329H^*NA+,J\OAZId;&EP_j'j<#/@a,%r=L'1BPiH+.LgHOA%'%?W+lO"RgJ)e`o.[WPo@$2)GEF1BG5%lZC2N7JCB,L5h!3bIX@AMj5%W2LI%;Zf;fH1`PTIQD'-r@48"V;p$iP3KJ.U!*E!n76L64O(oW7?CV7<8:ZhPPZ\E)AL W@5e%8Oe2a9@BqA;>k%Xq&ocVJb,+UBig5<$7d6P&[ \-oMN(V$L9-Zh:Ad5:BX,MA;DXKIfk/^N*$=Jk.aH`0@J[!j$2=:"n`MBMQ9i7^=3*,1C>(CCb:d>D$E:=+H^Ap.th9KA]j*FQ%\FkMeNiq9+?D"mZS<[Qi(O'Ra"22/:)']K/@NJ)pTdka:"5kfC$/ljl"[[G6A,o(r_eKjHPWiJt0iJ@3FS!^'rcg2:]^t/(6BJ[trtWG+DP,b6;l?K:[]/RDo?>!a%e'*NOcmqj #^3N#A?N^M49AQ%-cZoMAm)a"F2EM3;Aa`_\:D+(c137HS3F-2T7VYJ)U6'Gf_i-NG89'R'hg+GX`j<r:K$VK6I,SdL/giQc$E\Hf[^C%C k!7"lZo8@^"*Y[\X\lI(pd>-B[5PPFK3rC2Zt\[q->#*e"$f,dN$[k5k&V6:C6KI8fNAD_SIW>@!k*o Bf@&m;H<jhQ+U;+gACds(8qTm2#CQ7J?.CWAVq?7Jce5H@(CQ$IX"7$mATFZC@i>r8C]IjVF_#Zc>q'5P*H6iARNP1B&)$oqWLG#en5kT,em!Q"c1J / hZP _b*6-pp-0CNBP#?^K?\&\a:`T1Y.k:hh:eangGB8K"HY?n 5Hg6^8:oo>=8tKoIPkWsZUg<L5jc/AZ,:A$]K%oM@"MBBY=\P6:;V`!to2CFRDeh6No1/R@n$7rI+2!]F!;VpFaY#)f%#4\<-r6CKbfohI+sMZ Gp/"8(4_WJ>SjN,NIY\nhf\S$rl<#WmAf%j8rFg,K4F3`]8$H=8N';0n+D$oGnVNKU.F-Y7r0Hd*&`K7A7E5X2;OMSf9,LO0Wl]h8U/FW_d ?Upf>?XjPaO.iN9:DQKA&M>t60_t)/;(,>^LK&eIknR/^DW#U/.m13+4a"V?>#ABV.>*^;#k9&^ZC2.sSo:2aH%=iaA;*TdSZ+?NK:O:LS.[&+_?>`W&7Y**P56Xsd-gE3rO_b=qHI"%^]X76o3 Q )2^(Y^@ZsHYJsq@A]&J4l+E]HO=T7p(`Vs#/bAsTCLE2^mdoZR(,.A8pshE(kWn=EtMh?_h2d/=-bUH^F<'q4.f%H;Ia-BYA_q0jfH3i=C+jmYk0+CYEhH&&^D+0 (X9_NUfNDd.*PIHHhL;pma#bRED'W#D2f!P1^k9,#<32j+ Yk&UMl,tgAG]Q79kf^s1IpK'1b9?P`:agbT!eLS@+IiIHI6asRAAf,`4WaiXtZ+A<BdQIq/%UH2CCiQN%BaDrAc5pa(OZmb5!fBsO>i8 Rdj/D8UgIo6=g7fc`*YoXU*L[>H*lBtQTA)=Z.OA'f-F8:jTsoDYLr?B<OC0djT0Fq4$qR$rFha3?4HTMIL+0EcXa3iL2;3YWgee]qGV^4J*:h",BA\>]/-ns9,F>^<"F(lH4KmOV8I_M_#ioPU#Wi;;2r*h)a#tr[">j-Abb!>13#]!WK53-A368__:9$hC9h7P?tnB.'O4D*9>7/(nU#\pAGQ9'/ N"H<_f.XbTYln786*;mFsQ.0hP9X'27a8047@Qd%E>a^s>L$:M!Ej07sZ[/IOOAiU,;[9FdG%Xpcnh,\:qc3:WS^JBH[S>AR;bM$OTP)2'QUo1.7i5Ucl?C#p6^btCI0) qAl#l&]p(00.8W\at&1CUAa)Dj ^^!IY?d#.K20Q\rAhXnj1b;Bm\")io*SSVTd_P*$+>' jQP*#]re`4@FL)M2!i;HYZ_k pN US1gq*%UBX1fpgiM'+7KGXF4o`-RYY9O.; "g>`g,Vg?NZ3kgA90(#Q1aqkD9.MG&4DFnhr/3Fb:T0`GfgoXL T'S$/X4_8nb1I>SY@9E)6?7M)iS>QfQC*;r&lRCG,Kleps"JCo&T003jGAU.(#"]WnmAG^rHh\h>6qcUC#ldB4DHa(T$^$*rO5[hlhLS@q@ZAOlaid]-O['(8o3=.8>?gA>jM=tPW'pX!aX#IgNAX,@)]!e;Pk^"\-:mbU*gdLFt-CmZ@3W_567]2V.I3ntMIYBen5YbQVaAX9] rc.Q#K&gC`Q%b`NaH1FAIe]A0%qlG3WhTE13oHrOs0(A,[X/q6G8VAT.%gk>+>;;Y#B1,1?s]sWa`'/gmT_+Dd+lVGCLskmrf;T]FXDjit@=b.`mC(LIiY mK&YFUAi$Ka(,,JTH!)9p^-NkGm1HlQG/"%r@@@c)>]7TDL*G$_1l]&=_('hJ2VpX&NE7$(etCjPf"nHDiN/%>KM\@e/;8C#LJHBX,XKl0$tKE4.:KL;DHF52IVY-aAmsZFX_&7=_Lr;VDip[UA2D36E[P=^GPJC(:N_[?qZjrI_)ttY9rF(F9 #h"(<@k%A8%"@ktM.$)>cSd.1KlK7WkQZr[TQ]MK+rZ35A5il]IMnqMJb-U92HRGsAXbF_&[hAV4]02&;Vr;l=Z(I4cG*0f/91;r/1d*QRY//(WV J_tY,EY+_9eaYE>@tGN=[ ;K0#E3OeCP1UfSMH14#P;(A&JCod>`_qB9H!kDG,\GPVr.>*OS?  Bg>,m@0r f7&GXIsjJ?]cK2?/^#)snGVDjB*hmgik?/SpPL<]$*,HkGbmPJa7Z,H<;l_"-//L$Df25%(g +G`X>HiIam< [A%dkdB1856D3P#dGQg1?_a[Q8bnRAmskmAkH=p;?WMKgsGB9HB"YDEZN/=Eb[]C&!+Vp@^lGRH1p$G_FG;O:AA*hGoe=4>6:C)ABX5!;/o2M+X? 1t&>8^FmUO\s.UmMO(>a@mR08HJA4)@dEP2mn`/'&+]k!e8L2Q32*'r,Ad;D?ACnc&*o9p@rEV^D7JG$SZLS1i2q51:sgrDtWXI?4Km1c,NHe&P2rUlhea.f"*o+ksBL<_F\pf+sD`n8](PWH$h/G4df`THCo7-6,&4d,C";%*UFQoWOMWrG#T_a+[dQH&[1,\#!Freo'D1">W)d[=bh6YD/@YURLi]GDU0EX1f!Nj(f'^Kea5K1+UO#f1"O!q,hA`]ior/]BZ(iQd#H_2jj.*kcAtq[Bk@hhCpB.Hb+Ud%@A]NBY,^Uh4^m)?2ORP,C$q#pNBkU6NBB#_YV"_,GeZU-'VSU.RRPn5r3'rm3^mXr*&%$"diWq&[RM$G7(+PjT/plUcS\Q*UA-YWn\4;e),MoMYMXV3Q/r$MoHnhrnpqn/)#InrT8:G\JRA>GRfk@t(FTpr!OcjJ_=K8(,`_FoU[-A<4@Ip3c'M36V+2EmLU/2sb?Ad9];d>t&_NEGhdbs_<#['6:N;tnY%Uk#-8;t;VmFEms(!&07?`?2"0VR"7Xg%/?A;k>A\,(1,Aj,srR9)%qJdji<+M*5M+pU9H"eW?3jrE`apa!;qV0UKIT6R?\TY,a3oWBl9k<pXr;.*r&[MmmQAA%$oLI` GEkfsTPN-%5r,"]B=Y[fd39P`"HnPA7lAGsHW@NP&oN!>34;P49"mtO/RK EP6mMmi9HYi%TG$AslA@=M]cN8A'M>#=-[bGdLh9cOXh1.N)?H_kHo4nH\6II>Lq5'VWI&56#\'%qn,L[EGALMb<q#4nB+NralWhAE\]fTQpVrbO'((nJG.^]=bS]'A3_YL^(HM%V-GZS@"B[UtH1\%)-eN9=R:Bn6S+se&9M9:gP81lj*h(8RWj`E\Lq"L2$W/rUCCI:Ylb'2XWA?c&=C8_5/P86_fhg05B<=NLpDcR ;rg' SE8'L%mUI-9Xa**8@6'WJ,TTYjO66V`8A#olMgs$2_b".Q23Ai"nNI"4ECibgbEnr$8OD 4]3b=#;A@G-.VYKM"PKmq0P7,-0eSZgl>=Op60pU6=;A%U'LW4 MI;KR#qa;"ILAqjM000Gkq9KkH+;(:*.!c8<1tjH$A=c@Y./ikk)r;ZV*fJ]<(JA$teH/'Eg"Pfo"+8`/TB-r(% l2K'E:_Wf;5t!rcUpA%Fr3#5(\+PV0Jl;;Z'+D''@FS%Sr^Pi'=sGE'&;ATs`;GiaSBTjPkdiEce?k/a6+16dKP.?n5h3SXOa,c@.48=gqN/!sRpJ5G$)J2Y#.8no8d^:fVo\Q30HaWP1+l/]"K.oG;H_4AE,rd]L'G5(:CgAqFsoC:2DtH94<,D\=!CiYV8d0(j9rt-CaR*$#'pL_kZm????VMfoN?tIlB=cJ>HOVH:$]P-1mHoXXZ"I00Wdq5j]E!)&#S9n=%VV67\@B*9?CjlV>AD:J8/o%PG9[lBV'3)!"]%Z-p, -B#[a9MkZNTQ(V>Oh1+L!q6?]jc()`?20W"6I8HA\%4'q9J1S]rAb`Pas.Ts%7lWog6XQ\ *S6dMc,-Rd^C?\@bIFq` 3jO+o,j-29Wp!mN%e3P8_La[A!*UbM+mhJri`a!$#8=\,J.(->;/%$%L<^MRThi"s%oPQ,=?'4\1;SF3b@/$HeC]P&,(^;Sg0V6ZJ/O%k_qF:H+!q<)b(]3>^VC(@e,FT1l6!j=Q\"rVSSZjR9N]_<\s*@15N#06gt:J%8%4EFbktD1BZWA`RK/l@K43K#1.W:;jQE)cN1Cp@A?@RM;<lHd)q!oq9[W O5UKpC`#88Aja0i.fn">`%>+]5[oDL;N(+Bitm"Vk^6VJB-[rJ#6#GMH*je^)pM).U9lZGQXE?h?jkXoZ .G:T'E<\3#0apXS(#()fj@^0A8l3S"e?r3E/A2]hbSU\Y%JY$<&Zd)"cHs`jNf_8)*K75EGXaG02T4GY42/?X>#HNEHP?]ntgZ'l=I2CTa"TJ#fELgaMTZ@X/0%?s3%c&#Xd"$Zgo[oG?)?TBSoC9^%"\5)4Ccs$l"k(skSq`+C;D9pCgi$PkmfV,sBPInTf[s) #"q=KbP\lE$Et\pfaepfX@<=qHrj1) E!A2W:oFRZUed;2ZF4V9NqmU$>/e$2h]rHJ2bl.1H61)5bZ@H4I/e?T.3cN=YA3<fpigZ"fJ$$!$n&tQ2N:fO'Gi(CHMe0L2H(Q8M"7Q\<#n?gHFi)# Vk+^pp:rfc`cAqarbFsQY+;Ms_0/m&d$l-.+SaG#GPR0\K/;H/E9S-9llAZ0Ge&3-[X>B3m[^;$r\NlKb=ZgkVl0P?OrNR(F^^NDQgV0\N_K$8h&.1?QAE/ada%f\"NL&VYpfk_Ah%k.g$VrU%15WYcA"bdAKY<KP:fs9a6db@*h/<&O5t` 2dUJD@Ai. [nKs:3.U9iKp4ANWJEMZN8n?CrqG_Cr/q+h#3L%\)HkT6)OP4o([CsG9@L;-0#f8JNGYFc %o]n@IjLJCg>af8B89D0`mmRsTD6QPP'2EUOdV02/23/07NX]dBAC^CHln(7b&DGV4GdSVE>5MT@:g'<(I%E@Eoih:L"D@)2[rg)3@Ctrb'2()Oe1/7MpO"2A!57c_[-A;*]N_"2&;A/k9=!Ha7BYAq+'1(N;t_DA32ml09.J4RXaI4#NK'=8>H2P8g]9g;_#E'H\7R?1'%l3RUl;WT[i>.YkaKU#1IH4?YI,,CLSHVBVr=S@Xk4TA?%K`q#\YjT$Bq:Sb#U;R;%WZANs+Wf/eWHj*.,ZRi>mh7j$[Sn7m8H_&gH+-!e(Z7TLDOqI;pbJYA,aF<Its&KI5Q?;_E@hONF:Pq(rr`smD9UoHEaqdoj7 qm3G(c+P7Qcm[o&:+LC7]p/GXXH80F33??MYp l_8q5s,)VkZeJ?#s)cq(/fAh"g\n`j$jm;afp.&SqD$&]X,EAK^8D[Ag>MX#t*/ASaW#+)o9gr:/]9>XE_es6dO3RUPQC>]HS%)#b_%[Z^g0rm^q5W>[Y424TcF,mi0<'JU3o_eGcqKE%)Vj8+1MM7HFt5.Z2YcZ?WW4W*m$U@(O1-"imf_%1kgAVHRJ(:GptA!1id\<;'3mV][Q,bqEk%8 L/[KbsDk\h`pirL5\pp/?to+NK=Q= .s[OHR. 3>*\Yt4=6G5&2U1Oqq+bm8dZEH.Qd_Gc)(Ze;&Zn?:jC(3^2-W6*m*5:GrPS(JE&#MDIL(Td&3nrl-ge87?mtq )"(3$r_JCWcj'VRmd-24+.j3I4&X5fMb[sntUDWci$*K 3U:[]/YZLn08 %hb6GRFRW2U(p56 /Nq-Z]3r81kDG#p+E'T-Hhq$"5G"e)irQd0J9"&QB`ZffD&5!e]$];IfWsQU?gLS+9U08.4XroA+;s?0-k2d2R8`.m/UlS])l7$J)j`1:I-tffj$DSX)t#U;KkO/P'0^o@Sj+MO^lF!tAs>m&%XS'RYdC4Z<1_FY'[H".-;[&NP^ ]2nHOm!^RO:V9GEm'8sifqpcZ>l6Z1OiJkCGse2B!IL7\YP'cJ_6!CEg.J)fCi <5.UfrRlDY'&""3e`O"?sD7e:YrWai>;a_Bn#fZF)#8h_G5$Bisde?Jomn^@o'1>5LO`NbpW6?NJ!S5'iVQqi1862S_)o7><'O+ p4$/d!dZR(.&iplrrV7Kr@Vi ^G8?P8sn)XZ4<T^qU .j6tQ@a'n(%*?Grc[>)1L`^F/K1Q?`'8lA;DLDDmp5VMbpi+7GOd2$:pD<6%AM(Mh0kg?jD?NBSFW,6L&[PXNo$YgY//Ac[2+A7X7R7ZP#1')sAEN]_A2[K:M9h9lVE#\=;+Do&cnCp?3"'S$0YsF!7Dt><V:!X%lT?orUNR)A4#N:Wr'FMKc7_fD(e1g_hkV^'-Sa_MIp4BAFOHZBni2f$(1jQ1@C#no]N#j)LV*p6MT_)Ze9rF9ql89QBsGj2>3%2<_@#.W(\G+mcm'+[q'*Oc4a%E/A]MSncGaf;B(',QCGP2eL@%7D+g0%!FSLl]]L*.F;o)qZ@63<&F\).cDE<&2e -(5O<;2G8X5e[j:U]G-5U.WM)5#40mQAUSr)E":a*l7I&W[@*ZlT1ESJ3OQZ1@1cL*Ac<]MJd+%.USp+(=CAcI)_hnADV^s-GW6Fm+r,?$S28i^PJ'GsY<>)7<+b$PWq c'jtT#nr#AXVBFX,pcM`%OeGKWT7/!SqaqH9@X57F#JI*FKA_/1:*s&H#XO;-sOOS&G0i`]P"^1jo5W6>$%Bs:HgZ.9,WK3DcQ`W,aP+4:s5AWjM35_1)dks,7`f-VJOsE;D:c)H=7FZ/VC,t'csDfF%/Fp*T?@ie*VKUWkGTsa<9Ud,l;kR>/7jjs-eH4^j=VF.l@Tl7a,ApLbj,?PmL*t37#R)TVNE>9'LjZl^+@ha;WR'X9FjOU*Ot?k+#YE:7G>nW+<AT'8p!TUpZ,+]V>rDPR(L9MJY>ap?'1 A\EZK$bliYn&5&oT<Yl>P!D!K%BS[U!j;b0pY2 L*gBClCjlt*&<1Ko`FXB\:*ZbD]9K#`-YKZ&+g5h)F/^=97iE!ApL^rdR?1".l(e)t!h<0lg^;6!4@#1jn\Q<^$LBt\;  8`9V<`g4LC(so`<% sAY*a.P'Y=M>q-C?;k!?knDk!pZ%%$5K`XW,b8H1k9,)sEbWjs4*AC;!&H6fafG:Al,0c,eWQ4>,lDnFSf.DK;*`F7`b$WmhO_ZdOa01Uo#A?,RVD=,@H-%;/\CBD/-Jb")HH!(0XgSnIhK[%b5-/h^?Wq0Q'n!d.NHig]\K`5c"X^b"h&t,Pg- W"[X(gqPQF4W/$GtB;%AJ6[#VaHTgV8HNNV2^rKR%R_"MU:Y+-Ms4nB,1#ArtADMSY=\dYXeQ])g\M!2cJg#SPCHqh711ObJk&HV"qQ^od<LfK@:FV'm;$t^k:qE>*Jh2f/+m9;\Q"@IG$0JE/Sis9XS_2T!;K [nL+VWJG!s0&:@klHsX@(f*4R/`sPYR'>8og.[LK-Bb cq+Zt6JFbdaM\n;o,ohqe<mOA$3@5dfO-)pI,e#[QOo.k"Wl2h[Q'jk0[:4p!LVWA.+l\,1cRTL.oogstQ#6:.1=.4)9q92c1]LcaJ-K'n=W!^^Mpg`5/<(6>1r 2p&'i)&bEGE.ftQfZIsRh\C4H=>3M]d5@c+3?F`]MNZeKh:/[(JWbXNa]q`?F4jl8OJEQFI\>#B-t1r?1m_[I= 5:BHcP@3$d+aG"8;Mg#TL4.lT2A"pmGo@a"&nbID9)DCW_SVJeZBCClsPG/03gddPG7D@!A\Y&j5s93d:6kT'LX$Yt7gEP_L?(p.#r=*b-'sc@SE6F[(>4nn(ZoC<8AJ*k@(Ua(mCNt,N@b>qm,o^LQ9W&V^9A5I%Qh;RJ\E+\BQ%IoG(!3GO>l>CAi(a%mmB*\4V9(lAI2J%?7dS^3/b0--0g25foi="!]`r3B`ist5eWDsqF'GNI9q%#TmbQf.L#ReEont*o+oebK/OH=B+;*tiAsbQsnUFeLIQ?j]kr1rjM2TWiEbkmP1]eKPmR9/A]t!Te=W>9A57.dQP^mn2Vob'5jY,5orT*p5*`'@'^GEG[C`A-saaa#cQUo^#>i+4H6tEkHi4@6(]#W.HQT0FQ0IL%=-(!r9^!k2MWXTN-dt^BU/'"0f4tZ>gQ^4/6>3:kb!8h gZ#`[kD7QBPK8AH9/loBF`d+&(.72#=JC!egf 95%>9#IF]0.T-&Y%IUD+tLR1:C\&R!rZ9Uf2>LjOMn%Xn; YMQ5C[f(UhZ3nAb,CO7LW7$^!o,bB5VRhSt"i4i::S=7J5X[ .Rp!-E5#FQN;+qI]7,R(:SX1%qCWK,m\9="cesMOMHp$pS1T0 \C^,?Jt;_Mm4]=i1XCD!spSN?1KInk`qiFiWF.]NS(HN]_bh:VgO7'\etNMBrm,/4>&o`W+tf4 -FUmm5\r3[ALm9[dUJ').^8);Y^`3P'A^iVSjaXGN/sQhOITrQaU"p&6?$4!q6CE)>Glm2pGe-)AX@4V,XDT $`)7npm8=e%*!>2FF^aXQYV_[2d5C7I_-[j]DE^\J#Q&AMW!$W]G3+N,.\?h>%o0s0o\gqVHL:%N]iL=]9,j(m/Ap5moYVK^T"Sc(\^qk1pe33N=`j(<*V:b,(#h;6rS8iq1A)RBW@!G7O&V]l9?B;Mm+8<-fWe]Zo5d%VXW\h9a4%4o`NKq0B/n]i1@%9GQ^2^Q5k*.$=LJQ8kXREg(8RK8c#.^FYVT@_$.N,j'sOiLfPX4ePXH;)c3jd-[9Te2f;dqhqs=S1Xcl&KmS%I(;Nrp,*7Z58NA/4OXlQ?[%3.2co(`#KCT;3SJejOR')!?]^^1^-UYY/.8 823gU]>h=#BjfAn=*&mDcSKpPsL(G4KgA.5%@acdimWp?ef:eiQ*@X)Z)MZ-pe72V)P]e l-A!=/Z<%80KA5*$0F@:Tt%qDNs4^e.Z]CFA^S"JhaB7r?A-n=otK*Vi#)<58lo/R4l).aDAeLSFsno`1Z#P3t2GC3FAal78/hoK,>'/'Z>h`:8[-`^7G-#Q7d.Vp.O^b-\#E:q86[UP@32gn-R4$-dN'48YiPh=Wj/H.K[^>0e],)7j6tnNq=G9(lHZd=*24"@WP!\.rC_R3V>W f0CF;SKZTE1ZgZc?$p&`.eE]:5^?<`]T")RtQJiXFI%U$Y]+cc[ 33SM^_RGC<;&B^XnoL>"4g)6RaHjX:)!P%EA_91FCViV7)"lR3HYXWpet\#r>+f`X&g[tAHI9iZ+RB*!4/jP:Wn?`*A5Y$b!eWe_[Z$M\<`@OQm4&(RWRNg4@k^D(KhZ.*?K#=On8L5sGd?::5C67$Aa[.t)9S\1"(id(R)-O5 GIcCO;05;l4;MQ4)K^-i;UHS ^Y2]!ac8r=K9#i0(YVENL_>WO`dk'?[m0AQOSqX_UDGWBkhS,.@W)J6s0aAdj3Tk>I' $ghFc!V[+,SS!:sAIg*lao;?1Ule(YLR*M5hgS0sRY-ULD%8"6"Y*CFA(V6hW%KE\=V2D%:,63r^g08WZV:OD'?-pdNq7Xs i$aSa^,'saNZ.?M+g!YO(Qs]>N?IUY?TSA)=5QmS!@%U6W!MQ#Q3rS[tnb._ab&BM,OnhAE$QlJXT*H3MH$jKa.1sV+aEY5p:[5LgFE[+n01)l/B6iA'4kB6NV!#.,^LAK]r9Yi?mG?VoM9RkW6j96cnWCLG`4EGS+b)'_!4tAfYJN)H,'[:^'7G02\eEZVFkL^b1C5VW5%-HC5 Rb8"E%5!fJ#@l51_4a+j>&\36@h;AW;GpNcg)QVBS:SJn.CE*(5p'FqT_fe$8=ILSaA]KqU-'S-51i*AQU5d\m<5'VZt_nJFYYPa$h1NWY^[2Pn8rm[^A$K5!86p8g@_m@i6oAIE4ScABg2^@1#5c&V$G%b6qXMEWFP=hZ1I4@2,Z9OE6AjkPDrgAWXS!Qk]M<*%H0ck/5Q\[B/%)R`\]%?/8K-\VM3NF$W1s@Dp=6+bk#H2KV`b989I@RUiQ2[\5LJkcA#MD/ah$-g4GFC2&/>F][OmO0nT'ATVfl+JtK?5OeOlmXOsmW_]2:a-*#!EDefH(RA&d3hBVH51b`JNNcZjFmZW8LhhCfRdsX_;[LPk0^Amr'Y]MaFM>&"Ah@5oag&U>0sgOh4mqCk96t-5CDAAIrtBjMt6!'K(j/!Y (h/'9m3N8:?B".D<&37kX3Vd?kdMId!r2N VO :#/M9pebF+)s8_`k-jZ KhD<2Qi; ]"&.X8Yh=`_iN84L^>.,okJOs#e\:V9)_As;W7&fsW\9M9A?bpeq4[BAJj)^GanF;dRBATt!MoskAbDbjmkS7)(,J#<3n-$hfAM lP\F0Go-'khS`KU^>%d>-ROR%t?Jst90nsR3`9OO+mE6X\japPR"54,(bhMjc$";$h-e_H5=tp,[YicH^1Y`<AXO_"0M`/Mda?f4A2.oYt0CKf]+2D$h@C<>#K5%o%)D>QD: scf`r2dgX">cHlTH:>O@ZHq=r1MS^$gGN'Q'_MHD5n%7m9At6WGIAXS'%V*C%I(Hc@=aKUe]sWo LZG9-?USAg,kG:bZNZ\Q2Z@-aM^l5CFCQKa%(M=APehR>Q;-8-0P/!-'q 3#apC":a*D'E*a9[*!Q^"l-Bf=@@Llb6AtdX@D]E)T@rUe^+CUqm:o'']Tc>hSVnI0*mTmJ@r5`k9@Fk`R)2 ?`!FIV[Km(<W:a`+GdRnS^/q]o<>Ps)aAdN?*,Qk!,[^72@"0Fc!?'pr2jVr;W,Sc6>C*Ttp33,+@[p,/0^N]>b")p*3^c:p1UULHW'`Be"Q]%:>>!lJb:/f`j-Gisba?UA#G)FA^tE[=KQFMt-s-NVI\03s>h;`@E-D6t_6L @ Hq(Yf[.O(@;"R2i)7l/>4_`_NaT19i26)Jr_+d_$s X:\&;O%@[( :%Z-,$!9Ee@r5MHL6G8&?^!Adb]e@oD+9ghjPrk8-A&1KfVNA+1Yf1;04dqhb-<>5[#LJU#;t1K/!e;]$c_eMG0s+F%Y'6$A/5GJ;U])jA/JK4Si03G$`^7A0J@g10a;Z*B3IjG4@@R$G&oYI0W=!m6CaZ96WZSC7"=QM=FKpoGA)m`Md7:.amAMa5BToXgk@PAYXElF[]A@U\>AAU]t>MALHRkqRZ<(*o8coNQks[i(rlXl1>/#Nn2`GSaAE=ab>6Rt_` +=p'e9f#9QVU[#UgLV7IM*&6lRf8(.'-DNK>ZTA;/hkV`1&k+A8n9!6JO(3fb_;O3.[ QX4+o^09RMK0-'bi']\J\g+#04UmYei)g]%=#-ZG&PYQbY34(8D$6Q!PKT$+U2CrpR"[K6,\XAL'El-h&TJ%VJ'-qsL=qVdGNJo`V0bn[)oeX7S"qqLl50T=h*(d]Yo@@C)+)(6QDJ_[O&I=[:(O6ABIPAg"jFg+gm0=kl,GMtT<#L@ !sjU%S85O.iG`1SptR!Bks[AQ':h,\FM_#p69ZCI:VR6M1M/?ASYkm \ng;kEZ"<+31"U@(`*ar^?jd&M5Aie`T.RNs2$H;0BZqep.33K $CsM-4)9Af16*)TE>rZ+5b0;-"' &edIKN(`N7A8)8qsrW>)_s%d4f3o)lsG9jMBG ;1nS^#QE#YkA?,R6R>JfK=%&j]0*(&6p3icNN$h.:P1_t=!00#0l!SXlAPP?>03)\99)GUBkPlAWf`6&?@!l.BZqq8D n6sCeXg%M:EK2`%m1C$_kF+PW%IS@.%9s/CF(Og_:hT5 MJR6W<-:S99' d!:PgHA=.RG6-bUAcd1.5eY7&g]Ca1,;U?XLD]J)\l\rkG=Q4ML#9;HD$> i:;On'i:k4G:%F_6i[FG'2V<>k?^b6.lF;leO!GN>`T]$\mH.J9*mdF^0kNC:24 !5(S@X[AJ7 Q2h[K:1^Ab*J"56tmB%7$Rln"q&[h&=,BYh_At:?asAr#-fM)n]lK@%lA)h=%.%-X+LM8b=K9`6&;$0D,5X$QHS`hNP3m9tZN=s#:5kd6!Tc=&LW7br/$?6YN@L0E4h/Y&:DeAB64,D!osg%\Ij0A W(0A:QVGh*ne^n$m%K0tPW969Gqf85jH[*=2;8V%gpHV3KH'bqZj#i]QImc!'!rKVP5AP6l1K9^T:&DmQla*='?X1SgmA>;@'>K!n7mL%]]L+L_)NE*c36S6pRk.&P,#AFhISXq1d:(E@)ltEIq2Ik&KN[.Ln(AH\qqX/[87\(P]rM3Q[F 8hE:![%M/*2V3U.Ncn$8eT20-@NA*RNt%p_-"W]/fsC(Nop\Am"f.VW[0,jQfLCPm#XBBE2U^sV] GasoT^9Q (HDl.MMKbU,fNR>.[N28U;d>QHeeg?RrMJ5diRlXW4OdOO'YSL[Tj0KE2k1A;g,+3da@N>X&iR*DVB$hgOrB.0q%iA[/LU!#f-s.1gh/nd,8cK<B0p-.p')jE[X`VR6-2V9*0":](e*6!p7sFhgmi0a*q-g(t]^eOQCrO"-[SH0#0o0Z^pJZXOO`Z9EaV`C?^m#Iog#sYVgm-hfNIBGUR3tebZtKE'aN#Mr<QcE@'<M_Qo6<1k,s(8#k-p4spe`o#\eUG?- .;tNl>H9tlP)mr3Z$!'o+jX95fDM[t2"1G?ADrG9j7EM0,;WB-FpEm$sE[&"::Pnqq3/@H(,bW,f/KJZimq(WYlJ"eRMO`TXOpSYM6-Ob&d6S+Sf&+!Yg]4+A=qH5S)3d7*\mdiP?Amt?[ANU>OW#L8teRfSZ[^67<[f: _tX'AEHnAE[W.oCg8a$Pt_g`'hUe9L]R)93.*,M<X0R&t@#q\qkOhcn23?on@ZHTU-;\qS@%<;P:?h>W!-2]Z`.hh(;BT)2V/2m(LY&)<[1I">#]<[nSVMi+"9Nf1>_(KKoG9mT&s&_k\g7%o,qZJDOtRAl[#@\AI&^*fm!No$e7*4r+i^E^T<k>s/=osO'Q.`OSr_Y,L0TdQO!Gt#A)+2t^X?Li6\p+PB-4A(eI4$GBrC47;&FdG2AB.#Mf-_fP#W@ro;\jcEr0/ct12[+N%="D"UF\qhD3nJCm ptMaZ!-bS2:;0P>&[T]k]a$b-3XT\-'P=KL]A%Xh70nX:Uaff`i#Pgf,edW'_GKg7)g5gYt_,9\L]>go,jr!tgjAOlRTI"3DnSX(mtXKlKgA9bD35!>>*1_6/"@)NkVS%mKFfHmqZ7`.LBR;,p=_Q^D63lt\Z("HjpNb\4^0<m%JoPS:ST9?D9YciCmG2iS5Zg<02U*Ai?nLJ76">-<L9\PU Pk?V7NZ'd]t-AZ'dlO+>U0cth)+ZG"<2g;Xc.n]L$btADVq.e"VWSL1rV>=4C=0;o8:9to5FBNO,nAm^Dh3fR1j,!M2*\*;0e(C_i,km\PAn/fJ_^5nfOMk8=>,d;!ZB(#TKmVTo>;U\Ckq5Y>[/b-JPf7L@tL#d6'&NBV)f],\5I-S:#ASCGF!XI3BH^=breg"m8lAAbV0k_BSC2BZQ:U5"C0Jo1GGd`1gTH&N,IhHff.UnfZTB_WfS2Zn.Gqlnj7sZS?L%R_S8m+P)f#BZ,.]jj9;Al#9I";l:4Z2-IMIZl\]4KFmiq=(t1N&BA8L[H0r[Wl; ++?AU3o.A6T)cjD()7_99M"mVd.S#"LIoicsog^EW&k?V*X_Y?j-)4AT?Jr^58IJ:!p2G/q;iNrQXTMOF=JOBfL:ZBlh"L0"PTK5Q`1p\sK0Ne9Jn[I@ P&/e<:,>J!0k0iVd( -oVhY$&PS(>6#6D0R?@"/G;cdJJZ'kpIYjE0^W;XF)@6)ebFR5 D$<WN,Fch3(1j? <0DW?a674XLcm/TTJkg(ScO[?2nlkA6iin !4D"iL!/W.>i_h?4'XgH)kK9].eX,I+d 5@IUTA#m/_>^LdkKsCGg:6%?`CO-*2AhY=cAfQE:jq/LUfKS%Oe_%Ac2571+OS^:q\+JMM#DTiK$?qs2qAD?fp6Q'!4H*<07)Q`Qq/1++o)VCNW ";j<S&+-[ois:kC)MW,Ba'35Yoh1hR#"JlLPpPTXZ@Mr:fW:PMcajPaiR,"+a_3$A%YA]j5SdVR**sM9K!(V/G!#>0_l/:*MEAiXIPP&bs6%ea@Z=[;l`TqM1!o+7mHg-YD?3m%1GS00r<P5t_Y3+jVHRR-*RLOCFA:="StiBqqsoI0fGl!CV]PeACc.%SA"gn%jmS/Fmiqq&3=X!NUBc]E%k!5nZaJ)VVX;9B+pI2fO7Fk!"Afkr05Bg&-_A;IIcQW1EAK83'=;% a.Q8sA.fk2.Qcdm`,g=$CbdABJ)[&F*n')mgl`Hst,f?QW"`rU(a9([[\2Ikeb&,_"i_"r!E5\rhS6>^EK@J'=L"Lk\"A,VSWrSAki;r<'_nj>'B4%O*TQo1D<"\8 A J;Db)5VXGp.JEDoU&cCGK8:DqAh'DJ-@Q@9QmL9"3Vb6-P!IVl_aXc_Y`6,d4W1#9P-[O^$-$XpP3a5TP9QapQA.3Y,>S\9VE-s%!'-:J3[>@E&RU!B^l`5[/]5NF#E)KN3iJDVli&(^APc=W;C\ts_-A DQI1G&DRaQ["gUk'[.-qf<_?7:DTEOcsA"WZVI!1DA?6jC*3"KF1dik<9ZsM!*!sIW9A]?1A3H`Ggn."5\R"m^cEO0nP`UXAT^:r@A=GtfQsYK QCrXn=HkrAMhY24e-qFNG/N(E?tFiAS>++fFKXh_MKkGI$_#BhA]fm7W7nL4b-3>dsLfceR=.-644QJa@%SREh[fB%lQ L2203F:Z[re0bL*j_M<nstP<:#;\VKQGLs'U:K]h&N[Vb4kQ&UYN,-D.[0S_cUkC4G1f70%nI%T&[rTG`WL'E`j:Tk.>qpjB.=$=)1F6rVgEehOOA?,8Q/AL@^'f.=D&;AFKtF1!qa38E_e4EY.Ul/.qMA-^'-L;nZ2+k_!s-*Z\f?P&D9e`+T?U;X%EpP)+m_e`WaKK*S:f%.L[9Fsng43neJVmSA5VhlEhYV<4Qk/0$?7?!OIH7/%T+k;h.d?e;,Hp,FMVjL*]ZBAjbHL8e<:)#m HZC<]:3D\!gsl P%%k+#`ep.P@V8@FE;89DnX/oW*/Qleh*]5O=#eQ,h)6^XMds1%Sc?s*DXTj/F" cJ=\WI%pj;dpFa2Dbs0!g-JcCql!(t61`Lgg s3U-4*:f)@SG&dS.P5i$9[T/^ATKIBllJS$Z9-_!Y7[/`<Ao\GJT>QWbd]X9K274$"[1K.<(j;7 h=::Sm_hEn>l;kaZAnVtEV/C*f^n&At1FDY4nqJ=f=( Jnro]cA&UqH`M+Id@9h7ABJ)2&6%@#bbRJG5reK9l3ndDB]KoBnB;)/t 7QPTpk@6g(?q,eF'"rBXXI_-LqfA/cYARq0Ot?ANt95D3*f>1e'#2o*D^->`HJ(@q5E ZE%&hM'okp0R\*\MAAMoAMje-0SAU)%$\&bJ]49!njTfPEA*?AS`%2ecd)A>j'@S(Sl8:@@?!]`;6o,$k#J,LI`T?.; DaUU9)#^nCkr,-I'/*g>QJ:Ol% [<1KRqcj"TD\'O&Y2<%X0(Am=7o#VXg[h9Y"@1tV5&#@--Sr.(QU.0nf]P,4MRAl7\_H7-f0 \M/l.UUg\t/jI:'Zs!r'a%^o[k8*/hA0g&Ht6L(^A6Z*l2HK$1*PAZCN5fM(G^nT\V^O";oobZb>;#1WeTQdB;9%t%E9PtXBsN'QkjAi_CK<1*do1HS$lVpatOaAWH4`.*)7mP%gFIAo:A37TFF?Deh)B-PF)QP<'8p>A-D)\GLG+o_>+O*YepW=P[b]n++Sbn)0J?@ehKoD?VSmHiK++E\;$,#?,j#Ks2a!c3_R=K-DJ7.N,8aJ(gIfsX3c2)r]W)=@e:!-CDW`AEM-UBa7/MCc\GVGa"C+pN=B6Tc)b-jcR)?`?ljG1'4XU/7j#qFqg8>@MmXD;,%mni&W6U-9%.#A#J1)j6S:qe:7HNrN9f00@"=@g+o'=bA(LB(#M2Q0#(15*,#hI=0ei7nsbYW?rl0Jh2_'m9.CLpb2f^DLI4'h;kDoen2D%[njMd*]Brq',GS%4Ti'&lri]L[^1,llHKBI#LA_]"5F,^ .G&,@/ATTj67<&QA;A\[C5bKT>p$*d"-I?X+RFd=Pcm8WOk-O(+j[0inG64`nWU)>UX2K+8r9]8s)NXL'5L)Tkn/i>P\UKVb H-#/$Rk`J%Sma#PO/=H+gBY"1PWQ]-$?O/Xn"k09lk-i+t$&aEV!:tgY?5>k?Q"f9#HmnZK!Tt$5Yck7V3c?ngJ7sn4L8'kW[U7CVAjhCb`F/Q<RU*3?kSQO83c!G]=76=C6OENoL"J>q/6rP6-eIQ[RNfOihrr%[ta3RXVhh2Nj4A2Wd&<;sYQZXpo+4Qgaocf]b 34B;59\?%Zp_8TBbO/`4g2lAm'H/2%9/;eP-0.U`[,SOYJ:SVE][itH,RW"PbZ!MgHV4%[&-9LQS^O\C?B_YL%W r1/\2l`r5r-eTKc7:jRFI[3k(Bdbk5$3E'NGeg#!Y),<%'`Q+$Zh>N! ?K0:2:H`P`H1mq9kG+',b]^`-TJ6!VDE kXq7ODPC'db<HTc8Y \?'3?CLLWB<58:Aa3G$!YP9>FaE6>YRi08]PTC*GQgeXpnS9djJ\/8B6\i^40"ZC=e[O:-^5'F#3B^MlD(j,SCA\OLt0@bK:_6]i^3/QrapY0OcsfO4F-h(n\FqE5JT[?s?qF._HG JiHBZ`;*b#m]=(2%96l#.!rYe4((6K>DN;40gp@=iV_4=@33s=!+%_Q"N.7W)Hb[_/Kfh_gAKBL*NtJ-_!U(ms5KnL`.37@`C"sO-R#rNf25)WKiB`CM'7FJ,!b9#&+:J-6pb52+F[XBQN4WZG1fJS!Z*s,JmA6[KV`g+q6pq4EAc*5!WA80f_Q[>0]2*[tA<G$Aci\tYO%Z?37[Xl-8)9(<'F7r'lO"^*"rf#h1Vi#6=TtDmi0@#5D3?=^Am`GiK"R:N7*]<"c4# ;gZsp:3<69dbiHc7CG=Gr1Kgr(rt$,e7;.(oA3C1AfXY`q6pO0%rB!M+a_AD4Pj46.O2mI@7n/Q<[@,n@t5C':,T?AN:^[P57m(nl+Ud4el*[,M2jn5!(?2'M\S*7n(EK$TqA?THdj*g"?.YM3F'\atVAkckL:E;CKEA0_!dMc3n)h\Or^A'YiLPW&I3=NL.Y+B@tATD6MJV]=j[F8N'W*nA'hWpm(^(,*p.[BYnF84Bk??ZfX7(/i3_Aj=fKl/N&#kIi8dIAM8Q5Z%.Q2A"KfX/or\San76C0)s&Dlc!MY_R+-f4A.H;'$H>os4rf+#>f;'9)t7KAqc4nj+cB9)%]UrV6P\pS abT$k>HB YaIYN]j3r[RM;I&#`T-ADV52bqOo->D'X,3R3:=f/$Le%Q#g7qb)2[]^mJ<7+%N%%!`#A'L!tQ-s?Ri??bX:etWR_)R:."<%g2VUQEe(&'H%/4k0eD,Q%g9+ %O9\0Jam:+d5.aE+):XrnrDCZ)J1MO&=)5G@`bQS[Hn#E)N_Y$j'^N[&!^N.KL!^YXKH6=JRr?)Qk$_c+N(38A=_BrTSJLh;s].,D^-)U]H!*80l@_XA]<'iCPF$#ZGM'2,JWo=MP'&Y?HlMKd;Q7L<1#U(3f%8"iSNFfh.iFXTSAJQFgYp6\B)[TI)]N\ZNti]8+$OKoF=eI"AhS.VcC?E+7I1IoFV+R`]dJqfrF#@?01]/QVYk!n2aiq3,RWOJ.d!VR&h.RRm5"C1-#hSAI1NdXhq'b.MAP#YF"Zs`R+Uq8tV[KQs!bOlAG35odc0aHh=3qirWAd"?Z6I^.4lb^XHM"'X4E=[YDbS%I9pR[.J"kY6H,)2^Gk-K9SiUN"o/S-;0_sgoNSsh+kp.GAX=J5,E>\l'$. LGU$=Q$Q..^_Y%gf5ft@6)hX;6SSVD(2ES,cA,i9;&9p;U`sirQZ[_n_QP/,lBIKpaEs9=#l+*n=cJ&3bto9DC9UN%ZWiW?l>TE26L`D%lcqQ:U_Cf*5d+3%Il0k9>Y7D[r`#pPm[8,.]EiKIIVY:jI*@tNioeS-plYcaZ3YKc^3rUr8kS$a1:Ulll&Kbcs8a)cCXO.n_/?DKneYMB_AlA"giW'AkkjhA$5#Fqo%4khT_2ABAA^QI 0JT>b/E`r!bNVVXXNG!.*]i!PVfh]MT q@rt@:%d3mG8*qq b<17hcTcU+Rk ]d#.Aj0:Sgh)R^:MN6o[R&2i,+GdVdj-0-QIngWG;N`$DBX]l)K0%n;3C)A6$N:Uqp^=2(XBb!]&AS;Y1-;)IAY(o*3,"JEAmOX O/R`(q>=0P(3`rSP?:`mR3N-#En].K6e/h>Qf6[>WT"*pK0=6cMAUgL/hR=e(%Gg"nED KptIn1S_8P(ab9M?RY#^]G\3s(^qcq-6E_K.]hRDiM"sEU\ UWV\4Q7h;[2V9Z+dj!(E+W/Fl//UFb\`QLN%>YdO90@4O96K;_:M/4)W*Kj2e,QZXo!Xq(l@6<'+L=c_?,B3VA2AS?AfU R`X js9,kLt3$GCS%21rQ9seO!e&@;3AVdl)&3s@HCfAj:H8l,UUE^*b!0Q-AL8l\:^#2+ $KLAh&@C[(Sit(tV27A*6rlR=>7>6dM5hHA8AXh](F(==jB"mT&mA],Z#nU(50e\=8lQj[Y3d\N/XQFsHs<bNM/_:Yd+-iY2O_$QG=EBqmg,[LGP[d0cAhd_aXZ]0+TYT4&`tY'*H)m!ZR[$T?^Vdp,RI;oJVfKp::cpH:\POOh>7Ye^I1aW_BoEl'B@cj'pk]]3EcShAoPXg7jqHI6!KlVl(kb1"]6W?7c>Gg!,;m4<]'.XQ[DcUA.9/UnWfWBf`-%DTS&g*O#NsfW9P#Ags_HW'$%0RpUZG&kK45VaCW@;7TSA4,[Zt,,-@b18*@BY< ,1.Z_nlhV;:SXo&TpqJGWb99j^lX^,qY>%dSGtf)M'FgMW,*c27@0]ACL4fH4HH4rejDXr_T@0IA+LW K2nA^0ZTG:[B.s5J`0 ih'!10=[:OtA*W>8Qin#'1K,OrS-,1GT!,5,+2EM("!k9RAD=M`+p";q!S76o79;Ii7g"WD^DOT$k4X7E&-mZj&GfkZa sl:G;(05#jSq1Fm"Ym9q 5K!U.G%_@Eh]=,M(c5G[+:l-/)U,)Sl*%A\$3rW$X;AOXhAX'sf*7DBTi>9skJ%GQiYSk');4L"tMK<\(HVF%E&,coajVoUP^V_T5?-!MIkCnGC-m(2`mBGWj7(5T?(9AQ )0tYgAo?&:U=Bm"7ia[?PC>0)_qWWUU>/jP(q)+OWn6LTW \gfa>^kXsO^qQlD33@qAUseAl> "FdoEpAY7jtf1mJNj0=!/sSpBU[Ghs\q4j0abhL,A"f,4U:]21a*5!N$p$&9 ]0A;EOf67e\04b.-+3d].\mAkfdhC=@.ZUgng!9dqF$7R;l7)&lE&mjN$/"E,MAsGAQY<4&AF'[s:lG JT&lO=[ck6$$TQl*B@ViB#gPRaNF:oKs?GHXm$91<\D+J#AScG\fPC_!D:5iHm0QoU3aUL? 3WB>`C]7QB]pQE,B#!]CGCK66p%EG6[8AW@"*Dm<8H2#(:Fgtae4#!&CAV*?!A,>/5j()QJid19Wap'025k,sB(-1NVt\KAlm;/6lnQ'=$EoDl(A!I^6?0JVOO@t5Xj6a]glpg`Kb$pAVC`$Z`%*t4Sr^+3%CT?H'Q8:_C9q$qeDB2G@&NAN?3"2ct2!R`J`_Rdk<[2?#'4I-&eWNbEcH5O^A<,45kbAJTng5cjY3a$@#"7D>DgbL_oY[>2N<37$)A1o52B\fR mdT>'igh2Ij)VtGBU\6;<?g$APIHf EQd)f%VgQ0 &cdkjm\W@4KrXW09na.=?s?6\fF8f#<A5dDVV:peYQf+2i`FH2l+5VNKe+JM2i>d6C"t`L5eqC[KAaP4XPLQKYB?Dhmo?,Ul3(f]AdVF6E,#4?N;@+d[fAH`GcpAl j %m>5q\/=_HrDnj(S=l)gqNXXt5i3tOl$/3P!5&dINtg7XbOR)ngTV^`f1!#/[-;Jp%Jf$@9VtfOQbhA%%AbJ-$@/Tgf#p9ndpjVhjT:L0e`lJABr5<-&Mo/+m9:.)>SZ*%LXfiJLOT2g)HM,+D[U=7hAO:oLej8=eg7#`TK/@FFm8/l M"oXQAgoEK(]IfTt16t]=Cc9t1RKc+1B9ZHU9B+Xi:j^Mdh;3QkL42'MUp$ke?IdFVP@'>-W[PqLNLQ>P[P8Y-,ZtJ.2rlLo:pb1AXoKt^Ql]OTo/5DMrp_DDiAi#Aj0];_#:9LB]2%Fd4ni(*BrD=7D*MfeX"aF*0o]Tb<4mN;!J"N#g.Z'8p>8AAqrY0< d*PTA_9JA6<^^cW(E2g_,.O]B8XRHc9 g_1A)f(*o^=.TQqIGp1>6[Hhbk"I"rJ'D3Gs2*IA*['9aiT%<#+UB@_Y!IL/`k: GSk7YW[">kK=YP[aj8^X<`&?;*189@+ 5A!';)=k!n@&>K 99BErIqF^-HYH(tsdRoAD,-B>2K]@SkUBhFWd7/7L>ABL-6[Ai_!!X9khq_IRcMM<_$/Y]rBa@t+ab/`maX2JBXqApHG[0>sq@o]A-"EY7f&\VPn)A(%H65WEo.?d>CJBMnB/sEDOU&6_OtY,.)QE?j-`;qF[MQN?[%l(8M6)6(50.^^!8!GPGer__c-dA:TU]Jd)K\ oC+,0tIjPR9:Y&jMEk+E'p Z?-S?>Mb6eb3(j[+8^-Il=2<#/OH2hT0k>Z0[[ssS% jc&jJDqIj05q 2H)_4:tIeX,9O#k<@3j_kI(\mG`MJRJ&lq6Rlbn(Z(iXCLs3W=D`7O=%qE/a3L@rF,2 LHMlOd/+O85Kf%FH:Z5th-l%DNoKcPk6qHA0 SR`ng%p*^tf^hl;pQaHdRsaNiPIa%H$Fj['!_2IARV6nks2EqA$2Fg)]/dGf?,7HMD)#;=[es(W=gOOrQc%Afp+'Mh<1#3mV71a0a`R(b0BEm%H1H-j-YNWd338:"\d khVYX$npa2m\'p,$/C/,iPijo\,'$+)$VA>fX(BI=5L$Aq9U3j6gQ#&A1,V]="AX["74tC$$h:@12L8BIYH#2`h>#p)8,PeYJR%Ji?f,8aH!N6oQ)I%_d[+0aE$a--fXo"o?P-J/5T4&& Q]@ZH<1hindE]&N?!fBjUs Nt6>.(*Il"`3bH2M;,X[_-tGAY-or<3jPBii^BRB6e\_]%/='Qm?YO=BmQ;\o>6CXb _jV-p9Gi32@">$<__8(mV-2onU;SI4D1 @+7H%d3Na;"0MRd( Ip'GR;Y9-U+%tN;VZVe!C ;DKo"FH69j$OM:8![&VrKWlmb`m )W_hT7m1Ki"lERR )P 7Roe/E5T+Yr6 aF/*4\VFg?),8H'0<19moRd.P:>;:37Eq)PLcE(m+c2_i`L9Et+a[%QA#dhT20^;fq4Pi.b+dYh.fnaQ`K&_s$;7+2DK=G2sBY=Q]D05AOSgkW;gMpJk]/^e_8Y'HTa@hQ_4 F4k[Q.X.gH9,Z]MBh:@O,%m1<&&%q87meWipq8,BTSRh1jn2Tg]tJPjU4(J]$PGCb!jCYjt(=e51DQ:%4ce_e#61K!brrMtO0K^)Uc+qA:"bj:P0d-9HL2oj%72HJGJ^@Q)m7A(eMC"AM3CHg-@6plUUiJ-$M]0V!>^E?\M`Apcf&@YKq33(Xm]O`:ARIe@QAfsF!.QnrZ1"11A;ioWci%j3rETcn.?8[-b!^Am39b''D _kt,;D&^\moFpEbaFQk.iL0gsh!7`g=!=Z2mIS/Xi%A,sJQnE^o"642#0$%?"&5of9d<..7 $![*BQ#DhFerH@#oL*K2[oPr=8.pr>,Y%l=Aqar\;_UVZ]YBDO[IjF*M^YB;>ecZ@OO`!t#!jV7C%;bAtf%:gnfgDhkb"B=_pYmF6%WE@_2gV9-+<$cCNL]oAaM&5)m.GrSno/+>Q:^f&POh#KblmSf`3WtZo8.\TS[.6GLB+a6"%m3m38>n@KU\K90Aqn5j+,`"\F9Ya%\@qpK=Sa<T!33fYi=[2jmA,/$ r0a.C".=aZK@q$$ Ecg_kl.5^Q'Se;=/UT.age >g3km P9- 2,^RpC[q?9r[:m GcQJ/.M$OO&b.r! /X b.[_\moe/C-kSpon'7eK.g\Apt]612!=B7BS+)h*MY.9Y5Nq'5l\?%6[Np&!o\7!B)6]O#nDP,MJ-/F4PKCL46[EXg->I`nje*+1EJQ4_Z!W?98AD0t">@J1S4" 6DnV-?T*r"MH`!$Ec6VU)2gH##7P !/.Z';K8R1Ns/$0A10KQ9RTd/nel7AndJRfEAf24+#[C/c,WeEn4/Ws ALN+QJ!Q5;ib-Ucl5>O\%0//.fFi\S,c)%,K!,Y_6n0^nD5k\;nmbSLf_l <Yf.cs"o#gAZhK'SBW1-'&q:@-p65!GQ_&Uo!mN:kRl\=8_8HQLX1TaOANa/?(8NtU#i<^T!&ABOS9:^:PULc"ghLa6<9ms-QL'E0UWUbYIQ<.hIbP]JA8qgb17+l)shX(Lt8D.8?d+tq$Ym3bGk9Ng(Jq nOlf=C#O9+Q:k^cE=,]+c^T2UY$GmPqRK:1qdH&eH\b%N#0d#%P=%5Y@pUa(m3J=^.OU97naP_H^Q6=X5VgnEB\Rc\R]_rPPF +CjPJNLVfJ(^M9:L>C:RaAblU+[7UAfQHWP+q.`rT,PLWD)<8PB LH@<*lanqM=l/.\OkXJEFFV0tA#2'o,Bt7#PZ:bb3q0To=)S%N&rL30f.Id4o,3Ie1Vt= '^'3'^i9psXE\M"MS\,?S-Z nG8[C&V5TMabH4XVi9Gb.GMCP"D*ma7(#;nIn(WfG*hp;_2HsUF#GUd#=&7XL`[sVMi%j2)/-:->AUAHiQE"GXQfp5Z^@TKQ)YJ3E,)!AFb\IW#ETD$NZ(<;)L4D#Lofa=)(G7QR MNZ'[)?*"K f3teIhHA&A+Z;gN(2Db^A,M9Ak7 92o5EOtEhe%H4AC">Bob^kO_ o2)`2'1Y81je?]k_Pn]cY&sg\pb?c]"_ERiNa(5Ih$?aj`>or.b 9ef3`lX+^WpEDP"sAK7E`R?t*R]""hf\a.5ch9@FNE/k`-d$lO4,S"PLKkFo6pmpNX?-!.fN,?rMeIA5;^:m5AKA3h=<m6>XqIRgrkS!XW/W]RtKDUVtY?/Hg% ^A_#tU`%HI7`O;:=fi;CO]t&+=cWkkO= qW<&>Gn4DbX%WG^@LMiOA:DM?F_noP0[ti4p=eb=jUlQr-%?=tI_*h;j,FGg6n'[1+/YL2e%XQ%5Za?H1 FijKT=bQnh)Y,L5jJ'i(CiWe@k V3I(3\..UG^D,1c$8'^E"d1&OPb3+b;9'"4XIGCYW"3rc@7dn!lHr2NVI#-@GlePX,B^-/%GM_?AWi>=UO42JZtbN[=hB:__5lCt+\W_,4ABdQ,*aU V]ZJ8>7g\=L>KWe>'!C?6+Z)-0jRE&CA-Rps5K(70Sl1roE&LBrla.XhSmI\UtL1mcQ8be+cl4S+-aTsWbdr#fJIVl37Ap$.$"jJ;B'nQGQWIXlTh:(\9L1\kq'h3B9nm5h?D0F6"mHe:8WfR,:FZ`?B:Ls;/A *\FIk_&W!4'B[q=eqCG O74/*A)T;>1s$\fnot$3M/YYiY]U*S2808n3Qfk!F=@lZ=D(\N6ZeFj+6"g!$.Q,J*0,IO@Xc0m+/P )6J-K_8@A,(]XdT]DQ5NdUq)2]a ARkg"jCl.Chf?;X+#Pf4UtXtT_%I$L7&;t.4dr3A^eWFCM(l0]BHnG"r<_ ]3+&RcIbb4/sFEg=Jlo ZO+@;_]qG09Pf/iN+o*njqQ*]V6NkkH=o).iL/N(eaS[;Fm37b]/hhD9e)Akf;iWg:Y@#=RI`ke$N(M8/Vh[ih9YeB/kE/]6ISo:h>t4PVNP#d/I0jN]q0-]U0)5RK/B8E\ D6.O$J"^tm">HrScj`3pl/G<h+mG%\Ki2JHQ[&VaN/R2qUiXES^'\*L5AIV9;I/Kj>@m[_tl7LZ"K_V*9_:toSt`Jb&HKZ59Jd)M.U=2L*MK#RK]D+k_1O \rN$SjGgbPH6c4q&940efHh`_6pfr<`;mZ!+'%QF #Z"NL;b2tObIKb,oX_<]5?L:4H@.:^?Yr1N0XKrflHFe08O8iAoC&%_]5 rGLQ:;+];W-d5Xd\m@cMfo]n$$nbFR$D=!*sFI9g=t:UA9pGhX;Z_"G-j[XieTA@N8=8)$VV R#seSQ/-OO1g@ho:05*ZgY?=F$L$8FZ7isK[`M[P"#r9.8ij22-VnZmCmT;Zkg]fT_D= kCt`_MU#4HfD)7#QWf8 nfIKPKFK$lS=$n!\5YB)*/2<)1iAU2"8;OGU*M*j%A `i?USbJHUGmrenT3\=<k-J23`n `r\71d3Z3qp<;*oA2Vh,rd2A5/0%BM18]8j_!QkDN#6oTX?E9E?bcPpA$A*VO!nd3?Apg60\[o"++YAJEYigSs'(p9adY[0>#]A3NM$AnIAo J9E];p^10fG?g./pNe&$.o>&o>1eI/e &n^0m'Jc8eYdG*AX4lLWg9eAJ/d5;Kh-T'O%I\0)\("66bIG"5+2D@,C*tf#)_]ElQom_j%%ndqP2i]esMMcetM<`?5+P>K\?9?A=$*OQ#UA]\b[o+diY#>"0g8S]475sOa,-^)"nRcF+)ALo_FpEA,+/j/5!/4pR l<^g,NCj)eD]OW,-T93p+T<*e++H.#Y=/HAmhBtKs!7jc`pf6kV1aEA( 5B]9KBeVop.NV(:%GT.b.Fe`RcrX$-]aYZn$m@4t`7n[GVNm=i`0sP_$[;,2q=_4QW @bTWV`dCb8<^hcrBaqNB59ERMDEP[ps"4lRM0R<50k>osK$U0s's3A_n`1]6igsA1W1PiqsF3X'ccZ/9AO,YBP%m]q7N&+Vbcbr8_b7X8&n<3mbD/."]38%>p=Y!s1PhSV5ld+qO2oK/t"D2mgS)r="TmFF0^5 49)qG-GBn/k X`[J,nI/.>Wf,Cm'mI7B9\PX=.J]00CBkj)IoSG%isn6.K`cS4.rX-c#`.IPfP:I2Zo3'F5Ybo7Q4.24%+:1Z#CiiK(Mf9,>VBh'qphp%]56afof\X;UXnqL5&qT*f?%g2RT5AL R $j!.baUTI57,H7"[m:A0g;KjN,g9X%4bZl,f=nQ6.r;$'2=('\pb5&1hAfB"A1!F2!Ig>M5`Si;dk' Larm2<:[GRk%D6WCL_%K*to=+]RhCCqb(\EZE#.XU\geYpA]Q-S\Z24Pf(.FI9NopAptQ_94Fm#:kFBj;DW'K$a3tAnF3#oY<%EEiskpRq-"q_sPeHPIZ]O7E5E40TMV q3kU MNVRlRYRWI?tLlsb!A&-ZQ2Q0:j'AnA^NC*_N#Knf%+RO6EWS5b&s+hp9n7Jjt`NBHoTa5>*$C=q5=Zt[*jhRQRYX^#NaPfE;WB>NYk'PELnsn5.a N(8QWAa@VpQYUMO."U_U'j7XFVr]T ?Pk[HDbi6$Y8)8Jm8ahPI^3]$lLeRte_fA7VA.._H-GcAtMsC%$k&Er5QY>] $eLqENb)rRA&]"L^!0p dUK!l1NUh9N\@1rS1MiGSN4r&B\Y59U38)E+C:[(=bi)ieLR?jTRY;6,f%A#^(qC%j&2:[bDN:o*thZI,HHk7`?o'WbA=$TfEnGj3&^@<MrOK8LZsF/ie %+87>agOQJcpQ-[)W?IgsXO4Yl0h;fnKaDU5oI&FdiOeC$S2=p\SPR2C.pdn M[.65Y:b",dsJQ;acF=pP P)Q=OZ3N3@kMp\GdI4a7DUF-\r=^^jJcK.V26Ul#2>=A260Y8P&,g&aYR^fIh(rV5dRt;IcInk8E\Va:++%D<+1ETI>_:#"mjF/k(SYr0 +-@.+mWLM\=p)%XBFN/#Ao5MX7>$BFYkq`<7O9[;nXPLO)Fm$h!)[O6V(/hraN_=1m4o1q6benTM+U-FWJSEtI$&UKQ69cA;Cf5qOaE\A$B$0W'ns/F1lJ3]sl"q`T#b)o6@CGfs3N+i#R@*dsA;bicGN3I`ABl0pN1[UA0HKOa(RKdS,>o`R>?r-D'hWG]iTIAA&GJ_T)!`0I$Qe9MH[]3Ar33D4nd5(g><^5 H8-U_0 5c')PJdA73oOW?I],hh3C1.m3Z?:AcWU=p&7P!<^>Es_NeEiN-!$S1=r6/4WA@`LamN!o7>Am%Z@"\fn*O8IqFGp3fr6SGN*6BC/`R?> bt\R3+3K`2"C&AbU?>pk4]+MjSTrHs(F-Y.S4[9[ZL\@$IIB[W, 5.AWBXqJ9`,9 /k2)G PXeir$/jEdp^rdN&A JfUa(;<6\4/`_^OkN91CJ*dc#bjc^31p*Idd@hkSj3)Ft^P"oI*Rf%OlZI8n):UC`R9M%Yd$>"]25-_,o9"[bNAm7!@4HeP/9@O>rR]HGHhJmqr$Wnh@:Uc6\9.bB7/-QN,3le@Zk.T"#O#;g8[lU&3J>U^G;emN)b7gHi*^i,h(^I6riL0q>V6%ON$[5 VU#k#O&KGXUBAoi":>TKBbOld8Cp7Z*QedV!)qEp;GeRmL#0L1t)Bg*SEp9ZFWDZ!pof[[tfifAtE'[_M2ODcYe8G-QP\%`JimAQM'2=bQhXtt.=]a\17:QZ]>^[KgnAgU=HPk0\Jl2\L7=c`E.=*?kij%`@&C6fFG73qHg$%KAP6r4CFOi;7G^Y`3i[2Y>Ub&rLr7mp1>Y,F"]_0G!b*/(rC$Lk5F%`'BHD%AU-s%oSq[Ti-#[&^0Hr^j4b^+d@1)J'onFnf"KL5;Ar=Eo>,"#>TGm_(Z\/M>JXZn!-i,;&[Tg\`TqnFRTTAR[7%@_C^kA_nfNXs's!f*G;-ZW=,/%mfR?p70-Q-iA`"Z4:qM0SX?tB?ao1,O%ZS4aTe4[_(P6*g&7,DPj%DKp]oDtlZn9sgcK&jaFE`TjQ[B]05&\E^n4@e*hA]ZnnhoEA.sX\MJ%aNJ]NQB3WH]`[6d!$[m X ?XZmc41Hj3A`gd\,XKf#X)oCp7pgFt*OtSUEe>SdPD`.X;b)JaNA\^n$Hqq^Mh3_r?+eHn,8$5)cDH)M-!eWgOZ(]mlh`AJ^,tDp/$$J&;pH\%^\Y[API^i+AHK/i,3?26(PW55Hd0RC0VVPF?@Af?AViM.k brkN5LA3M?g_dD+(b8.tq,2S"F* Xtj.VbXlpKtTmP,mHh`)HLeXP#tpcBeZg-K)tlqbaXl'!E9%Ejo9P?0<=T;,ANC"5Bn#^H]?-d9!Se'+mp&o6YR(m25k2Rf@`CFUD[kdAQtj'I%NmQ/`W,BFdMG;;P%XaZN@D_.TTS5KfG3W]br<.]YjY'k.V+O#[0l1O &#g6C5AM(#_I.*\F.No3^C#s6][S8\MYs[iG2I2dPPG]W5JAVklQg_EG25j7`I'(jKo'IQ?0D]L#X,pf6=-RSB9j),A@6.+@#EM(_esBY)5>PX^L]&F"fgaFS]2TBfVJ*BEc9@>K%D#:>Hk9R#n8Hj;n8F]:;Et8UD)ArC:15Q0+1snt3Dj&\P.<q6r-@S%abjA)K6qe*+\#tIlsb=DQjS=.[[OD;&k;T70#&X$'A,>W/bPTOr&dUS..Z1GQK*KA(X%%$k/md0ZmN+E21iLMiJK'GFdS'@5L5!$j!JD#hJ>9s#UsqU':$(#)!NoWq*k$=hsXj=n`,AA6AAP"]Ak*5_P>0.VRZcP.A?0]$^P.94Xps^Me753/ONH_i*`*7oG)l!g8CGG%=1-fH^BIU_t\#?Fs);Gf('Xbae<<=:l)j#h\e;rY.ZU#F!N-:o.1-<$Qk. /M!rbGAc&r%=Vj&_,i-+M-"G]fX@1Aj#j7J+$/5hfbHUOA>bmb(7]@+jYCNCg>B>9M;0#rCq5oZ]r9@hb$e$R:P"+2D,'J '"ps:gb'TGEc@'t;"4DJ^k6aM-)(E*pScW4dAq%?Yr^,[!`.FW3q?^6aF40AYUWn,GM$Q3ZN.a2Oi).1P$>s008oRAV$XmF(!X:HeF:EJ`E$tnj,RSAR(`(Z_2"=A,)WE(j65.=r-3t&6b4[>/EQ5Iii1OBA:o;''k6q3W$N"+DnJgNKN^2%:[Zk="Xpn[f@7#GLKdFi<[>ZO"Y@ 7R#Vn5DNP]kl.6?QX<]JJ>"U(G>6;TV,'>X`N/>^<6e]Y=rEG/maO*SWSH5cMYhpfT:%TC3TAgm[aO&f2R"WSX39mtB)ED:`;-;W*7?*Oa6_I0YY[HPeFAsQ'A"5s_f'H^%BUN]1f\] ?p9LX+lWWreE"PZ].Ef7Qe2P?s6-^$t&'T&[0,EaBKthk\9*AlDW$s)CS[Qlib6-r[q@UshcoJBUc7ndrtbQPM2K#CBm6SI,i&A5:]>C +4_ZC#R%:mKOq0$FmMCUeP!Hg^Jr8P:% ?e%Jq19AG.\OAbFGV*\B9Y.?j98=S=bJQVrOjV&hHGTf+kj6@%%l$El[B-U85[bg""pjC6;r4Ya[dN`#[N/$1\YfI*l:DiL%?#N`9AHh6A2rLr(Vhc$[Z*C^U?SM1I86hto\\Tb6@UsglAIo%L\"lbh>h]G8/s+4)a *4olRYgfXB,!]:BDb=DA)ICp#)6c!BZ\])'K>PAX$,'0]5^E-ZI>MGac F)Jp9mi=rhr"%n[W*BMPIHkU"_:]Y?P*\N]AfdGkR?HEoOn&Ge9)BkUjH ENcm,MV:EP?QB>0B!SCDoBWb%I[A"8A7Ii5A2A)>e;ViJ#bC1XQ.g9jqLAO$nQe'g@ISjnFkg\t\Q^EVg:e(XaU-AT2,Xe.%D-g`W$PFDP7c_C1ln8Ui]pp@U*/2)'lc3Q>J$_5Nl%.a.=1<<46LR:WBdA2ETem5-^'p[6G_n;\gN=)N@E0DP>kfn!_46eMq`2Di4(K;+1G,X*!KZ'&(Gs6IdK_c<4n)p'gP.K!hp%g2+'pAHPdX.kq4.H10aO($ns)&JtK:2?^X=L$T!nd`:oHb$,O/$PM1 hGkFY5mi"^ZHKFN<0*\0rkWB[()Fg.1'^8pd#G`sA!X'r,o0[eiF^CM%G0pmYKKHg%gIWJ I1']6cLlFKg5nW:&:ofb+Ejk&naPs3iQBTG7H`.UDg;n'<38XtqH6-NX!5rG*h`n>r@'`.c9&F"eG+A?3G![`;O%*LiB;koOJt3a,\aG9L??iGc?RF,Y9)FH 19=WQT0W_bU -:J/!3Q(R5f! gD9&5HK,$B=d)1i-#,bT9Me9+PEY4*#Lo#bK6(ADp+_8MLO0!R/esc`#W/,ksGpTGJd1k0Zl8dk"LrEPI;`VfF"&]`bl<$9A`NPBAqEV91:IH4-mH-b$?W7oHKX.07\hlj]G`&QBi 4R@+l16$ T&P7KhnF_LKNG;DtSR&ch&;j$&828OT==(BMt,/WGBil%iW*j,HZ=HRO.TSV7m`>kbWTo9P$;l#2;spkK\j>E3?h-ZpNH!:&50TC]\&0-%hiHeZf4j<39n1e_Bl^+JhkBJA? DAatMI%1rZ(YF C_c!2D+_`t+kAFF=9@S)fjBPD8L]Oj6%J"5A S`4(OidbFqk",r-O N^g9j$C7Io9^!]KZk"s:m#90bM]D5E)js"Qa9+lk'Xb+ONY=,(-1 4aA6OgC(qdOV^"N] $AhU-9&2Kd;^UM9K`7$6.W3F1Fc\sp]/%]rG-Fk-(jj1qNr,5 5QqnA]@A[Nt/&0U1?eA?A[r6&Bk3,DjS17B@g4o[6Z3lAT>PXK"MG1fl`U27L-7IRk-//*\ k+6OJC1M;X:XY?s9-VjH*AOQ%QGK#o]bm$,`hQN&$0QF_.-(2`$"cbE0jQrH7pWZ99Z#%]*s&i/ctQ?r\9K%gjYMg!ZB48"q/q+n.fW6'*`0D3]gGFQj-B2X`&e&*Md%lgf-2:>lk1AH7h5>6pL3p"PSO)^)!=/?7(S:5%fpb<.]"!frm;o5/.qtpr4G,=Et+A"-_VS:Q2Ph&A#?p*FVUi9OPj)sYJK/d#Pj6ZU =gXMCK?h$WTY:#JjN=AA]K.dZY,B;AGO56C(c'g]$P-(\/DF*X"/jl96JA+gJn>l;]RdWp6jH#pNdt'1U7^4qgNl7K#O;PA&\;1a/s*,PmG$BZj6L,5+dO^Hq($;\je4;`5`D<"Y0-[o1_6\r.AF.emOM71,=T])=4RlPMa5g6.)mheX*t6)M7cVKQ8LV!BEd$R<. h2GqHFC0Ns+s?JYeXAt"C=H(apc;]J0pAnML& $Ma55qhEp&k=:9n7mPTOA7P8rS_E%an7;M^(:aY,D`U?3YH*^Zh)^na=bkW@JOo&f?E\qNC+Z(ck7%Z/r8F]c]M/si't?:2I@;o2?FT8O1,iGhM9Lc/^EB5lUKa-Ilj_f'b?KH6U)A&A:YnG.k8;.gc#iYhU/5PKO*2CkC)A=Wm9hAF[I?7rA=J;Mjb'9n-nQ7c?_Q/$L[VOe^_q;%%t)@\A;G&r3E1-Ce6hG(sYt9)qtJhs!gjpPa5H=Y^sj`7M:3l')69]7h/>Oo !E]7oAFhAf]O h<=)V+74ipr4'OWir3bB(rp](X@B9(j>O)&UV29,=r`\E\pgD6aLVO@4]p=QrA^d"48KtpS=JAXLU'U)FVN4mQ2helEl]%kf L/aPr4R57HoT+(JOA?Of>:BQ_fEV==N#Y=D-!jeEcm"U,a7HE!AI#Ap=c=p!?jq8rl("H/m*:3iN*+YI"cm?&!;ESGIao< +`8Uj!FAiL+r+lD(oh(\G\U<-mb>Zso$QRskn#&=QLl+)M\&D,mmcP(G.V@Q&\l6]%WSNUaJ1\EV+-Mo,H)f0c<Z$>@?=/-?hU\8n T8 9o4M.!^]X%i5VV7kL[l$UT4?D!aJH!:Lp`MgXJE_2LYVSA0s%P-a0[p596d%s %V!@0t5O#e(+ `E@" X[B >tQ>ai%n/D=:Oi&@%,Va'npZ so4N$!)k,_h4mpg ClW+6jrf^rt@\7:L0AUVG6j30g+Dmda`I*AcG[r-J^]S5ER:L ([\ 'Oj^$!PT^/K%qWl&^VLV@'Zq`WcbF+tL`M E#RJfj27.I$rC_hh.W==$s>Wo^8U<`3p'\)>6#:Kmt[IS;/FA1c3MOO;15qR\k%b74fT`^j8NQ]kbs%N.5k2))oGJ]GVe\gY">Cj+cc^:RgbqaGOG7*aPjU=4I1h8%Ym&)O/^UdMO]s_i4aCp&:Z8C2`R2BDAj['ZE(bY 423me^/KaMH04tC(Q>3 V fiIpUX>EKdp_.bCc2AWW\Tk>?KA-Z&jX$iQ/*iZO#HFd1:SrVX#E[ZkG.3hbt@*r44i4&XC/K]9%?Hs3caUV+&fIqI21*h4nnW4tVD&tVK44p];U,Y;LsLM8&>4l3r.:'YiW>)q2=K^!3h9O29F_m40jW7Bi##fM1^DnJ5oWrN_O:d;&SX=e=Erqo;JHn\o9CD00qVpT4IjMA`r1')8JY,(p8d5FAb1ERtAsArdH+)1!>c/As.1Af4q,Ads//k1^V%4q1htP*"KAAU$:8Tl#Xp' SY7!a0h)GrV2.g'JmbYRLO)LRA<4b>"`LY([l!QIeWG; gd,hdog "Y`#g+M:b_O0"\.f9E"1'O*o'eML4nD@:ARo5/G>7[rpTP\i:7 tU!rb#sBA4EEN)o)Ni[ ;2/-_A>F%U)GMj c[_s18UoP6k-A-t@"aN/KX9cA'Bp'hAc3Zp'i.O(iH=o4b5JRt6&`C\RE8D<.*KA_2fRf-IR?<aDo#7oeI+ @cbq@6QnaPeG+q@RXQSS,A2]J:ce.[VMq-8H$dJ2?YPGfr,$a6gXYkkZKCoEYMCe*HFbQCgYn$GfFr6ELPGH=QF7g%p;aj)dPeUmISchF\"]6P'FAH0f7iDjao-n'[qXI"PT4la?DUfc9k?'m.-N\i_:dC6/'UfH8BSZ!rAAd/+58iD,\I;#"kZ-NoUr$*li&@'0d W'RnmA%&+R^lS]WQABo2P3P^#>;>N;G2K-fTeXB%;%8fn;A,Q%%ns?><8o *QJF]rt7:1#[loX+;0\@"RL&[*9+.d^2Oa+2cc<d?\&kY;#g&CC`ik)@6F&mP/(#7>$(O>kMPCp3&$1aAV&(-aL^I$QM6?5UnJ"@]_Vs dBbJl_681=,g7pNAcVD@6MFFR+p=Na^QKhb5" m)1P&9d](6!0QB;@ZNN"[^RIGq?dteA/H&Wg?!NmJj)n9j?;Xrn)A.G000"[?bIi982-n6rAf`gnb]Li9_pD_00p\O!VJD#RJ:SM7,.OBk$a+/%ehlgR/`-a,3Dl[6U437I(g-dFm?3a,"0WAS`MSdckj;^91A,DS_jlfSnr'NBPn9An^:<>2,tT%e2IF?MH:%T:om3@b-H's/A8hT+",Ho@<0.:MHts;XK](7P9ro#NaFHsR6n#Sgd#56*RM+t95gWAo6;/RK5Z\\kSam[(9@)/;_!H]eXco]q3+hUF Op8eZt4 `OKe+LDOF]qTMDnY9!M@Fo_i2LFLsTlnM@cqcl(t*a/Sd$Vl@8Jj;a*@diN/...8;bboWLH ";eFtsQ3!S/U;]UA_n@+n2://?H"OZg!t/8BY18p7HCLq,]h/O$M^XNV[]B$!2mKZ&Dp#0dPk1lc\9`"OC!j^ KqIoc#/s\GAfsW18)-XA8fkOT7W;_BJGar%p`pQGl->3%W;3kb`NBh;jlPKtiT?opK"Z)m#(?2jYIt;c_Gi=m)noCh3nM,MURUo'"-A@Q$E!/YanjTG)F'>lV I!6D:6iX]8;[">h:$aQZt[I8J5b5ha'':)oK';Ah",Zk)mj)$IJ]53kP\9%bPcf2q1>J q;4c/b7U 3]5<Ji*PH&"e!2&i%s,PV&:+mM&gT^osaiZ BA6 jIsjqOJs[*'2pJWZ2?!MPBB[No_QWpD*8=41&0ikriorRAi3[QaID5ki5@SIKL-P7`a h9FWc./jQndQ3gC&mb&>EHe(m;rHk*JWSC `[`6o'U#MGFW+=#%]>gYQda..\Uai?714@2"n`26b5N]AKfOa"@himgc:Cf-?$K3*Na%'2P$R)OmJ48%&[i6c?+#f4@t?A!jBGktEl?gF^"=rbPBle;s0WfFpiWKpOO;#/5`\Qnghr'\0&QMbrZYB2nrrB"E?n9@F;/:;!H:/a5`YB4"L%+ Vs)6n^F'R\fA(C^n3f:AM"`+!#Pr*!k='5ZS'<lt8a0qpkHDcUiL')5+0S6>Ka-B!S]7\]W5DnaQZLXfeT0+l:PR6l[ZhB<6p2m#$XUl4K=-00dVAat_b371"\eYVPe+kK'?gFA9T;PAG5SFqN%;Jl.&FP&G?KG?`X,hdZQr"3)D#.ZrP&"eFHP4\>,>A9e_M@,51:Oc6,Z*`m?k]Ej@9B/l1e[/NSA#/PDK`+R^Z0:[$_9=1R,$!PhSOY_#c0\<;"J$tt:>s.0Vn\L.V07Han]b4!Ti"d,M%5)AC(8JohVLR5qJkkhB 1 4h:t()$A0d4>=k`nS$<^*T`,?-#4Lb/A/HC7Jfnt$Ys;@p6%%ofb1eg1d*[Ob%,S?DP#"[2Vt3,D[A'')R>XQief!P!GT>PaSE4cD&5d2D B=1b-*9`kAinr6pYq7QA']!%JA\b;QE&-B%76m*3T 1d[lW@nf(o(264V s];P]5A=;Ad#a2BsM1>oF^A+ 0fTQg]\ofTp`<&_e[A>YYFAo7b%#?\QUVS]l^AQ7@a2>WDBm&T)[CkA)H>h7q(m4)-Ilf6Ah%*rZ&Od!"no"AFLQFg\]ODV+j+_/Y#%c7fLZHD*USnfmKn=W+J%Y>\$H]]a&eIRgLgm36@KthJp)6^6r:AcJjicCR+dJZ)8AmNFH^MkSoG9G72Wq"oRn8bM+4Sj0Drg&)b<9s>+SJ:H!+B:.R$rCl%@r*8VGd7lmX[/Bp(\nhtU9No7OG%Z.n%!t40&=RA);(h&2re#QVjaI">Ie+&DpW"%44A@l$_?P*S.q#Kp;-?\1<n0S,C+^h;RfAG;@KdcrCfFcYOl3+DW!+89kD$>`((G9c\?G(O%^A6I1(%j"6_;(h-oS05i*]PVsl!B1bGr+,#F9B"Trdq2\#rXiV>&q8BTf8)ZPl`P[0dd&chG=?GiW-LC80L`6GP8/sf:S\/7CJ_,`sU!VeToliSQ4)oN,E2CjEt96D'A'$Jf_GHlPW05caah,O.?AjL3EcW0 U7,qU-E!pKce(2/0`8"77bgBQ*"q2Gh.+[@.E"tn=X0[h%CU1g?Bk&,>2d7nS5qtU!%?b:3<7O[!Ym;Ws&F.bq$$8V/-@D38X*<\46*T VX7rg$cCG?#W9 =CEi(:AYk38OAHBbo@6gPSM\)FF29a!l6U9A9iFq..l=45o23O-Y"ql1KW?!;O=7TFBdokoT5s(XkbBoRGs7pZ[s]k;;'`i*2olK%K6=]eapN&*G/A30`..,U+_n+;Qai_1\t[4%iXHT''ABsqHAWO4c7(!sY7@DAt>rS^`LJKmC)62:KCh!L>1>M0Zplodd..Kd9 U^c=h)_c0->jP=W+9Ip=c3q]Vo93^ZMQOG:!#ikFbN[dV0*+sK]A"q^V?e2?YbA;()aF5od-c;Uj:(.d/$C=\o-lHB)4+0KiAr`>Y%A$A47US3H9Ml!/i1I=&!Gsn4T6qY/N1Qio+m$p9'F:VhR q&B>XDo6'$>e6pdh*WYB7[5`k^"HtY)0?V]2_>BWto!K599ds]mUt,1KOt=3B!lcQ'E,>I"A?O`@9qMec$5$U-5\3pE:TQ7F9+]!"p`K=ek@>,dC#O/$8BpkYbVL\*6Wi8f2o,;VLS@RHr(]NkRQnk?8IL0oKLj'*N\Vrq:AN)aZ!"i;e(D(`*F:_.$f',ZEg]NdGT*S.:A6PkGf0?/@dmLP^A) Jh3rjQ0-kZ@OA^T41[DLG)O0Jtg'A#G+c2^X>l8g]1A\lB*)c&bnG8imS[ocBS.AXL%K^ .*L2`,CUAE.'DkbK4LZ_@)4MZS:Wlk('RHFUO&WsM;tK5fL5dm<-G_tmh><M48CSG#aDd =eP*OC;Sr6-64e74'>aA/"Rn>e-@cKaUr#`D"A%Bp2)>#0 Y-=s-jr:ita j_jD`jN+i(GL@)Cm%o@Afc`c$66HAt[k5gOGJt-