feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,253 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AddExpression extends BinaryArithmeticExpression {
/**
* constructor
*/
public AddExpression(long where, Expression left, Expression right) {
super(ADD, where, left, right);
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
if ((left.type == Type.tString) && !right.type.isType(TC_VOID)) {
type = Type.tString;
return;
} else if ((right.type == Type.tString) && !left.type.isType(TC_VOID)) {
type = Type.tString;
return;
}
super.selectType(env, ctx, tm);
}
public boolean isNonNull() {
// an addition expression cannot yield a null reference as a result
return true;
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a + b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a + b);
}
Expression eval(float a, float b) {
return new FloatExpression(where, a + b);
}
Expression eval(double a, double b) {
return new DoubleExpression(where, a + b);
}
Expression eval(String a, String b) {
return new StringExpression(where, a + b);
}
/**
* Inline the value of an AddExpression. If this AddExpression
* represents a concatenation of compile-time constant strings,
* dispatch to the special method inlineValueSB, which handles
* the inlining more efficiently.
*/
public Expression inlineValue(Environment env, Context ctx) {
if (type == Type.tString && isConstant()) {
StringBuffer buffer = inlineValueSB(env, ctx, new StringBuffer());
if (buffer != null) {
// We were able to evaluate the String concatenation.
return new StringExpression(where, buffer.toString());
}
}
// For some reason inlinValueSB() failed to produce a value.
// Use the older, less efficient, inlining mechanism.
return super.inlineValue(env, ctx);
}
/**
* Attempt to evaluate this expression. If this expression
* yields a value, append it to the StringBuffer `buffer'.
* If this expression cannot be evaluated at this time (for
* example if it contains a division by zero, a non-constant
* subexpression, or a subexpression which "refuses" to evaluate)
* then return `null' to indicate failure.
*
* It is anticipated that this method will be called to evaluate
* concatenations of compile-time constant strings. The call
* originates from AddExpression#inlineValue().
*
* This method does not use associativity to good effect in
* folding string concatenations. This is room for improvement.
*
* -------------
*
* A bit of history: this method was added because an
* expression like...
*
* "a" + "b" + "c" + "d"
*
* ...was evaluated at compile-time as...
*
* (new StringBuffer((new StringBuffer("a")).append("b").toString())).
* append((new StringBuffer("c")).append("d").toString()).toString()
*
* Alex Garthwaite, in profiling the memory allocation of the
* compiler, noticed this and suggested that the method inlineValueSB()
* be added to evaluate constant string concatenations in a more
* efficient manner. The compiler now builds the string in a
* top-down fashion, by accumulating the result in a StringBuffer
* which is allocated once and passed in as a parameter. The new
* evaluation scheme is equivalent to...
*
* (new StringBuffer("a")).append("b").append("c").append("d")
* .toString()
*
* ...which is more efficient. Since then, the code has been modified
* to fix certain problems. Now, for example, it can return `null'
* when it encounters a concatenation which it is not able to
* evaluate.
*
* See also Expression#inlineValueSB() and ExprExpression#inlineValueSB().
*/
protected StringBuffer inlineValueSB(Environment env,
Context ctx,
StringBuffer buffer) {
if (type != Type.tString) {
// This isn't a concatenation. It is actually an addition
// of some sort. Call the generic inlineValueSB()
return super.inlineValueSB(env, ctx, buffer);
}
buffer = left.inlineValueSB(env, ctx, buffer);
if (buffer != null) {
buffer = right.inlineValueSB(env, ctx, buffer);
}
return buffer;
}
/**
* Simplify
*/
Expression simplify() {
if (!type.isType(TC_CLASS)) {
// Can't simplify floating point add because of -0.0 strangeness
if (type.inMask(TM_INTEGER)) {
if (left.equals(0)) {
return right;
}
if (right.equals(0)) {
return left;
}
}
} else if (right.type.isType(TC_NULL)) {
right = new StringExpression(right.where, "null");
} else if (left.type.isType(TC_NULL)) {
left = new StringExpression(left.where, "null");
}
return this;
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
return (type.isType(TC_CLASS) ? 12 : 1)
+ left.costInline(thresh, env, ctx)
+ right.costInline(thresh, env, ctx);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iadd + type.getTypeCodeOffset());
}
/**
* Convert this expression to a string and append it to the string
* buffer on the top of the stack.
* If the needBuffer argument is true, the string buffer needs to be
* created, initialized, and pushed on the stack, first.
*/
void codeAppend(Environment env, Context ctx, Assembler asm,
ClassDeclaration sbClass, boolean needBuffer)
throws ClassNotFound, AmbiguousMember {
if (type.isType(TC_CLASS)) {
left.codeAppend(env, ctx, asm, sbClass, needBuffer);
right.codeAppend(env, ctx, asm, sbClass, false);
} else {
super.codeAppend(env, ctx, asm, sbClass, needBuffer);
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (type.isType(TC_CLASS)) {
try {
// optimize (""+foo) or (foo+"") to String.valueOf(foo)
if (left.equals("")) {
right.codeValue(env, ctx, asm);
right.ensureString(env, ctx, asm);
return;
}
if (right.equals("")) {
left.codeValue(env, ctx, asm);
left.ensureString(env, ctx, asm);
return;
}
ClassDeclaration sbClass =
env.getClassDeclaration(idJavaLangStringBuffer);
ClassDefinition sourceClass = ctx.field.getClassDefinition();
// Create the string buffer and append to it.
codeAppend(env, ctx, asm, sbClass, true);
// Convert the string buffer to a string
MemberDefinition f =
sbClass.getClassDefinition(env).matchMethod(env,
sourceClass,
idToString);
asm.add(where, opc_invokevirtual, f);
} catch (ClassNotFound e) {
throw new CompilerError(e);
} catch (AmbiguousMember e) {
throw new CompilerError(e);
}
} else {
super.codeValue(env, ctx, asm);
}
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AndExpression extends BinaryLogicalExpression {
/**
* constructor
*/
public AndExpression(long where, Expression left, Expression right) {
super(AND, where, left, right);
}
/*
* Check an "and" expression.
*
* cvars is modified so that
* cvar.vsTrue indicates variables with a known value if
* both the left and right hand side are true
* cvars.vsFalse indicates variables with a known value
* either the left or right hand side is false
*/
public void checkCondition(Environment env, Context ctx, Vset vset,
Hashtable exp, ConditionVars cvars) {
// Find out when the left side is true/false
left.checkCondition(env, ctx, vset, exp, cvars);
left = convert(env, ctx, Type.tBoolean, left);
Vset vsTrue = cvars.vsTrue.copy();
Vset vsFalse = cvars.vsFalse.copy();
// Only look at the right side if the left side is true
right.checkCondition(env, ctx, vsTrue, exp, cvars);
right = convert(env, ctx, Type.tBoolean, right);
// cvars.vsTrue already reports when both returned true
// cvars.vsFalse must be set to either the left or right side
// returning false
cvars.vsFalse = cvars.vsFalse.join(vsFalse);
}
/**
* Evaluate
*/
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a && b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.equals(true)) {
return right;
}
if (right.equals(false)) {
// Preserve effects of left argument.
return new CommaExpression(where, left, right).simplify();
}
if (right.equals(true)) {
return left;
}
if (left.equals(false)) {
return left;
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
if (whenTrue) {
Label lbl2 = new Label();
left.codeBranch(env, ctx, asm, lbl2, false);
right.codeBranch(env, ctx, asm, lbl, true);
asm.add(lbl2);
} else {
left.codeBranch(env, ctx, asm, lbl, false);
right.codeBranch(env, ctx, asm, lbl, false);
}
}
}

View File

@@ -0,0 +1,271 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ArrayAccessExpression extends UnaryExpression {
/**
* The index expression for the array access. Note that
* ArrayAccessExpression also `moonlights' as a structure for
* storing array types (like Object[]) which are used as part
* of cast expressions. For properly formed array types, the
* value of index is null. We need to be on the lookout for
* null indices in true array accesses, and non-null indices
* in array types. We also need to make sure general purpose
* methods (like copyInline(), which is called for both) are
* prepared to handle either null or non-null indices.
*/
Expression index;
/**
* constructor
*/
public ArrayAccessExpression(long where, Expression right, Expression index) {
super(ARRAYACCESS, where, Type.tError, right);
this.index = index;
}
/**
* Check expression type
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = right.checkValue(env, ctx, vset, exp);
if (index == null) {
env.error(where, "array.index.required");
return vset;
}
vset = index.checkValue(env, ctx, vset, exp);
index = convert(env, ctx, Type.tInt, index);
if (!right.type.isType(TC_ARRAY)) {
if (!right.type.isType(TC_ERROR)) {
env.error(where, "not.array", right.type);
}
return vset;
}
type = right.type.getElementType();
return vset;
}
public Vset checkAmbigName(Environment env, Context ctx,
Vset vset, Hashtable exp,
UnaryExpression loc) {
if (index == null) {
vset = right.checkAmbigName(env, ctx, vset, exp, this);
if (right.type == Type.tPackage) {
FieldExpression.reportFailedPackagePrefix(env, right);
return vset;
}
// Nope. Is this field expression a type?
if (right instanceof TypeExpression) {
Type atype = Type.tArray(right.type);
loc.right = new TypeExpression(where, atype);
return vset;
}
env.error(where, "array.index.required");
return vset;
}
return super.checkAmbigName(env, ctx, vset, exp, loc);
}
/*
* Check the array if it appears on the LHS of an assignment
*/
public Vset checkLHS(Environment env, Context ctx,
Vset vset, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
/*
* Check the array if it appears on the LHS of an op= expression
*/
public Vset checkAssignOp(Environment env, Context ctx,
Vset vset, Hashtable exp, Expression outside) {
return checkValue(env, ctx, vset, exp);
}
/**
* An array access expression never requires the use of an access method to perform
* an assignment to an array element, though an access method may be required to
* fetch the array object itself.
*/
public FieldUpdater getAssigner(Environment env, Context ctx) {
return null;
}
/**
* An array access expression never requires a field updater.
*/
public FieldUpdater getUpdater(Environment env, Context ctx) {
return null;
}
/**
* Convert to a type
*/
Type toType(Environment env, Context ctx) {
return toType(env, right.toType(env, ctx));
}
Type toType(Environment env, Type t) {
if (index != null) {
env.error(index.where, "array.dim.in.type");
}
return Type.tArray(t);
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
// It isn't possible to simply replace an array access
// with a CommaExpression as happens with many binary
// operators, because array accesses may have side effects
// such as NullPointerException or IndexOutOfBoundsException.
right = right.inlineValue(env, ctx);
index = index.inlineValue(env, ctx);
return this;
}
public Expression inlineValue(Environment env, Context ctx) {
// inlineValue() should not end up being called when the index is
// null. If it is null, we let this method fail with a
// NullPointerException.
right = right.inlineValue(env, ctx);
index = index.inlineValue(env, ctx);
return this;
}
public Expression inlineLHS(Environment env, Context ctx) {
return inlineValue(env, ctx);
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
ArrayAccessExpression e = (ArrayAccessExpression)clone();
e.right = right.copyInline(ctx);
if (index == null) {
// The index can be null when this node is being used to
// represent a type (e.g. Object[]) used in a cast expression.
// We need to copy such structures without complaint.
e.index = null;
} else {
e.index = index.copyInline(ctx);
}
return e;
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
// costInline() should not end up being called when the index is
// null. If it is null, we let this method fail with a
// NullPointerException.
return 1 + right.costInline(thresh, env, ctx)
+ index.costInline(thresh, env, ctx);
}
/**
* Code
*/
int codeLValue(Environment env, Context ctx, Assembler asm) {
// codeLValue() should not end up being called when the index is
// null. If it is null, we let this method fail with a
// NullPointerException.
right.codeValue(env, ctx, asm);
index.codeValue(env, ctx, asm);
return 2;
}
void codeLoad(Environment env, Context ctx, Assembler asm) {
switch (type.getTypeCode()) {
case TC_BOOLEAN:
case TC_BYTE:
asm.add(where, opc_baload);
break;
case TC_CHAR:
asm.add(where, opc_caload);
break;
case TC_SHORT:
asm.add(where, opc_saload);
break;
default:
asm.add(where, opc_iaload + type.getTypeCodeOffset());
}
}
void codeStore(Environment env, Context ctx, Assembler asm) {
switch (type.getTypeCode()) {
case TC_BOOLEAN:
case TC_BYTE:
asm.add(where, opc_bastore);
break;
case TC_CHAR:
asm.add(where, opc_castore);
break;
case TC_SHORT:
asm.add(where, opc_sastore);
break;
default:
asm.add(where, opc_iastore + type.getTypeCodeOffset());
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeLValue(env, ctx, asm);
codeLoad(env, ctx, asm);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
right.print(out);
out.print(" ");
if (index != null) {
index.print(out);
} else {
out.print("<empty>");
}
out.print(")");
}
}

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.*;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ArrayExpression extends NaryExpression {
/**
* Constructor
*/
public ArrayExpression(long where, Expression args[]) {
super(ARRAY, where, Type.tError, null, args);
}
/**
* Check expression type
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
env.error(where, "invalid.array.expr");
return vset;
}
public Vset checkInitializer(Environment env, Context ctx, Vset vset, Type t, Hashtable exp) {
if (!t.isType(TC_ARRAY)) {
if (!t.isType(TC_ERROR)) {
env.error(where, "invalid.array.init", t);
}
return vset;
}
type = t;
t = t.getElementType();
for (int i = 0 ; i < args.length ; i++) {
vset = args[i].checkInitializer(env, ctx, vset, t, exp);
args[i] = convert(env, ctx, t, args[i]);
}
return vset;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
Expression e = null;
for (int i = 0 ; i < args.length ; i++) {
args[i] = args[i].inline(env, ctx);
if (args[i] != null) {
e = (e == null) ? args[i] : new CommaExpression(where, e, args[i]);
}
}
return e;
}
public Expression inlineValue(Environment env, Context ctx) {
for (int i = 0 ; i < args.length ; i++) {
args[i] = args[i].inlineValue(env, ctx);
}
return this;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
int t = 0;
asm.add(where, opc_ldc, new Integer(args.length));
switch (type.getElementType().getTypeCode()) {
case TC_BOOLEAN: asm.add(where, opc_newarray, new Integer(T_BOOLEAN)); break;
case TC_BYTE: asm.add(where, opc_newarray, new Integer(T_BYTE)); break;
case TC_SHORT: asm.add(where, opc_newarray, new Integer(T_SHORT)); break;
case TC_CHAR: asm.add(where, opc_newarray, new Integer(T_CHAR)); break;
case TC_INT: asm.add(where, opc_newarray, new Integer(T_INT)); break;
case TC_LONG: asm.add(where, opc_newarray, new Integer(T_LONG)); break;
case TC_FLOAT: asm.add(where, opc_newarray, new Integer(T_FLOAT)); break;
case TC_DOUBLE: asm.add(where, opc_newarray, new Integer(T_DOUBLE)); break;
case TC_ARRAY:
asm.add(where, opc_anewarray, type.getElementType());
break;
case TC_CLASS:
asm.add(where, opc_anewarray, env.getClassDeclaration(type.getElementType()));
break;
default:
throw new CompilerError("codeValue");
}
for (int i = 0 ; i < args.length ; i++) {
// If the array element is the default initial value,
// then don't bother generating code for this element.
if (args[i].equalsDefault()) continue;
asm.add(where, opc_dup);
asm.add(where, opc_ldc, new Integer(i));
args[i].codeValue(env, ctx, asm);
switch (type.getElementType().getTypeCode()) {
case TC_BOOLEAN:
case TC_BYTE:
asm.add(where, opc_bastore);
break;
case TC_CHAR:
asm.add(where, opc_castore);
break;
case TC_SHORT:
asm.add(where, opc_sastore);
break;
default:
asm.add(where, opc_iastore + type.getElementType().getTypeCodeOffset());
}
}
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignAddExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignAddExpression(long where, Expression left, Expression right) {
super(ASGADD, where, left, right);
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return type.isType(TC_CLASS) ? 25 : super.costInline(thresh, env, ctx);
}
/**
* Code
*/
void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) {
if (itype.isType(TC_CLASS)) {
// Create code for String += <value>
try {
// Create new string buffer.
Type argTypes[] = {Type.tString};
ClassDeclaration c =
env.getClassDeclaration(idJavaLangStringBuffer);
if (updater == null) {
// No access method is needed.
asm.add(where, opc_new, c);
asm.add(where, opc_dup);
// stack: ...<buffer><buffer>
int depth = left.codeLValue(env, ctx, asm);
codeDup(env, ctx, asm, depth, 2); // copy past 2 string buffers
// stack: ...[<getter args>]<buffer><buffer>[<getter args>]
// where <buffer> isn't yet initialized, and the <getter args>
// has length depth and is whatever is needed to get/set the
// value
left.codeLoad(env, ctx, asm);
left.ensureString(env, ctx, asm); // Why is this needed?
// stack: ...[<getter args>]<buffer><buffer><string>
// call .<init>(String)
ClassDefinition sourceClass = ctx.field.getClassDefinition();
MemberDefinition f = c.getClassDefinition(env)
.matchMethod(env, sourceClass,
idInit, argTypes);
asm.add(where, opc_invokespecial, f);
// stack: ...[<getter args>]<initialized buffer>
// .append(value).toString()
right.codeAppend(env, ctx, asm, c, false);
f = c.getClassDefinition(env)
.matchMethod(env, sourceClass, idToString);
asm.add(where, opc_invokevirtual, f);
// stack: ...[<getter args>]<string>
// dup the string past the <getter args>, if necessary.
if (valNeeded) {
codeDup(env, ctx, asm, Type.tString.stackSize(), depth);
// stack: ...<string>[<getter args>]<string>
}
// store
left.codeStore(env, ctx, asm);
} else {
// Access method is required.
// (Handling this case fixes 4102566.)
updater.startUpdate(env, ctx, asm, false);
// stack: ...[<getter args>]<string>
left.ensureString(env, ctx, asm); // Why is this needed?
asm.add(where, opc_new, c);
// stack: ...[<getter args>]<string><buffer>
asm.add(where, opc_dup_x1);
// stack: ...[<getter args>]<buffer><string><buffer>
asm.add(where, opc_swap);
// stack: ...[<getter args>]<buffer><buffer><string>
// call .<init>(String)
ClassDefinition sourceClass = ctx.field.getClassDefinition();
MemberDefinition f = c.getClassDefinition(env)
.matchMethod(env, sourceClass,
idInit, argTypes);
asm.add(where, opc_invokespecial, f);
// stack: ...[<getter args>]<initialized buffer>
// .append(value).toString()
right.codeAppend(env, ctx, asm, c, false);
f = c.getClassDefinition(env)
.matchMethod(env, sourceClass, idToString);
asm.add(where, opc_invokevirtual, f);
// stack: .. [<getter args>]<string>
updater.finishUpdate(env, ctx, asm, valNeeded);
}
} catch (ClassNotFound e) {
throw new CompilerError(e);
} catch (AmbiguousMember e) {
throw new CompilerError(e);
}
} else {
super.code(env, ctx, asm, valNeeded);
}
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iadd + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignBitAndExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignBitAndExpression(long where, Expression left, Expression right) {
super(ASGBITAND, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iand + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignBitOrExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignBitOrExpression(long where, Expression left, Expression right) {
super(ASGBITOR, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ior + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignBitXorExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignBitXorExpression(long where, Expression left, Expression right) {
super(ASGBITXOR, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ixor + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignDivideExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignDivideExpression(long where, Expression left, Expression right) {
super(ASGDIV, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_idiv + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,157 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignExpression extends BinaryAssignExpression {
private FieldUpdater updater = null;
/**
* Constructor
*/
public AssignExpression(long where, Expression left, Expression right) {
super(ASSIGN, where, left, right);
}
/**
* Check an assignment expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
if (left instanceof IdentifierExpression) {
// we don't want to mark an identifier as having a value
// until having evaluated the right-hand side
vset = right.checkValue(env, ctx, vset, exp);
vset = left.checkLHS(env, ctx, vset, exp);
} else {
// normally left to right evaluation.
vset = left.checkLHS(env, ctx, vset, exp);
vset = right.checkValue(env, ctx, vset, exp);
}
type = left.type;
right = convert(env, ctx, type, right);
// Get field updater (access method) if needed, else null.
updater = left.getAssigner(env, ctx);
return vset;
}
/**
* Inline
*/
public Expression inlineValue(Environment env, Context ctx) {
if (implementation != null)
return implementation.inlineValue(env, ctx);
// Must be 'inlineLHS' here. But compare with similar case in
// 'AssignOpExpression' and 'IncDecExpression', which needs 'inlineValue'.
left = left.inlineLHS(env, ctx);
right = right.inlineValue(env, ctx);
if (updater != null) {
updater = updater.inline(env, ctx);
}
return this;
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
if (implementation != null)
return implementation.copyInline(ctx);
AssignExpression e = (AssignExpression)clone();
e.left = left.copyInline(ctx);
e.right = right.copyInline(ctx);
if (updater != null) {
e.updater = updater.copyInline(ctx);
}
return e;
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
/*----------*
return 2 + super.costInline(thresh, env, ctx);
*----------*/
return (updater != null)
// Cost of rhs expression + cost of access method call.
// Access method call cost includes lhs cost.
? right.costInline(thresh, env, ctx) +
updater.costInline(thresh, env, ctx, false)
// Cost of rhs expression + cost of lhs expression +
// cost of store instruction.
: right.costInline(thresh, env, ctx) +
left.costInline(thresh, env, ctx) + 2;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (updater == null) {
// Field is directly accessible.
int depth = left.codeLValue(env, ctx, asm);
right.codeValue(env, ctx, asm);
codeDup(env, ctx, asm, right.type.stackSize(), depth);
left.codeStore(env, ctx, asm);
} else {
// Must use access method.
// Left operand is always a 'FieldExpression', or
// is rewritten as one via 'implementation'.
updater.startAssign(env, ctx, asm);
right.codeValue(env, ctx, asm);
updater.finishAssign(env, ctx, asm, true);
}
}
public void code(Environment env, Context ctx, Assembler asm) {
if (updater == null) {
// Field is directly accessible.
left.codeLValue(env, ctx, asm);
right.codeValue(env, ctx, asm);
left.codeStore(env, ctx, asm);
} else {
// Must use access method.
// Left operand is always a 'FieldExpression', or
// is rewritten as one via 'implementation'.
updater.startAssign(env, ctx, asm);
right.codeValue(env, ctx, asm);
updater.finishAssign(env, ctx, asm, false);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignMultiplyExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignMultiplyExpression(long where, Expression left, Expression right) {
super(ASGMUL, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_imul + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,282 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public abstract
class AssignOpExpression extends BinaryAssignExpression {
protected Type itype; // Type of intermediate result, before assigning
final int NOINC = Integer.MAX_VALUE;
protected FieldUpdater updater = null; // Used also in 'AssignAddExpression'.
/**
* Constructor
*/
public AssignOpExpression(int op, long where, Expression left, Expression right) {
super(op, where, left, right);
}
/**
* Select the type
*
*/
final void selectType(Environment env, Context ctx, int tm) {
Type rtype = null; // special conversion type for RHS
switch(op) {
case ASGADD:
if (left.type == Type.tString) {
if (right.type == Type.tVoid) {
// The type of the right hand side can be
// anything except void. Fix for 4119864.
env.error(where, "incompatible.type",
opNames[op], Type.tVoid, Type.tString);
type = Type.tError;
} else {
type = itype = Type.tString;
}
return;
}
/* Fall through */
case ASGDIV: case ASGMUL: case ASGSUB: case ASGREM:
if ((tm & TM_DOUBLE) != 0) {
itype = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
itype = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
itype = Type.tLong;
} else {
itype = Type.tInt;
}
break;
case ASGBITAND: case ASGBITOR: case ASGBITXOR:
if ((tm & TM_BOOLEAN) != 0) {
itype = Type.tBoolean;
} else if ((tm & TM_LONG) != 0) {
itype = Type.tLong;
} else {
itype = Type.tInt;
}
break;
case ASGLSHIFT: case ASGRSHIFT: case ASGURSHIFT:
rtype = Type.tInt;
// Fix for bug 4134459.
// We allow any integral type (even long) to
// be the right hand side of a shift operation.
if (right.type.inMask(TM_INTEGER)) {
right = new ConvertExpression(where, Type.tInt, right);
}
// The intermediate type of the expression is the
// type of the left hand side after undergoing
// unary (not binary) type promotion. We ignore
// tm -- it contains information about both left
// and right hand sides -- and we compute the
// type only from the type of the lhs.
if (left.type == Type.tLong) {
itype = Type.tLong;
} else {
itype = Type.tInt;
}
break;
default:
throw new CompilerError("Bad assignOp type: " + op);
}
if (rtype == null) {
rtype = itype;
}
right = convert(env, ctx, rtype, right);
// The result is always the type of the left operand.
type = left.type;
}
/**
* Get the increment, return NOINC if an increment is not possible
*/
int getIncrement() {
if ((left.op == IDENT) && type.isType(TC_INT) && (right.op == INTVAL))
if ((op == ASGADD) || (op == ASGSUB))
if (((IdentifierExpression)left).field.isLocal()) {
int val = ((IntExpression)right).value;
if (op == ASGSUB)
val = -val;
if (val == (short)val)
return val;
}
return NOINC;
}
/**
* Check an assignment expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = left.checkAssignOp(env, ctx, vset, exp, this);
vset = right.checkValue(env, ctx, vset, exp);
int tm = left.type.getTypeMask() | right.type.getTypeMask();
if ((tm & TM_ERROR) != 0) {
return vset;
}
selectType(env, ctx, tm);
if (!type.isType(TC_ERROR)) {
convert(env, ctx, itype, left);
}
updater = left.getUpdater(env, ctx); // Must be called after 'checkAssignOp'.
return vset;
}
/**
* Inline
*/
public Expression inlineValue(Environment env, Context ctx) {
// Why not inlineLHS? But that does not work.
left = left.inlineValue(env, ctx);
right = right.inlineValue(env, ctx);
if (updater != null) {
updater = updater.inline(env, ctx);
}
return this;
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
AssignOpExpression e = (AssignOpExpression)clone();
e.left = left.copyInline(ctx);
e.right = right.copyInline(ctx);
if (updater != null) {
e.updater = updater.copyInline(ctx);
}
return e;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
/*----------*
return (getIncrement() != NOINC)
? 2
: (3 + super.costInline(thresh, env, ctx));
*----------*/
if (updater == null) {
return (getIncrement() != NOINC)
// Increment variable in place. Count 3 bytes for 'iinc'.
? 3
// Cost of rhs expression + cost of lhs expression + cost
// of load/op/store instructions. E.g.: iload = 1 or 2,
// istore = 1 or 2, iadd = 1. Cost could be higher if
// getfield/putfield or conversions needed, lower if rhs is
// a small constant. Costs are highly approximate.
: right.costInline(thresh, env, ctx) +
left.costInline(thresh, env, ctx) + 4;
} else {
// Cost of rhs expression + (2 * cost of access method call) +
// cost of operator. Does not account for cost of conversions,
// or duplications in value-needed context.
return right.costInline(thresh, env, ctx) +
updater.costInline(thresh, env, ctx, true) + 1;
}
}
/**
* Code
*/
void code(Environment env, Context ctx, Assembler asm, boolean valNeeded) {
// Handle cases in which a '+=' or '-=' operator can be optimized using
// the 'iinc' instruction. See also 'IncDecExpression.codeIncDec'.
// The 'iinc' instruction cannot be used if an access method call is required.
int val = getIncrement();
if (val != NOINC && updater == null) {
int v = ((LocalMember)((IdentifierExpression)left).field).number;
int[] operands = { v, val };
asm.add(where, opc_iinc, operands);
if (valNeeded) {
left.codeValue(env, ctx, asm);
}
return;
}
if (updater == null) {
// Field is directly accessible.
int depth = left.codeLValue(env, ctx, asm);
codeDup(env, ctx, asm, depth, 0);
left.codeLoad(env, ctx, asm);
codeConversion(env, ctx, asm, left.type, itype);
right.codeValue(env, ctx, asm);
codeOperation(env, ctx, asm);
codeConversion(env, ctx, asm, itype, type);
if (valNeeded) {
codeDup(env, ctx, asm, type.stackSize(), depth);
}
left.codeStore(env, ctx, asm);
} else {
// Must use access methods.
updater.startUpdate(env, ctx, asm, false);
codeConversion(env, ctx, asm, left.type, itype);
right.codeValue(env, ctx, asm);
codeOperation(env, ctx, asm);
codeConversion(env, ctx, asm, itype, type);
updater.finishUpdate(env, ctx, asm, valNeeded);
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
code(env, ctx, asm, true);
}
public void code(Environment env, Context ctx, Assembler asm) {
code(env, ctx, asm, false);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
left.print(out);
out.print(" ");
right.print(out);
out.print(")");
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignRemainderExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignRemainderExpression(long where, Expression left, Expression right) {
super(ASGREM, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_irem + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignShiftLeftExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignShiftLeftExpression(long where, Expression left, Expression right) {
super(ASGLSHIFT, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ishl + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignShiftRightExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignShiftRightExpression(long where, Expression left, Expression right) {
super(ASGRSHIFT, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ishr + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignSubtractExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignSubtractExpression(long where, Expression left, Expression right) {
super(ASGSUB, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_isub + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class AssignUnsignedShiftRightExpression extends AssignOpExpression {
/**
* Constructor
*/
public AssignUnsignedShiftRightExpression(long where, Expression left, Expression right) {
super(ASGURSHIFT, where, left, right);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iushr + itype.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryArithmeticExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryArithmeticExpression(int op, long where, Expression left, Expression right) {
super(op, where, left.type, left, right);
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
if ((tm & TM_DOUBLE) != 0) {
type = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
type = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else {
type = Type.tInt;
}
left = convert(env, ctx, type, left);
right = convert(env, ctx, type, right);
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryAssignExpression extends BinaryExpression {
Expression implementation;
/**
* Constructor
*/
BinaryAssignExpression(int op, long where, Expression left, Expression right) {
super(op, where, left.type, left, right);
}
public Expression getImplementation() {
if (implementation != null)
return implementation;
return this;
}
/**
* Order the expression based on precedence
*/
public Expression order() {
if (precedence() >= left.precedence()) {
UnaryExpression e = (UnaryExpression)left;
left = e.right;
e.right = order();
return e;
}
return this;
}
/**
* Check void expression
*/
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
if (implementation != null)
return implementation.inline(env, ctx);
return inlineValue(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
if (implementation != null)
return implementation.inlineValue(env, ctx);
left = left.inlineLHS(env, ctx);
right = right.inlineValue(env, ctx);
return this;
}
public Expression copyInline(Context ctx) {
if (implementation != null)
return implementation.copyInline(ctx);
return super.copyInline(ctx);
}
public int costInline(int thresh, Environment env, Context ctx) {
if (implementation != null)
return implementation.costInline(thresh, env, ctx);
return super.costInline(thresh, env, ctx);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
abstract public
class BinaryBitExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryBitExpression(int op, long where, Expression left, Expression right) {
super(op, where, left.type, left, right);
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
if ((tm & TM_BOOLEAN) != 0) {
type = Type.tBoolean;
} else if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else {
type = Type.tInt;
}
left = convert(env, ctx, type, left);
right = convert(env, ctx, type, right);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
left.codeValue(env, ctx, asm);
right.codeValue(env, ctx, asm);
codeOperation(env, ctx, asm);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryCompareExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryCompareExpression(int op, long where, Expression left, Expression right) {
super(op, where, Type.tBoolean, left, right);
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
Type t = Type.tInt;
if ((tm & TM_DOUBLE) != 0) {
t = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
t = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
t = Type.tLong;
}
left = convert(env, ctx, t, left);
right = convert(env, ctx, t, right);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryEqualityExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryEqualityExpression(int op, long where, Expression left, Expression right) {
super(op, where, Type.tBoolean, left, right);
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
Type t;
if ((tm & TM_ERROR) != 0) {
// who cares. One of them is an error.
return;
} else if ((tm & (TM_CLASS | TM_ARRAY | TM_NULL)) != 0) {
try {
if (env.explicitCast(left.type, right.type) ||
env.explicitCast(right.type, left.type)) {
return;
}
env.error(where, "incompatible.type",
left.type, left.type, right.type);
} catch (ClassNotFound e) {
env.error(where, "class.not.found", e.name, opNames[op]);
}
return;
} else if ((tm & TM_DOUBLE) != 0) {
t = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
t = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
t = Type.tLong;
} else if ((tm & TM_BOOLEAN) != 0) {
t = Type.tBoolean;
} else {
t = Type.tInt;
}
left = convert(env, ctx, t, left);
right = convert(env, ctx, t, right);
}
}

View File

@@ -0,0 +1,245 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Label;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryExpression extends UnaryExpression {
Expression left;
/**
* Constructor
*/
BinaryExpression(int op, long where, Type type, Expression left, Expression right) {
super(op, where, type, right);
this.left = left;
}
/**
* Order the expression based on precedence
*/
public Expression order() {
if (precedence() > left.precedence()) {
UnaryExpression e = (UnaryExpression)left;
left = e.right;
e.right = order();
return e;
}
return this;
}
/**
* Check a binary expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = left.checkValue(env, ctx, vset, exp);
vset = right.checkValue(env, ctx, vset, exp);
int tm = left.type.getTypeMask() | right.type.getTypeMask();
if ((tm & TM_ERROR) != 0) {
return vset;
}
selectType(env, ctx, tm);
if (type.isType(TC_ERROR)) {
env.error(where, "invalid.args", opNames[op]);
}
return vset;
}
/**
* Check if constant
*/
public boolean isConstant() {
switch (op) {
case MUL:
case DIV:
case REM:
case ADD:
case SUB:
case LSHIFT:
case RSHIFT:
case URSHIFT:
case LT:
case LE:
case GT:
case GE:
case EQ:
case NE:
case BITAND:
case BITXOR:
case BITOR:
case AND:
case OR:
return left.isConstant() && right.isConstant();
}
return false;
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return this;
}
Expression eval(long a, long b) {
return this;
}
Expression eval(float a, float b) {
return this;
}
Expression eval(double a, double b) {
return this;
}
Expression eval(boolean a, boolean b) {
return this;
}
Expression eval(String a, String b) {
return this;
}
Expression eval() {
// See also the eval() code in BinaryShiftExpression.java.
if (left.op == right.op) {
switch (left.op) {
case BYTEVAL:
case CHARVAL:
case SHORTVAL:
case INTVAL:
return eval(((IntegerExpression)left).value, ((IntegerExpression)right).value);
case LONGVAL:
return eval(((LongExpression)left).value, ((LongExpression)right).value);
case FLOATVAL:
return eval(((FloatExpression)left).value, ((FloatExpression)right).value);
case DOUBLEVAL:
return eval(((DoubleExpression)left).value, ((DoubleExpression)right).value);
case BOOLEANVAL:
return eval(((BooleanExpression)left).value, ((BooleanExpression)right).value);
case STRINGVAL:
return eval(((StringExpression)left).value, ((StringExpression)right).value);
}
}
return this;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
left = left.inline(env, ctx);
right = right.inline(env, ctx);
return (left == null) ? right : new CommaExpression(where, left, right);
}
public Expression inlineValue(Environment env, Context ctx) {
left = left.inlineValue(env, ctx);
right = right.inlineValue(env, ctx);
try {
return eval().simplify();
} catch (ArithmeticException e) {
// Got rid of this error message. It isn't illegal to
// have a program which does a constant division by
// zero. We return `this' to make the compiler to
// generate code here.
// (bugs 4019304, 4089107).
//
// env.error(where, "arithmetic.exception");
return this;
}
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
BinaryExpression e = (BinaryExpression)clone();
if (left != null) {
e.left = left.copyInline(ctx);
}
if (right != null) {
e.right = right.copyInline(ctx);
}
return e;
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1 + ((left != null) ? left.costInline(thresh, env, ctx) : 0) +
((right != null) ? right.costInline(thresh, env, ctx) : 0);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
throw new CompilerError("codeOperation: " + opNames[op]);
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (type.isType(TC_BOOLEAN)) {
Label l1 = new Label();
Label l2 = new Label();
codeBranch(env, ctx, asm, l1, true);
asm.add(true, where, opc_ldc, new Integer(0));
asm.add(true, where, opc_goto, l2);
asm.add(l1);
asm.add(true, where, opc_ldc, new Integer(1));
asm.add(l2);
} else {
left.codeValue(env, ctx, asm);
right.codeValue(env, ctx, asm);
codeOperation(env, ctx, asm);
}
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
if (left != null) {
left.print(out);
} else {
out.print("<null>");
}
out.print(" ");
if (right != null) {
right.print(out);
} else {
out.print("<null>");
}
out.print(")");
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
abstract public
class BinaryLogicalExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryLogicalExpression(int op, long where, Expression left, Expression right) {
super(op, where, Type.tBoolean, left, right);
}
/**
* Check a binary expression
*/
public Vset checkValue(Environment env, Context ctx,
Vset vset, Hashtable exp) {
ConditionVars cvars = new ConditionVars();
// evaluate the logical expression, determining which variables are
// set if the resulting value is true or false
checkCondition(env, ctx, vset, exp, cvars);
// return the intersection.
return cvars.vsTrue.join(cvars.vsFalse);
}
/*
* Every subclass of this class must define a genuine implementation
* of this method. It cannot inherit the method of Expression.
*/
abstract
public void checkCondition(Environment env, Context ctx, Vset vset,
Hashtable exp, ConditionVars cvars);
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
left = left.inlineValue(env, ctx);
right = right.inlineValue(env, ctx);
return this;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BinaryShiftExpression extends BinaryExpression {
/**
* constructor
*/
public BinaryShiftExpression(int op, long where, Expression left, Expression right) {
super(op, where, left.type, left, right);
}
/**
* Evaluate the expression
*/
Expression eval() {
// The eval code in BinaryExpression.java only works correctly
// for arithmetic expressions. For shift expressions, we get cases
// where the left and right operand may legitimately be of mixed
// types (long and int). This is a fix for 4082814.
if (left.op == LONGVAL && right.op == INTVAL) {
return eval(((LongExpression)left).value,
((IntExpression)right).value);
}
// Delegate the rest of the cases to our parent, so as to minimize
// impact on existing behavior.
return super.eval();
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
if (left.type == Type.tLong) {
type = Type.tLong;
} else if (left.type.inMask(TM_INTEGER)) {
type = Type.tInt;
left = convert(env, ctx, type, left);
} else {
type = Type.tError;
}
if (right.type.inMask(TM_INTEGER)) {
right = new ConvertExpression(where, Type.tInt, right);
} else {
right = convert(env, ctx, Type.tInt, right);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BitAndExpression extends BinaryBitExpression {
/**
* constructor
*/
public BitAndExpression(long where, Expression left, Expression right) {
super(BITAND, where, left, right);
}
/**
* Evaluate
*/
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a & b);
}
Expression eval(int a, int b) {
return new IntExpression(where, a & b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a & b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.equals(true))
return right;
if (right.equals(true))
return left;
if (left.equals(false) || left.equals(0))
return new CommaExpression(where, right, left).simplify();
if (right.equals(false) || right.equals(0))
return new CommaExpression(where, left, right).simplify();
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iand + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BitNotExpression extends UnaryExpression {
/**
* Constructor
*/
public BitNotExpression(long where, Expression right) {
super(BITNOT, where, right.type, right);
}
/**
* Select the type of the expression
*/
void selectType(Environment env, Context ctx, int tm) {
if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else {
type = Type.tInt;
}
right = convert(env, ctx, type, right);
}
/**
* Evaluate
*/
Expression eval(int a) {
return new IntExpression(where, ~a);
}
Expression eval(long a) {
return new LongExpression(where, ~a);
}
/**
* Simplify
*/
Expression simplify() {
if (right.op == BITNOT) {
return ((BitNotExpression)right).right;
}
return this;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
right.codeValue(env, ctx, asm);
if (type.isType(TC_INT)) {
asm.add(where, opc_ldc, new Integer(-1));
asm.add(where, opc_ixor);
} else {
asm.add(where, opc_ldc2_w, new Long(-1));
asm.add(where, opc_lxor);
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BitOrExpression extends BinaryBitExpression {
/**
* constructor
*/
public BitOrExpression(long where, Expression left, Expression right) {
super(BITOR, where, left, right);
}
/**
* Evaluate
*/
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a | b);
}
Expression eval(int a, int b) {
return new IntExpression(where, a | b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a | b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.equals(false) || left.equals(0))
return right;
if (right.equals(false) || right.equals(0))
return left;
if (left.equals(true))
return new CommaExpression(where, right, left).simplify();
if (right.equals(true))
return new CommaExpression(where, left, right).simplify();
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ior + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BitXorExpression extends BinaryBitExpression {
/**
* constructor
*/
public BitXorExpression(long where, Expression left, Expression right) {
super(BITXOR, where, left, right);
}
/**
* Evaluate
*/
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a ^ b);
}
Expression eval(int a, int b) {
return new IntExpression(where, a ^ b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a ^ b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.equals(true)) {
return new NotExpression(where, right);
}
if (right.equals(true)) {
return new NotExpression(where, left);
}
if (left.equals(false) || left.equals(0)) {
return right;
}
if (right.equals(false) || right.equals(0)) {
return left;
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ixor + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BooleanExpression extends ConstantExpression {
boolean value;
/**
* Constructor
*/
public BooleanExpression(long where, boolean value) {
super(BOOLEANVAL, where, Type.tBoolean);
this.value = value;
}
/**
* Get the value
*/
public Object getValue() {
return new Integer(value ? 1 : 0);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(boolean b) {
return value == b;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
return !value;
}
/*
* Check a "not" expression.
*
* cvars is modified so that
* cvar.vsTrue indicates variables with a known value if
* the expression is true.
* cvars.vsFalse indicates variables with a known value if
* the expression is false
*
* For constant expressions, set the side that corresponds to our
* already known value to vset. Set the side that corresponds to the
* other way to "impossible"
*/
public void checkCondition(Environment env, Context ctx,
Vset vset, Hashtable exp, ConditionVars cvars) {
if (value) {
cvars.vsFalse = Vset.DEAD_END;
cvars.vsTrue = vset;
} else {
cvars.vsFalse = vset;
cvars.vsTrue = Vset.DEAD_END;
}
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
if (value == whenTrue) {
asm.add(where, opc_goto, lbl);
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc, new Integer(value ? 1 : 0));
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value ? "true" : "false");
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class BreakStatement extends Statement {
Identifier lbl;
/**
* Constructor
*/
public BreakStatement(long where, Identifier lbl) {
super(BREAK, where);
this.lbl = lbl;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
reach(env, vset);
checkLabel(env, ctx);
CheckContext destctx = (CheckContext)new CheckContext(ctx, this).getBreakContext(lbl);
if (destctx != null) {
if (destctx.frameNumber != ctx.frameNumber) {
env.error(where, "branch.to.uplevel", lbl);
}
destctx.vsBreak = destctx.vsBreak.join(vset);
} else {
if (lbl != null) {
env.error(where, "label.not.found", lbl);
} else {
env.error(where, "invalid.break");
}
}
CheckContext exitctx = ctx.getTryExitContext();
if (exitctx != null) {
exitctx.vsTryExit = exitctx.vsTryExit.join(vset);
}
return DEAD_END;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
CodeContext destctx = (CodeContext)newctx.getBreakContext(lbl);
codeFinally(env, ctx, asm, destctx, null);
asm.add(where, opc_goto, destctx.breakLabel);
asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("break");
if (lbl != null) {
out.print(" " + lbl);
}
out.print(";");
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ByteExpression extends IntegerExpression {
/**
* Constructor
*/
public ByteExpression(long where, byte value) {
super(BYTEVAL, where, Type.tByte, value);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value + "b");
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CaseStatement extends Statement {
Expression expr;
/**
* Constructor
*/
public CaseStatement(long where, Expression expr) {
super(CASE, where);
this.expr = expr;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
if (expr != null) {
expr.checkValue(env, ctx, vset, exp);
expr = convert(env, ctx, Type.tInt, expr);
expr = expr.inlineValue(env, ctx);
}
return vset.clearDeadEnd();
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 6;
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
if (expr == null) {
out.print("default");
} else {
out.print("case ");
expr.print(out);
}
out.print(":");
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CastExpression extends BinaryExpression {
/**
* constructor
*/
public CastExpression(long where, Expression left, Expression right) {
super(CAST, where, left.type, left, right);
}
/**
* Check the expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
type = left.toType(env, ctx);
vset = right.checkValue(env, ctx, vset, exp);
if (type.isType(TC_ERROR) || right.type.isType(TC_ERROR)) {
// An error was already reported
return vset;
}
if (type.equals(right.type)) {
// The types are already the same
return vset;
}
try {
if (env.explicitCast(right.type, type)) {
right = new ConvertExpression(where, type, right);
return vset;
}
} catch (ClassNotFound e) {
env.error(where, "class.not.found", e.name, opNames[op]);
}
// The cast is not allowed
env.error(where, "invalid.cast", right.type, type);
return vset;
}
/**
* Check if constant
*/
public boolean isConstant() {
if (type.inMask(TM_REFERENCE) && !type.equals(Type.tString)) {
// must be a primitive type, or String
return false;
}
return right.isConstant();
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
return right.inline(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
return right.inlineValue(env, ctx);
}
public int costInline(int thresh, Environment env, Context ctx) {
if (ctx == null) {
return 1 + right.costInline(thresh, env, ctx);
}
// sourceClass is the current class trying to inline this method
ClassDefinition sourceClass = ctx.field.getClassDefinition();
try {
// We only allow the inlining if the current class can access
// the casting class
if (left.type.isType(TC_ARRAY) ||
sourceClass.permitInlinedAccess(env,
env.getClassDeclaration(left.type)))
return 1 + right.costInline(thresh, env, ctx);
} catch (ClassNotFound e) {
}
return thresh;
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
if (type.isType(TC_ERROR)) {
left.print(out);
} else {
out.print(type);
}
out.print(" ");
right.print(out);
out.print(")");
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 1994, 2004, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.LocalVariable;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CatchStatement extends Statement {
int mod;
Expression texpr;
Identifier id;
Statement body;
LocalMember field;
/**
* Constructor
*/
public CatchStatement(long where, Expression texpr, IdentifierToken id, Statement body) {
super(CATCH, where);
this.mod = id.getModifiers();
this.texpr = texpr;
this.id = id.getName();
this.body = body;
}
/** @deprecated */
@Deprecated
public CatchStatement(long where, Expression texpr, Identifier id, Statement body) {
super(CATCH, where);
this.texpr = texpr;
this.id = id;
this.body = body;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = reach(env, vset);
ctx = new Context(ctx, this);
Type type = texpr.toType(env, ctx);
try {
if (ctx.getLocalField(id) != null) {
env.error(where, "local.redefined", id);
}
if (type.isType(TC_ERROR)) {
// error message printed out elsewhere
} else if (!type.isType(TC_CLASS)) {
env.error(where, "catch.not.throwable", type);
} else {
ClassDefinition def = env.getClassDefinition(type);
if (!def.subClassOf(env,
env.getClassDeclaration(idJavaLangThrowable))) {
env.error(where, "catch.not.throwable", def);
}
}
field = new LocalMember(where, ctx.field.getClassDefinition(), mod, type, id);
ctx.declare(env, field);
vset.addVar(field.number);
return body.check(env, ctx, vset, exp);
} catch (ClassNotFound e) {
env.error(where, "class.not.found", e.name, opNames[op]);
return vset;
}
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
ctx = new Context(ctx, this);
if (field.isUsed()) {
ctx.declare(env, field);
}
if (body != null) {
body = body.inline(env, ctx);
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
CatchStatement s = (CatchStatement)clone();
if (body != null) {
s.body = body.copyInline(ctx, valNeeded);
}
if (field != null) {
s.field = field.copyInline(ctx);
}
return s;
}
/**
* Compute cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx){
int cost = 1;
if (body != null) {
cost += body.costInline(thresh, env,ctx);
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
if (field.isUsed()) {
newctx.declare(env, field);
asm.add(where, opc_astore, new LocalVariable(field, field.number));
} else {
asm.add(where, opc_pop);
}
if (body != null) {
body.code(env, newctx, asm);
}
//asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("catch (");
texpr.print(out);
out.print(" " + id + ") ");
if (body != null) {
body.print(out, indent);
} else {
out.print("<empty>");
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CharExpression extends IntegerExpression {
/**
* Constructor
*/
public CharExpression(long where, char value) {
super(CHARVAL, where, Type.tChar, value);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value + "c");
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CheckContext extends Context {
public Vset vsBreak = Vset.DEAD_END;
public Vset vsContinue = Vset.DEAD_END;
// Accumulate (join) all DA/DU state prior to
// any abnormal exit from a try-statement.
// This field is ignored unless this
// context is associated with a try-statement.
public Vset vsTryExit = Vset.DEAD_END;
/**
* Create a new nested context, for a block statement
*/
CheckContext(Context ctx, Statement stat) {
super(ctx, stat);
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
class CodeContext extends Context {
Label breakLabel;
Label contLabel;
/**
* Create a new nested context, for a block statement
*/
CodeContext(Context ctx, Node node) {
super(ctx, node);
switch (node.op) {
case DO:
case WHILE:
case FOR:
case FINALLY:
case SYNCHRONIZED:
this.breakLabel = new Label();
this.contLabel = new Label();
break;
case SWITCH:
case TRY:
case INLINEMETHOD:
case INLINENEWINSTANCE:
this.breakLabel = new Label();
break;
default:
if ((node instanceof Statement) && (((Statement)node).labels != null)) {
this.breakLabel = new Label();
}
}
}
}

View File

@@ -0,0 +1,150 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CommaExpression extends BinaryExpression {
/**
* constructor
*/
public CommaExpression(long where, Expression left, Expression right) {
super(COMMA, where, (right != null) ? right.type : Type.tVoid, left, right);
}
/**
* Check void expression
*/
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = left.check(env, ctx, vset, exp);
vset = right.check(env, ctx, vset, exp);
return vset;
}
/**
* Select the type
*/
void selectType(Environment env, Context ctx, int tm) {
type = right.type;
}
/**
* Simplify
*/
Expression simplify() {
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return this;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
if (left != null) {
left = left.inline(env, ctx);
}
if (right != null) {
right = right.inline(env, ctx);
}
return simplify();
}
public Expression inlineValue(Environment env, Context ctx) {
if (left != null) {
left = left.inline(env, ctx);
}
if (right != null) {
right = right.inlineValue(env, ctx);
}
return simplify();
}
/**
* Code
*/
int codeLValue(Environment env, Context ctx, Assembler asm) {
if (right == null) {
// throw an appropriate error
return super.codeLValue(env, ctx, asm);
} else {
// Fully code the left-hand side. Do the LValue part of the
// right-hand side now. The remainder will be done by codeLoad or
// codeStore
if (left != null) {
left.code(env, ctx, asm);
}
return right.codeLValue(env, ctx, asm);
}
}
void codeLoad(Environment env, Context ctx, Assembler asm) {
// The left-hand part has already been handled by codeLValue.
if (right == null) {
// throw an appropriate error
super.codeLoad(env, ctx, asm);
} else {
right.codeLoad(env, ctx, asm);
}
}
void codeStore(Environment env, Context ctx, Assembler asm) {
// The left-hand part has already been handled by codeLValue.
if (right == null) {
// throw an appropriate error
super.codeStore(env, ctx, asm);
} else {
right.codeStore(env, ctx, asm);
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (left != null) {
left.code(env, ctx, asm);
}
right.codeValue(env, ctx, asm);
}
public void code(Environment env, Context ctx, Assembler asm) {
if (left != null) {
left.code(env, ctx, asm);
}
if (right != null) {
right.code(env, ctx, asm);
}
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class CompoundStatement extends Statement {
Statement args[];
/**
* Constructor
*/
public CompoundStatement(long where, Statement args[]) {
super(STAT, where);
this.args = args;
// To avoid the need for subsequent null checks:
for (int i = 0 ; i < args.length ; i++) {
if (args[i] == null) {
args[i] = new CompoundStatement(where, new Statement[0]);
}
}
}
/**
* Insert a new statement at the front.
* This is used to introduce an implicit super-class constructor call.
*/
public void insertStatement(Statement s) {
Statement newargs[] = new Statement[1+args.length];
newargs[0] = s;
for (int i = 0 ; i < args.length ; i++) {
newargs[i+1] = args[i];
}
this.args = newargs;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
if (args.length > 0) {
vset = reach(env, vset);
CheckContext newctx = new CheckContext(ctx, this);
// In this environment, 'resolveName' will look for local classes.
Environment newenv = Context.newEnvironment(env, newctx);
for (int i = 0 ; i < args.length ; i++) {
vset = args[i].checkBlockStatement(newenv, newctx, vset, exp);
}
vset = vset.join(newctx.vsBreak);
}
return ctx.removeAdditionalVars(vset);
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
ctx = new Context(ctx, this);
boolean expand = false;
int count = 0;
for (int i = 0 ; i < args.length ; i++) {
Statement s = args[i];
if (s != null) {
if ((s = s.inline(env, ctx)) != null) {
if ((s.op == STAT) && (s.labels == null)) {
count += ((CompoundStatement)s).args.length;
} else {
count++;
}
expand = true;
}
args[i] = s;
}
}
switch (count) {
case 0:
return null;
case 1:
for (int i = args.length ; i-- > 0 ;) {
if (args[i] != null) {
return eliminate(env, args[i]);
}
}
break;
}
if (expand || (count != args.length)) {
Statement newArgs[] = new Statement[count];
for (int i = args.length ; i-- > 0 ;) {
Statement s = args[i];
if (s != null) {
if ((s.op == STAT) && (s.labels == null)) {
Statement a[] = ((CompoundStatement)s).args;
for (int j = a.length ; j-- > 0 ; ) {
newArgs[--count] = a[j];
}
} else {
newArgs[--count] = s;
}
}
}
args = newArgs;
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
CompoundStatement s = (CompoundStatement)clone();
s.args = new Statement[args.length];
for (int i = 0 ; i < args.length ; i++) {
s.args[i] = args[i].copyInline(ctx, valNeeded);
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
int cost = 0;
for (int i = 0 ; (i < args.length) && (cost < thresh) ; i++) {
cost += args[i].costInline(thresh, env, ctx);
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
for (int i = 0 ; i < args.length ; i++) {
args[i].code(env, newctx, asm);
}
asm.add(newctx.breakLabel);
}
/**
* Check if the first thing is a constructor invocation
*/
public Expression firstConstructor() {
return (args.length > 0) ? args[0].firstConstructor() : null;
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("{\n");
for (int i = 0 ; i < args.length ; i++) {
printIndent(out, indent+1);
if (args[i] != null) {
args[i].print(out, indent + 1);
} else {
out.print("<empty>");
}
out.print("\n");
}
printIndent(out, indent);
out.print("}");
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
/**
* This class is used to hold two sets of variables,
* one for the true branch, one for the false branch.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
class ConditionVars {
Vset vsTrue;
Vset vsFalse;
}

View File

@@ -0,0 +1,235 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ConditionalExpression extends BinaryExpression {
Expression cond;
/**
* Constructor
*/
public ConditionalExpression(long where, Expression cond, Expression left, Expression right) {
super(COND, where, Type.tError, left, right);
this.cond = cond;
}
/**
* Order the expression based on precedence
*/
public Expression order() {
if (precedence() > cond.precedence()) {
UnaryExpression e = (UnaryExpression)cond;
cond = e.right;
e.right = order();
return e;
}
return this;
}
/**
* Check the expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
ConditionVars cvars = cond.checkCondition(env, ctx, vset, exp);
vset = left.checkValue(env, ctx, cvars.vsTrue, exp).join(
right.checkValue(env, ctx, cvars.vsFalse, exp) );
cond = convert(env, ctx, Type.tBoolean, cond);
int tm = left.type.getTypeMask() | right.type.getTypeMask();
if ((tm & TM_ERROR) != 0) {
type = Type.tError;
return vset;
}
if (left.type.equals(right.type)) {
type = left.type;
} else if ((tm & TM_DOUBLE) != 0) {
type = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
type = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else if ((tm & TM_REFERENCE) != 0) {
try {
// This is wrong. We should be using their most common
// ancestor, instead.
type = env.implicitCast(right.type, left.type)
? left.type : right.type;
} catch (ClassNotFound e) {
type = Type.tError;
}
} else if (((tm & TM_CHAR) != 0) && left.fitsType(env, ctx, Type.tChar) && right.fitsType(env, ctx, Type.tChar)) {
type = Type.tChar;
} else if (((tm & TM_SHORT) != 0) && left.fitsType(env, ctx, Type.tShort) && right.fitsType(env, ctx, Type.tShort)) {
type = Type.tShort;
} else if (((tm & TM_BYTE) != 0) && left.fitsType(env, ctx, Type.tByte) && right.fitsType(env, ctx, Type.tByte)) {
type = Type.tByte;
} else {
type = Type.tInt;
}
left = convert(env, ctx, type, left);
right = convert(env, ctx, type, right);
return vset;
}
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = cond.checkValue(env, ctx, vset, exp);
cond = convert(env, ctx, Type.tBoolean, cond);
return left.check(env, ctx, vset.copy(), exp).join(right.check(env, ctx, vset, exp));
}
/**
* Check if constant
*/
public boolean isConstant() {
return cond.isConstant() && left.isConstant() && right.isConstant();
}
/**
* Simplify
*/
Expression simplify() {
if (cond.equals(true)) {
return left;
}
if (cond.equals(false)) {
return right;
}
return this;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
left = left.inline(env, ctx);
right = right.inline(env, ctx);
if ((left == null) && (right == null)) {
return cond.inline(env, ctx);
}
if (left == null) {
left = right;
right = null;
cond = new NotExpression(where, cond);
}
cond = cond.inlineValue(env, ctx);
return simplify();
}
public Expression inlineValue(Environment env, Context ctx) {
cond = cond.inlineValue(env, ctx);
left = left.inlineValue(env, ctx);
right = right.inlineValue(env, ctx);
return simplify();
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
// We need to check if right is null in case costInline()
// is called after this expression has been inlined.
// This call can happen, for example, in MemberDefinition#cleanup().
// (Fix for 4069861).
return 1 +
cond.costInline(thresh, env, ctx) +
left.costInline(thresh, env, ctx) +
((right == null) ? 0 : right.costInline(thresh, env, ctx));
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
ConditionalExpression e = (ConditionalExpression)clone();
e.cond = cond.copyInline(ctx);
e.left = left.copyInline(ctx);
// If copyInline() is called after inlining is complete,
// right could be null.
e.right = (right == null) ? null : right.copyInline(ctx);
return e;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
Label l1 = new Label();
Label l2 = new Label();
cond.codeBranch(env, ctx, asm, l1, false);
left.codeValue(env, ctx, asm);
asm.add(where, opc_goto, l2);
asm.add(l1);
right.codeValue(env, ctx, asm);
asm.add(l2);
}
public void code(Environment env, Context ctx, Assembler asm) {
Label l1 = new Label();
cond.codeBranch(env, ctx, asm, l1, false);
left.code(env, ctx, asm);
if (right != null) {
Label l2 = new Label();
asm.add(where, opc_goto, l2);
asm.add(l1);
right.code(env, ctx, asm);
asm.add(l2);
} else {
asm.add(l1);
}
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
cond.print(out);
out.print(" ");
left.print(out);
out.print(" ");
if (right != null) {
right.print(out);
} else {
out.print("<null>");
}
out.print(")");
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
class ConstantExpression extends Expression {
/**
* Constructor
*/
public ConstantExpression(int op, long where, Type type) {
super(op, where, type);
}
/**
* Return true if constant
*/
public boolean isConstant() {
return true;
}
}

View File

@@ -0,0 +1,861 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class Context implements Constants {
Context prev;
Node node;
int varNumber;
LocalMember locals;
LocalMember classes;
MemberDefinition field;
int scopeNumber;
int frameNumber;
/**
* Create the initial context for a method
* The incoming context is inherited from
*/
public Context(Context ctx, MemberDefinition field) {
this.field = field;
if (ctx == null) {
this.frameNumber = 1;
this.scopeNumber = 2;
this.varNumber = 0;
} else {
this.prev = ctx;
this.locals = ctx.locals;
this.classes = ctx.classes;
if (field != null &&
(field.isVariable() || field.isInitializer())) {
// Variables and initializers are inlined into a constructor.
// Model this by inheriting the frame number of the parent,
// which will contain a "this" parameter.
this.frameNumber = ctx.frameNumber;
this.scopeNumber = ctx.scopeNumber + 1;
} else {
this.frameNumber = ctx.scopeNumber + 1;
this.scopeNumber = this.frameNumber + 1;
}
this.varNumber = ctx.varNumber;
}
}
/**
* Create a new context, for initializing a class.
*/
public Context(Context ctx, ClassDefinition c) {
this(ctx, (MemberDefinition)null);
}
/**
* Create a new nested context, for a block statement
*/
Context(Context ctx, Node node) {
if (ctx == null) {
this.frameNumber = 1;
this.scopeNumber = 2;
this.varNumber = 0;
} else {
this.prev = ctx;
this.locals = ctx.locals;
// Inherit local classes from surrounding block,
// just as for local variables. Fixes 4074421.
this.classes = ctx.classes;
this.varNumber = ctx.varNumber;
this.field = ctx.field;
this.frameNumber = ctx.frameNumber;
this.scopeNumber = ctx.scopeNumber + 1;
this.node = node;
}
}
public Context(Context ctx) {
this(ctx, (Node)null);
}
/**
* Declare local
*/
public int declare(Environment env, LocalMember local) {
//System.out.println( "DECLARE= " + local.getName() + "=" + varNumber + ", read=" + local.readcount + ", write=" + local.writecount + ", hash=" + local.hashCode());
local.scopeNumber = scopeNumber;
if (this.field == null && idThis.equals(local.getName())) {
local.scopeNumber += 1; // Anticipate variable or initializer.
}
if (local.isInnerClass()) {
local.prev = classes;
classes = local;
return 0;
}
// Originally the statement:
//
// local.subModifiers(M_INLINEABLE);
//
// was here with the comment:
//
// // prevent inlining across call sites
//
// This statement prevented constant local variables from
// inlining. It didn't seem to do anything useful.
//
// The statement has been removed and an assertion has been
// added which mandates that the only members which are marked
// with M_INLINEABLE are the ones for which isConstant() is true.
// (Fix for 4106244.)
//
// Addition to the above comment: they might also be
// final variables initialized with 'this', 'super', or other
// final identifiers. See VarDeclarationStatement.inline().
// So I've removed the assertion. The original subModifiers
// call appears to have been there to fix nested class translation
// breakage, which has been fixed in VarDeclarationStatement
// now instead. (Fix for 4073244.)
local.prev = locals;
locals = local;
local.number = varNumber;
varNumber += local.getType().stackSize();
return local.number;
}
/**
* Get a local variable by name
*/
public
LocalMember getLocalField(Identifier name) {
for (LocalMember f = locals ; f != null ; f = f.prev) {
if (name.equals(f.getName())) {
return f;
}
}
return null;
}
/**
* Get the scope number for a reference to a member of this class
* (Larger scope numbers are more deeply nested.)
* @see LocalMember#scopeNumber
*/
public
int getScopeNumber(ClassDefinition c) {
for (Context ctx = this; ctx != null; ctx = ctx.prev) {
if (ctx.field == null) continue;
if (ctx.field.getClassDefinition() == c) {
return ctx.frameNumber;
}
}
return -1;
}
private
MemberDefinition getFieldCommon(Environment env, Identifier name,
boolean apparentOnly) throws AmbiguousMember, ClassNotFound {
// Note: This is structured as a pair of parallel lookups.
// If we were to redesign Context, we might prefer to walk
// along a single chain of scopes.
LocalMember lf = getLocalField(name);
int ls = (lf == null) ? -2 : lf.scopeNumber;
ClassDefinition thisClass = field.getClassDefinition();
// Also look for a class member in a shallower scope.
for (ClassDefinition c = thisClass;
c != null;
c = c.getOuterClass()) {
MemberDefinition f = c.getVariable(env, name, thisClass);
if (f != null && getScopeNumber(c) > ls) {
if (apparentOnly && f.getClassDefinition() != c) {
continue;
}
return f;
}
}
return lf;
}
/**
* Assign a number to a class field.
* (This is used to track definite assignment of some blank finals.)
*/
public int declareFieldNumber(MemberDefinition field) {
return declare(null, new LocalMember(field));
}
/**
* Retrieve a number previously assigned by declareMember().
* Return -1 if there was no such assignment in this context.
*/
public int getFieldNumber(MemberDefinition field) {
for (LocalMember f = locals ; f != null ; f = f.prev) {
if (f.getMember() == field) {
return f.number;
}
}
return -1;
}
/**
* Return the local field or member field corresponding to a number.
* Return null if there is no such field.
*/
public MemberDefinition getElement(int number) {
for (LocalMember f = locals ; f != null ; f = f.prev) {
if (f.number == number) {
MemberDefinition field = f.getMember();
return (field != null) ? field : f;
}
}
return null;
}
/**
* Get a local class by name
*/
public
LocalMember getLocalClass(Identifier name) {
for (LocalMember f = classes ; f != null ; f = f.prev) {
if (name.equals(f.getName())) {
return f;
}
}
return null;
}
private
MemberDefinition getClassCommon(Environment env, Identifier name,
boolean apparentOnly) throws ClassNotFound {
LocalMember lf = getLocalClass(name);
int ls = (lf == null) ? -2 : lf.scopeNumber;
// Also look for a class member in a shallower scope.
for (ClassDefinition c = field.getClassDefinition();
c != null;
c = c.getOuterClass()) {
// QUERY: We may need to get the inner class from a
// superclass of 'c'. This call is prepared to
// resolve the superclass if necessary. Can we arrange
// to assure that it is always previously resolved?
// This is one of a small number of problematic calls that
// requires 'getSuperClass' to resolve superclasses on demand.
// See 'ClassDefinition.getInnerClass(env, nm)'.
MemberDefinition f = c.getInnerClass(env, name);
if (f != null && getScopeNumber(c) > ls) {
if (apparentOnly && f.getClassDefinition() != c) {
continue;
}
return f;
}
}
return lf;
}
/**
* Get either a local variable, or a field in a current class
*/
public final
MemberDefinition getField(Environment env, Identifier name) throws AmbiguousMember, ClassNotFound {
return getFieldCommon(env, name, false);
}
/**
* Like getField, except that it skips over inherited fields.
* Used for error checking.
*/
public final
MemberDefinition getApparentField(Environment env, Identifier name) throws AmbiguousMember, ClassNotFound {
return getFieldCommon(env, name, true);
}
/**
* Check if the given field is active in this context.
*/
public boolean isInScope(LocalMember field) {
for (LocalMember f = locals ; f != null ; f = f.prev) {
if (field == f) {
return true;
}
}
return false;
}
/**
* Notice a reference (usually an uplevel one).
* Update the references list of every enclosing class
* which is enclosed by the scope of the target.
* Update decisions about which uplevels to make into fields.
* Return the uplevel reference descriptor, or null if it's local.
* <p>
* The target must be in scope in this context.
* So, call this method only from the check phase.
* (In other phases, the context may be less complete.)
* <p>
* This can and should be called both before and after classes are frozen.
* It should be a no-op, and will raise a compiler error if not.
*/
public UplevelReference noteReference(Environment env, LocalMember target) {
int targetScopeNumber = !isInScope(target) ? -1 : target.scopeNumber;
// Walk outward visiting each scope.
// Note each distinct frame (i.e., enclosing method).
// For each frame in which the variable is uplevel,
// record the event in the references list of the enclosing class.
UplevelReference res = null;
int currentFrameNumber = -1;
for (Context refctx = this; refctx != null; refctx = refctx.prev) {
if (currentFrameNumber == refctx.frameNumber) {
continue; // we're processing frames, not contexts
}
currentFrameNumber = refctx.frameNumber;
if (targetScopeNumber >= currentFrameNumber) {
break; // the target is native to this frame
}
// process a frame which is using this variable as an uplevel
ClassDefinition refc = refctx.field.getClassDefinition();
UplevelReference r = refc.getReference(target);
r.noteReference(env, refctx);
// remember the reference pertaining to the innermost frame
if (res == null) {
res = r;
}
}
return res;
}
/**
* Implement a reference (usually an uplevel one).
* Call noteReference() first, to make sure the reference
* lists are up to date.
* <p>
* The resulting expression tree does not need checking;
* it can be code-generated right away.
* If the reference is not uplevel, the result is an IDENT or THIS.
*/
public Expression makeReference(Environment env, LocalMember target) {
UplevelReference r = noteReference(env, target);
// Now create a referencing expression.
if (r != null) {
return r.makeLocalReference(env, this);
} else if (idThis.equals(target.getName())) {
return new ThisExpression(0, target);
} else {
return new IdentifierExpression(0, target);
}
}
/**
* Return a local expression which can serve as the base reference
* for the given field. If the field is a constructor, return an
* expression for the implicit enclosing instance argument.
* <p>
* Return null if there is no need for such an argument,
* or if there was an error.
*/
public Expression findOuterLink(Environment env, long where,
MemberDefinition f) {
// reqc is the base pointer type required to use f
ClassDefinition fc = f.getClassDefinition();
ClassDefinition reqc = f.isStatic() ? null
: !f.isConstructor() ? fc
: fc.isTopLevel() ? null
: fc.getOuterClass();
if (reqc == null) {
return null;
}
return findOuterLink(env, where, reqc, f, false);
}
private static boolean match(Environment env,
ClassDefinition thisc, ClassDefinition reqc) {
try {
return thisc == reqc
|| reqc.implementedBy(env, thisc.getClassDeclaration());
} catch (ClassNotFound ee) {
return false;
}
}
public Expression findOuterLink(Environment env, long where,
ClassDefinition reqc,
MemberDefinition f,
boolean needExactMatch) {
if (field.isStatic()) {
if (f == null) {
// say something like: undefined variable A.this
Identifier nm = reqc.getName().getFlatName().getName();
env.error(where, "undef.var", Identifier.lookup(nm,idThis));
} else if (f.isConstructor()) {
env.error(where, "no.outer.arg", reqc, f.getClassDeclaration());
} else if (f.isMethod()) {
env.error(where, "no.static.meth.access",
f, f.getClassDeclaration());
} else {
env.error(where, "no.static.field.access", f.getName(),
f.getClassDeclaration());
}
// This is an attempt at error recovery.
// Unfortunately, the constructor may throw
// a null pointer exception after failing to resolve
// 'idThis'. Since an error message has already been
// issued previously, this exception is caught and
// silently ignored. Ideally, we should avoid throwing
// the exception.
Expression e = new ThisExpression(where, this);
e.type = reqc.getType();
return e;
}
// use lp to scan for current instances (locals named "this")
LocalMember lp = locals;
// thise is a link expression being built up
Expression thise = null;
// root is the local variable (idThis) at the far left of thise
LocalMember root = null;
// thisc is the class of the link expression thise
ClassDefinition thisc = null;
// conCls is the class of the "this", in a constructor
ClassDefinition conCls = null;
if (field.isConstructor()) {
conCls = field.getClassDefinition();
}
if (!field.isMethod()) {
thisc = field.getClassDefinition();
thise = new ThisExpression(where, this);
}
while (true) {
if (thise == null) {
// start fresh from lp
while (lp != null && !idThis.equals(lp.getName())) {
lp = lp.prev;
}
if (lp == null) {
break;
}
thise = new ThisExpression(where, lp);
thisc = lp.getClassDefinition();
root = lp;
lp = lp.prev;
}
// Require exact class identity when called with
// 'needExactMatch' true. This is done when checking
// the '<class>.this' syntax. Fixes 4102393 and 4133457.
if (thisc == reqc ||
(!needExactMatch && match(env, thisc, reqc))) {
break;
}
// move out one step, if the current instance has an outer link
MemberDefinition outerMember = thisc.findOuterMember();
if (outerMember == null) {
thise = null;
continue; // try to find more help in lp
}
ClassDefinition prevc = thisc;
thisc = prevc.getOuterClass();
if (prevc == conCls) {
// Must pick up "this$C" from the constructor argument,
// not from "this.this$C", since the latter may not be
// initialized properly. (This way is cheaper too.)
Identifier nm = outerMember.getName();
IdentifierExpression arg = new IdentifierExpression(where, nm);
arg.bind(env, this);
thise = arg;
} else {
thise = new FieldExpression(where, thise, outerMember);
}
}
if (thise != null) {
// mark crossed scopes
// ?????
//ensureAvailable(root);
return thise;
}
if (f == null) {
// say something like: undefined variable A.this
Identifier nm = reqc.getName().getFlatName().getName();
env.error(where, "undef.var", Identifier.lookup(nm,idThis));
} else if (f.isConstructor()) {
env.error(where, "no.outer.arg", reqc, f.getClassDefinition());
} else {
env.error(where, "no.static.field.access", f, field);
}
// avoid floodgating:
Expression e = new ThisExpression(where, this);
e.type = reqc.getType();
return e;
}
/**
* Is there a "this" of type reqc in scope?
*/
public static boolean outerLinkExists(Environment env,
ClassDefinition reqc,
ClassDefinition thisc) {
while (!match(env, thisc, reqc)) {
if (thisc.isTopLevel()) {
return false;
}
thisc = thisc.getOuterClass();
}
return true;
}
/**
* From which enclosing class do members of this type come?
*/
public ClassDefinition findScope(Environment env, ClassDefinition reqc) {
ClassDefinition thisc = field.getClassDefinition();
while (thisc != null && !match(env, thisc, reqc)) {
thisc = thisc.getOuterClass();
}
return thisc;
}
/**
* Resolve a type name from within a local scope.
* @see Environment#resolveName
*/
Identifier resolveName(Environment env, Identifier name) {
// This logic is pretty much exactly parallel to that of
// Environment.resolveName().
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. Environment.resolveName.)
Identifier rhead = resolveName(env, name.getHead());
if (rhead.hasAmbigPrefix()) {
// The first identifier component refers to an
// ambiguous class. Limp on. We throw away the
// rest of the classname as it is irrelevant.
// (part of solution for 4059855).
return rhead;
}
if (!env.classExists(rhead)) {
return env.resolvePackageQualifiedName(name);
}
try {
return env.getClassDefinition(rhead).
resolveInnerClass(env, name.getTail());
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
return Identifier.lookupInner(rhead, name.getTail());
}
}
// Look for an unqualified name in enclosing scopes.
try {
MemberDefinition f = getClassCommon(env, name, false);
if (f != null) {
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
// look in imports, etc.
return env.resolveName(name);
}
/**
* Return the name of a lexically apparent type,
* skipping inherited members, and ignoring
* the current pacakge and imports.
* This is used for error checking.
*/
public
Identifier getApparentClassName(Environment env, Identifier name) {
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. Environment.resolveName.)
Identifier rhead = getApparentClassName(env, name.getHead());
return (rhead == null) ? idNull
: Identifier.lookup(rhead,
name.getTail());
}
// Look for an unqualified name in enclosing scopes.
try {
MemberDefinition f = getClassCommon(env, name, true);
if (f != null) {
return f.getInnerClass().getName();
}
} catch (ClassNotFound ee) {
// a missing superclass, or something catastrophic
}
// the enclosing class name is the only apparent package member:
Identifier topnm = field.getClassDefinition().getTopClass().getName();
if (topnm.getName().equals(name)) {
return topnm;
}
return idNull;
}
/**
* Raise an error if a blank final was definitely unassigned
* on entry to a loop, but has possibly been assigned on the
* back-branch. If this is the case, the loop may be assigning
* it multiple times.
*/
public void checkBackBranch(Environment env, Statement loop,
Vset vsEntry, Vset vsBack) {
for (LocalMember f = locals ; f != null ; f = f.prev) {
if (f.isBlankFinal()
&& vsEntry.testVarUnassigned(f.number)
&& !vsBack.testVarUnassigned(f.number)) {
env.error(loop.where, "assign.to.blank.final.in.loop",
f.getName());
}
}
}
/**
* Check if a field can reach another field (only considers
* forward references, not the access modifiers).
*/
public boolean canReach(Environment env, MemberDefinition f) {
return field.canReach(env, f);
}
/**
* Get the context that corresponds to a label, return null if
* not found.
*/
public
Context getLabelContext(Identifier lbl) {
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
if ((ctx.node != null) && (ctx.node instanceof Statement)) {
if (((Statement)(ctx.node)).hasLabel(lbl))
return ctx;
}
}
return null;
}
/**
* Get the destination context of a break
*/
public
Context getBreakContext(Identifier lbl) {
if (lbl != null) {
return getLabelContext(lbl);
}
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
if (ctx.node != null) {
switch (ctx.node.op) {
case SWITCH:
case FOR:
case DO:
case WHILE:
return ctx;
}
}
}
return null;
}
/**
* Get the destination context of a continue
*/
public
Context getContinueContext(Identifier lbl) {
if (lbl != null) {
return getLabelContext(lbl);
}
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
if (ctx.node != null) {
switch (ctx.node.op) {
case FOR:
case DO:
case WHILE:
return ctx;
}
}
}
return null;
}
/**
* Get the destination context of a return (the method body)
*/
public
CheckContext getReturnContext() {
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
// The METHOD node is set up by Statement.checkMethod().
if (ctx.node != null && ctx.node.op == METHOD) {
return (CheckContext)ctx;
}
}
return null;
}
/**
* Get the context of the innermost surrounding try-block.
* Consider only try-blocks contained within the same method.
* (There could be others when searching from within a method
* of a local class, but they are irrelevant to our purpose.)
* This is used for recording DA/DU information preceding
* all abnormal transfers of control: break, continue, return,
* and throw.
*/
public
CheckContext getTryExitContext() {
for (Context ctx = this;
ctx != null && ctx.node != null && ctx.node.op != METHOD;
ctx = ctx.prev) {
if (ctx.node.op == TRY) {
return (CheckContext)ctx;
}
}
return null;
}
/**
* Get the nearest inlined context
*/
Context getInlineContext() {
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
if (ctx.node != null) {
switch (ctx.node.op) {
case INLINEMETHOD:
case INLINENEWINSTANCE:
return ctx;
}
}
}
return null;
}
/**
* Get the context of a field that is being inlined
*/
Context getInlineMemberContext(MemberDefinition field) {
for (Context ctx = this ; ctx != null ; ctx = ctx.prev) {
if (ctx.node != null) {
switch (ctx.node.op) {
case INLINEMETHOD:
if (((InlineMethodExpression)ctx.node).field.equals(field)) {
return ctx;
}
break;
case INLINENEWINSTANCE:
if (((InlineNewInstanceExpression)ctx.node).field.equals(field)) {
return ctx;
}
}
}
}
return null;
}
/**
* Remove variables from the vset set that are no longer part of
* this context.
*/
public final Vset removeAdditionalVars(Vset vset) {
return vset.removeAdditionalVars(varNumber);
}
public final int getVarNumber() {
return varNumber;
}
/**
* Return the number of the innermost current instance reference.
*/
public int getThisNumber() {
LocalMember thisf = getLocalField(idThis);
if (thisf != null
&& thisf.getClassDefinition() == field.getClassDefinition()) {
return thisf.number;
}
// this is a variable; there is no "this" (should not happen)
return varNumber;
}
/**
* Return the field containing the present context.
*/
public final MemberDefinition getField() {
return field;
}
/**
* Extend an environment with the given context.
* The resulting environment behaves the same as
* the given one, except that resolveName() takes
* into account local class names in this context.
*/
public static Environment newEnvironment(Environment env, Context ctx) {
return new ContextEnvironment(env, ctx);
}
}
final
class ContextEnvironment extends Environment {
Context ctx;
Environment innerEnv;
ContextEnvironment(Environment env, Context ctx) {
super(env, env.getSource());
this.ctx = ctx;
this.innerEnv = env;
}
public Identifier resolveName(Identifier name) {
return ctx.resolveName(innerEnv, name);
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ContinueStatement extends Statement {
Identifier lbl;
/**
* Constructor
*/
public ContinueStatement(long where, Identifier lbl) {
super(CONTINUE, where);
this.lbl = lbl;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
reach(env, vset);
// A new context is established here because the 'continue' statement
// itself may be labelled, however erroneously. A 'CheckContext' must
// be used here, as 'getContinueContext' is expected to return one.
CheckContext destctx = (CheckContext)new CheckContext(ctx, this).getContinueContext(lbl);
if (destctx != null) {
switch (destctx.node.op) {
case FOR:
case DO:
case WHILE:
if (destctx.frameNumber != ctx.frameNumber) {
env.error(where, "branch.to.uplevel", lbl);
}
destctx.vsContinue = destctx.vsContinue.join(vset);
break;
default:
env.error(where, "invalid.continue");
}
} else {
if (lbl != null) {
env.error(where, "label.not.found", lbl);
} else {
env.error(where, "invalid.continue");
}
}
CheckContext exitctx = ctx.getTryExitContext();
if (exitctx != null) {
exitctx.vsTryExit = exitctx.vsTryExit.join(vset);
}
return DEAD_END;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext destctx = (CodeContext)ctx.getContinueContext(lbl);
codeFinally(env, ctx, asm, destctx, null);
asm.add(where, opc_goto, destctx.contLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("continue");
if (lbl != null) {
out.print(" " + lbl);
}
out.print(";");
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ConvertExpression extends UnaryExpression {
/**
* Constructor
*/
public ConvertExpression(long where, Type type, Expression right) {
super(CONVERT, where, type, right);
}
/**
* Check the value
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
return right.checkValue(env, ctx, vset, exp);
}
/**
* Simplify
*/
Expression simplify() {
switch (right.op) {
case BYTEVAL:
case CHARVAL:
case SHORTVAL:
case INTVAL: {
int value = ((IntegerExpression)right).value;
switch (type.getTypeCode()) {
case TC_BYTE: return new ByteExpression(right.where, (byte)value);
case TC_CHAR: return new CharExpression(right.where, (char)value);
case TC_SHORT: return new ShortExpression(right.where, (short)value);
case TC_INT: return new IntExpression(right.where, (int)value);
case TC_LONG: return new LongExpression(right.where, (long)value);
case TC_FLOAT: return new FloatExpression(right.where, (float)value);
case TC_DOUBLE: return new DoubleExpression(right.where, (double)value);
}
break;
}
case LONGVAL: {
long value = ((LongExpression)right).value;
switch (type.getTypeCode()) {
case TC_BYTE: return new ByteExpression(right.where, (byte)value);
case TC_CHAR: return new CharExpression(right.where, (char)value);
case TC_SHORT: return new ShortExpression(right.where, (short)value);
case TC_INT: return new IntExpression(right.where, (int)value);
case TC_FLOAT: return new FloatExpression(right.where, (float)value);
case TC_DOUBLE: return new DoubleExpression(right.where, (double)value);
}
break;
}
case FLOATVAL: {
float value = ((FloatExpression)right).value;
switch (type.getTypeCode()) {
case TC_BYTE: return new ByteExpression(right.where, (byte)value);
case TC_CHAR: return new CharExpression(right.where, (char)value);
case TC_SHORT: return new ShortExpression(right.where, (short)value);
case TC_INT: return new IntExpression(right.where, (int)value);
case TC_LONG: return new LongExpression(right.where, (long)value);
case TC_DOUBLE: return new DoubleExpression(right.where, (double)value);
}
break;
}
case DOUBLEVAL: {
double value = ((DoubleExpression)right).value;
switch (type.getTypeCode()) {
case TC_BYTE: return new ByteExpression(right.where, (byte)value);
case TC_CHAR: return new CharExpression(right.where, (char)value);
case TC_SHORT: return new ShortExpression(right.where, (short)value);
case TC_INT: return new IntExpression(right.where, (int)value);
case TC_LONG: return new LongExpression(right.where, (long)value);
case TC_FLOAT: return new FloatExpression(right.where, (float)value);
}
break;
}
}
return this;
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return right.equals(i);
}
public boolean equals(boolean b) {
return right.equals(b);
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
// super.inline throws away the op.
// This is sometimes incorrect, since casts can have side effects.
if (right.type.inMask(TM_REFERENCE) && type.inMask(TM_REFERENCE)) {
try {
if (!env.implicitCast(right.type, type))
return inlineValue(env, ctx);
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
}
return super.inline(env, ctx);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
right.codeValue(env, ctx, asm);
codeConversion(env, ctx, asm, right.type, type);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " " + type.toString() + " ");
right.print(out);
out.print(")");
}
}

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class DeclarationStatement extends Statement {
int mod;
Expression type;
Statement args[];
/**
* Constructor
*/
public DeclarationStatement(long where, int mod, Expression type, Statement args[]) {
super(DECLARATION, where);
this.mod = mod;
this.type = type;
this.args = args;
}
/**
* Check statement
* Report an error unless the call is checkBlockStatement.
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
env.error(where, "invalid.decl");
return checkBlockStatement(env, ctx, vset, exp);
}
Vset checkBlockStatement(Environment env, Context ctx, Vset vset, Hashtable exp) {
if (labels != null) {
env.error(where, "declaration.with.label", labels[0]);
}
vset = reach(env, vset);
Type t = type.toType(env, ctx);
for (int i = 0 ; i < args.length ; i++) {
vset = args[i].checkDeclaration(env, ctx, vset, mod, t, exp);
}
return vset;
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
int n = 0;
for (int i = 0 ; i < args.length ; i++) {
if ((args[i] = args[i].inline(env, ctx)) != null) {
n++;
}
}
return (n == 0) ? null : this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
DeclarationStatement s = (DeclarationStatement)clone();
if (type != null) {
s.type = type.copyInline(ctx);
}
s.args = new Statement[args.length];
for (int i = 0; i < args.length; i++){
if (args[i] != null){
s.args[i] = args[i].copyInline(ctx, valNeeded);
}
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
int cost = 1;
for (int i = 0; i < args.length; i++){
if (args[i] != null){
cost += args[i].costInline(thresh, env, ctx);
}
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
for (int i = 0 ; i < args.length ; i++) {
if (args[i] != null) {
args[i].code(env, ctx, asm);
}
}
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
out.print("declare ");
super.print(out, indent);
type.print(out);
out.print(" ");
for (int i = 0 ; i < args.length ; i++) {
if (i > 0) {
out.print(", ");
}
if (args[i] != null) {
args[i].print(out);
} else {
out.print("<empty>");
}
}
out.print(";");
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 1995, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
abstract public
class DivRemExpression extends BinaryArithmeticExpression {
/**
* constructor
*/
public DivRemExpression(int op, long where, Expression left, Expression right) {
super(op, where, left, right);
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
// Do not toss out integer divisions or remainders since they
// can cause a division by zero.
if (type.inMask(TM_INTEGER)) {
right = right.inlineValue(env, ctx);
if (right.isConstant() && !right.equals(0)) {
// We know the division can be elided
left = left.inline(env, ctx);
return left;
} else {
left = left.inlineValue(env, ctx);
try {
return eval().simplify();
} catch (ArithmeticException e) {
env.error(where, "arithmetic.exception");
return this;
}
}
} else {
// float & double divisions don't cause arithmetic errors
return super.inline(env, ctx);
}
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class DivideExpression extends DivRemExpression {
/**
* constructor
*/
public DivideExpression(long where, Expression left, Expression right) {
super(DIV, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a / b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a / b);
}
Expression eval(float a, float b) {
return new FloatExpression(where, a / b);
}
Expression eval(double a, double b) {
return new DoubleExpression(where, a / b);
}
/**
* Simplify
*/
Expression simplify() {
// This code here was wrong. What if the expression is a float?
// In any case, if the expression throws an exception, we
// should just throw the exception at run-time. Throwing
// it at compile-time is not correct.
// (Fix for 4019300)
//
// if (right.equals(0)) {
// throw new ArithmeticException("/ by zero");
// }
if (right.equals(1)) {
return left;
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_idiv + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class DoStatement extends Statement {
Statement body;
Expression cond;
/**
* Constructor
*/
public DoStatement(long where, Statement body, Expression cond) {
super(DO, where);
this.body = body;
this.cond = cond;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env,ctx);
CheckContext newctx = new CheckContext(ctx, this);
// remember what was unassigned on entry
Vset vsEntry = vset.copy();
vset = body.check(env, newctx, reach(env, vset), exp);
vset = vset.join(newctx.vsContinue);
// get to the test either by falling through the body, or through
// a "continue" statement.
ConditionVars cvars =
cond.checkCondition(env, newctx, vset, exp);
cond = convert(env, newctx, Type.tBoolean, cond);
// make sure the back-branch fits the entry of the loop
ctx.checkBackBranch(env, this, vsEntry, cvars.vsTrue);
// exit the loop through the test returning false, or a "break"
vset = newctx.vsBreak.join(cvars.vsFalse);
return ctx.removeAdditionalVars(vset);
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
ctx = new Context(ctx, this);
if (body != null) {
body = body.inline(env, ctx);
}
cond = cond.inlineValue(env, ctx);
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
DoStatement s = (DoStatement)clone();
s.cond = cond.copyInline(ctx);
if (body != null) {
s.body = body.copyInline(ctx, valNeeded);
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1 + cond.costInline(thresh, env, ctx)
+ ((body != null) ? body.costInline(thresh, env, ctx) : 0);
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
Label l1 = new Label();
asm.add(l1);
CodeContext newctx = new CodeContext(ctx, this);
if (body != null) {
body.code(env, newctx, asm);
}
asm.add(newctx.contLabel);
cond.codeBranch(env, newctx, asm, l1, true);
asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("do ");
body.print(out, indent);
out.print(" while ");
cond.print(out);
out.print(";");
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class DoubleExpression extends ConstantExpression {
double value;
/**
* Constructor
*/
public DoubleExpression(long where, double value) {
super(DOUBLEVAL, where, Type.tDouble);
this.value = value;
}
/**
* Get the value
*/
public Object getValue() {
return new Double(value);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return value == i;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
// don't allow -0.0
return (Double.doubleToLongBits(value) == 0);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc2_w, new Double(value));
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value + "D");
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class EqualExpression extends BinaryEqualityExpression {
/**
* constructor
*/
public EqualExpression(long where, Expression left, Expression right) {
super(EQ, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a == b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a == b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a == b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a == b);
}
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a == b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new EqualExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_BOOLEAN:
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmpeq : opc_if_icmpne, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpl);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpl);
break;
case TC_ARRAY:
case TC_CLASS:
case TC_NULL:
if (right.equals(0)) {
asm.add(where, whenTrue ? opc_ifnull : opc_ifnonnull, lbl, whenTrue);
} else {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_acmpeq : opc_if_acmpne, lbl, whenTrue);
}
return;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_ifeq : opc_ifne, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 1994, 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.util.Hashtable;
/**
* Parenthesized expressions.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ExprExpression extends UnaryExpression {
/**
* Constructor
*/
public ExprExpression(long where, Expression right) {
super(EXPR, where, right.type, right);
}
/**
* Check a condition. We must pass it on to our unparenthesised form.
*/
public void checkCondition(Environment env, Context ctx, Vset vset,
Hashtable exp, ConditionVars cvars) {
right.checkCondition(env, ctx, vset, exp, cvars);
type = right.type;
}
/**
* Check the expression if it appears as an lvalue.
* We just pass it on to our unparenthesized subexpression.
* (Part of fix for 4090372)
*/
public Vset checkAssignOp(Environment env, Context ctx,
Vset vset, Hashtable exp, Expression outside) {
vset = right.checkAssignOp(env, ctx, vset, exp, outside);
type = right.type;
return vset;
}
/**
* Delegate to our subexpression.
* (Part of fix for 4090372)
*/
public FieldUpdater getUpdater(Environment env, Context ctx) {
return right.getUpdater(env, ctx);
}
// Allow (x) = 9;
//
// I will hold off on this until I'm sure about it. Nobody's
// going to clammer for this one.
//
// public Vset checkLHS(Environment env, Context ctx,
// Vset vset, Hashtable exp) {
// vset = right.check(env, ctx, vset, exp);
// type = right.type;
// return vset;
// }
public boolean isNull() {
return right.isNull();
}
public boolean isNonNull() {
return right.isNonNull();
}
// Probably not necessary
public Object getValue() {
return right.getValue();
}
/**
* Delegate to our subexpression.
* See the comment in AddExpression#inlineValueSB() for
* information about this method.
*/
protected StringBuffer inlineValueSB(Environment env,
Context ctx,
StringBuffer buffer) {
return right.inlineValueSB(env, ctx, buffer);
}
/**
* Select the type of the expression
*/
void selectType(Environment env, Context ctx, int tm) {
type = right.type;
}
/**
* Simplify
*/
Expression simplify() {
return right;
}
}

View File

@@ -0,0 +1,775 @@
/*
* Copyright (c) 1994, 2004, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Label;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class Expression extends Node {
Type type;
/**
* Constructor
*/
Expression(int op, long where, Type type) {
super(op, where);
this.type = type;
}
/**
* Type checking may assign a more complex implementation
* to an innocuous-looking expression (like an identifier).
* Return that implementation, or the original expression itself
* if there is no special implementation.
* <p>
* This appears at present to be dead code, and is not called
* from within javac. Access to the implementation generally
* occurs within the same class, and thus uses the underlying
* field directly.
*/
public Expression getImplementation() {
return this;
}
public Type getType() {
return type;
}
/**
* Return the precedence of the operator
*/
int precedence() {
return (op < opPrecedence.length) ? opPrecedence[op] : 100;
}
/**
* Order the expression based on precedence
*/
public Expression order() {
return this;
}
/**
* Return true if constant, according to JLS 15.27.
* A constant expression must inline away to a literal constant.
*/
public boolean isConstant() {
return false;
}
/**
* Return the constant value.
*/
public Object getValue() {
return null;
}
/**
* Check if the expression is known to be equal to a given value.
* Returns false for any expression other than a literal constant,
* thus should be called only after simplification (inlining) has
* been performed.
*/
public boolean equals(int i) {
return false;
}
public boolean equals(boolean b) {
return false;
}
public boolean equals(Identifier id) {
return false;
}
public boolean equals(String s) {
return false;
}
/**
* Check if the expression must be a null reference.
*/
public boolean isNull() {
return false;
}
/**
* Check if the expression cannot be a null reference.
*/
public boolean isNonNull() {
return false;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
return false;
}
/**
* Convert an expresion to a type
*/
Type toType(Environment env, Context ctx) {
env.error(where, "invalid.type.expr");
return Type.tError;
}
/**
* Convert an expresion to a type in a context where a qualified
* type name is expected, e.g., in the prefix of a qualified type
* name.
*/
/*-----------------------------------------------------*
Type toQualifiedType(Environment env, Context ctx) {
env.error(where, "invalid.type.expr");
return Type.tError;
}
*-----------------------------------------------------*/
/**
* See if this expression fits in the given type.
* This is useful because some larger numbers fit into
* smaller types.
* <p>
* If it is an "int" constant expression, inline it, if necessary,
* to examine its numerical value. See JLS 5.2 and 15.24.
*/
public boolean fitsType(Environment env, Context ctx, Type t) {
try {
if (env.isMoreSpecific(this.type, t)) {
return true;
}
if (this.type.isType(TC_INT) && this.isConstant() && ctx != null) {
// Tentative inlining is harmless for constant expressions.
Expression n = this.inlineValue(env, ctx);
if (n != this && n instanceof ConstantExpression) {
return n.fitsType(env, ctx, t);
}
}
return false;
} catch (ClassNotFound e) {
return false;
}
}
/** @deprecated (for backward compatibility) */
@Deprecated
public boolean fitsType(Environment env, Type t) {
return fitsType(env, (Context) null, t);
}
/**
* Check an expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
return vset;
}
public Vset checkInitializer(Environment env, Context ctx, Vset vset, Type t, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
throw new CompilerError("check failed");
}
public Vset checkLHS(Environment env, Context ctx,
Vset vset, Hashtable exp) {
env.error(where, "invalid.lhs.assignment");
type = Type.tError;
return vset;
}
/**
* Return a <code>FieldUpdater</code> object to be used in updating the
* value of the location denoted by <code>this</code>, which must be an
* expression suitable for the left-hand side of an assignment.
* This is used for implementing assignments to private fields for which
* an access method is required. Returns null if no access method is
* needed, in which case the assignment is handled in the usual way, by
* direct access. Only simple assignment expressions are handled here
* Assignment operators and pre/post increment/decrement operators are
* are handled by 'getUpdater' below.
* <p>
* Called during the checking phase.
*/
public FieldUpdater getAssigner(Environment env, Context ctx) {
throw new CompilerError("getAssigner lhs");
}
/**
* Return a <code>FieldUpdater</code> object to be used in updating the value of the
* location denoted by <code>this</code>, which must be an expression suitable for the
* left-hand side of an assignment. This is used for implementing the assignment
* operators and the increment/decrement operators on private fields that require an
* access method, e.g., uplevel from an inner class. Returns null if no access method
* is needed.
* <p>
* Called during the checking phase.
*/
public FieldUpdater getUpdater(Environment env, Context ctx) {
throw new CompilerError("getUpdater lhs");
}
public Vset checkAssignOp(Environment env, Context ctx,
Vset vset, Hashtable exp, Expression outside) {
if (outside instanceof IncDecExpression)
env.error(where, "invalid.arg", opNames[outside.op]);
else
env.error(where, "invalid.lhs.assignment");
type = Type.tError;
return vset;
}
/**
* Check something that might be an AmbiguousName (refman 6.5.2).
* A string of dot-separated identifiers might be, in order of preference:
* <nl>
* <li> a variable name followed by fields or types
* <li> a type name followed by fields or types
* <li> a package name followed a type and then fields or types
* </nl>
* If a type name is found, it rewrites itself as a <tt>TypeExpression</tt>.
* If a node decides it can only be a package prefix, it sets its
* type to <tt>Type.tPackage</tt>. The caller must detect this
* and act appropriately to verify the full package name.
* @arg loc the expression containing the ambiguous expression
*/
public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
UnaryExpression loc) {
return checkValue(env, ctx, vset, exp);
}
/**
* Check a condition. Return a ConditionVars(), which indicates when
* which variables are set if the condition is true, and which are set if
* the condition is false.
*/
public ConditionVars checkCondition(Environment env, Context ctx,
Vset vset, Hashtable exp) {
ConditionVars cvars = new ConditionVars();
checkCondition(env, ctx, vset, exp, cvars);
return cvars;
}
/*
* Check a condition.
*
* cvars is modified so that
* cvar.vsTrue indicates variables with a known value if result = true
* cvars.vsFalse indicates variables with a known value if !result
*
* The default action is to simply call checkValue on the expression, and
* to see both vsTrue and vsFalse to the result.
*/
public void checkCondition(Environment env, Context ctx,
Vset vset, Hashtable exp, ConditionVars cvars) {
cvars.vsTrue = cvars.vsFalse = checkValue(env, ctx, vset, exp);
// unshare side effects:
cvars.vsFalse = cvars.vsFalse.copy();
}
/**
* Evaluate.
*
* Attempt to compute the value of an expression node. If all operands are
* literal constants of the same kind (e.g., IntegerExpression nodes), a
* new constant node of the proper type is returned representing the value
* as computed at compile-time. Otherwise, the original node 'this' is
* returned.
*/
Expression eval() {
return this;
}
/**
* Simplify.
*
* Attempt to simplify an expression node by returning a semantically-
* equivalent expression that is presumably less costly to execute. There
* is some overlap with the intent of 'eval', as compile-time evaluation of
* conditional expressions and the short-circuit boolean operators is
* performed here. Other simplifications include logical identities
* involving logical negation and comparisons. If no simplification is
* possible, the original node 'this' is returned. It is assumed that the
* children of the node have previously been recursively simplified and
* evaluated. A result of 'null' indicates that the expression may be
* elided entirely.
*/
Expression simplify() {
return this;
}
/**
* Inline.
*
* Recursively simplify each child of an expression node, destructively
* replacing the child with the simplified result. Also attempts to
* simplify the current node 'this', and returns the simplified result.
*
* The name 'inline' is somthing of a misnomer, as these methods are
* responsible for compile-time expression simplification in general.
* The 'eval' and 'simplify' methods apply to a single expression node
* only -- it is 'inline' and 'inlineValue' that drive the simplification
* of entire expressions.
*/
public Expression inline(Environment env, Context ctx) {
return null;
}
public Expression inlineValue(Environment env, Context ctx) {
return this;
}
/**
* Attempt to evaluate this expression. If this expression
* yields a value, append it to the StringBuffer `buffer'.
* If this expression cannot be evaluated at this time (for
* example if it contains a division by zero, a non-constant
* subexpression, or a subexpression which "refuses" to evaluate)
* then return `null' to indicate failure.
*
* It is anticipated that this method will be called to evaluate
* concatenations of compile-time constant strings. The call
* originates from AddExpression#inlineValue().
*
* See AddExpression#inlineValueSB() for detailed comments.
*/
protected StringBuffer inlineValueSB(Environment env,
Context ctx,
StringBuffer buffer) {
Expression inlined = inlineValue(env, ctx);
Object val = inlined.getValue();
if (val == null && !inlined.isNull()){
// This (supposedly constant) expression refuses to yield
// a value. This can happen, in particular, when we are
// trying to evaluate a division by zero. It can also
// happen in cases where isConstant() is able to classify
// expressions as constant that the compiler's inlining
// mechanisms aren't able to evaluate; this is rare,
// and all such cases that we have found so far
// (e.g. 4082814, 4106244) have been plugged up.
//
// We return a null to indicate that we have failed to
// evaluate the concatenation.
return null;
}
// For boolean and character expressions, getValue() returns
// an Integer. We need to take care, when appending the result
// of getValue(), that we preserve the type.
// Fix for 4103959, 4102672.
if (type == Type.tChar) {
buffer.append((char)((Integer)val).intValue());
} else if (type == Type.tBoolean) {
buffer.append(((Integer)val).intValue() != 0);
} else {
buffer.append(val);
}
return buffer;
}
public Expression inlineLHS(Environment env, Context ctx) {
return null;
}
/**
* The cost of inlining this expression.
* This cost controls the inlining of methods, and does not determine
* the compile-time simplifications performed by 'inline' and friends.
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
if (type.isType(TC_BOOLEAN)) {
codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_ifne : opc_ifeq, lbl, whenTrue);
} else {
throw new CompilerError("codeBranch " + opNames[op]);
}
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (type.isType(TC_BOOLEAN)) {
Label l1 = new Label();
Label l2 = new Label();
codeBranch(env, ctx, asm, l1, true);
asm.add(true, where, opc_ldc, new Integer(0));
asm.add(true, where, opc_goto, l2);
asm.add(l1);
asm.add(true, where, opc_ldc, new Integer(1));
asm.add(l2);
} else {
throw new CompilerError("codeValue");
}
}
public void code(Environment env, Context ctx, Assembler asm) {
codeValue(env, ctx, asm);
switch (type.getTypeCode()) {
case TC_VOID:
break;
case TC_DOUBLE:
case TC_LONG:
asm.add(where, opc_pop2);
break;
default:
asm.add(where, opc_pop);
break;
}
}
int codeLValue(Environment env, Context ctx, Assembler asm) {
print(System.out);
throw new CompilerError("invalid lhs");
}
void codeLoad(Environment env, Context ctx, Assembler asm) {
print(System.out);
throw new CompilerError("invalid load");
}
void codeStore(Environment env, Context ctx, Assembler asm) {
print(System.out);
throw new CompilerError("invalid store");
}
/**
* Convert this expression to a string.
*/
void ensureString(Environment env, Context ctx, Assembler asm)
throws ClassNotFound, AmbiguousMember
{
if (type == Type.tString && isNonNull()) {
return;
}
// Make sure it's a non-null string.
ClassDefinition sourceClass = ctx.field.getClassDefinition();
ClassDeclaration stClass = env.getClassDeclaration(Type.tString);
ClassDefinition stClsDef = stClass.getClassDefinition(env);
// FIX FOR 4071548
// We use 'String.valueOf' to do the conversion, in order to
// correctly handle null references and efficiently handle
// primitive types. For reference types, we force the argument
// to be interpreted as of 'Object' type, thus avoiding the
// the special-case overloading of 'valueOf' for character arrays.
// This special treatment would conflict with JLS 15.17.1.1.
if (type.inMask(TM_REFERENCE)) {
// Reference type
if (type != Type.tString) {
// Convert non-string object to string. If object is
// a string, we don't need to convert it, except in the
// case that it is null, which is handled below.
Type argType1[] = {Type.tObject};
MemberDefinition f1 =
stClsDef.matchMethod(env, sourceClass, idValueOf, argType1);
asm.add(where, opc_invokestatic, f1);
}
// FIX FOR 4030173
// If the argument was null, then value is "null", but if the
// argument was not null, 'toString' was called and could have
// returned null. We call 'valueOf' again to make sure that
// the result is a non-null string. See JLS 15.17.1.1. The
// approach taken here minimizes code size -- open code would
// be faster. The 'toString' method for an array class cannot
// be overridden, thus we know that it will never return null.
if (!type.inMask(TM_ARRAY|TM_NULL)) {
Type argType2[] = {Type.tString};
MemberDefinition f2 =
stClsDef.matchMethod(env, sourceClass, idValueOf, argType2);
asm.add(where, opc_invokestatic, f2);
}
} else {
// Primitive type
Type argType[] = {type};
MemberDefinition f =
stClsDef.matchMethod(env, sourceClass, idValueOf, argType);
asm.add(where, opc_invokestatic, f);
}
}
/**
* Convert this expression to a string and append it to the string
* buffer on the top of the stack.
* If the needBuffer argument is true, the string buffer needs to be
* created, initialized, and pushed on the stack, first.
*/
void codeAppend(Environment env, Context ctx, Assembler asm,
ClassDeclaration sbClass, boolean needBuffer)
throws ClassNotFound, AmbiguousMember
{
ClassDefinition sourceClass = ctx.field.getClassDefinition();
ClassDefinition sbClsDef = sbClass.getClassDefinition(env);
MemberDefinition f;
if (needBuffer) {
// need to create the string buffer
asm.add(where, opc_new, sbClass); // create the class
asm.add(where, opc_dup);
if (equals("")) {
// make an empty string buffer
f = sbClsDef.matchMethod(env, sourceClass, idInit);
} else {
// optimize by initializing the buffer with the string
codeValue(env, ctx, asm);
ensureString(env, ctx, asm);
Type argType[] = {Type.tString};
f = sbClsDef.matchMethod(env, sourceClass, idInit, argType);
}
asm.add(where, opc_invokespecial, f);
} else {
// append this item to the string buffer
codeValue(env, ctx, asm);
// FIX FOR 4071548
// 'StringBuffer.append' converts its argument as if by
// 'valueOf', treating character arrays specially. This
// violates JLS 15.17.1.1, which requires that concatenation
// convert non-primitive arguments using 'toString'. We force
// the treatment of all reference types as type 'Object', thus
// invoking an overloading of 'append' that has the required
// semantics.
Type argType[] =
{ (type.inMask(TM_REFERENCE) && type != Type.tString)
? Type.tObject
: type };
f = sbClsDef.matchMethod(env, sourceClass, idAppend, argType);
asm.add(where, opc_invokevirtual, f);
}
}
/**
* Code
*/
void codeDup(Environment env, Context ctx, Assembler asm, int items, int depth) {
switch (items) {
case 0:
return;
case 1:
switch (depth) {
case 0:
asm.add(where, opc_dup);
return;
case 1:
asm.add(where, opc_dup_x1);
return;
case 2:
asm.add(where, opc_dup_x2);
return;
}
break;
case 2:
switch (depth) {
case 0:
asm.add(where, opc_dup2);
return;
case 1:
asm.add(where, opc_dup2_x1);
return;
case 2:
asm.add(where, opc_dup2_x2);
return;
}
break;
}
throw new CompilerError("can't dup: " + items + ", " + depth);
}
void codeConversion(Environment env, Context ctx, Assembler asm, Type f, Type t) {
int from = f.getTypeCode();
int to = t.getTypeCode();
switch (to) {
case TC_BOOLEAN:
if (from != TC_BOOLEAN) {
break;
}
return;
case TC_BYTE:
if (from != TC_BYTE) {
codeConversion(env, ctx, asm, f, Type.tInt);
asm.add(where, opc_i2b);
}
return;
case TC_CHAR:
if (from != TC_CHAR) {
codeConversion(env, ctx, asm, f, Type.tInt);
asm.add(where, opc_i2c);
}
return;
case TC_SHORT:
if (from != TC_SHORT) {
codeConversion(env, ctx, asm, f, Type.tInt);
asm.add(where, opc_i2s);
}
return;
case TC_INT:
switch (from) {
case TC_BYTE:
case TC_CHAR:
case TC_SHORT:
case TC_INT:
return;
case TC_LONG:
asm.add(where, opc_l2i);
return;
case TC_FLOAT:
asm.add(where, opc_f2i);
return;
case TC_DOUBLE:
asm.add(where, opc_d2i);
return;
}
break;
case TC_LONG:
switch (from) {
case TC_BYTE:
case TC_CHAR:
case TC_SHORT:
case TC_INT:
asm.add(where, opc_i2l);
return;
case TC_LONG:
return;
case TC_FLOAT:
asm.add(where, opc_f2l);
return;
case TC_DOUBLE:
asm.add(where, opc_d2l);
return;
}
break;
case TC_FLOAT:
switch (from) {
case TC_BYTE:
case TC_CHAR:
case TC_SHORT:
case TC_INT:
asm.add(where, opc_i2f);
return;
case TC_LONG:
asm.add(where, opc_l2f);
return;
case TC_FLOAT:
return;
case TC_DOUBLE:
asm.add(where, opc_d2f);
return;
}
break;
case TC_DOUBLE:
switch (from) {
case TC_BYTE:
case TC_CHAR:
case TC_SHORT:
case TC_INT:
asm.add(where, opc_i2d);
return;
case TC_LONG:
asm.add(where, opc_l2d);
return;
case TC_FLOAT:
asm.add(where, opc_f2d);
return;
case TC_DOUBLE:
return;
}
break;
case TC_CLASS:
switch (from) {
case TC_NULL:
return;
case TC_CLASS:
case TC_ARRAY:
try {
if (!env.implicitCast(f, t)) {
asm.add(where, opc_checkcast, env.getClassDeclaration(t));
}
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
return;
}
break;
case TC_ARRAY:
switch (from) {
case TC_NULL:
return;
case TC_CLASS:
case TC_ARRAY:
try {
if (!env.implicitCast(f, t)) {
asm.add(where, opc_checkcast, t);
}
return;
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
}
break;
}
throw new CompilerError("codeConversion: " + from + ", " + to);
}
/**
* Check if the first thing is a constructor invocation
*/
public Expression firstConstructor() {
return null;
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
return (Expression)clone();
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(opNames[op]);
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ExpressionStatement extends Statement {
Expression expr;
/**
* Constructor
*/
public ExpressionStatement(long where, Expression expr) {
super(EXPRESSION, where);
this.expr = expr;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
return expr.check(env, ctx, reach(env, vset), exp);
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
if (expr != null) {
expr = expr.inline(env, ctx);
return (expr == null) ? null : this;
}
return null;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
ExpressionStatement s = (ExpressionStatement)clone();
s.expr = expr.copyInline(ctx);
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return expr.costInline(thresh, env, ctx);
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
expr.code(env, ctx, asm);
}
/**
* Check if the first thing is a constructor invocation
*/
public Expression firstConstructor() {
return expr.firstConstructor();
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
if (expr != null) {
expr.print(out);
} else {
out.print("<empty>");
}
out.print(";");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 1997, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* This class encapsulates the information required to generate an update to a private
* field referenced from another class, e.g., an inner class. An expression denoting a
* reference to the object to which the field belongs is associated with getter and
* setter methods.
* <p>
* We use this class only for assignment, increment, and decrement operators, in which
* the old value is first retrieved and then a new value is computed and stored.
* Simple assignment expressions in which a value is copied without modification are
* handled by another mechanism.
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
class FieldUpdater implements Constants {
// Location for reporting errors.
// Errors will always indicate compiler failure, but these will be easier to diagnose
// if the bogus error is localized to the offending assignment.
private long where;
// The field to which this updater applies.
// It would be easy to eliminate the need to store the field here, but we retain it for
// diagnostic purposes.
private MemberDefinition field;
// Expression denoting the object to which the getter and setter are applied.
// If the field is static, 'base' may be null, but need not be, as a static field
// may be selected from an object reference. Even though the value of the object
// reference will be ignored, it may have side-effects.
private Expression base;
// The getter and setter methods, generated by 'getAccessMember' and 'getUpdateMember'.
private MemberDefinition getter;
private MemberDefinition setter;
// The number of words occupied on the stack by the object reference.
// For static fields, this is zero.
private int depth;
/**
* Constructor.
*/
public FieldUpdater(long where, MemberDefinition field,
Expression base, MemberDefinition getter, MemberDefinition setter) {
this.where = where;
this.field = field;
this.base = base;
this.getter = getter;
this.setter = setter;
}
/**
* Since the object reference expression may be captured before it has been inlined,
* we must inline it later. A <code>FieldUpdater</code> is inlined essentially as if
* it were a child of the assignment node to which it belongs.
*/
public FieldUpdater inline(Environment env, Context ctx) {
if (base != null) {
if (field.isStatic()) {
base = base.inline(env, ctx);
} else {
base = base.inlineValue(env, ctx);
}
}
return this;
}
public FieldUpdater copyInline(Context ctx) {
return new FieldUpdater(where, field, base.copyInline(ctx), getter, setter);
}
public int costInline(int thresh, Environment env, Context ctx, boolean needGet) {
// Size of 'invokestatic' call for access method is 3 bytes.
int cost = needGet ? 7 : 3; // getter needs extra invokestatic + dup
// Size of expression to compute 'this' arg if needed.
if (!field.isStatic() && base != null) {
cost += base.costInline(thresh, env, ctx);
}
// We ignore the cost of duplicating value in value-needed context.
return cost;
}
/**
* Duplicate <code>items</code> words from the top of the stack, locating them
* below the topmost <code>depth</code> words on the stack.
*/
// This code was cribbed from 'Expression.java'. We cannot reuse that code here,
// because we do not inherit from class 'Expression'.
private void codeDup(Assembler asm, int items, int depth) {
switch (items) {
case 0:
return;
case 1:
switch (depth) {
case 0:
asm.add(where, opc_dup);
return;
case 1:
asm.add(where, opc_dup_x1);
return;
case 2:
asm.add(where, opc_dup_x2);
return;
}
break;
case 2:
switch (depth) {
case 0:
asm.add(where, opc_dup2);
return;
case 1:
asm.add(where, opc_dup2_x1);
return;
case 2:
asm.add(where, opc_dup2_x2);
return;
}
break;
}
throw new CompilerError("can't dup: " + items + ", " + depth);
}
/**
* Begin a field update by an assignment, increment, or decrement operator.
* The current value of the field is left at the top of the stack.
* If <code>valNeeded</code> is true, we arrange for the initial value to remain
* on the stack after the update.
*/
public void startUpdate(Environment env, Context ctx, Assembler asm, boolean valNeeded) {
if (!(getter.isStatic() && setter.isStatic())) {
throw new CompilerError("startUpdate isStatic");
}
if (!field.isStatic()) {
// Provide explicit 'this' argument.
base.codeValue(env, ctx, asm);
depth = 1;
} else {
// May need to evaluate 'base' for effect.
// If 'base' was a type expression, it should have previously been inlined away.
if (base != null) {
base.code(env, ctx, asm);
}
depth = 0;
}
codeDup(asm, depth, 0);
asm.add(where, opc_invokestatic, getter);
if (valNeeded) {
codeDup(asm, field.getType().stackSize(), depth);
}
}
/**
* Complete a field update by an assignment, increment, or decrement operator.
* The original value of the field left on the stack by <code>startUpdate</code>
* must have been replaced with the updated value, with no other stack alterations.
* If <code>valNeeded</code> is true, we arrange for the updated value to remain
* on the stack after the update. The <code>valNeeded</code> argument must not be
* true in both <code>startUpdate</code> and <code>finishUpdate</code>.
*/
public void finishUpdate(Environment env, Context ctx, Assembler asm, boolean valNeeded) {
if (valNeeded) {
codeDup(asm, field.getType().stackSize(), depth);
}
asm.add(where, opc_invokestatic, setter);
}
/**
* Like above, but used when assigning a new value independent of the
* old, as in a simple assignment expression. After 'startAssign',
* code must be emitted to leave one additional value on the stack without
* altering any others, followed by 'finishAssign'.
*/
public void startAssign(Environment env, Context ctx, Assembler asm) {
if (!setter.isStatic()) {
throw new CompilerError("startAssign isStatic");
}
if (!field.isStatic()) {
// Provide explicit 'this' argument.
base.codeValue(env, ctx, asm);
depth = 1;
} else {
// May need to evaluate 'base' for effect.
// If 'base' was a type expression, it should have previously been inlined away.
if (base != null) {
base.code(env, ctx, asm);
}
depth = 0;
}
}
public void finishAssign(Environment env, Context ctx, Assembler asm, boolean valNeeded) {
if (valNeeded) {
codeDup(asm, field.getType().stackSize(), depth);
}
asm.add(where, opc_invokestatic, setter);
}
}

View File

@@ -0,0 +1,360 @@
/*
* Copyright (c) 1994, 2004, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import sun.tools.asm.TryData;
import sun.tools.asm.CatchData;
import java.io.PrintStream;
import java.util.Hashtable;
import java.util.Enumeration;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class FinallyStatement extends Statement {
Statement body;
Statement finalbody;
boolean finallyCanFinish; // does finalBody never return?
boolean needReturnSlot; // set by inner return statement
Statement init; // try object expression or declaration from parser
LocalMember tryTemp; // temp holding the try object, if any
/**
* Constructor
*/
public FinallyStatement(long where, Statement body, Statement finalbody) {
super(FINALLY, where);
this.body = body;
this.finalbody = finalbody;
}
// /**
// * Constructor for try (init) {body}
// */
// public FinallyStatement(long where, Statement init, Statement body, int junk) {
// this(where, body, null);
// this.init = init;
// }
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = reach(env, vset);
Hashtable newexp = new Hashtable();
// Handle the proposed 'try (init) { stmts } finally { stmts }' syntax.
// This feature has not been adopted, and support is presently disabled.
/*-----------------------------------------------------------*
if (init != null) {
ClassDefinition sourceClass = ctx.field.getClassDefinition();
Expression tryExpr = null;
DeclarationStatement tryDecl = null;
long where = init.getWhere();
// find out whether init is a simple expression or a declaration
if (init.getOp() == EXPRESSION) {
tryExpr = ((ExpressionStatement)init).expr;
init = null; // restore it below
vset = tryExpr.checkValue(env, ctx, vset, exp);
} else if (init.getOp() == DECLARATION) {
tryDecl = (DeclarationStatement) init;
init = null; // restore it below
vset = tryDecl.checkBlockStatement(env, ctx, vset, exp);
if (tryDecl.args.length != 1) {
env.error(where, "invalid.decl");
} else {
LocalMember field =
((VarDeclarationStatement) tryDecl.args[0]).field;
tryExpr = new IdentifierExpression(where, field);
tryExpr.type = field.getType();
}
} else {
env.error(where, "invalid.expr");
vset = init.check(env, ctx, vset, exp);
}
Type type = (tryExpr == null) ? Type.tError : tryExpr.getType();
MemberDefinition tryEnter = null;
MemberDefinition tryExit = null;
if (!type.isType(TC_CLASS)) {
if (!type.isType(TC_ERROR)) {
env.error(where, "invalid.method.invoke", type);
}
} else {
Identifier idTryEnter = Identifier.lookup("tryEnter");
Identifier idTryExit = Identifier.lookup("tryExit");
Type tTryMethod = Type.tMethod(Type.tVoid);
try {
ClassDefinition tryClass = env.getClassDefinition(type);
tryEnter = tryClass.matchMethod(env, sourceClass, idTryEnter);
tryExit = tryClass.matchMethod(env, sourceClass, idTryExit);
if (tryEnter != null && !tryEnter.getType().equals(tTryMethod)) {
tryEnter = null;
}
if (tryExit != null && !tryExit.getType().equals(tTryMethod)) {
tryExit = null;
}
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, ctx.field);
} catch (AmbiguousMember ee) {
Identifier id = ee.field1.getName();
env.error(where, "ambig.field", id, ee.field1, ee.field2);
}
}
if (tryEnter == null || tryExit == null) {
// Make a better (more didactic) error here!
env.error(where, "invalid.method.invoke", type);
} else {
tryTemp = new LocalMember(where, sourceClass, 0,
type, Identifier.lookup("<try_object>"));
ctx = new Context(ctx, this);
ctx.declare(env, tryTemp);
Expression e;
e = new IdentifierExpression(where, tryTemp);
e = new AssignExpression(where, e, tryExpr);
e = new MethodExpression(where, e, tryEnter, new Expression[0]);
e.type = Type.tVoid;
Statement enterCall = new ExpressionStatement(where, e);
// store it on the init, for code generation
if (tryDecl != null) {
Statement args2[] = { tryDecl.args[0], enterCall };
tryDecl.args = args2;
init = tryDecl;
} else {
init = enterCall;
}
e = new IdentifierExpression(where, tryTemp);
e = new MethodExpression(where, e, tryExit, new Expression[0]);
e.type = Type.tVoid;
Statement exitCall = new ExpressionStatement(where, e);
finalbody = exitCall;
}
}
*-----------------------------------------------------------*/
// Check the try part. We reach the end of the try part either by
// finishing normally, or doing a break to the label of the try/finally.
// NOTE: I don't think newctx1.vsBreak is ever used -- see TryStatement.
CheckContext newctx1 = new CheckContext(ctx, this);
Vset vset1 = body.check(env, newctx1, vset.copy(), newexp)
.join(newctx1.vsBreak);
// Check the finally part.
CheckContext newctx2 = new CheckContext(ctx, this);
// Should never access this field. The null indicates the finally part.
newctx2.vsContinue = null;
Vset vset2 = finalbody.check(env, newctx2, vset, exp);
finallyCanFinish = !vset2.isDeadEnd();
vset2 = vset2.join(newctx2.vsBreak);
// If !finallyCanFinish, then the only possible exceptions that can
// occur at this point are the ones preceding the try/finally, or
// the ones generated by the finally. Anything in the try is
// irrelevant. Otherwise, we have to merge in all the exceptions
// generated by the body into exp.
if (finallyCanFinish) {
// Add newexp's back into exp; cf. ThrowStatement.check().
for (Enumeration e = newexp.keys() ; e.hasMoreElements() ; ) {
Object def = e.nextElement();
exp.put(def, newexp.get(def));
}
}
return ctx.removeAdditionalVars(vset1.addDAandJoinDU(vset2));
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
if (tryTemp != null) {
ctx = new Context(ctx, this);
ctx.declare(env, tryTemp);
}
if (init != null) {
init = init.inline(env, ctx);
}
if (body != null) {
body = body.inline(env, ctx);
}
if (finalbody != null) {
finalbody = finalbody.inline(env, ctx);
}
if (body == null) {
return eliminate(env, finalbody);
}
if (finalbody == null) {
return eliminate(env, body);
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
FinallyStatement s = (FinallyStatement)clone();
if (tryTemp != null) {
s.tryTemp = tryTemp.copyInline(ctx);
}
if (init != null) {
s.init = init.copyInline(ctx, valNeeded);
}
if (body != null) {
s.body = body.copyInline(ctx, valNeeded);
}
if (finalbody != null) {
s.finalbody = finalbody.copyInline(ctx, valNeeded);
}
return s;
}
/**
* Compute cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx){
int cost = 4;
if (init != null) {
cost += init.costInline(thresh, env,ctx);
if (cost >= thresh) return cost;
}
if (body != null) {
cost += body.costInline(thresh, env,ctx);
if (cost >= thresh) return cost;
}
if (finalbody != null) {
cost += finalbody.costInline(thresh, env,ctx);
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
ctx = new Context(ctx);
Integer num1 = null, num2 = null;
Label endLabel = new Label();
if (tryTemp != null) {
ctx.declare(env, tryTemp);
}
if (init != null) {
CodeContext exprctx = new CodeContext(ctx, this);
init.code(env, exprctx, asm);
}
if (finallyCanFinish) {
LocalMember f1, f2;
ClassDefinition thisClass = ctx.field.getClassDefinition();
if (needReturnSlot) {
Type returnType = ctx.field.getType().getReturnType();
LocalMember localfield = new LocalMember(0, thisClass, 0,
returnType,
idFinallyReturnValue);
ctx.declare(env, localfield);
env.debugOutput("Assigning return slot to " + localfield.number);
}
// allocate space for the exception and return address
f1 = new LocalMember(where, thisClass, 0, Type.tObject, null);
f2 = new LocalMember(where, thisClass, 0, Type.tInt, null);
num1 = new Integer(ctx.declare(env, f1));
num2 = new Integer(ctx.declare(env, f2));
}
TryData td = new TryData();
td.add(null);
// Main body
CodeContext bodyctx = new CodeContext(ctx, this);
asm.add(where, opc_try, td); // start of protected code
body.code(env, bodyctx, asm);
asm.add(bodyctx.breakLabel);
asm.add(td.getEndLabel()); // end of protected code
// Cleanup afer body
if (finallyCanFinish) {
asm.add(where, opc_jsr, bodyctx.contLabel);
asm.add(where, opc_goto, endLabel);
} else {
// just goto the cleanup code. It will never return.
asm.add(where, opc_goto, bodyctx.contLabel);
}
// Catch code
CatchData cd = td.getCatch(0);
asm.add(cd.getLabel());
if (finallyCanFinish) {
asm.add(where, opc_astore, num1); // store exception
asm.add(where, opc_jsr, bodyctx.contLabel);
asm.add(where, opc_aload, num1); // rethrow exception
asm.add(where, opc_athrow);
} else {
// pop exception off stack. Fall through to finally code
asm.add(where, opc_pop);
}
// The finally part, which is marked by the contLabel. Update
// breakLabel: since break's in the finally are different
// contLabel: to null to indicate no longer in the protected code.
asm.add(bodyctx.contLabel);
bodyctx.contLabel = null;
bodyctx.breakLabel = endLabel;
if (finallyCanFinish) {
asm.add(where, opc_astore, num2); // save the return address
finalbody.code(env, bodyctx, asm); // execute the cleanup code
asm.add(where, opc_ret, num2); // return
} else {
finalbody.code(env, bodyctx, asm); // execute the cleanup code
}
asm.add(endLabel); // breaks come here
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("try ");
if (body != null) {
body.print(out, indent);
} else {
out.print("<empty>");
}
out.print(" finally ");
if (finalbody != null) {
finalbody.print(out, indent);
} else {
out.print("<empty>");
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class FloatExpression extends ConstantExpression {
float value;
/**
* Constructor
*/
public FloatExpression(long where, float value) {
super(FLOATVAL, where, Type.tFloat);
this.value = value;
}
/**
* Get the value
*/
public Object getValue() {
return new Float(value);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return value == i;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
// don't allow -0.0
return (Float.floatToIntBits(value) == 0);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc, new Float(value));
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value +"F");
}
}

View File

@@ -0,0 +1,216 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ForStatement extends Statement {
Statement init;
Expression cond;
Expression inc;
Statement body;
/**
* Constructor
*/
public ForStatement(long where, Statement init, Expression cond, Expression inc, Statement body) {
super(FOR, where);
this.init = init;
this.cond = cond;
this.inc = inc;
this.body = body;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
vset = reach(env, vset);
Context initctx = new Context(ctx, this);
if (init != null) {
vset = init.checkBlockStatement(env, initctx, vset, exp);
}
CheckContext newctx = new CheckContext(initctx, this);
// remember what was unassigned on entry
Vset vsEntry = vset.copy();
ConditionVars cvars;
if (cond != null) {
cvars = cond.checkCondition(env, newctx, vset, exp);
cond = convert(env, newctx, Type.tBoolean, cond);
} else {
// a missing test is equivalent to "true"
cvars = new ConditionVars();
cvars.vsFalse = Vset.DEAD_END;
cvars.vsTrue = vset;
}
vset = body.check(env, newctx, cvars.vsTrue, exp);
vset = vset.join(newctx.vsContinue);
if (inc != null) {
vset = inc.check(env, newctx, vset, exp);
}
// Make sure the back-branch fits the entry of the loop.
// Must include variables declared in the for-init part in the
// set of variables visible upon loop entry that must be checked.
initctx.checkBackBranch(env, this, vsEntry, vset);
// exit by testing false or executing a break;
vset = newctx.vsBreak.join(cvars.vsFalse);
return ctx.removeAdditionalVars(vset);
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
ctx = new Context(ctx, this);
if (init != null) {
Statement body[] = {init, this};
init = null;
return new CompoundStatement(where, body).inline(env, ctx);
}
if (cond != null) {
cond = cond.inlineValue(env, ctx);
}
if (body != null) {
body = body.inline(env, ctx);
}
if (inc != null) {
inc = inc.inline(env, ctx);
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
ForStatement s = (ForStatement)clone();
if (init != null) {
s.init = init.copyInline(ctx, valNeeded);
}
if (cond != null) {
s.cond = cond.copyInline(ctx);
}
if (body != null) {
s.body = body.copyInline(ctx, valNeeded);
}
if (inc != null) {
s.inc = inc.copyInline(ctx);
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
int cost = 2;
if (init != null) {
cost += init.costInline(thresh, env, ctx);
}
if (cond != null) {
cost += cond.costInline(thresh, env, ctx);
}
if (body != null) {
cost += body.costInline(thresh, env, ctx);
}
if (inc != null) {
cost += inc.costInline(thresh, env, ctx);
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
if (init != null) {
init.code(env, newctx, asm);
}
Label l1 = new Label();
Label l2 = new Label();
asm.add(where, opc_goto, l2);
asm.add(l1);
if (body != null) {
body.code(env, newctx, asm);
}
asm.add(newctx.contLabel);
if (inc != null) {
inc.code(env, newctx, asm);
}
asm.add(l2);
if (cond != null) {
cond.codeBranch(env, newctx, asm, l1, true);
} else {
asm.add(where, opc_goto, l1);
}
asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("for (");
if (init != null) {
init.print(out, indent);
out.print(" ");
} else {
out.print("; ");
}
if (cond != null) {
cond.print(out);
out.print(" ");
}
out.print("; ");
if (inc != null) {
inc.print(out);
}
out.print(") ");
if (body != null) {
body.print(out, indent);
} else {
out.print(";");
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class GreaterExpression extends BinaryCompareExpression {
/**
* constructor
*/
public GreaterExpression(long where, Expression left, Expression right) {
super(GT, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a > b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a > b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a > b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a > b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new LessExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmpgt : opc_if_icmple, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpl);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpl);
break;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_ifgt : opc_ifle, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class GreaterOrEqualExpression extends BinaryCompareExpression {
/**
* constructor
*/
public GreaterOrEqualExpression(long where, Expression left, Expression right) {
super(GE, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a >= b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a >= b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a >= b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a >= b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new LessOrEqualExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmpge : opc_if_icmplt, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpl);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpl);
break;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_ifge : opc_iflt, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,477 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.LocalVariable;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class IdentifierExpression extends Expression {
Identifier id;
MemberDefinition field;
Expression implementation;
/**
* Constructor
*/
public IdentifierExpression(long where, Identifier id) {
super(IDENT, where, Type.tError);
this.id = id;
}
public IdentifierExpression(IdentifierToken id) {
this(id.getWhere(), id.getName());
}
public IdentifierExpression(long where, MemberDefinition field) {
super(IDENT, where, field.getType());
this.id = field.getName();
this.field = field;
}
public Expression getImplementation() {
if (implementation != null)
return implementation;
return this;
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(Identifier id) {
return this.id.equals(id);
}
/**
* Assign a value to this identifier. [It must already be "bound"]
*/
private Vset assign(Environment env, Context ctx, Vset vset) {
if (field.isLocal()) {
LocalMember local = (LocalMember)field;
if (local.scopeNumber < ctx.frameNumber) {
env.error(where, "assign.to.uplevel", id);
}
if (local.isFinal()) {
// allow definite single assignment of blank finals
if (!local.isBlankFinal()) {
env.error(where, "assign.to.final", id);
} else if (!vset.testVarUnassigned(local.number)) {
env.error(where, "assign.to.blank.final", id);
}
}
vset.addVar(local.number);
local.writecount++;
} else if (field.isFinal()) {
vset = FieldExpression.checkFinalAssign(env, ctx, vset,
where, field);
}
return vset;
}
/**
* Get the value of this identifier. [ It must already be "bound"]
*/
private Vset get(Environment env, Context ctx, Vset vset) {
if (field.isLocal()) {
LocalMember local = (LocalMember)field;
if (local.scopeNumber < ctx.frameNumber && !local.isFinal()) {
env.error(where, "invalid.uplevel", id);
}
if (!vset.testVar(local.number)) {
env.error(where, "var.not.initialized", id);
vset.addVar(local.number);
}
local.readcount++;
} else {
if (!field.isStatic()) {
if (!vset.testVar(ctx.getThisNumber())) {
env.error(where, "access.inst.before.super", id);
implementation = null;
}
}
if (field.isBlankFinal()) {
int number = ctx.getFieldNumber(field);
if (number >= 0 && !vset.testVar(number)) {
env.error(where, "var.not.initialized", id);
}
}
}
return vset;
}
/**
* Bind to a field
*/
boolean bind(Environment env, Context ctx) {
try {
field = ctx.getField(env, id);
if (field == null) {
for (ClassDefinition cdef = ctx.field.getClassDefinition();
cdef != null; cdef = cdef.getOuterClass()) {
if (cdef.findAnyMethod(env, id) != null) {
env.error(where, "invalid.var", id,
ctx.field.getClassDeclaration());
return false;
}
}
env.error(where, "undef.var", id);
return false;
}
type = field.getType();
// Check access permission
if (!ctx.field.getClassDefinition().canAccess(env, field)) {
env.error(where, "no.field.access",
id, field.getClassDeclaration(),
ctx.field.getClassDeclaration());
return false;
}
// Find out how to access this variable.
if (field.isLocal()) {
LocalMember local = (LocalMember)field;
if (local.scopeNumber < ctx.frameNumber) {
// get a "val$x" copy via the current object
implementation = ctx.makeReference(env, local);
}
} else {
MemberDefinition f = field;
if (f.reportDeprecated(env)) {
env.error(where, "warn.field.is.deprecated",
id, f.getClassDefinition());
}
ClassDefinition fclass = f.getClassDefinition();
if (fclass != ctx.field.getClassDefinition()) {
// Maybe an inherited field hides an apparent variable.
MemberDefinition f2 = ctx.getApparentField(env, id);
if (f2 != null && f2 != f) {
ClassDefinition c = ctx.findScope(env, fclass);
if (c == null) c = f.getClassDefinition();
if (f2.isLocal()) {
env.error(where, "inherited.hides.local",
id, c.getClassDeclaration());
} else {
env.error(where, "inherited.hides.field",
id, c.getClassDeclaration(),
f2.getClassDeclaration());
}
}
}
// Rewrite as a FieldExpression.
// Access methods for private fields, if needed, will be added
// during subsequent processing of the FieldExpression. See
// method 'FieldExpression.checkCommon'. This division of labor
// is somewhat awkward, as most further processing of a
// FieldExpression during the checking phase is suppressed when
// the referenced field is pre-set as it is here.
if (f.isStatic()) {
Expression base = new TypeExpression(where,
f.getClassDeclaration().getType());
implementation = new FieldExpression(where, null, f);
} else {
Expression base = ctx.findOuterLink(env, where, f);
if (base != null) {
implementation = new FieldExpression(where, base, f);
}
}
}
// Check forward reference
if (!ctx.canReach(env, field)) {
env.error(where, "forward.ref",
id, field.getClassDeclaration());
return false;
}
return true;
} catch (ClassNotFound e) {
env.error(where, "class.not.found", e.name, ctx.field);
} catch (AmbiguousMember e) {
env.error(where, "ambig.field", id,
e.field1.getClassDeclaration(),
e.field2.getClassDeclaration());
}
return false;
}
/**
* Check expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
if (field != null) {
// An internally pre-set field, such as an argument copying
// an uplevel value. Do not re-check it.
return vset;
}
if (bind(env, ctx)) {
vset = get(env, ctx, vset);
ctx.field.getClassDefinition().addDependency(field.getClassDeclaration());
if (implementation != null)
vset = implementation.checkValue(env, ctx, vset, exp);
}
return vset;
}
/**
* Check the expression if it appears on the LHS of an assignment
*/
public Vset checkLHS(Environment env, Context ctx,
Vset vset, Hashtable exp) {
if (!bind(env, ctx))
return vset;
vset = assign(env, ctx, vset);
if (implementation != null)
vset = implementation.checkValue(env, ctx, vset, exp);
return vset;
}
/**
* Check the expression if it appears on the LHS of an op= expression
*/
public Vset checkAssignOp(Environment env, Context ctx,
Vset vset, Hashtable exp, Expression outside) {
if (!bind(env, ctx))
return vset;
vset = assign(env, ctx, get(env, ctx, vset));
if (implementation != null)
vset = implementation.checkValue(env, ctx, vset, exp);
return vset;
}
/**
* Return an accessor if one is needed for assignments to this expression.
*/
public FieldUpdater getAssigner(Environment env, Context ctx) {
if (implementation != null)
return implementation.getAssigner(env, ctx);
return null;
}
/**
* Return an updater if one is needed for assignments to this expression.
*/
public FieldUpdater getUpdater(Environment env, Context ctx) {
if (implementation != null)
return implementation.getUpdater(env, ctx);
return null;
}
/**
* Check if the present name is part of a scoping prefix.
*/
public Vset checkAmbigName(Environment env, Context ctx, Vset vset, Hashtable exp,
UnaryExpression loc) {
try {
if (ctx.getField(env, id) != null) {
// if this is a local field, there's nothing more to do.
return checkValue(env, ctx, vset, exp);
}
} catch (ClassNotFound ee) {
} catch (AmbiguousMember ee) {
}
// Can this be interpreted as a type?
ClassDefinition c = toResolvedType(env, ctx, true);
// Is it a real type??
if (c != null) {
loc.right = new TypeExpression(where, c.getType());
return vset;
}
// We hope it is a package prefix. Let the caller decide.
type = Type.tPackage;
return vset;
}
/**
* Convert an identifier to a known type, or null.
*/
private ClassDefinition toResolvedType(Environment env, Context ctx,
boolean pkgOK) {
Identifier rid = ctx.resolveName(env, id);
Type t = Type.tClass(rid);
if (pkgOK && !env.classExists(t)) {
return null;
}
if (env.resolve(where, ctx.field.getClassDefinition(), t)) {
try {
ClassDefinition c = env.getClassDefinition(t);
// Maybe an inherited class hides an apparent class.
if (c.isMember()) {
ClassDefinition sc = ctx.findScope(env, c.getOuterClass());
if (sc != c.getOuterClass()) {
Identifier rid2 = ctx.getApparentClassName(env, id);
if (!rid2.equals(idNull) && !rid2.equals(rid)) {
env.error(where, "inherited.hides.type",
id, sc.getClassDeclaration());
}
}
}
if (!c.getLocalName().equals(id.getFlatName().getName())) {
env.error(where, "illegal.mangled.name", id, c);
}
return c;
} catch (ClassNotFound ee) {
}
}
return null;
}
/**
* Convert an identifier to a type.
* If one is not known, use the current package as a qualifier.
*/
Type toType(Environment env, Context ctx) {
ClassDefinition c = toResolvedType(env, ctx, false);
if (c != null) {
return c.getType();
}
return Type.tError;
}
/**
* Convert an expresion to a type in a context where a qualified
* type name is expected, e.g., in the prefix of a qualified type
* name. We do not necessarily know where the package prefix ends,
* so we operate similarly to 'checkAmbiguousName'. This is the
* base case -- the first component of the qualified name.
*/
/*-------------------------------------------------------*
Type toQualifiedType(Environment env, Context ctx) {
// We do not look for non-type fields. Is this correct?
ClassDefinition c = toResolvedType(env, ctx, true);
// Is it a real type?
if (c != null) {
return c.getType();
}
// We hope it is a package prefix. Let the caller decide.
return Type.tPackage;
}
*-------------------------------------------------------*/
/**
* Check if constant: Will it inline away?
*/
public boolean isConstant() {
if (implementation != null)
return implementation.isConstant();
if (field != null) {
return field.isConstant();
}
return false;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
return null;
}
public Expression inlineValue(Environment env, Context ctx) {
if (implementation != null)
return implementation.inlineValue(env, ctx);
if (field == null) {
return this;
}
try {
if (field.isLocal()) {
if (field.isInlineable(env, false)) {
Expression e = (Expression)field.getValue(env);
return (e == null) ? this : e.inlineValue(env, ctx);
}
return this;
}
return this;
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
}
public Expression inlineLHS(Environment env, Context ctx) {
if (implementation != null)
return implementation.inlineLHS(env, ctx);
return this;
}
public Expression copyInline(Context ctx) {
if (implementation != null)
return implementation.copyInline(ctx);
IdentifierExpression e =
(IdentifierExpression)super.copyInline(ctx);
if (field != null && field.isLocal()) {
e.field = ((LocalMember)field).getCurrentInlineCopy(ctx);
}
return e;
}
public int costInline(int thresh, Environment env, Context ctx) {
if (implementation != null)
return implementation.costInline(thresh, env, ctx);
return super.costInline(thresh, env, ctx);
}
/**
* Code local vars (object fields have been inlined away)
*/
int codeLValue(Environment env, Context ctx, Assembler asm) {
return 0;
}
void codeLoad(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_iload + type.getTypeCodeOffset(),
new Integer(((LocalMember)field).number));
}
void codeStore(Environment env, Context ctx, Assembler asm) {
LocalMember local = (LocalMember)field;
asm.add(where, opc_istore + type.getTypeCodeOffset(),
new LocalVariable(local, local.number));
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeLValue(env, ctx, asm);
codeLoad(env, ctx, asm);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(id + "#" + ((field != null) ? field.hashCode() : 0));
if (implementation != null) {
out.print("/IMPL=");
implementation.print(out);
}
}
}

View File

@@ -0,0 +1,203 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class IfStatement extends Statement {
Expression cond;
Statement ifTrue;
Statement ifFalse;
/**
* Constructor
*/
public IfStatement(long where, Expression cond, Statement ifTrue, Statement ifFalse) {
super(IF, where);
this.cond = cond;
this.ifTrue = ifTrue;
this.ifFalse = ifFalse;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
CheckContext newctx = new CheckContext(ctx, this);
// Vset vsExtra = vset.copy(); // See comment below.
ConditionVars cvars =
cond.checkCondition(env, newctx, reach(env, vset), exp);
cond = convert(env, newctx, Type.tBoolean, cond);
// The following code, now deleted, was apparently an erroneous attempt
// at providing better error diagnostics. The comment read: 'If either
// the true clause or the false clause is unreachable, do a reasonable
// check on the child anyway.'
// Vset vsTrue = cvars.vsTrue.isDeadEnd() ? vsExtra : cvars.vsTrue;
// Vset vsFalse = cvars.vsFalse.isDeadEnd() ? vsExtra : cvars.vsFalse;
// Unfortunately, this violates the rules laid out in the JLS, and leads to
// blatantly incorrect results. For example, 'i' will not be recognized
// as definitely assigned following the statement 'if (true) i = 1;'.
// It is best to slavishly follow the JLS here. A cleverer approach could
// only correctly issue warnings, as JLS 16.2.6 is quite explicit, and it
// is OK for a dead branch of an if-statement to omit an assignment that
// would be required in the other branch. A complication: This code also
// had the effect of implementing the special-case rules for 'if-then' and
// 'if-then-else' in JLS 14.19, "Unreachable Statements". We now use
// 'Vset.clearDeadEnd' to remove the dead-end status of unreachable branches
// without affecting the definite-assignment status of the variables, thus
// maintaining a correct implementation of JLS 16.2.6. Fixes 4094353.
// Note that the code below will not consider the branches unreachable if
// the entire statement is unreachable. This is consistent with the error
// recovery policy that reports the only the first unreachable statement
// along an acyclic execution path.
Vset vsTrue = cvars.vsTrue.clearDeadEnd();
Vset vsFalse = cvars.vsFalse.clearDeadEnd();
vsTrue = ifTrue.check(env, newctx, vsTrue, exp);
if (ifFalse != null)
vsFalse = ifFalse.check(env, newctx, vsFalse, exp);
vset = vsTrue.join(vsFalse.join(newctx.vsBreak));
return ctx.removeAdditionalVars(vset);
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
ctx = new Context(ctx, this);
cond = cond.inlineValue(env, ctx);
// The compiler currently needs to perform inlining on both
// branches of the if statement -- even if `cond' is a constant
// true or false. Why? The compiler will later try to compile
// all classes that it has seen; this includes classes that
// appear in dead code. If we don't inline the dead branch here
// then the compiler will never perform inlining on any local
// classes appearing on the dead code. When the compiler tries
// to compile an un-inlined local class with uplevel references,
// it dies. (bug 4059492)
//
// A better solution to this would be to walk the dead branch and
// mark any local classes appearing therein as unneeded. Then the
// compilation phase could skip these classes.
if (ifTrue != null) {
ifTrue = ifTrue.inline(env, ctx);
}
if (ifFalse != null) {
ifFalse = ifFalse.inline(env, ctx);
}
if (cond.equals(true)) {
return eliminate(env, ifTrue);
}
if (cond.equals(false)) {
return eliminate(env, ifFalse);
}
if ((ifTrue == null) && (ifFalse == null)) {
return eliminate(env, new ExpressionStatement(where, cond).inline(env, ctx));
}
if (ifTrue == null) {
cond = new NotExpression(cond.where, cond).inlineValue(env, ctx);
return eliminate(env, new IfStatement(where, cond, ifFalse, null));
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
IfStatement s = (IfStatement)clone();
s.cond = cond.copyInline(ctx);
if (ifTrue != null) {
s.ifTrue = ifTrue.copyInline(ctx, valNeeded);
}
if (ifFalse != null) {
s.ifFalse = ifFalse.copyInline(ctx, valNeeded);
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
int cost = 1 + cond.costInline(thresh, env, ctx);
if (ifTrue != null) {
cost += ifTrue.costInline(thresh, env, ctx);
}
if (ifFalse != null) {
cost += ifFalse.costInline(thresh, env, ctx);
}
return cost;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
Label l1 = new Label();
cond.codeBranch(env, newctx, asm, l1, false);
ifTrue.code(env, newctx, asm);
if (ifFalse != null) {
Label l2 = new Label();
asm.add(true, where, opc_goto, l2);
asm.add(l1);
ifFalse.code(env, newctx, asm);
asm.add(l2);
} else {
asm.add(l1);
}
asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("if ");
cond.print(out);
out.print(" ");
ifTrue.print(out, indent);
if (ifFalse != null) {
out.print(" else ");
ifFalse.print(out, indent);
}
}
}

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class IncDecExpression extends UnaryExpression {
private FieldUpdater updater = null;
/**
* Constructor
*/
public IncDecExpression(int op, long where, Expression right) {
super(op, where, right.type, right);
}
/**
* Check an increment or decrement expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = right.checkAssignOp(env, ctx, vset, exp, this);
if (right.type.inMask(TM_NUMBER)) {
type = right.type;
} else {
if (!right.type.isType(TC_ERROR)) {
env.error(where, "invalid.arg.type", right.type, opNames[op]);
}
type = Type.tError;
}
updater = right.getUpdater(env, ctx); // Must be called after 'checkAssignOp'.
return vset;
}
/**
* Check void expression
*/
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
return inlineValue(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
// Why not inlineLHS? But that does not work.
right = right.inlineValue(env, ctx);
if (updater != null) {
updater = updater.inline(env, ctx);
}
return this;
}
public int costInline(int thresh, Environment env, Context ctx) {
if (updater == null) {
if ((right.op == IDENT) && type.isType(TC_INT) &&
(((IdentifierExpression)right).field.isLocal())) {
// Increment variable in place. Count 3 bytes for 'iinc'.
return 3;
}
// Cost to load lhs reference, fetch local, increment, and store.
// Load/store cost will be higher if variable is a field. Note that
// costs are highly approximate. See 'AssignOpExpression.costInline'
// Does not account for cost of conversions,or duplications in
// value-needed context..
return right.costInline(thresh, env, ctx) + 4;
} else {
// Cost of two access method calls (get/set) + cost of increment.
return updater.costInline(thresh, env, ctx, true) + 1;
}
}
/**
* Code
*/
private void codeIncDecOp(Assembler asm, boolean inc) {
switch (type.getTypeCode()) {
case TC_BYTE:
asm.add(where, opc_ldc, new Integer(1));
asm.add(where, inc ? opc_iadd : opc_isub);
asm.add(where, opc_i2b);
break;
case TC_SHORT:
asm.add(where, opc_ldc, new Integer(1));
asm.add(where, inc ? opc_iadd : opc_isub);
asm.add(where, opc_i2s);
break;
case TC_CHAR:
asm.add(where, opc_ldc, new Integer(1));
asm.add(where, inc ? opc_iadd : opc_isub);
asm.add(where, opc_i2c);
break;
case TC_INT:
asm.add(where, opc_ldc, new Integer(1));
asm.add(where, inc ? opc_iadd : opc_isub);
break;
case TC_LONG:
asm.add(where, opc_ldc2_w, new Long(1));
asm.add(where, inc ? opc_ladd : opc_lsub);
break;
case TC_FLOAT:
asm.add(where, opc_ldc, new Float(1));
asm.add(where, inc ? opc_fadd : opc_fsub);
break;
case TC_DOUBLE:
asm.add(where, opc_ldc2_w, new Double(1));
asm.add(where, inc ? opc_dadd : opc_dsub);
break;
default:
throw new CompilerError("invalid type");
}
}
void codeIncDec(Environment env, Context ctx, Assembler asm, boolean inc, boolean prefix, boolean valNeeded) {
// The 'iinc' instruction cannot be used if an access method call is required.
if ((right.op == IDENT) && type.isType(TC_INT) &&
(((IdentifierExpression)right).field.isLocal()) && updater == null) {
if (valNeeded && !prefix) {
right.codeLoad(env, ctx, asm);
}
int v = ((LocalMember)((IdentifierExpression)right).field).number;
int[] operands = { v, inc ? 1 : -1 };
asm.add(where, opc_iinc, operands);
if (valNeeded && prefix) {
right.codeLoad(env, ctx, asm);
}
return;
}
if (updater == null) {
// Field is directly accessible.
int depth = right.codeLValue(env, ctx, asm);
codeDup(env, ctx, asm, depth, 0);
right.codeLoad(env, ctx, asm);
if (valNeeded && !prefix) {
codeDup(env, ctx, asm, type.stackSize(), depth);
}
codeIncDecOp(asm, inc);
if (valNeeded && prefix) {
codeDup(env, ctx, asm, type.stackSize(), depth);
}
right.codeStore(env, ctx, asm);
} else {
// Must use access methods.
updater.startUpdate(env, ctx, asm, (valNeeded && !prefix));
codeIncDecOp(asm, inc);
updater.finishUpdate(env, ctx, asm, (valNeeded && prefix));
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Label;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class InlineMethodExpression extends Expression {
MemberDefinition field;
Statement body;
/**
* Constructor
*/
InlineMethodExpression(long where, Type type, MemberDefinition field, Statement body) {
super(INLINEMETHOD, where, type);
this.field = field;
this.body = body;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
body = body.inline(env, new Context(ctx, this));
if (body == null) {
return null;
} else if (body.op == INLINERETURN) {
Expression expr = ((InlineReturnStatement)body).expr;
if (expr != null && type.isType(TC_VOID)) {
throw new CompilerError("value on inline-void return");
}
return expr;
} else {
return this;
}
}
public Expression inlineValue(Environment env, Context ctx) {
// When this node was constructed, "copyInline" walked the body
// with a "valNeeded" flag which made all returns either void
// or value-bearing. The type of this node reflects that
// earlier choice. The present inline/inlineValue distinction
// is ignored.
return inline(env, ctx);
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
InlineMethodExpression e = (InlineMethodExpression)clone();
if (body != null) {
e.body = body.copyInline(ctx, true);
}
return e;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
// pop the result if there is any (usually, type is already void)
super.code(env, ctx, asm);
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
CodeContext newctx = new CodeContext(ctx, this);
body.code(env, newctx, asm);
asm.add(newctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + "\n");
body.print(out, 1);
out.print(")");
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Label;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Vector;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class InlineNewInstanceExpression extends Expression {
MemberDefinition field;
Statement body;
/**
* Constructor
*/
InlineNewInstanceExpression(long where, Type type, MemberDefinition field, Statement body) {
super(INLINENEWINSTANCE, where, type);
this.field = field;
this.body = body;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
return inlineValue(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
if (body != null) {
LocalMember v = (LocalMember)field.getArguments().elementAt(0);
Context newctx = new Context(ctx, this);
newctx.declare(env, v);
body = body.inline(env, newctx);
}
if ((body != null) && (body.op == INLINERETURN)) {
body = null;
}
return this;
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
InlineNewInstanceExpression e = (InlineNewInstanceExpression)clone();
e.body = body.copyInline(ctx, true);
return e;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
codeCommon(env, ctx, asm, false);
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeCommon(env, ctx, asm, true);
}
private void codeCommon(Environment env, Context ctx, Assembler asm,
boolean forValue) {
asm.add(where, opc_new, field.getClassDeclaration());
if (body != null) {
LocalMember v = (LocalMember)field.getArguments().elementAt(0);
CodeContext newctx = new CodeContext(ctx, this);
newctx.declare(env, v);
asm.add(where, opc_astore, new Integer(v.number));
body.code(env, newctx, asm);
asm.add(newctx.breakLabel);
if (forValue) {
asm.add(where, opc_aload, new Integer(v.number));
}
}
}
/**
* Print
*/
public void print(PrintStream out) {
LocalMember v = (LocalMember)field.getArguments().elementAt(0);
out.println("(" + opNames[op] + "#" + v.hashCode() + "=" + field.hashCode());
if (body != null) {
body.print(out, 1);
} else {
out.print("<empty>");
}
out.print(")");
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class InlineReturnStatement extends Statement {
Expression expr;
/**
* Constructor
*/
public InlineReturnStatement(long where, Expression expr) {
super(INLINERETURN, where);
this.expr = expr;
}
/**
* Get the destination context of a break
*/
Context getDestination(Context ctx) {
for (; ctx != null ; ctx = ctx.prev) {
if ((ctx.node != null) && ((ctx.node.op == INLINEMETHOD) || (ctx.node.op == INLINENEWINSTANCE))) {
return ctx;
}
}
return null;
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
if (expr != null) {
expr = expr.inlineValue(env, ctx);
}
return this;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
InlineReturnStatement s = (InlineReturnStatement)clone();
if (expr != null) {
s.expr = expr.copyInline(ctx);
}
return s;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1 + ((expr != null) ? expr.costInline(thresh, env, ctx) : 0);
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
if (expr != null) {
expr.codeValue(env, ctx, asm);
}
CodeContext destctx = (CodeContext)getDestination(ctx);
asm.add(where, opc_goto, destctx.breakLabel);
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("inline-return");
if (expr != null) {
out.print(" ");
expr.print(out);
}
out.print(";");
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class InstanceOfExpression extends BinaryExpression {
/**
* constructor
*/
public InstanceOfExpression(long where, Expression left, Expression right) {
super(INSTANCEOF, where, Type.tBoolean, left, right);
}
/**
* Check the expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = left.checkValue(env, ctx, vset, exp);
right = new TypeExpression(right.where, right.toType(env, ctx));
if (right.type.isType(TC_ERROR) || left.type.isType(TC_ERROR)) {
// An error was already reported
return vset;
}
if (!right.type.inMask(TM_CLASS|TM_ARRAY)) {
env.error(right.where, "invalid.arg.type", right.type, opNames[op]);
return vset;
}
try {
if (!env.explicitCast(left.type, right.type)) {
env.error(where, "invalid.instanceof", left.type, right.type);
}
} catch (ClassNotFound e) {
env.error(where, "class.not.found", e.name, opNames[op]);
}
return vset;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
return left.inline(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
left = left.inlineValue(env, ctx);
return this;
}
public int costInline(int thresh, Environment env, Context ctx) {
if (ctx == null) {
return 1 + left.costInline(thresh, env, ctx);
}
// sourceClass is the current class trying to inline this method
ClassDefinition sourceClass = ctx.field.getClassDefinition();
try {
// We only allow the inlining if the current class can access
// the "instance of" class
if (right.type.isType(TC_ARRAY) ||
sourceClass.permitInlinedAccess(env, env.getClassDeclaration(right.type)))
return 1 + left.costInline(thresh, env, ctx);
} catch (ClassNotFound e) {
}
return thresh;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
left.codeValue(env, ctx, asm);
if (right.type.isType(TC_CLASS)) {
asm.add(where, opc_instanceof, env.getClassDeclaration(right.type));
} else {
asm.add(where, opc_instanceof, right.type);
}
}
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_ifne : opc_ifeq, lbl, whenTrue);
}
public void code(Environment env, Context ctx, Assembler asm) {
left.code(env, ctx, asm);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + " ");
left.print(out);
out.print(" ");
if (right.op == TYPE) {
out.print(right.type.toString());
} else {
right.print(out);
}
out.print(")");
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class IntExpression extends IntegerExpression {
/**
* Constructor
*/
public IntExpression(long where, int value) {
super(INTVAL, where, Type.tInt, value);
}
/**
* Equality, this is needed so that switch statements
* can put IntExpressions in a hashtable
*/
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof IntExpression)) {
return value == ((IntExpression)obj).value;
}
return false;
}
/**
* Hashcode, this is needed so that switch statements
* can put IntExpressions in a hashtable
*/
public int hashCode() {
return value;
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value);
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class IntegerExpression extends ConstantExpression {
int value;
/**
* Constructor
*/
IntegerExpression(int op, long where, Type type, int value) {
super(op, where, type);
this.value = value;
}
/**
* See if this number fits in the given type.
*/
public boolean fitsType(Environment env, Context ctx, Type t) {
if (this.type.isType(TC_CHAR)) {
// A char constant is not really an int constant,
// so do not report that 'a' fits in a byte or short,
// even if its value is in fact 7-bit ascii. See JLS 5.2.
return super.fitsType(env, ctx, t);
}
switch (t.getTypeCode()) {
case TC_BYTE:
return value == (byte)value;
case TC_SHORT:
return value == (short)value;
case TC_CHAR:
return value == (char)value;
}
return super.fitsType(env, ctx, t);
}
/**
* Get the value
*/
public Object getValue() {
return new Integer(value);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return value == i;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
return value == 0;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc, new Integer(value));
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class LengthExpression extends UnaryExpression {
/**
* Constructor
*/
public LengthExpression(long where, Expression right) {
super(LENGTH, where, Type.tInt, right);
}
/**
* Select the type of the expression
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
vset = right.checkValue(env, ctx, vset, exp);
if (!right.type.isType(TC_ARRAY)) {
env.error(where, "invalid.length", right.type);
}
return vset;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
right.codeValue(env, ctx, asm);
asm.add(where, opc_arraylength);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class LessExpression extends BinaryCompareExpression {
/**
* constructor
*/
public LessExpression(long where, Expression left, Expression right) {
super(LT, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a < b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a < b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a < b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a < b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new GreaterExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmplt : opc_if_icmpge, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpg);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpg);
break;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_iflt : opc_ifge, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class LessOrEqualExpression extends BinaryCompareExpression {
/**
* constructor
*/
public LessOrEqualExpression(long where, Expression left, Expression right) {
super(LE, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a <= b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a <= b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a <= b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a <= b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new GreaterOrEqualExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmple : opc_if_icmpgt, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpg);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpg);
break;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_ifle : opc_ifgt, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.tree.*;
import java.util.Vector;
/**
* A local Field
*
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class LocalMember extends MemberDefinition {
/**
* The number of the variable
*/
int number = -1;
/**
* Some statistics
*/
int readcount;
int writecount;
/**
* An indication of which block the variable comes from.
* Helps identify uplevel references.
*/
int scopeNumber;
/**
* Return current nesting level, i.e., the value of 'scopeNumber'.
* Made public for the benefit of 'ClassDefinition.resolveName'.
*/
public int getScopeNumber() {
return scopeNumber;
}
/**
* Used by copyInline to record the original of this copy.
*/
LocalMember originalOfCopy;
/**
* The previous local variable, this list is used to build a nested
* context of local variables.
*/
LocalMember prev;
/**
* Constructor
*/
public LocalMember(long where, ClassDefinition clazz, int modifiers, Type type,
Identifier name) {
super(where, clazz, modifiers, type, name, null, null);
}
/**
* Constructor for a block-inner class.
*/
public LocalMember(ClassDefinition innerClass) {
super(innerClass);
// The class's "real" name is something like "foo$1$bar", but locally:
name = innerClass.getLocalName();
}
/**
* Constructor for a proxy to an instance or class variable.
*/
LocalMember(MemberDefinition field) {
this(0, null, 0, field.getType(), idClass);
// use this random slot to store the info:
accessPeer = field;
}
/**
* Is this a proxy for the given field?
*/
final MemberDefinition getMember() {
return (name == idClass) ? accessPeer : null;
}
/**
* Special checks
*/
public boolean isLocal() {
return true;
}
/**
* Make a copy of this field, which is an argument to a method
* or constructor. Arrange so that when occurrences of the field
* are encountered in an immediately following copyInline() operation,
* the expression nodes will replace the original argument by the
* fresh copy.
*/
public LocalMember copyInline(Context ctx) {
LocalMember copy = new LocalMember(where, clazz, modifiers, type, name);
copy.readcount = this.readcount;
copy.writecount = this.writecount;
copy.originalOfCopy = this;
// Make a temporary link from the original.
// It only stays valid through the next call to copyInline().
// (This means that recursive inlining won't work.)
// To stay honest, we mark these inline copies:
copy.addModifiers(M_LOCAL);
if (this.accessPeer != null
&& (this.accessPeer.getModifiers() & M_LOCAL) == 0) {
throw new CompilerError("local copyInline");
}
this.accessPeer = copy;
return copy;
}
/**
* Returns the previous result of copyInline(ctx).
* Must be called in the course of an Expression.copyInline()
* operation that immediately follows the LocalMember.copyInline().
* Return "this" if there is no such copy.
*/
public LocalMember getCurrentInlineCopy(Context ctx) {
MemberDefinition accessPeer = this.accessPeer;
if (accessPeer != null && (accessPeer.getModifiers() & M_LOCAL) != 0) {
LocalMember copy = (LocalMember)accessPeer;
return copy;
}
return this;
}
/**
* May inline copies of all the arguments of the given method.
*/
static public LocalMember[] copyArguments(Context ctx, MemberDefinition field) {
Vector v = field.getArguments();
LocalMember res[] = new LocalMember[v.size()];
v.copyInto(res);
for (int i = 0; i < res.length; i++) {
res[i] = res[i].copyInline(ctx);
}
return res;
}
/**
* Call this when finished with the result of a copyArguments() call.
*/
static public void doneWithArguments(Context ctx, LocalMember res[]) {
for (int i = 0; i < res.length; i++) {
if (res[i].originalOfCopy.accessPeer == res[i]) {
res[i].originalOfCopy.accessPeer = null;
}
}
}
/**
* Is this local variable's value stable and simple enough to be directly
* substituted for occurrences of the variable itself?
* (This decision is made by VarDeclarationStatement.inline().)
*/
public boolean isInlineable(Environment env, boolean fromFinal) {
return (getModifiers() & M_INLINEABLE) != 0;
}
/**
* Check if used
*/
public boolean isUsed() {
return (readcount != 0) || (writecount != 0);
}
// Used by class Context, only on members of MemberDefinition.available:
LocalMember getAccessVar() {
return (LocalMember)accessPeer;
}
void setAccessVar(LocalMember f) {
accessPeer = f;
}
// Used by class Context, only on "AccessVar" constructor args
MemberDefinition getAccessVarMember() {
return accessPeer;
}
void setAccessVarMember(MemberDefinition f) {
accessPeer = f;
}
/**
* Return value
*/
public Node getValue(Environment env) {
return (Expression)getValue();
}
/**
* Value number for vsets, or -1 if none.
*/
public int getNumber(Context ctx) {
return number;
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class LongExpression extends ConstantExpression {
long value;
/**
* Constructor
*/
public LongExpression(long where, long value) {
super(LONGVAL, where, Type.tLong);
this.value = value;
}
/**
* Get the value
*/
public Object getValue() {
return new Long(value);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return value == i;
}
/**
* Check if the expression is equal to its default static value
*/
public boolean equalsDefault() {
return value == 0;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc2_w, new Long(value));
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value + "L");
}
}

View File

@@ -0,0 +1,949 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class MethodExpression extends NaryExpression {
Identifier id;
ClassDefinition clazz; // The class in which the called method is defined
MemberDefinition field;
Expression implementation;
private boolean isSuper; // Set if qualified by 'super' or '<class>.super'.
/**
* constructor
*/
public MethodExpression(long where, Expression right, Identifier id, Expression args[]) {
super(METHOD, where, Type.tError, right, args);
this.id = id;
}
public MethodExpression(long where, Expression right, MemberDefinition field, Expression args[]) {
super(METHOD, where, field.getType().getReturnType(), right, args);
this.id = field.getName();
this.field = field;
this.clazz = field.getClassDefinition();
}
// This is a hack used only within certain access methods generated by
// 'SourceClass.getAccessMember'. It allows an 'invokespecial' instruction
// to be forced even though 'super' does not appear within the call.
// Such access methods are needed for access to protected methods when using
// the qualified '<class>.super.<method>(...)' notation.
public MethodExpression(long where, Expression right,
MemberDefinition field, Expression args[], boolean forceSuper) {
this(where, right, field, args);
this.isSuper = forceSuper;
}
public Expression getImplementation() {
if (implementation != null)
return implementation;
return this;
}
/**
* Check expression type
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
ClassDeclaration c = null;
boolean isArray = false;
boolean staticRef = false;
// Access method to use if required.
MemberDefinition implMethod = null;
ClassDefinition ctxClass = ctx.field.getClassDefinition();
// When calling a constructor, we may need to add an
// additional argument to transmit the outer instance link.
Expression args[] = this.args;
if (id.equals(idInit)){
ClassDefinition conCls = ctxClass;
try {
Expression conOuter = null;
if (right instanceof SuperExpression) {
// outer.super(...)
conCls = conCls.getSuperClass().getClassDefinition(env);
conOuter = ((SuperExpression)right).outerArg;
} else if (right instanceof ThisExpression) {
// outer.this(...)
conOuter = ((ThisExpression)right).outerArg;
}
args = NewInstanceExpression.
insertOuterLink(env, ctx, where, conCls, conOuter, args);
} catch (ClassNotFound ee) {
// the same error is handled elsewhere
}
}
Type argTypes[] = new Type[args.length];
// The effective accessing class, for access checking.
// This is normally the immediately enclosing class.
ClassDefinition sourceClass = ctxClass;
try {
if (right == null) {
staticRef = ctx.field.isStatic();
// Find the first outer scope that mentions the method.
ClassDefinition cdef = ctxClass;
MemberDefinition m = null;
for (; cdef != null; cdef = cdef.getOuterClass()) {
m = cdef.findAnyMethod(env, id);
if (m != null) {
break;
}
}
if (m == null) {
// this is the scope for error diagnosis
c = ctx.field.getClassDeclaration();
} else {
// found the innermost scope in which m occurs
c = cdef.getClassDeclaration();
// Maybe an inherited method hides an apparent method.
// Keep looking at enclosing scopes to find out.
if (m.getClassDefinition() != cdef) {
ClassDefinition cdef2 = cdef;
while ((cdef2 = cdef2.getOuterClass()) != null) {
MemberDefinition m2 = cdef2.findAnyMethod(env, id);
if (m2 != null && m2.getClassDefinition() == cdef2) {
env.error(where, "inherited.hides.method",
id, cdef.getClassDeclaration(),
cdef2.getClassDeclaration());
break;
}
}
}
}
} else {
if (id.equals(idInit)) {
int thisN = ctx.getThisNumber();
if (!ctx.field.isConstructor()) {
env.error(where, "invalid.constr.invoke");
return vset.addVar(thisN);
}
// As a consequence of the DA/DU rules in the JLS (draft of
// forthcoming 2e), all variables are both definitely assigned
// and definitely unassigned in unreachable code. Normally, this
// correctly suppresses DA/DU-related errors in such code.
// The use of the DA status of the 'this' variable for the extra
// check below on correct constructor usage, however, does not quite
// fit into this DA/DU scheme. The current representation of
// Vsets for unreachable dead-ends, does not allow 'clearVar'
// to work, as the DA/DU bits (all on) are implicitly represented
// by the fact that the Vset is a dead-end. The DA/DU status
// of the 'this' variable is supposed to be temporarily
// cleared at the beginning of a constructor and during the
// checking of constructor arguments (see below in this method).
// Since 'clearVar' has no effect on dead-ends, we may
// find the 'this' variable in an erroneously definitely-assigned state.
// As a workaround, we suppress the following error message when
// the Vset is a dead-end, i.e., when we are in unreachable code.
// Unfortunately, the special-case treatment of reachability for
// if-then and if-then-else allows unreachable code in some circumstances,
// thus it is possible that no error message will be emitted at all.
// While this behavior is strictly incorrect (thus we call this a
// workaround), the problematic code is indeed unreachable and will
// not be executed. In fact, it will be entirely omitted from the
// translated program, and can cause no harm at runtime. A correct
// solution would require modifying the representation of the DA/DU
// analysis to use finite Vsets only, restricting the universe
// of variables about which assertions are made (even in unreachable
// code) to variables that are actually in scope. Alternatively, the
// Vset extension and the dead-end marker (currently a reserved value
// of the extension) could be represented orthogonally. In either case,
// 'clearVar' could then be made to work on (non-canonical) dead ends.
// See file 'Vset.java'.
if (!vset.isReallyDeadEnd() && vset.testVar(thisN)) {
env.error(where, "constr.invoke.not.first");
return vset;
}
vset = vset.addVar(thisN);
if (right instanceof SuperExpression) {
// supers require this specific kind of checking
vset = right.checkAmbigName(env, ctx, vset, exp, this);
} else {
vset = right.checkValue(env, ctx, vset, exp);
}
} else {
vset = right.checkAmbigName(env, ctx, vset, exp, this);
if (right.type == Type.tPackage) {
FieldExpression.reportFailedPackagePrefix(env, right);
return vset;
}
if (right instanceof TypeExpression) {
staticRef = true;
}
}
if (right.type.isType(TC_CLASS)) {
c = env.getClassDeclaration(right.type);
} else if (right.type.isType(TC_ARRAY)) {
isArray = true;
c = env.getClassDeclaration(Type.tObject);
} else {
if (!right.type.isType(TC_ERROR)) {
env.error(where, "invalid.method.invoke", right.type);
}
return vset;
}
// Normally, the effective accessing class is the innermost
// class surrounding the current method call, but, for calls
// of the form '<class>.super.<method>(...)', it is <class>.
// This allows access to protected members of a superclass
// from within a class nested within one of its subclasses.
// Otherwise, for example, the call below to 'matchMethod'
// may fail due to the rules for visibility of inaccessible
// members. For consistency, we treat qualified 'this' in
// the same manner, as error diagnostics will be affected.
// QUERY: Are there subtle unexplored language issues here?
if (right instanceof FieldExpression) {
Identifier id = ((FieldExpression)right).id;
if (id == idThis) {
sourceClass = ((FieldExpression)right).clazz;
} else if (id == idSuper) {
isSuper = true;
sourceClass = ((FieldExpression)right).clazz;
}
} else if (right instanceof SuperExpression) {
isSuper = true;
}
// Fix for 4158650. When we extend a protected inner
// class in a different package, we may not have access
// to the type of our superclass. Allow the call to
// the superclass constructor from within our constructor
// Note that this check does not apply to constructor
// calls in new instance expressions -- those are part
// of NewInstanceExpression#check().
if (id != idInit) {
// Required by JLS 6.6.1. Fixes 4143715.
// (See also 4094658.)
if (!FieldExpression.isTypeAccessible(where, env,
right.type,
sourceClass)) {
ClassDeclaration cdecl =
sourceClass.getClassDeclaration();
if (staticRef) {
env.error(where, "no.type.access",
id, right.type.toString(), cdecl);
} else {
env.error(where, "cant.access.member.type",
id, right.type.toString(), cdecl);
}
}
}
}
// Compose a list of argument types
boolean hasErrors = false;
// "this" is not defined during argument checking
if (id.equals(idInit)) {
vset = vset.clearVar(ctx.getThisNumber());
}
for (int i = 0 ; i < args.length ; i++) {
vset = args[i].checkValue(env, ctx, vset, exp);
argTypes[i] = args[i].type;
hasErrors = hasErrors || argTypes[i].isType(TC_ERROR);
}
// "this" is defined after the constructor invocation
if (id.equals(idInit)) {
vset = vset.addVar(ctx.getThisNumber());
}
// Check if there are any type errors in the arguments
if (hasErrors) {
return vset;
}
// Get the method field, given the argument types
clazz = c.getClassDefinition(env);
if (field == null) {
field = clazz.matchMethod(env, sourceClass, id, argTypes);
if (field == null) {
if (id.equals(idInit)) {
if (diagnoseMismatch(env, args, argTypes))
return vset;
String sig = clazz.getName().getName().toString();
sig = Type.tMethod(Type.tError, argTypes).typeString(sig, false, false);
env.error(where, "unmatched.constr", sig, c);
return vset;
}
String sig = id.toString();
sig = Type.tMethod(Type.tError, argTypes).typeString(sig, false, false);
if (clazz.findAnyMethod(env, id) == null) {
if (ctx.getField(env, id) != null) {
env.error(where, "invalid.method", id, c);
} else {
env.error(where, "undef.meth", sig, c);
}
} else if (diagnoseMismatch(env, args, argTypes)) {
} else {
env.error(where, "unmatched.meth", sig, c);
}
return vset;
}
}
type = field.getType().getReturnType();
// Make sure that static references are allowed
if (staticRef && !field.isStatic()) {
env.error(where, "no.static.meth.access",
field, field.getClassDeclaration());
return vset;
}
if (field.isProtected()
&& !(right == null)
&& !(right instanceof SuperExpression
// Extension of JLS 6.6.2 for qualified 'super'.
|| (right instanceof FieldExpression &&
((FieldExpression)right).id == idSuper))
&& !sourceClass.protectedAccess(env, field, right.type)) {
env.error(where, "invalid.protected.method.use",
field.getName(), field.getClassDeclaration(),
right.type);
return vset;
}
// In <class>.super.<method>(), we cannot simply evaluate
// <class>.super to an object reference (as we would for
// <class>.super.<field>) and then perform an 'invokespecial'.
// An 'invokespecial' must be performed from within (a subclass of)
// the class in which the target method is located.
if (right instanceof FieldExpression &&
((FieldExpression)right).id == idSuper) {
if (!field.isPrivate()) {
// The private case is handled below.
// Use an access method unless the effective accessing class
// (the class qualifying the 'super') is the same as the
// immediately enclosing class, i.e., the qualification was
// unnecessary.
if (sourceClass != ctxClass) {
implMethod = sourceClass.getAccessMember(env, ctx, field, true);
}
}
}
// Access method for private field if not in the same class.
if (implMethod == null && field.isPrivate()) {
ClassDefinition cdef = field.getClassDefinition();
if (cdef != ctxClass) {
implMethod = cdef.getAccessMember(env, ctx, field, false);
}
}
// Make sure that we are not invoking an abstract method
if (field.isAbstract() && (right != null) && (right.op == SUPER)) {
env.error(where, "invoke.abstract", field, field.getClassDeclaration());
return vset;
}
if (field.reportDeprecated(env)) {
if (field.isConstructor()) {
env.error(where, "warn.constr.is.deprecated", field);
} else {
env.error(where, "warn.meth.is.deprecated",
field, field.getClassDefinition());
}
}
// Check for recursive constructor
if (field.isConstructor() && ctx.field.equals(field)) {
env.error(where, "recursive.constr", field);
}
// When a package-private class defines public or protected
// members, those members may sometimes be accessed from
// outside of the package in public subclasses. In these
// cases, we need to massage the method call to refer to
// to an accessible subclass rather than the package-private
// parent class. Part of fix for 4135692.
// Find out if the class which contains this method
// call has access to the class which declares the
// public or protected method referent.
// We don't perform this translation on constructor calls.
if (sourceClass == ctxClass) {
ClassDefinition declarer = field.getClassDefinition();
if (!field.isConstructor() &&
declarer.isPackagePrivate() &&
!declarer.getName().getQualifier()
.equals(sourceClass.getName().getQualifier())) {
//System.out.println("The access of member " +
// field + " declared in class " +
// declarer +
// " is not allowed by the VM from class " +
// accessor +
// ". Replacing with an access of class " +
// clazz);
// We cannot make this access at the VM level.
// Construct a member which will stand for this
// method in clazz and set `field' to refer to it.
field =
MemberDefinition.makeProxyMember(field, clazz, env);
}
}
sourceClass.addDependency(field.getClassDeclaration());
if (sourceClass != ctxClass) {
ctxClass.addDependency(field.getClassDeclaration());
}
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, ctx.field);
return vset;
} catch (AmbiguousMember ee) {
env.error(where, "ambig.field", id, ee.field1, ee.field2);
return vset;
}
// Make sure it is qualified
if ((right == null) && !field.isStatic()) {
right = ctx.findOuterLink(env, where, field);
vset = right.checkValue(env, ctx, vset, exp);
}
// Cast arguments
argTypes = field.getType().getArgumentTypes();
for (int i = 0 ; i < args.length ; i++) {
args[i] = convert(env, ctx, argTypes[i], args[i]);
}
if (field.isConstructor()) {
MemberDefinition m = field;
if (implMethod != null) {
m = implMethod;
}
int nargs = args.length;
Expression[] newargs = args;
if (nargs > this.args.length) {
// Argument was added above.
// Maintain the model for hidden outer args in outer.super(...):
Expression rightI;
if (right instanceof SuperExpression) {
rightI = new SuperExpression(right.where, ctx);
((SuperExpression)right).outerArg = args[0];
} else if (right instanceof ThisExpression) {
rightI = new ThisExpression(right.where, ctx);
} else {
throw new CompilerError("this.init");
}
if (implMethod != null) {
// Need dummy argument for access method.
// Dummy argument follows outer instance link.
// Leave 'this.args' equal to 'newargs' but
// without the outer instance link.
newargs = new Expression[nargs+1];
this.args = new Expression[nargs];
newargs[0] = args[0]; // outer instance
this.args[0] = newargs[1] = new NullExpression(where); // dummy argument
for (int i = 1 ; i < nargs ; i++) {
this.args[i] = newargs[i+1] = args[i];
}
} else {
// Strip outer instance link from 'this.args'.
// ASSERT(this.arg.length == nargs-1);
for (int i = 1 ; i < nargs ; i++) {
this.args[i-1] = args[i];
}
}
implementation = new MethodExpression(where, rightI, m, newargs);
implementation.type = type; // Is this needed?
} else {
// No argument was added.
if (implMethod != null) {
// Need dummy argument for access method.
// Dummy argument is first, as there is no outer instance link.
newargs = new Expression[nargs+1];
newargs[0] = new NullExpression(where);
for (int i = 0 ; i < nargs ; i++) {
newargs[i+1] = args[i];
}
}
implementation = new MethodExpression(where, right, m, newargs);
}
} else {
// Have ordinary method.
// Argument should have been added only for a constructor.
if (args.length > this.args.length) {
throw new CompilerError("method arg");
}
if (implMethod != null) {
//System.out.println("Calling " + field + " via " + implMethod);
Expression oldargs[] = this.args;
if (field.isStatic()) {
Expression call = new MethodExpression(where, null, implMethod, oldargs);
implementation = new CommaExpression(where, right, call);
} else {
// Access method needs an explicit 'this' pointer.
int nargs = oldargs.length;
Expression newargs[] = new Expression[nargs+1];
newargs[0] = right;
for (int i = 0; i < nargs; i++) {
newargs[i+1] = oldargs[i];
}
implementation = new MethodExpression(where, null, implMethod, newargs);
}
}
}
// Follow super() by variable initializations
if (ctx.field.isConstructor() &&
field.isConstructor() && (right != null) && (right.op == SUPER)) {
Expression e = makeVarInits(env, ctx);
if (e != null) {
if (implementation == null)
implementation = (Expression)this.clone();
implementation = new CommaExpression(where, implementation, e);
}
}
// Throw the declared exceptions.
ClassDeclaration exceptions[] = field.getExceptions(env);
if (isArray && (field.getName() == idClone) &&
(field.getType().getArgumentTypes().length == 0)) {
/* Arrays pretend that they have "public Object clone()" that doesn't
* throw anything, according to the language spec.
*/
exceptions = new ClassDeclaration[0];
/* See if there's a bogus catch for it, to issue a warning. */
for (Context p = ctx; p != null; p = p.prev) {
if (p.node != null && p.node.op == TRY) {
((TryStatement) p.node).arrayCloneWhere = where;
}
}
}
for (int i = 0 ; i < exceptions.length ; i++) {
if (exp.get(exceptions[i]) == null) {
exp.put(exceptions[i], this);
}
}
// Mark all blank finals as definitely assigned following 'this(...)'.
// Correctness follows inductively from the requirement that all blank finals
// be definitely assigned at the completion of every constructor.
if (ctx.field.isConstructor() &&
field.isConstructor() && (right != null) && (right.op == THIS)) {
ClassDefinition cls = field.getClassDefinition();
for (MemberDefinition f = cls.getFirstMember() ; f != null ; f = f.getNextMember()) {
if (f.isVariable() && f.isBlankFinal() && !f.isStatic()) {
// Static variables should also be considered defined as well, but this
// is handled in 'SourceClass.checkMembers', and we should not interfere.
vset = vset.addVar(ctx.getFieldNumber(f));
}
}
}
return vset;
}
/**
* Check void expression
*/
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
/**
* We're about to report a "unmatched method" error.
* Try to issue a better diagnostic by comparing the actual argument types
* with the method (or methods) available.
* In particular, if there is an argument which fails to match <em>any</em>
* method, we report a type mismatch error against that particular argument.
* The diagnostic will report a target type taken from one of the methods.
* <p>
* Return false if we couldn't think of anything smart to say.
*/
boolean diagnoseMismatch(Environment env, Expression args[],
Type argTypes[]) throws ClassNotFound {
Type margType[] = new Type[1];
boolean saidSomething = false;
int start = 0;
while (start < argTypes.length) {
int code = clazz.diagnoseMismatch(env, id, argTypes, start, margType);
String opName = (id.equals(idInit)) ? "constructor" : opNames[op];
if (code == -2) {
env.error(where, "wrong.number.args", opName);
saidSomething = true;
}
if (code < 0) break;
int i = code >> 2;
boolean castOK = (code & 2) != 0;
boolean ambig = (code & 1) != 0;
Type targetType = margType[0];
// At least one argument is offensive to all overloadings.
// targetType is one of the argument types it does not match.
String ttype = ""+targetType;
// The message might be slightly misleading, if there are other
// argument types that also would match. Hint at this:
//if (ambig) ttype = "{"+ttype+";...}";
if (castOK)
env.error(args[i].where, "explicit.cast.needed", opName, argTypes[i], ttype);
else
env.error(args[i].where, "incompatible.type", opName, argTypes[i], ttype);
saidSomething = true;
start = i+1; // look for other bad arguments, too
}
return saidSomething;
}
/**
* Inline
*/
static final int MAXINLINECOST = Statement.MAXINLINECOST;
private
Expression inlineMethod(Environment env, Context ctx, Statement s, boolean valNeeded) {
if (env.dump()) {
System.out.println("INLINE METHOD " + field + " in " + ctx.field);
}
LocalMember v[] = LocalMember.copyArguments(ctx, field);
Statement body[] = new Statement[v.length + 2];
int n = 0;
if (field.isStatic()) {
body[0] = new ExpressionStatement(where, right);
} else {
if ((right != null) && (right.op == SUPER)) {
right = new ThisExpression(right.where, ctx);
}
body[0] = new VarDeclarationStatement(where, v[n++], right);
}
for (int i = 0 ; i < args.length ; i++) {
body[i + 1] = new VarDeclarationStatement(where, v[n++], args[i]);
}
//System.out.print("BEFORE:"); s.print(System.out); System.out.println();
// Note: If !valNeeded, then all returns in the body of the method
// change to void returns.
body[body.length - 1] = (s != null) ? s.copyInline(ctx, valNeeded) : null;
//System.out.print("COPY:"); body[body.length - 1].print(System.out); System.out.println();
LocalMember.doneWithArguments(ctx, v);
// Make sure the type matches what the return statements are returning.
Type type = valNeeded ? this.type : Type.tVoid;
Expression e = new InlineMethodExpression(where, type, field, new CompoundStatement(where, body));
return valNeeded ? e.inlineValue(env, ctx) : e.inline(env, ctx);
}
public Expression inline(Environment env, Context ctx) {
if (implementation != null)
return implementation.inline(env, ctx);
try {
if (right != null) {
right = field.isStatic() ? right.inline(env, ctx) : right.inlineValue(env, ctx);
}
for (int i = 0 ; i < args.length ; i++) {
args[i] = args[i].inlineValue(env, ctx);
}
// ctxClass is the current class trying to inline this method
ClassDefinition ctxClass = ctx.field.getClassDefinition();
Expression e = this;
if (env.opt() && field.isInlineable(env, clazz.isFinal()) &&
// Don't inline if a qualified non-static method: the call
// itself might throw NullPointerException as a side effect
((right == null) || (right.op==THIS) || field.isStatic()) &&
// We only allow the inlining if the current class can access
// the field, the field's class, and right's declared type.
ctxClass.permitInlinedAccess(env,
field.getClassDeclaration()) &&
ctxClass.permitInlinedAccess(env, field) &&
(right==null || ctxClass.permitInlinedAccess(env,
env.getClassDeclaration(right.type))) &&
((id == null) || !id.equals(idInit)) &&
(!ctx.field.isInitializer()) && ctx.field.isMethod() &&
(ctx.getInlineMemberContext(field) == null)) {
Statement s = (Statement)field.getValue(env);
if ((s == null) ||
(s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST)) {
e = inlineMethod(env, ctx, s, false);
}
}
return e;
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
}
public Expression inlineValue(Environment env, Context ctx) {
if (implementation != null)
return implementation.inlineValue(env, ctx);
try {
if (right != null) {
right = field.isStatic() ? right.inline(env, ctx) : right.inlineValue(env, ctx);
}
if (field.getName().equals(idInit)) {
ClassDefinition refc = field.getClassDefinition();
UplevelReference r = refc.getReferencesFrozen();
if (r != null) {
r.willCodeArguments(env, ctx);
}
}
for (int i = 0 ; i < args.length ; i++) {
args[i] = args[i].inlineValue(env, ctx);
}
// ctxClass is the current class trying to inline this method
ClassDefinition ctxClass = ctx.field.getClassDefinition();
if (env.opt() && field.isInlineable(env, clazz.isFinal()) &&
// Don't inline if a qualified non-static method: the call
// itself might throw NullPointerException as a side effect
((right == null) || (right.op==THIS) || field.isStatic()) &&
// We only allow the inlining if the current class can access
// the field, the field's class, and right's declared type.
ctxClass.permitInlinedAccess(env,
field.getClassDeclaration()) &&
ctxClass.permitInlinedAccess(env, field) &&
(right==null || ctxClass.permitInlinedAccess(env,
env.getClassDeclaration(right.type))) &&
(!ctx.field.isInitializer()) && ctx.field.isMethod() &&
(ctx.getInlineMemberContext(field) == null)) {
Statement s = (Statement)field.getValue(env);
if ((s == null) ||
(s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST)) {
return inlineMethod(env, ctx, s, true);
}
}
return this;
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
}
public Expression copyInline(Context ctx) {
if (implementation != null)
return implementation.copyInline(ctx);
return super.copyInline(ctx);
}
public int costInline(int thresh, Environment env, Context ctx) {
if (implementation != null)
return implementation.costInline(thresh, env, ctx);
// for now, don't allow calls to super() to be inlined. We may fix
// this later
if ((right != null) && (right.op == SUPER)) {
return thresh;
}
return super.costInline(thresh, env, ctx);
}
/*
* Grab all instance initializer code from the class definition,
* and return as one bolus. Note that we are assuming the
* the relevant fields have already been checked.
* (See the pre-pass in SourceClass.checkMembers which ensures this.)
*/
private Expression makeVarInits(Environment env, Context ctx) {
// insert instance initializers
ClassDefinition clazz = ctx.field.getClassDefinition();
Expression e = null;
for (MemberDefinition f = clazz.getFirstMember() ; f != null ; f = f.getNextMember()) {
if ((f.isVariable() || f.isInitializer()) && !f.isStatic()) {
try {
f.check(env);
} catch (ClassNotFound ee) {
env.error(f.getWhere(), "class.not.found", ee.name,
f.getClassDefinition());
}
Expression val = null;
if (f.isUplevelValue()) {
if (f != clazz.findOuterMember()) {
// it's too early to accumulate these
continue;
}
IdentifierExpression arg =
new IdentifierExpression(where, f.getName());
if (!arg.bind(env, ctx)) {
throw new CompilerError("bind "+arg.id);
}
val = arg;
} else if (f.isInitializer()) {
Statement s = (Statement)f.getValue();
val = new InlineMethodExpression(where, Type.tVoid, f, s);
} else {
val = (Expression)f.getValue();
}
// append all initializers to "e":
// This section used to check for variables which were
// initialized to their default values and elide such
// initialization. This is specifically disallowed by
// JLS 12.5 numeral 4, which requires a textual ordering
// on the execution of initializers.
if ((val != null)) { // && !val.equals(0)) {
long p = f.getWhere();
val = val.copyInline(ctx);
Expression init = val;
if (f.isVariable()) {
Expression v = new ThisExpression(p, ctx);
v = new FieldExpression(p, v, f);
init = new AssignExpression(p, v, val);
}
e = (e == null) ? init : new CommaExpression(p, e, init);
}
}
}
return e;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
if (implementation != null)
throw new CompilerError("codeValue");
int i = 0; // argument index
if (field.isStatic()) {
if (right != null) {
right.code(env, ctx, asm);
}
} else if (right == null) {
asm.add(where, opc_aload, new Integer(0));
} else if (right.op == SUPER) {
// 'super.<method>(...)', 'super(...)', or '<expr>.super(...)'
/*****
isSuper = true;
*****/
right.codeValue(env, ctx, asm);
if (idInit.equals(id)) {
// 'super(...)' or '<expr>.super(...)' only
ClassDefinition refc = field.getClassDefinition();
UplevelReference r = refc.getReferencesFrozen();
if (r != null) {
// When calling a constructor for a class with
// embedded uplevel references, add extra arguments.
if (r.isClientOuterField()) {
// the extra arguments are inserted after this one
args[i++].codeValue(env, ctx, asm);
}
r.codeArguments(env, ctx, asm, where, field);
}
}
} else {
right.codeValue(env, ctx, asm);
/*****
if (right.op == FIELD &&
((FieldExpression)right).id == idSuper) {
// '<class>.super.<method>(...)'
isSuper = true;
}
*****/
}
for ( ; i < args.length ; i++) {
args[i].codeValue(env, ctx, asm);
}
if (field.isStatic()) {
asm.add(where, opc_invokestatic, field);
} else if (field.isConstructor() || field.isPrivate() || isSuper) {
asm.add(where, opc_invokespecial, field);
} else if (field.getClassDefinition().isInterface()) {
asm.add(where, opc_invokeinterface, field);
} else {
asm.add(where, opc_invokevirtual, field);
}
if (right != null && right.op == SUPER && idInit.equals(id)) {
// 'super(...)' or '<expr>.super(...)'
ClassDefinition refc = ctx.field.getClassDefinition();
UplevelReference r = refc.getReferencesFrozen();
if (r != null) {
// After calling a superclass constructor in a class with
// embedded uplevel references, initialize uplevel fields.
r.codeInitialization(env, ctx, asm, where, field);
}
}
}
/**
* Check if the first thing is a constructor invocation
*/
public Expression firstConstructor() {
return id.equals(idInit) ? this : null;
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op]);
if (right != null) {
out.print(" ");
right.print(out);
}
out.print(" " + ((id == null) ? idInit : id));
for (int i = 0 ; i < args.length ; i++) {
out.print(" ");
if (args[i] != null) {
args[i].print(out);
} else {
out.print("<null>");
}
}
out.print(")");
if (implementation != null) {
out.print("/IMPL=");
implementation.print(out);
}
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class MultiplyExpression extends BinaryArithmeticExpression {
/**
* constructor
*/
public MultiplyExpression(long where, Expression left, Expression right) {
super(MUL, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a * b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a * b);
}
Expression eval(float a, float b) {
return new FloatExpression(where, a * b);
}
Expression eval(double a, double b) {
return new DoubleExpression(where, a * b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.equals(1)) {
return right;
}
if (right.equals(1)) {
return left;
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_imul + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NaryExpression extends UnaryExpression {
Expression args[];
/**
* Constructor
*/
NaryExpression(int op, long where, Type type, Expression right, Expression args[]) {
super(op, where, type, right);
this.args = args;
}
/**
* Create a copy of the expression for method inlining
*/
public Expression copyInline(Context ctx) {
NaryExpression e = (NaryExpression)clone();
if (right != null) {
e.right = right.copyInline(ctx);
}
e.args = new Expression[args.length];
for (int i = 0 ; i < args.length ; i++) {
if (args[i] != null) {
e.args[i] = args[i].copyInline(ctx);
}
}
return e;
}
/**
* The cost of inlining this expression
*/
public int costInline(int thresh, Environment env, Context ctx) {
int cost = 3;
if (right != null)
cost += right.costInline(thresh, env, ctx);
for (int i = 0 ; (i < args.length) && (cost < thresh) ; i++) {
if (args[i] != null) {
cost += args[i].costInline(thresh, env, ctx);
}
}
return cost;
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("(" + opNames[op] + "#" + hashCode());
if (right != null) {
out.print(" ");
right.print(out);
}
for (int i = 0 ; i < args.length ; i++) {
out.print(" ");
if (args[i] != null) {
args[i].print(out);
} else {
out.print("<null>");
}
}
out.print(")");
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NegativeExpression extends UnaryExpression {
/**
* Constructor
*/
public NegativeExpression(long where, Expression right) {
super(NEG, where, right.type, right);
}
/**
* Select the type of the expression
*/
void selectType(Environment env, Context ctx, int tm) {
if ((tm & TM_DOUBLE) != 0) {
type = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
type = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else {
type = Type.tInt;
}
right = convert(env, ctx, type, right);
}
/**
* Evaluate
*/
Expression eval(int a) {
return new IntExpression(where, -a);
}
Expression eval(long a) {
return new LongExpression(where, -a);
}
Expression eval(float a) {
return new FloatExpression(where, -a);
}
Expression eval(double a) {
return new DoubleExpression(where, -a);
}
/**
* Simplify
*/
Expression simplify() {
if (right.op == NEG) {
return ((NegativeExpression)right).right;
}
return this;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
right.codeValue(env, ctx, asm);
asm.add(where, opc_ineg + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.ArrayData;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NewArrayExpression extends NaryExpression {
Expression init;
/**
* Constructor
*/
public NewArrayExpression(long where, Expression right, Expression args[]) {
super(NEWARRAY, where, Type.tError, right, args);
}
public NewArrayExpression(long where, Expression right, Expression args[], Expression init) {
this(where, right, args);
this.init = init;
}
/**
* Check
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
type = right.toType(env, ctx);
boolean flag = (init != null); // flag says that dims are forbidden
for (int i = 0 ; i < args.length ; i++) {
Expression dim = args[i];
if (dim == null) {
if (i == 0 && !flag) {
env.error(where, "array.dim.missing");
}
flag = true;
} else {
if (flag) {
env.error(dim.where, "invalid.array.dim");
}
vset = dim.checkValue(env, ctx, vset, exp);
args[i] = convert(env, ctx, Type.tInt, dim);
}
type = Type.tArray(type);
}
if (init != null) {
vset = init.checkInitializer(env, ctx, vset, type, exp);
init = convert(env, ctx, type, init);
}
return vset;
}
public Expression copyInline(Context ctx) {
NewArrayExpression e = (NewArrayExpression)super.copyInline(ctx);
if (init != null) {
e.init = init.copyInline(ctx);
}
return e;
}
/**
* Inline
*/
public Expression inline(Environment env, Context ctx) {
Expression e = null;
for (int i = 0 ; i < args.length ; i++) {
if (args[i] != null) {
e = (e != null) ? new CommaExpression(where, e, args[i]) : args[i];
}
}
if (init != null)
e = (e != null) ? new CommaExpression(where, e, init) : init;
return (e != null) ? e.inline(env, ctx) : null;
}
public Expression inlineValue(Environment env, Context ctx) {
if (init != null)
return init.inlineValue(env, ctx); // args are all null
for (int i = 0 ; i < args.length ; i++) {
if (args[i] != null) {
args[i] = args[i].inlineValue(env, ctx);
}
}
return this;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
int t = 0;
for (int i = 0 ; i < args.length ; i++) {
if (args[i] != null) {
args[i].codeValue(env, ctx, asm);
t++;
}
}
if (args.length > 1) {
asm.add(where, opc_multianewarray, new ArrayData(type, t));
return;
}
switch (type.getElementType().getTypeCode()) {
case TC_BOOLEAN:
asm.add(where, opc_newarray, new Integer(T_BOOLEAN)); break;
case TC_BYTE:
asm.add(where, opc_newarray, new Integer(T_BYTE)); break;
case TC_SHORT:
asm.add(where, opc_newarray, new Integer(T_SHORT)); break;
case TC_CHAR:
asm.add(where, opc_newarray, new Integer(T_CHAR)); break;
case TC_INT:
asm.add(where, opc_newarray, new Integer(T_INT)); break;
case TC_LONG:
asm.add(where, opc_newarray, new Integer(T_LONG)); break;
case TC_FLOAT:
asm.add(where, opc_newarray, new Integer(T_FLOAT)); break;
case TC_DOUBLE:
asm.add(where, opc_newarray, new Integer(T_DOUBLE)); break;
case TC_ARRAY:
asm.add(where, opc_anewarray, type.getElementType()); break;
case TC_CLASS:
asm.add(where, opc_anewarray,
env.getClassDeclaration(type.getElementType()));
break;
default:
throw new CompilerError("codeValue");
}
}
}

View File

@@ -0,0 +1,545 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NewInstanceExpression extends NaryExpression {
MemberDefinition field;
Expression outerArg;
ClassDefinition body;
// Access method for constructor, if needed.
MemberDefinition implMethod = null;
/**
* Constructor
*/
public NewInstanceExpression(long where, Expression right, Expression args[]) {
super(NEWINSTANCE, where, Type.tError, right, args);
}
public NewInstanceExpression(long where, Expression right,
Expression args[],
Expression outerArg, ClassDefinition body) {
this(where, right, args);
this.outerArg = outerArg;
this.body = body;
}
/**
* From the "new" in an expression of the form outer.new InnerCls(...),
* return the "outer" expression, or null if there is none.
*/
public Expression getOuterArg() {
return outerArg;
}
int precedence() {
return 100;
}
public Expression order() {
// act like a method or field reference expression:
if (outerArg != null && opPrecedence[FIELD] > outerArg.precedence()) {
UnaryExpression e = (UnaryExpression)outerArg;
outerArg = e.right;
e.right = order();
return e;
}
return this;
}
/**
* Check expression type
*/
public Vset checkValue(Environment env, Context ctx, Vset vset, Hashtable exp) {
// What type?
ClassDefinition def = null;
Expression alreadyChecked = null;
try {
if (outerArg != null) {
vset = outerArg.checkValue(env, ctx, vset, exp);
// Remember the expression that we already checked
// so that we don't attempt to check it again when
// it appears as an argument to the constructor.
// Fix for 4030426.
alreadyChecked = outerArg;
// Check outerArg and the type name together.
Identifier typeName = FieldExpression.toIdentifier(right);
// According to the inner classes spec, the type name in a
// qualified 'new' expression must be a single identifier.
if (typeName != null && typeName.isQualified()) {
env.error(where, "unqualified.name.required", typeName);
}
if (typeName == null || !outerArg.type.isType(TC_CLASS)) {
if (!outerArg.type.isType(TC_ERROR)) {
env.error(where, "invalid.field.reference",
idNew, outerArg.type);
}
outerArg = null;
} else {
// Don't perform checks on components of qualified name
// ('getQualifiedClassDefinition'), because a qualified
// name is illegal in this context, and will have previously
// been reported as an error.
ClassDefinition oc = env.getClassDefinition(outerArg.type);
Identifier nm = oc.resolveInnerClass(env, typeName);
right = new TypeExpression(right.where, Type.tClass(nm));
// Check access directly, since we're not calling toType().
env.resolve(right.where, ctx.field.getClassDefinition(),
right.type);
// and fall through to env.getClassDefinition() below
}
}
if (!(right instanceof TypeExpression)) {
// The call to 'toType' should perform component access checks.
right = new TypeExpression(right.where, right.toType(env, ctx));
}
if (right.type.isType(TC_CLASS))
def = env.getClassDefinition(right.type);
} catch (AmbiguousClass ee) {
env.error(where, "ambig.class", ee.name1, ee.name2);
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, ctx.field);
}
Type t = right.type;
boolean hasErrors = t.isType(TC_ERROR);
if (!t.isType(TC_CLASS)) {
if (!hasErrors) {
env.error(where, "invalid.arg.type", t, opNames[op]);
hasErrors = true;
}
}
// If we failed to find a class or a class was ambiguous, def
// may be null. Bail out. This allows us to report multiple
// unfound or ambiguous classes rather than tripping over an
// internal compiler error.
if (def == null) {
type = Type.tError;
return vset;
}
// Add an extra argument, maybe.
Expression args[] = this.args;
args = NewInstanceExpression.
insertOuterLink(env, ctx, where, def, outerArg, args);
if (args.length > this.args.length)
outerArg = args[0]; // recopy the checked arg
else if (outerArg != null)
// else set it to void (maybe it has a side-effect)
outerArg = new CommaExpression(outerArg.where, outerArg, null);
// Compose a list of argument types
Type argTypes[] = new Type[args.length];
for (int i = 0 ; i < args.length ; i++) {
// Don't check 'outerArg' again. Fix for 4030426.
if (args[i] != alreadyChecked) {
vset = args[i].checkValue(env, ctx, vset, exp);
}
argTypes[i] = args[i].type;
hasErrors = hasErrors || argTypes[i].isType(TC_ERROR);
}
try {
// Check if there are any type errors in the arguments
if (hasErrors) {
type = Type.tError;
return vset;
}
// Get the source class that this declaration appears in.
ClassDefinition sourceClass = ctx.field.getClassDefinition();
ClassDeclaration c = env.getClassDeclaration(t);
// If this is an anonymous class, handle it specially now.
if (body != null) {
// The current package.
Identifier packageName = sourceClass.getName().getQualifier();
// This is an anonymous class.
ClassDefinition superDef = null;
if (def.isInterface()) {
// For interfaces, our superclass is java.lang.Object.
// We could just assume that java.lang.Object has
// one constructor with no arguments in the code
// that follows, but we don't. This way, if Object
// grows a new constructor (unlikely) then the
// compiler should handle it.
superDef = env.getClassDefinition(idJavaLangObject);
} else {
// Otherwise, def is actually our superclass.
superDef = def;
}
// Try to find a matching constructor in our superclass.
MemberDefinition constructor =
superDef.matchAnonConstructor(env, packageName, argTypes);
if (constructor != null) {
// We've found one. Process the body.
//
// Note that we are passing in the constructors' argument
// types, rather than the argument types of the actual
// expressions, to checkLocalClass(). Previously,
// the expression types were passed in. This could
// lead to trouble when one of the argument types was
// the special internal type tNull. (bug 4054689).
if (tracing)
env.dtEvent(
"NewInstanceExpression.checkValue: ANON CLASS " +
body + " SUPER " + def);
vset = body.checkLocalClass(env, ctx, vset,
def, args,
constructor.getType()
.getArgumentTypes());
// Set t to be the true type of this expression.
// (bug 4102056).
t = body.getClassDeclaration().getType();
def = body;
}
} else {
// Check if it is an interface
if (def.isInterface()) {
env.error(where, "new.intf", c);
return vset;
}
// Check for abstract class
if (def.mustBeAbstract(env)) {
env.error(where, "new.abstract", c);
return vset;
}
}
// Get the constructor that the "new" expression should call.
field = def.matchMethod(env, sourceClass, idInit, argTypes);
// Report an error if there is no matching constructor.
if (field == null) {
MemberDefinition anyInit = def.findAnyMethod(env, idInit);
if (anyInit != null &&
new MethodExpression(where, right, anyInit, args)
.diagnoseMismatch(env, args, argTypes))
return vset;
String sig = c.getName().getName().toString();
sig = Type.tMethod(Type.tError, argTypes).typeString(sig, false, false);
env.error(where, "unmatched.constr", sig, c);
return vset;
}
if (field.isPrivate()) {
ClassDefinition cdef = field.getClassDefinition();
if (cdef != sourceClass) {
// Use access method.
implMethod = cdef.getAccessMember(env, ctx, field, false);
}
}
// Check for abstract anonymous class
if (def.mustBeAbstract(env)) {
env.error(where, "new.abstract", c);
return vset;
}
if (field.reportDeprecated(env)) {
env.error(where, "warn.constr.is.deprecated",
field, field.getClassDefinition());
}
// According to JLS 6.6.2, a protected constructor may be accessed
// by a class instance creation expression only from within the
// package in which it is defined.
if (field.isProtected() &&
!(sourceClass.getName().getQualifier().equals(
field.getClassDeclaration().getName().getQualifier()))) {
env.error(where, "invalid.protected.constructor.use",
sourceClass);
}
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, opNames[op]);
return vset;
} catch (AmbiguousMember ee) {
env.error(where, "ambig.constr", ee.field1, ee.field2);
return vset;
}
// Cast arguments
argTypes = field.getType().getArgumentTypes();
for (int i = 0 ; i < args.length ; i++) {
args[i] = convert(env, ctx, argTypes[i], args[i]);
}
if (args.length > this.args.length) {
outerArg = args[0]; // recopy the checked arg
// maintain an accurate tree
for (int i = 1 ; i < args.length ; i++) {
this.args[i-1] = args[i];
}
}
// Throw the declared exceptions.
ClassDeclaration exceptions[] = field.getExceptions(env);
for (int i = 0 ; i < exceptions.length ; i++) {
if (exp.get(exceptions[i]) == null) {
exp.put(exceptions[i], this);
}
}
type = t;
return vset;
}
/**
* Given a list of arguments for a constructor,
* return a possibly modified list which includes the hidden
* argument which initializes the uplevel self pointer.
* @arg def the class which perhaps contains an outer link.
* @arg outerArg if non-null, an explicit location in which to construct.
*/
public static Expression[] insertOuterLink(Environment env, Context ctx,
long where, ClassDefinition def,
Expression outerArg,
Expression args[]) {
if (!def.isTopLevel() && !def.isLocal()) {
Expression args2[] = new Expression[1+args.length];
System.arraycopy(args, 0, args2, 1, args.length);
try {
if (outerArg == null)
outerArg = ctx.findOuterLink(env, where,
def.findAnyMethod(env, idInit));
} catch (ClassNotFound e) {
// die somewhere else
}
args2[0] = outerArg;
args = args2;
}
return args;
}
/**
* Check void expression
*/
public Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
return checkValue(env, ctx, vset, exp);
}
/**
* Inline
*/
final int MAXINLINECOST = Statement.MAXINLINECOST;
public Expression copyInline(Context ctx) {
NewInstanceExpression e = (NewInstanceExpression)super.copyInline(ctx);
if (outerArg != null) {
e.outerArg = outerArg.copyInline(ctx);
}
return e;
}
Expression inlineNewInstance(Environment env, Context ctx, Statement s) {
if (env.dump()) {
System.out.println("INLINE NEW INSTANCE " + field + " in " + ctx.field);
}
LocalMember v[] = LocalMember.copyArguments(ctx, field);
Statement body[] = new Statement[v.length + 2];
int o = 1;
if (outerArg != null && !outerArg.type.isType(TC_VOID)) {
o = 2;
body[1] = new VarDeclarationStatement(where, v[1], outerArg);
} else if (outerArg != null) {
body[0] = new ExpressionStatement(where, outerArg);
}
for (int i = 0 ; i < args.length ; i++) {
body[i+o] = new VarDeclarationStatement(where, v[i+o], args[i]);
}
//System.out.print("BEFORE:"); s.print(System.out); System.out.println();
body[body.length - 1] = (s != null) ? s.copyInline(ctx, false) : null;
//System.out.print("COPY:"); body[body.length - 1].print(System.out); System.out.println();
//System.out.print("AFTER:"); s.print(System.out); System.out.println();
LocalMember.doneWithArguments(ctx, v);
return new InlineNewInstanceExpression(where, type, field, new CompoundStatement(where, body)).inline(env, ctx);
}
public Expression inline(Environment env, Context ctx) {
return inlineValue(env, ctx);
}
public Expression inlineValue(Environment env, Context ctx) {
if (body != null) {
body.inlineLocalClass(env);
}
ClassDefinition refc = field.getClassDefinition();
UplevelReference r = refc.getReferencesFrozen();
if (r != null) {
r.willCodeArguments(env, ctx);
}
//right = right.inlineValue(env, ctx);
try {
if (outerArg != null) {
if (outerArg.type.isType(TC_VOID))
outerArg = outerArg.inline(env, ctx);
else
outerArg = outerArg.inlineValue(env, ctx);
}
for (int i = 0 ; i < args.length ; i++) {
args[i] = args[i].inlineValue(env, ctx);
}
// This 'false' that fy put in is inexplicable to me
// the decision to not inline new instance expressions
// should be revisited. - dps
if (false && env.opt() && field.isInlineable(env, false) &&
(!ctx.field.isInitializer()) && ctx.field.isMethod() &&
(ctx.getInlineMemberContext(field) == null)) {
Statement s = (Statement)field.getValue(env);
if ((s == null)
|| (s.costInline(MAXINLINECOST, env, ctx) < MAXINLINECOST)) {
return inlineNewInstance(env, ctx, s);
}
}
} catch (ClassNotFound e) {
throw new CompilerError(e);
}
if (outerArg != null && outerArg.type.isType(TC_VOID)) {
Expression e = outerArg;
outerArg = null;
return new CommaExpression(where, e, this);
}
return this;
}
public int costInline(int thresh, Environment env, Context ctx) {
if (body != null) {
return thresh; // don't copy classes...
}
if (ctx == null) {
return 2 + super.costInline(thresh, env, ctx);
}
// sourceClass is the current class trying to inline this method
ClassDefinition sourceClass = ctx.field.getClassDefinition();
try {
// We only allow the inlining if the current class can access
// the field and the field's class;
if ( sourceClass.permitInlinedAccess(env, field.getClassDeclaration())
&& sourceClass.permitInlinedAccess(env, field)) {
return 2 + super.costInline(thresh, env, ctx);
}
} catch (ClassNotFound e) {
}
return thresh;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
codeCommon(env, ctx, asm, false);
}
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeCommon(env, ctx, asm, true);
}
private void codeCommon(Environment env, Context ctx, Assembler asm,
boolean forValue) {
asm.add(where, opc_new, field.getClassDeclaration());
if (forValue) {
asm.add(where, opc_dup);
}
ClassDefinition refc = field.getClassDefinition();
UplevelReference r = refc.getReferencesFrozen();
if (r != null) {
r.codeArguments(env, ctx, asm, where, field);
}
if (outerArg != null) {
outerArg.codeValue(env, ctx, asm);
switch (outerArg.op) {
case THIS:
case SUPER:
case NEW:
// guaranteed non-null
break;
case FIELD: {
MemberDefinition f = ((FieldExpression)outerArg).field;
if (f != null && f.isNeverNull()) {
break;
}
// else fall through:
}
default:
// Test for nullity by invoking some trivial operation
// that can throw a NullPointerException.
try {
ClassDefinition c = env.getClassDefinition(idJavaLangObject);
MemberDefinition getc = c.getFirstMatch(idGetClass);
asm.add(where, opc_dup);
asm.add(where, opc_invokevirtual, getc);
asm.add(where, opc_pop);
} catch (ClassNotFound e) {
}
}
}
if (implMethod != null) {
// Constructor call will be via an access method.
// Pass 'null' as the value of the dummy argument.
asm.add(where, opc_aconst_null);
}
for (int i = 0 ; i < args.length ; i++) {
args[i].codeValue(env, ctx, asm);
}
asm.add(where, opc_invokespecial,
((implMethod != null) ? implMethod : field));
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 1994, 2013, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
import java.io.ByteArrayOutputStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class Node implements Constants, Cloneable {
int op;
long where;
/**
* Constructor
*/
Node(int op, long where) {
this.op = op;
this.where = where;
}
/**
* Get the operator
*/
public int getOp() {
return op;
}
/**
* Get where
*/
public long getWhere() {
return where;
}
/**
* Implicit conversions
*/
public Expression convert(Environment env, Context ctx, Type t, Expression e) {
if (e.type.isType(TC_ERROR) || t.isType(TC_ERROR)) {
// An error was already reported
return e;
}
if (e.type.equals(t)) {
// The types are already the same
return e;
}
try {
if (e.fitsType(env, ctx, t)) {
return new ConvertExpression(where, t, e);
}
if (env.explicitCast(e.type, t)) {
env.error(where, "explicit.cast.needed", opNames[op], e.type, t);
return new ConvertExpression(where, t, e);
}
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, opNames[op]);
}
// The cast is not allowed
env.error(where, "incompatible.type", opNames[op], e.type, t);
return new ConvertExpression(where, Type.tError, e);
}
/**
* Print
*/
public void print(PrintStream out) {
throw new CompilerError("print");
}
/**
* Clone this object.
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw (InternalError) new InternalError().initCause(e);
}
}
/*
* Useful for simple debugging
*/
public String toString() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
print(new PrintStream(bos));
return bos.toString();
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NotEqualExpression extends BinaryEqualityExpression {
/**
* constructor
*/
public NotEqualExpression(long where, Expression left, Expression right) {
super(NE, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new BooleanExpression(where, a != b);
}
Expression eval(long a, long b) {
return new BooleanExpression(where, a != b);
}
Expression eval(float a, float b) {
return new BooleanExpression(where, a != b);
}
Expression eval(double a, double b) {
return new BooleanExpression(where, a != b);
}
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a != b);
}
/**
* Simplify
*/
Expression simplify() {
if (left.isConstant() && !right.isConstant()) {
return new NotEqualExpression(where, right, left);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
left.codeValue(env, ctx, asm);
switch (left.type.getTypeCode()) {
case TC_BOOLEAN:
case TC_INT:
if (!right.equals(0)) {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_icmpne : opc_if_icmpeq, lbl, whenTrue);
return;
}
break;
case TC_LONG:
right.codeValue(env, ctx, asm);
asm.add(where, opc_lcmp);
break;
case TC_FLOAT:
right.codeValue(env, ctx, asm);
asm.add(where, opc_fcmpl);
break;
case TC_DOUBLE:
right.codeValue(env, ctx, asm);
asm.add(where, opc_dcmpl);
break;
case TC_ARRAY:
case TC_CLASS:
case TC_NULL:
if (right.equals(0)) {
asm.add(where, whenTrue ? opc_ifnonnull : opc_ifnull, lbl, whenTrue);
} else {
right.codeValue(env, ctx, asm);
asm.add(where, whenTrue ? opc_if_acmpne : opc_if_acmpeq, lbl, whenTrue);
}
return;
default:
throw new CompilerError("Unexpected Type");
}
asm.add(where, whenTrue ? opc_ifne : opc_ifeq, lbl, whenTrue);
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NotExpression extends UnaryExpression {
/**
* Constructor
*/
public NotExpression(long where, Expression right) {
super(NOT, where, Type.tBoolean, right);
}
/**
* Select the type of the expression
*/
void selectType(Environment env, Context ctx, int tm) {
right = convert(env, ctx, Type.tBoolean, right);
}
/*
* Check a "not" expression.
*
* cvars is modified so that
* cvar.vsTrue indicates variables with a known value if
* the expression is true.
* cvars.vsFalse indicates variables with a known value if
* the expression is false
*
* For "not" expressions, we look at the inside expression, and then
* swap true and false.
*/
public void checkCondition(Environment env, Context ctx, Vset vset,
Hashtable exp, ConditionVars cvars) {
right.checkCondition(env, ctx, vset, exp, cvars);
right = convert(env, ctx, Type.tBoolean, right);
// swap true and false
Vset temp = cvars.vsFalse;
cvars.vsFalse = cvars.vsTrue;
cvars.vsTrue = temp;
}
/**
* Evaluate
*/
Expression eval(boolean a) {
return new BooleanExpression(where, !a);
}
/**
* Simplify
*/
Expression simplify() {
// Check if the expression can be optimized
switch (right.op) {
case NOT:
return ((NotExpression)right).right;
case EQ:
case NE:
case LT:
case LE:
case GT:
case GE:
break;
default:
return this;
}
// Can't negate real comparisons
BinaryExpression bin = (BinaryExpression)right;
if (bin.left.type.inMask(TM_REAL)) {
return this;
}
// Negate comparison
switch (right.op) {
case EQ:
return new NotEqualExpression(where, bin.left, bin.right);
case NE:
return new EqualExpression(where, bin.left, bin.right);
case LT:
return new GreaterOrEqualExpression(where, bin.left, bin.right);
case LE:
return new GreaterExpression(where, bin.left, bin.right);
case GT:
return new LessOrEqualExpression(where, bin.left, bin.right);
case GE:
return new LessExpression(where, bin.left, bin.right);
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
right.codeBranch(env, ctx, asm, lbl, !whenTrue);
}
/**
* Instead of relying on the default code generation which uses
* conditional branching, generate a simpler stream using XOR.
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
right.codeValue(env, ctx, asm);
asm.add(where, opc_ldc, new Integer(1));
asm.add(where, opc_ixor);
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class NullExpression extends ConstantExpression {
/**
* Constructor
*/
public NullExpression(long where) {
super(NULL, where, Type.tNull);
}
/**
* Check if the expression is equal to a value
*/
public boolean equals(int i) {
return i == 0;
}
public boolean isNull() {
return true;
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_aconst_null);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("null");
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class OrExpression extends BinaryLogicalExpression {
/**
* constructor
*/
public OrExpression(long where, Expression left, Expression right) {
super(OR, where, left, right);
}
/*
* Check an "or" expression.
*
* cvars is modified so that
* cvar.vsTrue indicates variables with a known value if
* either the left and right hand side isn true
* cvars.vsFalse indicates variables with a known value if
* both the left or right hand side are false
*/
public void checkCondition(Environment env, Context ctx, Vset vset,
Hashtable exp, ConditionVars cvars) {
// Find out when the left side is true/false
left.checkCondition(env, ctx, vset, exp, cvars);
left = convert(env, ctx, Type.tBoolean, left);
Vset vsTrue = cvars.vsTrue.copy();
Vset vsFalse = cvars.vsFalse.copy();
// Only look at the right side if the left side is false
right.checkCondition(env, ctx, vsFalse, exp, cvars);
right = convert(env, ctx, Type.tBoolean, right);
// cvars.vsFalse actually reports that both returned false
// cvars.vsTrue must be set back to either left side or the right
// side returning false;
cvars.vsTrue = cvars.vsTrue.join(vsTrue);
}
/**
* Evaluate
*/
Expression eval(boolean a, boolean b) {
return new BooleanExpression(where, a || b);
}
/**
* Simplify
*/
Expression simplify() {
if (right.equals(false)) {
return left;
}
if (left.equals(true)) {
return left;
}
if (left.equals(false)) {
return right;
}
if (right.equals(true)) {
// Preserve effects of left argument.
return new CommaExpression(where, left, right).simplify();
}
return this;
}
/**
* Code
*/
void codeBranch(Environment env, Context ctx, Assembler asm, Label lbl, boolean whenTrue) {
if (whenTrue) {
left.codeBranch(env, ctx, asm, lbl, true);
right.codeBranch(env, ctx, asm, lbl, true);
} else {
Label lbl2 = new Label();
left.codeBranch(env, ctx, asm, lbl2, true);
right.codeBranch(env, ctx, asm, lbl, false);
asm.add(lbl2);
}
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class PositiveExpression extends UnaryExpression {
/**
* Constructor
*/
public PositiveExpression(long where, Expression right) {
super(POS, where, right.type, right);
}
/**
* Select the type of the expression
*/
void selectType(Environment env, Context ctx, int tm) {
if ((tm & TM_DOUBLE) != 0) {
type = Type.tDouble;
} else if ((tm & TM_FLOAT) != 0) {
type = Type.tFloat;
} else if ((tm & TM_LONG) != 0) {
type = Type.tLong;
} else {
type = Type.tInt;
}
right = convert(env, ctx, type, right);
}
/**
* Simplify
*/
Expression simplify() {
return right;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class PostDecExpression extends IncDecExpression {
/**
* Constructor
*/
public PostDecExpression(long where, Expression right) {
super(POSTDEC, where, right);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, false, false, true);
}
public void code(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, false, false, false);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class PostIncExpression extends IncDecExpression {
/**
* Constructor
*/
public PostIncExpression(long where, Expression right) {
super(POSTINC, where, right);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, true, false, true);
}
public void code(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, true, false, false);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class PreDecExpression extends IncDecExpression {
/**
* Constructor
*/
public PreDecExpression(long where, Expression right) {
super(PREDEC, where, right);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, false, true, true);
}
public void code(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, false, true, false);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class PreIncExpression extends IncDecExpression {
/**
* Constructor
*/
public PreIncExpression(long where, Expression right) {
super(PREINC, where, right);
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, true, true, true);
}
public void code(Environment env, Context ctx, Assembler asm) {
codeIncDec(env, ctx, asm, true, true, false);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class RemainderExpression extends DivRemExpression {
/**
* constructor
*/
public RemainderExpression(long where, Expression left, Expression right) {
super(REM, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a % b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a % b);
}
Expression eval(float a, float b) {
return new FloatExpression(where, a % b);
}
Expression eval(double a, double b) {
return new DoubleExpression(where, a % b);
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_irem + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,181 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ReturnStatement extends Statement {
Expression expr;
/**
* Constructor
*/
public ReturnStatement(long where, Expression expr) {
super(RETURN, where);
this.expr = expr;
}
/**
* Check statement
*/
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
checkLabel(env, ctx);
vset = reach(env, vset);
if (expr != null) {
vset = expr.checkValue(env, ctx, vset, exp);
}
// Make sure the return isn't inside a static initializer
if (ctx.field.isInitializer()) {
env.error(where, "return.inside.static.initializer");
return DEAD_END;
}
// Check return type
if (ctx.field.getType().getReturnType().isType(TC_VOID)) {
if (expr != null) {
if (ctx.field.isConstructor()) {
env.error(where, "return.with.value.constr", ctx.field);
} else {
env.error(where, "return.with.value", ctx.field);
}
expr = null;
}
} else {
if (expr == null) {
env.error(where, "return.without.value", ctx.field);
} else {
expr = convert(env, ctx, ctx.field.getType().getReturnType(), expr);
}
}
CheckContext mctx = ctx.getReturnContext();
if (mctx != null) {
mctx.vsBreak = mctx.vsBreak.join(vset);
}
CheckContext exitctx = ctx.getTryExitContext();
if (exitctx != null) {
exitctx.vsTryExit = exitctx.vsTryExit.join(vset);
}
if (expr != null) {
// see if we are returning a value out of a try or synchronized
// statement. If so, find the outermost one. . . .
Node outerFinallyNode = null;
for (Context c = ctx; c != null; c = c.prev) {
if (c.node == null) {
continue;
}
if (c.node.op == METHOD) {
// Don't search outside current method. Fixes 4084230.
break;
}
if (c.node.op == SYNCHRONIZED) {
outerFinallyNode = c.node;
break;
} else if (c.node.op == FINALLY
&& ((CheckContext)c).vsContinue != null) {
outerFinallyNode = c.node;
}
}
if (outerFinallyNode != null) {
if (outerFinallyNode.op == FINALLY) {
((FinallyStatement)outerFinallyNode).needReturnSlot = true;
} else {
((SynchronizedStatement)outerFinallyNode).needReturnSlot = true;
}
}
}
return DEAD_END;
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
if (expr != null) {
expr = expr.inlineValue(env, ctx);
}
return this;
}
/**
* The cost of inlining this statement
*/
public int costInline(int thresh, Environment env, Context ctx) {
return 1 + ((expr != null) ? expr.costInline(thresh, env, ctx) : 0);
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
Expression e = (expr != null) ? expr.copyInline(ctx) : null;
if ((!valNeeded) && (e != null)) {
Statement body[] = {
new ExpressionStatement(where, e),
new InlineReturnStatement(where, null)
};
return new CompoundStatement(where, body);
}
return new InlineReturnStatement(where, e);
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
if (expr == null) {
codeFinally(env, ctx, asm, null, null);
asm.add(where, opc_return);
} else {
expr.codeValue(env, ctx, asm);
codeFinally(env, ctx, asm, null, expr.type);
asm.add(where, opc_ireturn + expr.type.getTypeCodeOffset());
}
}
/**
* Print
*/
public void print(PrintStream out, int indent) {
super.print(out, indent);
out.print("return");
if (expr != null) {
out.print(" ");
expr.print(out);
}
out.print(";");
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ShiftLeftExpression extends BinaryShiftExpression {
/**
* constructor
*/
public ShiftLeftExpression(long where, Expression left, Expression right) {
super(LSHIFT, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a << b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a << b);
}
/**
* Simplify
*/
Expression simplify() {
if (right.equals(0)) {
return left;
}
if (left.equals(0)) {
return new CommaExpression(where, right, left).simplify();
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ishl + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ShiftRightExpression extends BinaryShiftExpression {
/**
* constructor
*/
public ShiftRightExpression(long where, Expression left, Expression right) {
super(RSHIFT, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a >> b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a >> b);
}
/**
* Simplify
*/
Expression simplify() {
if (right.equals(0)) {
return left;
}
if (left.equals(0)) {
return new CommaExpression(where, right, left).simplify();
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ishr + type.getTypeCodeOffset());
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class ShortExpression extends IntegerExpression {
/**
* Constructor
*/
public ShortExpression(long where, short value) {
super(SHORTVAL, where, Type.tShort, value);
}
/**
* Print
*/
public void print(PrintStream out) {
out.print(value + "s");
}
}

View File

@@ -0,0 +1,342 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import sun.tools.asm.Label;
import java.io.PrintStream;
import java.util.Hashtable;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class Statement extends Node {
public static final Vset DEAD_END = Vset.DEAD_END;
Identifier labels[] = null;
/**
* Constructor
*/
Statement(int op, long where) {
super(op, where);
}
/**
* An empty statement. Its costInline is infinite.
*/
public static final Statement empty = new Statement(STAT, 0);
/**
* The largest possible interesting inline cost value.
*/
public static final int MAXINLINECOST =
Integer.getInteger("javac.maxinlinecost",
30).intValue();
/**
* Insert a bit of code at the front of a statement.
* Side-effect s2, if it is a CompoundStatement.
*/
public static Statement insertStatement(Statement s1, Statement s2) {
if (s2 == null) {
s2 = s1;
} else if (s2 instanceof CompoundStatement) {
// Do not add another level of block nesting.
((CompoundStatement)s2).insertStatement(s1);
} else {
Statement body[] = { s1, s2 };
s2 = new CompoundStatement(s1.getWhere(), body);
}
return s2;
}
/**
* Set the label of a statement
*/
public void setLabel(Environment env, Expression e) {
if (e.op == IDENT) {
if (labels == null) {
labels = new Identifier[1];
} else {
// this should almost never happen. Multiple labels on
// the same statement. But handle it gracefully.
Identifier newLabels[] = new Identifier[labels.length + 1];
System.arraycopy(labels, 0, newLabels, 1, labels.length);
labels = newLabels;
}
labels[0] = ((IdentifierExpression)e).id;
} else {
env.error(e.where, "invalid.label");
}
}
/**
* Check a statement
*/
public Vset checkMethod(Environment env, Context ctx, Vset vset, Hashtable exp) {
// Set up ctx.getReturnContext() for the sake of ReturnStatement.check().
CheckContext mctx = new CheckContext(ctx, new Statement(METHOD, 0));
ctx = mctx;
vset = check(env, ctx, vset, exp);
// Check for return
if (!ctx.field.getType().getReturnType().isType(TC_VOID)) {
// In general, we suppress further error messages due to
// unreachable statements after reporting the first error
// along a flow path (using 'clearDeadEnd'). Here, we
// report an error anyway, because the end of the method
// should be unreachable despite the earlier error. The
// difference in treatment is due to the fact that, in this
// case, the error is reachability, not unreachability.
// NOTE: In addition to this subtle difference in the quality
// of the error diagnostics, this treatment is essential to
// preserve the correctness of using 'clearDeadEnd' to implement
// the special-case reachability rules for if-then and if-then-else.
if (!vset.isDeadEnd()) {
env.error(ctx.field.getWhere(), "return.required.at.end", ctx.field);
}
}
// Simulate a return at the end.
vset = vset.join(mctx.vsBreak);
return vset;
}
Vset checkDeclaration(Environment env, Context ctx, Vset vset, int mod, Type t, Hashtable exp) {
throw new CompilerError("checkDeclaration");
}
/**
* Make sure the labels on this statement do not duplicate the
* labels on any enclosing statement. Provided as a convenience
* for subclasses.
*/
protected void checkLabel(Environment env, Context ctx) {
if (labels != null) {
loop: for (int i = 0; i < labels.length; i++) {
// Make sure there is not a double label on this statement.
for (int j = i+1; j < labels.length; j++) {
if (labels[i] == labels[j]) {
env.error(where, "nested.duplicate.label", labels[i]);
continue loop;
}
}
// Make sure no enclosing statement has the same label.
CheckContext destCtx =
(CheckContext) ctx.getLabelContext(labels[i]);
if (destCtx != null) {
// Check to make sure the label is in not uplevel.
if (destCtx.frameNumber == ctx.frameNumber) {
env.error(where, "nested.duplicate.label", labels[i]);
}
}
} // end loop
}
}
Vset check(Environment env, Context ctx, Vset vset, Hashtable exp) {
throw new CompilerError("check");
}
/** This is called in contexts where declarations are valid. */
Vset checkBlockStatement(Environment env, Context ctx, Vset vset, Hashtable exp) {
return check(env, ctx, vset, exp);
}
Vset reach(Environment env, Vset vset) {
if (vset.isDeadEnd()) {
env.error(where, "stat.not.reached");
vset = vset.clearDeadEnd();
}
return vset;
}
/**
* Inline
*/
public Statement inline(Environment env, Context ctx) {
return this;
}
/**
* Eliminate this statement, which is only possible if it has no label.
*/
public Statement eliminate(Environment env, Statement s) {
if ((s != null) && (labels != null)) {
Statement args[] = {s};
s = new CompoundStatement(where, args);
s.labels = labels;
}
return s;
}
/**
* Code
*/
public void code(Environment env, Context ctx, Assembler asm) {
throw new CompilerError("code");
}
/**
* Generate the code to call all finally's for a break, continue, or
* return statement. We must call "jsr" on all the cleanup code between
* the current context "ctx", and the destination context "stopctx".
* If 'save' isn't null, there is also a value on the top of the stack
*/
void codeFinally(Environment env, Context ctx, Assembler asm,
Context stopctx, Type save) {
Integer num = null;
boolean haveCleanup = false; // there is a finally or synchronize;
boolean haveNonLocalFinally = false; // some finally doesn't return;
for (Context c = ctx; (c != null) && (c != stopctx); c = c.prev) {
if (c.node == null)
continue;
if (c.node.op == SYNCHRONIZED) {
haveCleanup = true;
} else if (c.node.op == FINALLY
&& ((CodeContext)c).contLabel != null) {
// c.contLabel == null indicates we're in the "finally" part
haveCleanup = true;
FinallyStatement st = ((FinallyStatement)(c.node));
if (!st.finallyCanFinish) {
haveNonLocalFinally = true;
// after hitting a non-local finally, no need generating
// further code, because it won't get executed.
break;
}
}
}
if (!haveCleanup) {
// there is no cleanup that needs to be done. Just quit.
return;
}
if (save != null) {
// This statement has a return value on the stack.
ClassDefinition def = ctx.field.getClassDefinition();
if (!haveNonLocalFinally) {
// Save the return value in the register which should have
// been reserved.
LocalMember lf = ctx.getLocalField(idFinallyReturnValue);
num = new Integer(lf.number);
asm.add(where, opc_istore + save.getTypeCodeOffset(), num);
} else {
// Pop the return value.
switch(ctx.field.getType().getReturnType().getTypeCode()) {
case TC_VOID:
break;
case TC_DOUBLE: case TC_LONG:
asm.add(where, opc_pop2); break;
default:
asm.add(where, opc_pop); break;
}
}
}
// Call each of the cleanup functions, as necessary.
for (Context c = ctx ; (c != null) && (c != stopctx) ; c = c.prev) {
if (c.node == null)
continue;
if (c.node.op == SYNCHRONIZED) {
asm.add(where, opc_jsr, ((CodeContext)c).contLabel);
} else if (c.node.op == FINALLY
&& ((CodeContext)c).contLabel != null) {
FinallyStatement st = ((FinallyStatement)(c.node));
Label label = ((CodeContext)c).contLabel;
if (st.finallyCanFinish) {
asm.add(where, opc_jsr, label);
} else {
// the code never returns, so we're done.
asm.add(where, opc_goto, label);
break;
}
}
}
// Move the return value from the register back to the stack.
if (num != null) {
asm.add(where, opc_iload + save.getTypeCodeOffset(), num);
}
}
/*
* Return true if the statement has the given label
*/
public boolean hasLabel (Identifier lbl) {
Identifier labels[] = this.labels;
if (labels != null) {
for (int i = labels.length; --i >= 0; ) {
if (labels[i].equals(lbl)) {
return true;
}
}
}
return false;
}
/**
* Check if the first thing is a constructor invocation
*/
public Expression firstConstructor() {
return null;
}
/**
* Create a copy of the statement for method inlining
*/
public Statement copyInline(Context ctx, boolean valNeeded) {
return (Statement)clone();
}
public int costInline(int thresh, Environment env, Context ctx) {
return thresh;
}
/**
* Print
*/
void printIndent(PrintStream out, int indent) {
for (int i = 0 ; i < indent ; i++) {
out.print(" ");
}
}
public void print(PrintStream out, int indent) {
if (labels != null) {
for (int i = labels.length; --i >= 0; )
out.print(labels[i] + ": ");
}
}
public void print(PrintStream out) {
print(out, 0);
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
import java.io.PrintStream;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class StringExpression extends ConstantExpression {
String value;
/**
* Constructor
*/
public StringExpression(long where, String value) {
super(STRINGVAL, where, Type.tString);
this.value = value;
}
public boolean equals(String s) {
return value.equals(s);
}
public boolean isNonNull() {
return true; // string literal is never null
}
/**
* Code
*/
public void codeValue(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_ldc, this);
}
/**
* Get the value
*/
public Object getValue() {
return value;
}
/**
* Hashcode
*/
public int hashCode() {
return value.hashCode() ^ 3213;
}
/**
* Equality
*/
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof StringExpression)) {
return value.equals(((StringExpression)obj).value);
}
return false;
}
/**
* Print
*/
public void print(PrintStream out) {
out.print("\"" + value + "\"");
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 1994, 2003, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.tree;
import sun.tools.java.*;
import sun.tools.asm.Assembler;
/**
* WARNING: The contents of this source file are not part of any
* supported API. Code that depends on them does so at its own risk:
* they are subject to change or removal without notice.
*/
public
class SubtractExpression extends BinaryArithmeticExpression {
/**
* constructor
*/
public SubtractExpression(long where, Expression left, Expression right) {
super(SUB, where, left, right);
}
/**
* Evaluate
*/
Expression eval(int a, int b) {
return new IntExpression(where, a - b);
}
Expression eval(long a, long b) {
return new LongExpression(where, a - b);
}
Expression eval(float a, float b) {
return new FloatExpression(where, a - b);
}
Expression eval(double a, double b) {
return new DoubleExpression(where, a - b);
}
/**
* Simplify
*/
Expression simplify() {
// Can't simplify floating point subtract because of -0.0 strangeness
if (type.inMask(TM_INTEGER)) {
if (left.equals(0)) {
return new NegativeExpression(where, right);
}
if (right.equals(0)) {
return left;
}
}
return this;
}
/**
* Code
*/
void codeOperation(Environment env, Context ctx, Assembler asm) {
asm.add(where, opc_isub + type.getTypeCodeOffset());
}
}

Some files were not shown because too many files have changed in this diff Show More