diff --git a/classpath/ikvm/internal/WeakIdentityMap.java b/classpath/ikvm/internal/WeakIdentityMap.java index 944fc1db..b6a203a0 100644 --- a/classpath/ikvm/internal/WeakIdentityMap.java +++ b/classpath/ikvm/internal/WeakIdentityMap.java @@ -59,6 +59,11 @@ public final class WeakIdentityMap { if (key == null) throw new NullPointerException(); + putImpl(key, value, true); + } + + private void putImpl(Object key, Object value, boolean tryGC) + { int emptySlot = -1; int keySlot = -1; for (int i = 0; i < keys.length; i++) @@ -85,6 +90,12 @@ public final class WeakIdentityMap } else { + if (tryGC) + { + GC.Collect(0); + putImpl(key, value, false); + return; + } int len = keys.length; WeakReference[] newkeys = new WeakReference[len * 2]; Object[] newvalues = new Object[newkeys.length]; diff --git a/runtime/ByteCode.cs b/runtime/ByteCode.cs index 54cb4df7..46ecf69f 100644 --- a/runtime/ByteCode.cs +++ b/runtime/ByteCode.cs @@ -379,6 +379,7 @@ enum NormalizedByteCode : byte __ifnull = 198, __ifnonnull = 199, // This is where the pseudo-bytecodes start + __athrow_no_unmap = 244, __dynamic_getstatic = 245, __dynamic_putstatic = 246, __dynamic_getfield = 247, diff --git a/runtime/ClassFile.cs b/runtime/ClassFile.cs index 8e2e5874..b941a3e1 100644 --- a/runtime/ClassFile.cs +++ b/runtime/ClassFile.cs @@ -2497,6 +2497,14 @@ namespace IKVM.Internal } } + internal bool IsBranchTarget + { + get + { + return (flags & InstructionFlags.BranchTarget) != 0; + } + } + internal void PatchOpCode(NormalizedByteCode bc) { this.normopcode = bc; diff --git a/runtime/compiler.cs b/runtime/compiler.cs index 36097678..e1e20e1d 100644 --- a/runtime/compiler.cs +++ b/runtime/compiler.cs @@ -1382,7 +1382,7 @@ class Compiler // if there was a forward branch to this instruction, it is forward reachable instructionIsForwardReachable |= block.HasLabel(i); - if(block.HasLabel(i) || (instr.flags & ClassFile.Method.InstructionFlags.BranchTarget) != 0) + if(block.HasLabel(i) || instr.IsBranchTarget) { block.MarkLabel(i); } @@ -1714,6 +1714,10 @@ class Compiler && thisType.GetMethodWrapper("fillInStackTrace", "()Ljava.lang.Throwable;", true).DeclaringType == java_lang_Throwable) { ilGenerator.Emit(OpCodes.Call, suppressFillInStackTraceMethod); + if(!code[i + 1].IsBranchTarget) + { + code[i + 1].PatchOpCode(NormalizedByteCode.__athrow_no_unmap); + } } } method.EmitNewobj(ilGenerator); @@ -2766,8 +2770,14 @@ class Compiler case NormalizedByteCode.__monitorexit: ilGenerator.Emit(OpCodes.Call, monitorExitMethod); break; + case NormalizedByteCode.__athrow_no_unmap: + if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) + { + ilGenerator.Emit(OpCodes.Castclass, typeof(Exception)); + } + ilGenerator.Emit(OpCodes.Throw); + break; case NormalizedByteCode.__athrow: - // TODO we shouldn't call unmap when we know it isn't needed if(ma.GetRawStackTypeWrapper(i, 0).IsUnloadable) { ilGenerator.Emit(OpCodes.Castclass, typeof(Exception)); @@ -2948,6 +2958,7 @@ class Compiler case NormalizedByteCode.__areturn: case NormalizedByteCode.__return: case NormalizedByteCode.__athrow: + case NormalizedByteCode.__athrow_no_unmap: case NormalizedByteCode.__static_error: instructionIsForwardReachable = false; break;