169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit. 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License. Alternatively, the contents of this file may be used under 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later. 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis, 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License. 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.compiler; 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*; 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*; 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.*; 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* Code generator accepting extended Java syntax for Javassist. 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class JvstCodeGen extends MemberCodeGen { 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String paramArrayName = null; 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String paramListName = null; 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] paramTypeList = null; 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int paramVarBase = 0; // variable index for $0 or $1. 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private boolean useParam0 = false; // true if $0 is used. 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String param0Type = null; // JVM name 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String sigName = "$sig"; 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String dollarTypeName = "$type"; 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String clazzName = "$class"; 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private CtClass dollarType = null; 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass returnType = null; 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String returnCastName = null; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private String returnVarName = null; // null if $_ is not used. 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String wrapperCastName = "$w"; 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String proceedName = null; 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static final String cflowName = "$cflow"; 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ProceedHandler procHandler = null; // null if not used. 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public JvstCodeGen(Bytecode b, CtClass cc, ClassPool cp) { 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super(b, cc, cp); 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setTypeChecker(new JvstTypeChecker(cc, cp, this)); 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Index of $1. 5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int indexOfParam1() { 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return paramVarBase + (useParam0 ? 1 : 0); 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Records a ProceedHandler obejct. 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param name the name of the special method call. 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * it is usually $proceed. 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void setProceedHandler(ProceedHandler h, String name) { 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal proceedName = name; 6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal procHandler = h; 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* If the type of the expression compiled last is void, 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * add ACONST_NULL and change exprType, arrayDim, className. 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void addNullIfVoid() { 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exprType == VOID) { 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(ACONST_NULL); 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = jvmJavaLangObject; 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* To support $args, $sig, and $type. 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * $args is an array of parameter list. 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void atMember(Member mem) throws CompileError { 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = mem.get(); 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name.equals(paramArrayName)) { 8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal compileParameterList(bytecode, paramTypeList, indexOfParam1()); 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 1; 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = jvmJavaLangObject; 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name.equals(sigName)) { 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList)); 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addInvokestatic("javassist/runtime/Desc", "getParams", 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "(Ljava/lang/String;)[Ljava/lang/Class;"); 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 1; 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = "java/lang/Class"; 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name.equals(dollarTypeName)) { 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (dollarType == null) 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(dollarTypeName + " is not available"); 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addLdc(Descriptor.of(dollarType)); 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal callGetType("getType"); 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name.equals(clazzName)) { 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (param0Type == null) 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError(clazzName + " is not available"); 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addLdc(param0Type); 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal callGetType("getClazz"); 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.atMember(mem); 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void callGetType(String method) { 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addInvokestatic("javassist/runtime/Desc", method, 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "(Ljava/lang/String;)Ljava/lang/Class;"); 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = "java/lang/Class"; 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atFieldAssign(Expr expr, int op, ASTree left, 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree right, boolean doDup) throws CompileError 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (left instanceof Member 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && ((Member)left).get().equals(paramArrayName)) { 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (op != '=') 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("bad operator for " + paramArrayName); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal right.accept(this); 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (arrayDim != 1 || exprType != CLASS) 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("invalid type for " + paramArrayName); 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atAssignParamList(paramTypeList, bytecode); 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!doDup) 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(POP); 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.atFieldAssign(expr, op, left, right, doDup); 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atAssignParamList(CtClass[] params, Bytecode code) 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params == null) 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int varNo = indexOfParam1(); 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = params.length; 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(DUP); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIconst(i); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(AALOAD); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal compileUnwrapValue(params[i], code); 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addStore(varNo, params[i]); 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal varNo += is2word(exprType, arrayDim) ? 2 : 1; 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void atCastExpr(CastExpr expr) throws CompileError { 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList classname = expr.getClassName(); 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (classname != null && expr.getArrayDim() == 0) { 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree p = classname.head(); 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (p instanceof Symbol && classname.tail() == null) { 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String typename = ((Symbol)p).get(); 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (typename.equals(returnCastName)) { 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atCastToRtype(expr); 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (typename.equals(wrapperCastName)) { 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atCastToWrapper(expr); 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.atCastExpr(expr); 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Inserts a cast operator to the return type. 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If the return type is void, this does nothing. 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atCastToRtype(CastExpr expr) throws CompileError { 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr.getOprand().accept(this); 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exprType == VOID || isRefType(exprType) || arrayDim > 0) 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal compileUnwrapValue(returnType, bytecode); 18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (returnType instanceof CtPrimitiveType) { 18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)returnType; 19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int destType = MemberResolver.descToType(pt.getDescriptor()); 19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atNumCastExpr(exprType, destType); 19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = destType; 19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = null; 19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("invalid cast"); 19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atCastToWrapper(CastExpr expr) throws CompileError { 20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal expr.getOprand().accept(this); 20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (isRefType(exprType) || arrayDim > 0) 20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; // Object type. do nothing. 20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass clazz = resolver.lookupClass(exprType, arrayDim, className); 20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (clazz instanceof CtPrimitiveType) { 20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)clazz; 20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String wrapper = pt.getWrapperName(); 20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addNew(wrapper); // new <wrapper> 21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(DUP); // dup 21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (pt.getDataSize() > 1) 21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(DUP2_X2); // dup2_x2 21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(DUP2_X1); // dup2_x1 21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(POP2); // pop2 21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addInvokespecial(wrapper, "<init>", 21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "(" + pt.getDescriptor() + ")V"); 21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // invokespecial 22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = jvmJavaLangObject; 22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Delegates to a ProcHandler object if the method call is 22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * $proceed(). It may process $cflow(). 22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void atCallExpr(CallExpr expr) throws CompileError { 23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree method = expr.oprand1(); 23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (method instanceof Member) { 23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = ((Member)method).get(); 23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (procHandler != null && name.equals(proceedName)) { 23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal procHandler.doit(this, bytecode, (ASTList)expr.oprand2()); 23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name.equals(cflowName)) { 23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atCflow((ASTList)expr.oprand2()); 23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.atCallExpr(expr); 24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* To support $cflow(). 24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atCflow(ASTList cname) throws CompileError { 24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal StringBuffer sbuf = new StringBuffer(); 25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cname == null || cname.tail() != null) 25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("bad " + cflowName); 25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal makeCflowName(sbuf, cname.head()); 25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String name = sbuf.toString(); 25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Object[] names = resolver.getClassPool().lookupCflow(name); 25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (names == null) 25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("no such " + cflowName + ": " + name); 25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addGetstatic((String)names[0], (String)names[1], 26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "Ljavassist/runtime/Cflow;"); 26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addInvokevirtual("javassist.runtime.Cflow", 26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "value", "()I"); 26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = INT; 26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = null; 26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Syntax: 26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <cflow> : $cflow '(' <cflow name> ')' 27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <cflow name> : <identifier> ('.' <identifier>)* 27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private static void makeCflowName(StringBuffer sbuf, ASTree name) 27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (name instanceof Symbol) { 27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append(((Symbol)name).get()); 27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (name instanceof Expr) { 28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Expr expr = (Expr)name; 28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (expr.getOperator() == '.') { 28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal makeCflowName(sbuf, expr.oprand1()); 28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal sbuf.append('.'); 28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal makeCflowName(sbuf, expr.oprand2()); 28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("bad " + cflowName); 29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* To support $$. ($$) is equivalent to ($1, ..., $n). 29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It can be used only as a parameter list of method call. 29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public boolean isParamListName(ASTList args) { 29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (paramTypeList != null 29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && args != null && args.tail() == null) { 29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree left = args.head(); 30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return (left instanceof Member 30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal && ((Member)left).get().equals(paramListName)); 30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return false; 30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int getMethodArgsLength(ASTList args) { 30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!isParamListName(args)) 31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return super.getMethodArgsLength(args); 31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return paramTypeList.length; 31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int getMethodArgsLength(ASTList args) { 31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String pname = paramListName; 31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = 0; 31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (args != null) { 32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree a = args.head(); 32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (a instanceof Member && ((Member)a).get().equals(pname)) { 32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (paramTypeList != null) 32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal n += paramTypeList.length; 32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++n; 32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args = args.tail(); 32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return n; 33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void atMethodArgs(ASTList args, int[] types, int[] dims, 33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String[] cnames) throws CompileError { 33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] params = paramTypeList; 33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String pname = paramListName; 33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int i = 0; 33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while (args != null) { 34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree a = args.head(); 34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (a instanceof Member && ((Member)a).get().equals(pname)) { 34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params != null) { 34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = params.length; 34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int regno = indexOfParam1(); 34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int k = 0; k < n; ++k) { 34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass p = params[k]; 34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal regno += bytecode.addLoad(regno, p); 34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(p); 34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal types[i] = exprType; 35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dims[i] = arrayDim; 35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cnames[i] = className; 35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++i; 35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal a.accept(this); 35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal types[i] = exprType; 35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dims[i] = arrayDim; 36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cnames[i] = className; 36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++i; 36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args = args.tail(); 36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void atMethodArgs(ASTList args, int[] types, int[] dims, 37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String[] cnames) throws CompileError { 37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!isParamListName(args)) { 37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal super.atMethodArgs(args, types, dims, cnames); 37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] params = paramTypeList; 37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params == null) 37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = params.length; 38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int regno = indexOfParam1(); 38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass p = params[i]; 38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal regno += bytecode.addLoad(regno, p); 38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(p); 38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal types[i] = exprType; 38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dims[i] = arrayDim; 38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cnames[i] = className; 38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* called by Javac#recordSpecialProceed(). 39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal void compileInvokeSpecial(ASTree target, String classname, 39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String methodname, String descriptor, 39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTList args) 39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal target.accept(this); 40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int nargs = getMethodArgsLength(args); 40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atMethodArgs(args, new int[nargs], new int[nargs], 40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new String[nargs]); 40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addInvokespecial(classname, methodname, descriptor); 40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setReturnType(descriptor, false, false); 40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addNullIfVoid(); 40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* 41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes it valid to write "return <expr>;" for a void method. 41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void atReturnStmnt(Stmnt st) throws CompileError { 41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ASTree result = st.getLeft(); 41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (result != null && returnType == CtClass.voidType) { 41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal compileExpr(result); 41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (is2word(exprType, arrayDim)) 41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(POP2); 41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (exprType != VOID) 41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal bytecode.addOpcode(POP); 42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal result = null; 42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atReturnStmnt2(result); 42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes a cast to the return type ($r) available. 42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * It also enables $_. 43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * <p>If the return type is void, ($r) does nothing. 43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The type of $_ is java.lang.Object. 43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param resultName null if $_ is not used. 43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @return -1 or the variable index assigned to $_. 43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int recordReturnType(CtClass type, String castName, 43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String resultName, SymbolTable tbl) throws CompileError 43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal returnType = type; 44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal returnCastName = castName; 44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal returnVarName = resultName; 44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (resultName == null) 44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; 44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int varNo = getMaxLocals(); 44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int locals = varNo + recordVar(type, resultName, varNo, tbl); 44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setMaxLocals(locals); 44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return varNo; 45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes $type available. 45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void recordType(CtClass t) { 45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal dollarType = t; 45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes method parameters $0, $1, ..., $args, $$, and $class available. 46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * $0 is equivalent to THIS if the method is not static. Otherwise, 46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * if the method is static, then $0 is not available. 46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int recordParams(CtClass[] params, boolean isStatic, 46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String prefix, String paramVarName, 46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String paramsName, SymbolTable tbl) 46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return recordParams(params, isStatic, prefix, paramVarName, 47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal paramsName, !isStatic, 0, getThisName(), tbl); 47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes method parameters $0, $1, ..., $args, $$, and $class available. 47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * $0 is available only if use0 is true. It might not be equivalent 47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * to THIS. 47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param params the parameter types (the types of $1, $2, ..) 48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param prefix it must be "$" (the first letter of $0, $1, ...) 48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramVarName it must be "$args" 48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramsName it must be "$$" 48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param use0 true if $0 is used. 48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param paramBase the register number of $0 (use0 is true) 48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * or $1 (otherwise). 48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param target the class of $0. If use0 is false, target 48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * can be null. The value of "target" is also used 48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * as the name of the type represented by $class. 48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param isStatic true if the method in which the compiled bytecode 49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * is embedded is static. 49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int recordParams(CtClass[] params, boolean isStatic, 49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String prefix, String paramVarName, 49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String paramsName, boolean use0, 49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int paramBase, String target, 49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl) 49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int varNo; 50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal paramTypeList = params; 50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal paramArrayName = paramVarName; 50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal paramListName = paramsName; 50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal paramVarBase = paramBase; 50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal useParam0 = use0; 50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (target != null) 50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal param0Type = MemberResolver.jvmToJavaName(target); 50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal inStaticMethod = isStatic; 51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal varNo = paramBase; 51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (use0) { 51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String varName = prefix + "0"; 51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator decl 51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new Declarator(CLASS, MemberResolver.javaToJvmName(target), 51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 0, varNo++, new Symbol(varName)); 51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tbl.append(varName, decl); 51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < params.length; ++i) 52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl); 52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (getMaxLocals() < varNo) 52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setMaxLocals(varNo); 52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return varNo; 52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes the given variable name available. 53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param type variable type 53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param varName variable name 53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public int recordVariable(CtClass type, String varName, SymbolTable tbl) 53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (varName == null) 53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return -1; 54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int varNo = getMaxLocals(); 54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int locals = varNo + recordVar(type, varName, varNo, tbl); 54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setMaxLocals(locals); 54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return varNo; 54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private int recordVar(CtClass cc, String varName, int varNo, 54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl) throws CompileError 55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (cc == CtClass.voidType) { 55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = 0; 55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = jvmJavaLangObject; 55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(cc); 55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator decl 56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new Declarator(exprType, className, arrayDim, 56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal varNo, new Symbol(varName)); 56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tbl.append(varName, decl); 56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return is2word(exprType, arrayDim) ? 2 : 1; 56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /** 56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Makes the given variable name available. 56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param typeDesc the type descriptor of the variable 57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param varName variable name 57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param varNo an index into the local variable array 57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void recordVariable(String typeDesc, String varName, int varNo, 57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SymbolTable tbl) throws CompileError 57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal char c; 57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int dim = 0; 57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal while ((c = typeDesc.charAt(dim)) == '[') 57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++dim; 58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int type = MemberResolver.descToType(c); 58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String cname = null; 58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type == CLASS) { 58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (dim == 0) 58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = typeDesc.substring(1, typeDesc.length() - 1); 58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal cname = typeDesc.substring(dim + 1, typeDesc.length() - 1); 58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Declarator decl 59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal = new Declarator(type, cname, dim, varNo, new Symbol(varName)); 59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal tbl.append(varName, decl); 59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* compileParameterList() returns the stack size used 59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * by the produced code. 59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * This method correctly computes the max_stack value. 59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * @param regno the index of the local variable in which 60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the first argument is received. 60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * (0: static method, 1: regular method.) 60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public static int compileParameterList(Bytecode code, 60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] params, int regno) { 60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params == null) { 60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIconst(0); // iconst_0 60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addAnewarray(javaLangObject); // anewarray Object 60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 1; 61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtClass[] args = new CtClass[1]; 61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int n = params.length; 61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIconst(n); // iconst_<n> 61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addAnewarray(javaLangObject); // anewarray Object 61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (int i = 0; i < n; ++i) { 61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(Bytecode.DUP); // dup 61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addIconst(i); // iconst_<i> 61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (params[i].isPrimitive()) { 62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)params[i]; 62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String wrapper = pt.getWrapperName(); 62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addNew(wrapper); // new <wrapper> 62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(Bytecode.DUP); // dup 62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal int s = code.addLoad(regno, pt); // ?load <regno> 62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal regno += s; 62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal args[0] = pt; 62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addInvokespecial(wrapper, "<init>", 62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Descriptor.ofMethod(CtClass.voidType, args)); 62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // invokespecial 63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addAload(regno); // aload <regno> 63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ++regno; 63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addOpcode(Bytecode.AASTORE); // aastore 63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return 8; 64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal protected void compileUnwrapValue(CtClass type, Bytecode code) 64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throws CompileError 64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal { 64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type == CtClass.voidType) { 64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal addNullIfVoid(); 64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return; 64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (exprType == VOID) 65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("invalid type for " + returnCastName); 65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type instanceof CtPrimitiveType) { 65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)type; 65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // pt is not voidType. 65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal String wrapper = pt.getWrapperName(); 65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addCheckcast(wrapper); 65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addInvokevirtual(wrapper, pt.getGetMethodName(), 66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal pt.getGetMethodDescriptor()); 66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(type); 66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal code.addCheckcast(type); 66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(type); 66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Sets exprType, arrayDim, and className; 67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * If type is void, then this method does nothing. 67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void setType(CtClass type) throws CompileError { 67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(type, 0); 67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal private void setType(CtClass type, int dim) throws CompileError { 67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type.isPrimitive()) { 67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)type; 67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = MemberResolver.descToType(pt.getDescriptor()); 68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = dim; 68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = null; 68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else if (type.isArray()) 68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal try { 68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal setType(type.getComponentType(), dim + 1); 68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal catch (NotFoundException e) { 68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("undefined type: " + type.getName()); 68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else { 69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal exprType = CLASS; 69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal arrayDim = dim; 69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal className = MemberResolver.javaToJvmName(type.getName()); 69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal /* Performs implicit coercion from exprType to type. 69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */ 69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal public void doNumCast(CtClass type) throws CompileError { 70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (arrayDim == 0 && !isRefType(exprType)) 70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (type instanceof CtPrimitiveType) { 70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal CtPrimitiveType pt = (CtPrimitiveType)type; 70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal atNumCastExpr(exprType, 70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal MemberResolver.descToType(pt.getDescriptor())); 70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal else 70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal throw new CompileError("type mismatch"); 70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 710