--- old/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java 2016-02-04 23:02:22.518174458 +0100 +++ new/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java 2016-02-04 23:02:22.394174453 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -894,17 +894,16 @@ // Per-thread RendererContext private static final ThreadLocal rdrCtxThreadLocal; - // RendererContext queue when ThreadLocal is disabled - private static final ConcurrentLinkedQueue rdrCtxQueue; + // RendererContext queue when + // ThreadLocal is disabled or for child contexts (reentrance) + private static final ConcurrentLinkedQueue rdrCtxQueue + = new ConcurrentLinkedQueue(); // Static initializer to use TL or CLQ mode static { - // CLQ mode by default: useThreadLocal = MarlinProperties.isUseThreadLocal(); rdrCtxThreadLocal = (useThreadLocal) ? new ThreadLocal() : null; - rdrCtxQueue = (!useThreadLocal) ? new ConcurrentLinkedQueue() - : null; // Soft reference by default: String refType = AccessController.doPrivileged( @@ -1026,20 +1025,28 @@ @SuppressWarnings({"unchecked"}) static RendererContext getRendererContext() { RendererContext rdrCtx = null; - final Object ref = (useThreadLocal) ? rdrCtxThreadLocal.get() - : rdrCtxQueue.poll(); - if (ref != null) { - // resolve reference: - rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) - : ((Reference) ref).get(); - } - // create a new RendererContext if none is available - if (rdrCtx == null) { - rdrCtx = RendererContext.createContext(); - if (useThreadLocal) { + if (useThreadLocal) { + final Object ref = rdrCtxThreadLocal.get(); + if (ref != null) { + rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) + : ((Reference) ref).get(); + } + if (rdrCtx == null) { + // create a new RendererContext (TL) if none is available + rdrCtx = RendererContext.createContext(false); // update thread local reference: rdrCtxThreadLocal.set(rdrCtx.reference); } + // Check reentrance: + if (rdrCtx.usedTL) { + // get or create another RendererContext: + rdrCtx = getOrCreateContextFromQueue(); + } else { + // TL mode: set used flag: + rdrCtx.usedTL = true; + } + } else { + rdrCtx = getOrCreateContextFromQueue(); } if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.start(); @@ -1047,6 +1054,21 @@ return rdrCtx; } + @SuppressWarnings({"unchecked"}) + private static RendererContext getOrCreateContextFromQueue() { + RendererContext rdrCtx = null; + final Object ref = rdrCtxQueue.poll(); + if (ref != null) { + rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) + : ((Reference) ref).get(); + } + if (rdrCtx == null) { + // create a new RendererContext (QUEUE) if none is available + rdrCtx = RendererContext.createContext(true); + } + return rdrCtx; + } + /** * Reset and return the given RendererContext instance for reuse * @param rdrCtx RendererContext instance @@ -1057,8 +1079,11 @@ if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.stop(); } - if (!useThreadLocal) { + if (!useThreadLocal || rdrCtx.storageQueue) { rdrCtxQueue.offer(rdrCtx.reference); + } else { + // TL mode: unset used flag: + rdrCtx.usedTL = false; } } }