use of org.codehaus.groovy.classgen.BytecodeExpression in project groovy by apache.
the class StaticTypesCallSiteWriter method writeListDotProperty.
private void writeListDotProperty(final Expression receiver, final String methodName, final MethodVisitor mv, final boolean safe) {
ClassNode componentType = (ClassNode) receiver.getNodeMetaData(StaticCompilationMetadataKeys.COMPONENT_TYPE);
if (componentType == null) {
componentType = OBJECT_TYPE;
}
// for lists, replace list.foo with:
// def result = new ArrayList(list.size())
// for (e in list) { result.add (e.foo) }
// result
CompileStack compileStack = controller.getCompileStack();
Label exit = new Label();
if (safe) {
receiver.visit(controller.getAcg());
Label doGet = new Label();
mv.visitJumpInsn(IFNONNULL, doGet);
controller.getOperandStack().remove(1);
mv.visitInsn(ACONST_NULL);
mv.visitJumpInsn(GOTO, exit);
mv.visitLabel(doGet);
}
Variable tmpList = new VariableExpression("tmpList", make(ArrayList.class));
int var = compileStack.defineTemporaryVariable(tmpList, false);
Variable iterator = new VariableExpression("iterator", Iterator_TYPE);
int it = compileStack.defineTemporaryVariable(iterator, false);
Variable nextVar = new VariableExpression("next", componentType);
final int next = compileStack.defineTemporaryVariable(nextVar, false);
mv.visitTypeInsn(NEW, "java/util/ArrayList");
mv.visitInsn(DUP);
receiver.visit(controller.getAcg());
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true);
controller.getOperandStack().remove(1);
mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "(I)V", false);
mv.visitVarInsn(ASTORE, var);
Label l1 = new Label();
mv.visitLabel(l1);
receiver.visit(controller.getAcg());
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true);
controller.getOperandStack().remove(1);
mv.visitVarInsn(ASTORE, it);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, it);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
Label l3 = new Label();
mv.visitJumpInsn(IFEQ, l3);
mv.visitVarInsn(ALOAD, it);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
mv.visitTypeInsn(CHECKCAST, BytecodeHelper.getClassInternalName(componentType));
mv.visitVarInsn(ASTORE, next);
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitVarInsn(ALOAD, var);
final ClassNode finalComponentType = componentType;
PropertyExpression pexp = new PropertyExpression(new BytecodeExpression() {
@Override
public void visit(final MethodVisitor mv) {
mv.visitVarInsn(ALOAD, next);
}
@Override
public ClassNode getType() {
return finalComponentType;
}
}, methodName);
pexp.visit(controller.getAcg());
controller.getOperandStack().box();
controller.getOperandStack().remove(1);
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);
mv.visitInsn(POP);
Label l5 = new Label();
mv.visitLabel(l5);
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l3);
mv.visitVarInsn(ALOAD, var);
if (safe) {
mv.visitLabel(exit);
}
controller.getOperandStack().push(make(ArrayList.class));
controller.getCompileStack().removeVar(next);
controller.getCompileStack().removeVar(it);
controller.getCompileStack().removeVar(var);
}
use of org.codehaus.groovy.classgen.BytecodeExpression in project groovy-core by groovy.
the class BinaryExpressionHelper method execMethodAndStoreForSubscriptOperator.
private void execMethodAndStoreForSubscriptOperator(int op, String method, Expression expression, VariableSlotLoader usesSubscript, Expression orig) {
final OperandStack operandStack = controller.getOperandStack();
writePostOrPrefixMethod(op, method, expression, orig);
// we need special code for arrays to store the result (like for a[1]++)
if (usesSubscript != null) {
CompileStack compileStack = controller.getCompileStack();
BinaryExpression be = (BinaryExpression) expression;
ClassNode methodResultType = operandStack.getTopOperand();
final int resultIdx = compileStack.defineTemporaryVariable("postfix_" + method, methodResultType, true);
BytecodeExpression methodResultLoader = new VariableSlotLoader(methodResultType, resultIdx, operandStack);
// execute the assignment, this will leave the right side
// (here the method call result) on the stack
assignToArray(be, be.getLeftExpression(), usesSubscript, methodResultLoader);
compileStack.removeVar(resultIdx);
} else // here we handle a.b++ and a++
if (expression instanceof VariableExpression || expression instanceof FieldExpression || expression instanceof PropertyExpression) {
operandStack.dup();
controller.getCompileStack().pushLHS(true);
expression.visit(controller.getAcg());
controller.getCompileStack().popLHS();
}
// other cases don't need storing, so nothing to be done for them
}
use of org.codehaus.groovy.classgen.BytecodeExpression in project groovy-core by groovy.
the class BinaryExpressionHelper method evaluateEqual.
public void evaluateEqual(BinaryExpression expression, boolean defineVariable) {
AsmClassGenerator acg = controller.getAcg();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expression rightExpression = expression.getRightExpression();
Expression leftExpression = expression.getLeftExpression();
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if (defineVariable && rightExpression instanceof EmptyExpression && !(leftExpression instanceof TupleExpression)) {
VariableExpression ve = (VariableExpression) leftExpression;
BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
operandStack.loadOrStoreVariable(var, false);
return;
}
// let's evaluate the RHS and store the result
ClassNode rhsType;
if (rightExpression instanceof ListExpression && lhsType.isArray()) {
ListExpression list = (ListExpression) rightExpression;
ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions());
array.setSourcePosition(list);
array.visit(acg);
} else if (rightExpression instanceof EmptyExpression) {
rhsType = leftExpression.getType();
loadInitValue(rhsType);
} else {
rightExpression.visit(acg);
}
rhsType = operandStack.getTopOperand();
boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
int rhsValueId;
if (directAssignment) {
VariableExpression var = (VariableExpression) leftExpression;
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) {
// GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed
rhsType = ClassHelper.getWrapper(rhsType);
operandStack.box();
}
// form as it is closure shared
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNull(rightExpression)) {
operandStack.doGroovyCast(var.getOriginType());
// these two are never reached in bytecode and only there
// to avoid verifyerrors and compiler infrastructure hazzle
operandStack.box();
operandStack.doGroovyCast(lhsType);
}
// normal type transformation
if (!ClassHelper.isPrimitiveType(lhsType) && isNull(rightExpression)) {
operandStack.replace(lhsType);
} else {
operandStack.doGroovyCast(lhsType);
}
rhsType = lhsType;
rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex();
} else {
rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true);
}
// TODO: if rhs is VariableSlotLoader already, then skip crating a new one
BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType, rhsValueId, operandStack);
// assignment for subscript
if (leftExpression instanceof BinaryExpression) {
BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
if (leftBinExpr.getOperation().getType() == Types.LEFT_SQUARE_BRACKET) {
assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader);
}
compileStack.removeVar(rhsValueId);
return;
}
compileStack.pushLHS(true);
// multiple declaration
if (leftExpression instanceof TupleExpression) {
TupleExpression tuple = (TupleExpression) leftExpression;
int i = 0;
for (Expression e : tuple.getExpressions()) {
VariableExpression var = (VariableExpression) e;
MethodCallExpression call = new MethodCallExpression(rhsValueLoader, "getAt", new ArgumentListExpression(new ConstantExpression(i)));
call.visit(acg);
i++;
if (defineVariable) {
operandStack.doGroovyCast(var);
compileStack.defineVariable(var, true);
operandStack.remove(1);
} else {
acg.visitVariableExpression(var);
}
}
} else // single declaration
if (defineVariable) {
rhsValueLoader.visit(acg);
operandStack.remove(1);
compileStack.popLHS();
return;
} else // normal assignment
{
int mark = operandStack.getStackLength();
// to leave a copy of the rightExpression value on the stack after the assignment.
rhsValueLoader.visit(acg);
TypeChooser typeChooser = controller.getTypeChooser();
ClassNode targetType = typeChooser.resolveType(leftExpression, controller.getClassNode());
operandStack.doGroovyCast(targetType);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
compileStack.popLHS();
// return value of assignment
rhsValueLoader.visit(acg);
compileStack.removeVar(rhsValueId);
}
use of org.codehaus.groovy.classgen.BytecodeExpression in project groovy by apache.
the class StaticTypesCallSiteWriter method makeGroovyObjectGetPropertySite.
@Override
public void makeGroovyObjectGetPropertySite(final Expression receiver, final String propertyName, final boolean safe, final boolean implicitThis) {
ClassNode receiverType = controller.getClassNode();
if (!isThisExpression(receiver) || controller.isInGeneratedFunction()) {
// GROOVY-9967, et al.
receiverType = getPropertyOwnerType(receiver);
}
if (implicitThis && controller.getInvocationWriter() instanceof StaticInvocationWriter) {
Expression currentCall = ((StaticInvocationWriter) controller.getInvocationWriter()).getCurrentCall();
if (currentCall != null) {
String implicitReceiver = currentCall.getNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER);
if (implicitReceiver != null) {
String[] pathElements = implicitReceiver.split("\\.");
BytecodeExpression thisLoader = bytecodeX(CLOSURE_TYPE, mv -> mv.visitVarInsn(ALOAD, 0));
PropertyExpression pexp = propX(thisLoader, constX(pathElements[0]), safe);
for (int i = 1, n = pathElements.length; i < n; i += 1) {
pexp.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, CLOSURE_TYPE);
pexp = propX(pexp, pathElements[i]);
}
pexp.visit(controller.getAcg());
return;
}
}
}
if (makeGetPropertyWithGetter(receiver, receiverType, propertyName, safe, implicitThis))
return;
if (makeGetPrivateFieldWithBridgeMethod(receiver, receiverType, propertyName, safe, implicitThis))
return;
if (makeGetField(receiver, receiverType, propertyName, safe, implicitThis))
return;
boolean isScriptVariable = (receiverType.isScript() && receiver instanceof VariableExpression && ((VariableExpression) receiver).getAccessedVariable() == null);
if (!isScriptVariable && controller.getClassNode().getOuterClass() == null) {
// inner class still needs dynamic property sequence
addPropertyAccessError(receiver, propertyName, receiverType);
}
MethodCallExpression call = callX(receiver, "getProperty", args(constX(propertyName)));
call.setImplicitThis(implicitThis);
call.setMethodTarget(GROOVYOBJECT_GETPROPERTY_METHOD);
call.setSafe(safe);
call.visit(controller.getAcg());
}
use of org.codehaus.groovy.classgen.BytecodeExpression in project groovy by apache.
the class BinaryExpressionHelper method evaluateEqual.
public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
AsmClassGenerator acg = controller.getAcg();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expression leftExpression = expression.getLeftExpression();
Expression rightExpression = expression.getRightExpression();
boolean directAssignment = defineVariable && !(leftExpression instanceof TupleExpression);
if (directAssignment && rightExpression instanceof EmptyExpression) {
VariableExpression ve = (VariableExpression) leftExpression;
BytecodeVariable var = compileStack.defineVariable(ve, controller.getTypeChooser().resolveType(ve, controller.getClassNode()), false);
operandStack.loadOrStoreVariable(var, false);
return;
}
// evaluate the RHS and store the result
// TODO: LHS has not been visited, it could be a variable in a closure and type chooser is not aware.
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if (rightExpression instanceof ListExpression && lhsType.isArray()) {
ListExpression list = (ListExpression) rightExpression;
ArrayExpression array = new ArrayExpression(lhsType.getComponentType(), list.getExpressions());
array.setSourcePosition(list);
array.visit(acg);
} else if (rightExpression instanceof EmptyExpression) {
// TODO: lhsType?
loadInitValue(leftExpression.getType());
} else {
rightExpression.visit(acg);
}
ClassNode rhsType = operandStack.getTopOperand();
int rhsValueId;
if (directAssignment) {
VariableExpression var = (VariableExpression) leftExpression;
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(rhsType)) {
// GROOVY-5570: if a closure shared variable is a primitive type, it must be boxed
rhsType = ClassHelper.getWrapper(rhsType);
operandStack.box();
}
// form as it is closure shared
if (var.isClosureSharedVariable() && ClassHelper.isPrimitiveType(var.getOriginType()) && isNullConstant(rightExpression)) {
operandStack.doGroovyCast(var.getOriginType());
// these two are never reached in bytecode and only there
// to avoid verify errors and compiler infrastructure hazzle
operandStack.box();
operandStack.doGroovyCast(lhsType);
}
// normal type transformation
if (!ClassHelper.isPrimitiveType(lhsType) && isNullConstant(rightExpression)) {
operandStack.replace(lhsType);
} else {
operandStack.doGroovyCast(lhsType);
}
rhsType = lhsType;
rhsValueId = compileStack.defineVariable(var, lhsType, true).getIndex();
} else {
rhsValueId = compileStack.defineTemporaryVariable("$rhs", rhsType, true);
}
// TODO: if RHS is VariableSlotLoader already, then skip creating a new one
BytecodeExpression rhsValueLoader = new VariableSlotLoader(rhsType, rhsValueId, operandStack);
// assignment for subscript
if (leftExpression instanceof BinaryExpression) {
BinaryExpression leftBinExpr = (BinaryExpression) leftExpression;
if (leftBinExpr.getOperation().getType() == LEFT_SQUARE_BRACKET) {
assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader, leftBinExpr.isSafe());
}
compileStack.removeVar(rhsValueId);
return;
}
compileStack.pushLHS(true);
if (leftExpression instanceof TupleExpression) {
// multiple declaration
TupleExpression tuple = (TupleExpression) leftExpression;
int i = 0;
for (Expression e : tuple.getExpressions()) {
callX(rhsValueLoader, "getAt", args(constX(i++))).visit(acg);
if (defineVariable) {
Variable v = (Variable) e;
operandStack.doGroovyCast(v);
compileStack.defineVariable(v, true);
operandStack.remove(1);
} else {
e.visit(acg);
}
}
} else if (defineVariable) {
// single declaration
rhsValueLoader.visit(acg);
operandStack.remove(1);
compileStack.popLHS();
return;
} else {
// normal assignment
int mark = operandStack.getStackLength();
rhsValueLoader.visit(acg);
leftExpression.visit(acg);
operandStack.remove(operandStack.getStackLength() - mark);
}
compileStack.popLHS();
// return value of assignment
rhsValueLoader.visit(acg);
compileStack.removeVar(rhsValueId);
}
Aggregations