1 /* 2 * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.tools.tree; 27 28 import sun.tools.java.*; 29 import sun.tools.asm.Assembler; 30 import sun.tools.asm.Label; 31 import sun.tools.asm.TryData; 32 import sun.tools.asm.CatchData; 33 import java.io.PrintStream; 34 import java.util.Hashtable; 35 36 /** 37 * WARNING: The contents of this source file are not part of any 38 * supported API. Code that depends on them does so at its own risk: 39 * they are subject to change or removal without notice. 40 */ 41 public 42 class SynchronizedStatement extends Statement { 43 Expression expr; 44 Statement body; 45 boolean needReturnSlot; // set by inner return statement 46 47 /** 48 * Constructor 49 */ 50 public SynchronizedStatement(long where, Expression expr, Statement body) { 51 super(SYNCHRONIZED, where); 52 this.expr = expr; 53 this.body = body; 54 } 55 56 /** 57 * Check statement 58 */ 59 Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) { 60 checkLabel(env, ctx); 61 CheckContext newctx = new CheckContext(ctx, this); 62 vset = reach(env, vset); 63 vset = expr.checkValue(env, newctx, vset, exp); 64 if (expr.type.equals(Type.tNull)) { 65 env.error(expr.where, "synchronized.null"); 66 } 67 expr = convert(env, newctx, Type.tClass(idJavaLangObject), expr); 68 vset = body.check(env, newctx, vset, exp); 69 return ctx.removeAdditionalVars(vset.join(newctx.vsBreak)); 70 } 71 72 /** 73 * Inline 74 */ 75 public Statement inline(Environment env, Context ctx) { 76 if (body != null) { 77 body = body.inline(env, ctx); 78 } 79 expr = expr.inlineValue(env, ctx); 80 return this; 81 } 82 83 /** 84 * Create a copy of the statement for method inlining 85 */ 86 public Statement copyInline(Context ctx, boolean valNeeded) { 87 SynchronizedStatement s = (SynchronizedStatement)clone(); 88 s.expr = expr.copyInline(ctx); 89 if (body != null) { 90 s.body = body.copyInline(ctx, valNeeded); 91 } 92 return s; 93 } 94 95 /** 96 * Compute cost of inlining this statement 97 */ 98 public int costInline(int thresh, Environment env, Context ctx){ 99 int cost = 1; 100 if (expr != null) { 101 cost += expr.costInline(thresh, env,ctx); 102 if (cost >= thresh) return cost; 103 } 104 if (body != null) { 105 cost += body.costInline(thresh, env,ctx); 106 } 107 return cost; 108 } 109 110 /** 111 * Code 112 */ 113 public void code(Environment env, Context ctx, Assembler asm) { 114 ClassDefinition clazz = ctx.field.getClassDefinition(); 115 expr.codeValue(env, ctx, asm); 116 ctx = new Context(ctx); 117 118 if (needReturnSlot) { 119 Type returnType = ctx.field.getType().getReturnType(); 120 LocalMember localfield = new LocalMember(0, clazz, 0, returnType, 121 idFinallyReturnValue); 122 ctx.declare(env, localfield); 123 env.debugOutput("Assigning return slot to " + localfield.number); 124 } 125 126 LocalMember f1 = new LocalMember(where, clazz, 0, Type.tObject, null); 127 LocalMember f2 = new LocalMember(where, clazz, 0, Type.tInt, null); 128 Integer num1 = new Integer(ctx.declare(env, f1)); 129 Integer num2 = new Integer(ctx.declare(env, f2)); 130 131 Label endLabel = new Label(); 132 133 TryData td = new TryData(); 134 td.add(null); 135 136 // lock the object 137 asm.add(where, opc_astore, num1); 138 asm.add(where, opc_aload, num1); 139 asm.add(where, opc_monitorenter); 140 141 // Main body 142 CodeContext bodyctx = new CodeContext(ctx, this); 143 asm.add(where, opc_try, td); 144 if (body != null) { 145 body.code(env, bodyctx, asm); 146 } else { 147 asm.add(where, opc_nop); 148 } 149 asm.add(bodyctx.breakLabel); 150 asm.add(td.getEndLabel()); 151 152 // Cleanup afer body 153 asm.add(where, opc_aload, num1); 154 asm.add(where, opc_monitorexit); 155 asm.add(where, opc_goto, endLabel); 156 157 // Catch code 158 CatchData cd = td.getCatch(0); 159 asm.add(cd.getLabel()); 160 asm.add(where, opc_aload, num1); 161 asm.add(where, opc_monitorexit); 162 asm.add(where, opc_athrow); 163 164 // Final body 165 asm.add(bodyctx.contLabel); 166 asm.add(where, opc_astore, num2); 167 asm.add(where, opc_aload, num1); 168 asm.add(where, opc_monitorexit); 169 asm.add(where, opc_ret, num2); 170 171 asm.add(endLabel); 172 } 173 174 /** 175 * Print 176 */ 177 public void print(PrintStream out, int indent) { 178 super.print(out, indent); 179 out.print("synchronized "); 180 expr.print(out); 181 out.print(" "); 182 if (body != null) { 183 body.print(out, indent); 184 } else { 185 out.print("{}"); 186 } 187 } 188 }