asmclassgenerator.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,558 行 · 第 1/5 页
JAVA
1,558 行
break;
case Types.RIGHT_SHIFT_EQUAL :
evaluateBinaryExpressionWithAsignment("rightShift", expression);
break;
case Types.RIGHT_SHIFT_UNSIGNED :
evaluateBinaryExpression("rightShiftUnsigned", expression);
break;
case Types.RIGHT_SHIFT_UNSIGNED_EQUAL :
evaluateBinaryExpressionWithAsignment("rightShiftUnsigned", expression);
break;
case Types.KEYWORD_INSTANCEOF :
evaluateInstanceof(expression);
break;
case Types.FIND_REGEX :
evaluateBinaryExpression(findRegexMethod, expression);
break;
case Types.MATCH_REGEX :
evaluateBinaryExpression(matchRegexMethod, expression);
break;
case Types.LEFT_SQUARE_BRACKET :
if (leftHandExpression) {
throwException("Should not be called here. Possible reason: postfix operation on array.");
// This is handled right now in the evaluateEqual()
// should support this here later
//evaluateBinaryExpression("putAt", expression);
} else {
evaluateBinaryExpression("getAt", expression);
}
break;
case Types.KEYWORD_IN :
evaluateBinaryExpression(isCaseMethod, expression);
break;
default :
throwException("Operation: " + expression.getOperation() + " not supported");
}
}
private void load(Expression exp) {
boolean wasLeft = leftHandExpression;
leftHandExpression = false;
// if (CREATE_DEBUG_INFO)
// helper.mark("-- loading expression: " + exp.getClass().getName() +
// " at [" + exp.getLineNumber() + ":" + exp.getColumnNumber() + "]");
//exp.visit(this);
visitAndAutoboxBoolean(exp);
// if (CREATE_DEBUG_INFO)
// helper.mark(" -- end of loading --");
leftHandExpression = wasLeft;
}
public void visitPostfixExpression(PostfixExpression expression) {
switch (expression.getOperation().getType()) {
case Types.PLUS_PLUS :
evaluatePostfixMethod("next", expression.getExpression());
break;
case Types.MINUS_MINUS :
evaluatePostfixMethod("previous", expression.getExpression());
break;
}
}
private void throwException(String s) {
throw new RuntimeParserException(s, currentASTNode);
}
public void visitPrefixExpression(PrefixExpression expression) {
switch (expression.getOperation().getType()) {
case Types.PLUS_PLUS :
evaluatePrefixMethod("next", expression.getExpression());
break;
case Types.MINUS_MINUS :
evaluatePrefixMethod("previous", expression.getExpression());
break;
}
}
public void visitClosureExpression(ClosureExpression expression) {
ClassNode innerClass = createClosureClass(expression);
addInnerClass(innerClass);
String innerClassinternalName = BytecodeHelper.getClassInternalName(innerClass);
passingClosureParams = true;
List constructors = innerClass.getDeclaredConstructors();
ConstructorNode node = (ConstructorNode) constructors.get(0);
Parameter[] localVariableParams = node.getParameters();
cv.visitTypeInsn(NEW, innerClassinternalName);
cv.visitInsn(DUP);
if (isStaticMethod() || classNode.isStaticClass()) {
visitClassExpression(new ClassExpression(classNode));
visitClassExpression(new ClassExpression(getOutermostClass()));
} else {
cv.visitVarInsn(ALOAD, 0);
loadThis();
}
// now lets load the various parameters we're passing
// we start at index 1 because the first variable we pass
// is the owner instance and at this point it is already
// on the stack
for (int i = 2; i < localVariableParams.length; i++) {
Parameter param = localVariableParams[i];
String name = param.getName();
// compileStack.containsVariable(name) means to ask if the variable is already declared
// compileStack.getScope().isReferencedClassVariable(name) means to ask if the variable is a field
// If it is no field and is not yet declared, then it is either a closure shared variable or
// an already declared variable.
if (!compileStack.containsVariable(name) && compileStack.getScope().isReferencedClassVariable(name)) {
visitFieldExpression(new FieldExpression(classNode.getField(name)));
} else {
Variable v = compileStack.getVariable(name,classNode.getSuperClass()!=ClassHelper.CLOSURE_TYPE);
if (v==null) {
// variable is not on stack because we are
// inside a nested Closure and this variable
// was not used before
// then load it from the Closure field
FieldNode field = classNode.getField(name);
cv.visitVarInsn(ALOAD, 0);
cv.visitFieldInsn(GETFIELD, internalClassName, name, BytecodeHelper.getTypeDescription(field.getType()));
// and define it
// Note:
// we can simply define it here and don't have to
// be afraid about name problems because a second
// variable with that name is not allowed inside the closure
param.setClosureSharedVariable(false);
v = compileStack.defineVariable(param,true);
param.setClosureSharedVariable(true);
v.setHolder(true);
}
cv.visitVarInsn(ALOAD, v.getIndex());
}
}
passingClosureParams = false;
// we may need to pass in some other constructors
//cv.visitMethodInsn(INVOKESPECIAL, innerClassinternalName, "<init>", prototype + ")V");
cv.visitMethodInsn(
INVOKESPECIAL,
innerClassinternalName,
"<init>",
BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, localVariableParams));
}
/**
* Loads either this object or if we're inside a closure then load the top level owner
*/
protected void loadThisOrOwner() {
if (isInnerClass()) {
visitFieldExpression(new FieldExpression(classNode.getField("owner")));
} else {
loadThis();
}
}
public void visitRegexExpression(RegexExpression expression) {
expression.getRegex().visit(this);
regexPattern.call(cv);
}
/**
* Generate byte code for constants
* @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#14152">Class field types</a>
*/
public void visitConstantExpression(ConstantExpression expression) {
Object value = expression.getValue();
helper.loadConstant(value);
}
public void visitSpreadExpression(SpreadExpression expression) {
throw new GroovyBugError("SpreadExpression should not be visited here");
}
public void visitSpreadMapExpression(SpreadMapExpression expression) {
Expression subExpression = expression.getExpression();
subExpression.visit(this);
spreadMap.call(cv);
}
public void visitMethodPointerExpression(MethodPointerExpression expression) {
Expression subExpression = expression.getExpression();
subExpression.visit(this);
helper.loadConstant(expression.getMethodName());
getMethodPointer.call(cv);
}
public void visitNegationExpression(NegationExpression expression) {
Expression subExpression = expression.getExpression();
subExpression.visit(this);
negation.call(cv);
}
public void visitBitwiseNegExpression(BitwiseNegExpression expression) {
Expression subExpression = expression.getExpression();
subExpression.visit(this);
bitNegation.call(cv);
}
public void visitCastExpression(CastExpression expression) {
ClassNode type = expression.getType();
visitAndAutoboxBoolean(expression.getExpression());
doConvertAndCast(type, expression.getExpression(), expression.isIgnoringAutoboxing(),false,expression.isCoerce());
}
public void visitNotExpression(NotExpression expression) {
Expression subExpression = expression.getExpression();
subExpression.visit(this);
// if we do !object, then the cast to boolean will
// do the conversion of Object to boolean. so a simple
// call to unbox is enough here.
if (
!isComparisonExpression(subExpression) &&
!(subExpression instanceof BooleanExpression))
{
helper.unbox(boolean.class);
}
helper.negateBoolean();
}
/**
* return a primitive boolean value of the BooleanExpresion.
* @param expression
*/
public void visitBooleanExpression(BooleanExpression expression) {
compileStack.pushBooleanExpression();
expression.getExpression().visit(this);
if (!isComparisonExpression(expression.getExpression())) {
// comment out for optimization when boolean values are not autoboxed for eg. function calls.
// Class typeClass = expression.getExpression().getTypeClass();
// if (typeClass != null && typeClass != boolean.class) {
helper.unbox(boolean.class); // to return a primitive boolean
// }
}
compileStack.pop();
}
private void makeInvokeMethodCall(MethodCallExpression call, boolean useSuper, MethodCallerMultiAdapter adapter) {
// receiver
// we operate on GroovyObject if possible
Expression objectExpression = call.getObjectExpression();
if (!isStaticMethod() && !isStaticContext() && isThisExpression(call.getObjectExpression()))
{
objectExpression = new CastExpression(ClassHelper.make(GroovyObject.class),objectExpression);
}
// message name
Expression messageName = new CastExpression(ClassHelper.STRING_TYPE,call.getMethod());
if (useSuper) {
makeCall(new ClassExpression(getOutermostClass().getSuperClass()),
objectExpression, messageName,
call.getArguments(), adapter,
call.isSafe(), call.isSpreadSafe(),
false
);
} else {
makeCall(objectExpression, messageName,
call.getArguments(), adapter,
call.isSafe(), call.isSpreadSafe(),
call.isImplicitThis()
);
}
}
private void makeCall(
Expression receiver, Expression message, Expression arguments,
MethodCallerMultiAdapter adapter,
boolean safe, boolean spreadSafe, boolean implicitThis
) {
ClassNode cn = classNode;
if (isInClosure() && !implicitThis) {
cn = getOutermostClass();
}
makeCall(new ClassExpression(cn), receiver, message, arguments,
adapter, safe, spreadSafe, implicitThis);
}
private void makeCall(
ClassExpression sender,
Expression receiver, Expression message, Expression arguments,
MethodCallerMultiAdapter adapter,
boolean safe, boolean spreadSafe, boolean implicitThis
) {
// ensure VariableArguments are read, not stored
boolean lhs = leftHandExpression;
leftHandExpression = false;
// sender
sender.visit(this);
// receiver
boolean oldVal = this.implicitThis;
this.implicitThis = implicitThis;
receiver.visit(this);
this.implicitThis = oldVal;
// message
if (message!=null) message.visit(this);
// arguments
boolean containsSpreadExpression = cont
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?