You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2016/11/16 14:00:49 UTC
groovy git commit: Refine safe index for assignment
Repository: groovy
Updated Branches:
refs/heads/parrot d30f059bf -> e058a848b
Refine safe index for assignment
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/e058a848
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/e058a848
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/e058a848
Branch: refs/heads/parrot
Commit: e058a848bb7092acf95e0664a6eb97d00472246b
Parents: d30f059
Author: Daniel Sun <su...@apache.org>
Authored: Wed Nov 16 21:57:53 2016 +0800
Committer: Daniel Sun <su...@apache.org>
Committed: Wed Nov 16 21:57:53 2016 +0800
----------------------------------------------------------------------
.../classgen/asm/BinaryExpressionHelper.java | 30 ++++-----
.../BinaryExpressionMultiTypeDispatcher.java | 6 +-
...ypesBinaryExpressionMultiTypeDispatcher.java | 11 +--
.../test/resources/core/SafeIndex_02x.groovy | 38 +++++++++--
.../test/resources/core/SafeIndex_03x.groovy | 70 +++++++++++++++++---
5 files changed, 117 insertions(+), 38 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/e058a848/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
index d86c58d..033d04e 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionHelper.java
@@ -18,8 +18,6 @@
*/
package org.codehaus.groovy.classgen.asm;
-import groovy.lang.GroovyRuntimeException;
-
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
@@ -28,8 +26,6 @@ import org.codehaus.groovy.ast.tools.WideningCategories;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.BytecodeExpression;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
-import org.codehaus.groovy.syntax.SyntaxException;
-import org.codehaus.groovy.syntax.Token;
import org.codehaus.groovy.syntax.Types;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -249,7 +245,7 @@ public class BinaryExpressionHelper {
}
}
- protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader) {
+ protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
// let's replace this assignment to a subscript operator with a
// method call
// e.g. x[5] = 10
@@ -258,7 +254,7 @@ public class BinaryExpressionHelper {
ArgumentListExpression ae = new ArgumentListExpression(index,rhsValueLoader);
controller.getInvocationWriter().makeCall(
parent, receiver, new ConstantExpression("putAt"),
- ae, InvocationWriter.invokeMethod, false, false, false);
+ ae, InvocationWriter.invokeMethod, safe, false, false);
controller.getOperandStack().pop();
// return value of assignment
rhsValueLoader.visit(controller.getAcg());
@@ -281,7 +277,7 @@ public class BinaryExpressionHelper {
ClassNode lhsType = controller.getTypeChooser().resolveType(leftExpression, controller.getClassNode());
if ( defineVariable &&
- rightExpression instanceof EmptyExpression &&
+ rightExpression instanceof EmptyExpression &&
!(leftExpression instanceof TupleExpression) )
{
VariableExpression ve = (VariableExpression) leftExpression;
@@ -337,13 +333,13 @@ public class BinaryExpressionHelper {
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);
+ 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);
+ assignToArray(expression, leftBinExpr.getLeftExpression(), leftBinExpr.getRightExpression(), rhsValueLoader, leftBinExpr.isSafe());
}
compileStack.removeVar(rhsValueId);
return;
@@ -416,7 +412,7 @@ public class BinaryExpressionHelper {
boolean done = false;
if ( ClassHelper.isPrimitiveType(leftType) &&
- ClassHelper.isPrimitiveType(rightType))
+ ClassHelper.isPrimitiveType(rightType))
{
BinaryExpressionMultiTypeDispatcher helper = new BinaryExpressionMultiTypeDispatcher(getController());
done = helper.doPrimitiveCompare(leftType, rightType, expression);
@@ -519,9 +515,9 @@ public class BinaryExpressionHelper {
}
protected void evaluateArrayAssignmentWithOperator(String method, BinaryExpression expression, BinaryExpression leftBinExpr) {
- CompileStack compileStack = getController().getCompileStack();
- AsmClassGenerator acg = getController().getAcg();
- OperandStack os = getController().getOperandStack();
+ CompileStack compileStack = getController().getCompileStack();
+ AsmClassGenerator acg = getController().getAcg();
+ OperandStack os = getController().getOperandStack();
// e.g. x[a] += b
// to avoid loading x and a twice we transform the expression to use
@@ -602,7 +598,7 @@ public class BinaryExpressionHelper {
// save copy for later
operandStack.dup();
- ClassNode expressionType = operandStack.getTopOperand();
+ ClassNode expressionType = operandStack.getTopOperand();
int tempIdx = compileStack.defineTemporaryVariable("postfix_" + method, expressionType, true);
// execute Method
@@ -658,7 +654,7 @@ public class BinaryExpressionHelper {
// subscription
if (expression instanceof BinaryExpression) {
BinaryExpression be = (BinaryExpression) expression;
- if (be.getOperation().getType()==Types.LEFT_SQUARE_BRACKET) {
+ if (be.getOperation().getType()== Types.LEFT_SQUARE_BRACKET) {
// right expression is the subscript expression
// we store the result of the subscription on the stack
Expression subscript = be.getRightExpression();
@@ -695,13 +691,13 @@ public class BinaryExpressionHelper {
// execute the assignment, this will leave the right side
// (here the method call result) on the stack
- assignToArray(be, be.getLeftExpression(), usesSubscript, methodResultLoader);
+ assignToArray(be, be.getLeftExpression(), usesSubscript, methodResultLoader, be.isSafe());
compileStack.removeVar(resultIdx);
}
// here we handle a.b++ and a++
else if (expression instanceof VariableExpression ||
- expression instanceof FieldExpression ||
+ expression instanceof FieldExpression ||
expression instanceof PropertyExpression)
{
operandStack.dup();
http://git-wip-us.apache.org/repos/asf/groovy/blob/e058a848/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
index e011501..c8a8fc6 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/BinaryExpressionMultiTypeDispatcher.java
@@ -356,7 +356,7 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
}
@Override
- protected void assignToArray(Expression orig, Expression receiver, Expression index, Expression rhsValueLoader) {
+ protected void assignToArray(Expression orig, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
ClassNode current = getController().getClassNode();
ClassNode arrayType = getController().getTypeChooser().resolveType(receiver, current);
ClassNode arrayComponentType = arrayType.getComponentType();
@@ -364,7 +364,7 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
BinaryExpressionWriter bew = binExpWriter[operationType];
AsmClassGenerator acg = getController().getAcg();
- if (bew.arraySet(true) && arrayType.isArray()) {
+ if (bew.arraySet(true) && arrayType.isArray() && !safe) {
OperandStack operandStack = getController().getOperandStack();
// load the array
@@ -386,7 +386,7 @@ public class BinaryExpressionMultiTypeDispatcher extends BinaryExpressionHelper
operandStack.remove(3);
rhsValueLoader.visit(acg);
} else {
- super.assignToArray(orig, receiver, index, rhsValueLoader);
+ super.assignToArray(orig, receiver, index, rhsValueLoader, safe);
}
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/e058a848/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index 9441007..4a3c9dc 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -177,7 +177,7 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
ClassNode componentType = StaticTypeCheckingVisitor.inferLoopElementType(typeChooser.resolveType(receiver, classNode));
Parameter iterator = new Parameter(componentType, "for$it$" + counter);
VariableExpression iteratorAsVar = new VariableExpression(iterator);
- PropertyExpression pexp = spreadExpression instanceof AttributeExpression?
+ PropertyExpression pexp = spreadExpression instanceof AttributeExpression ?
new AttributeExpression(iteratorAsVar, spreadExpression.getProperty(), true):
new PropertyExpression(iteratorAsVar, spreadExpression.getProperty(), true);
pexp.setImplicitThis(spreadExpression.isImplicitThis());
@@ -347,15 +347,16 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
return false;
}
- protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader) {
+ @Override
+ protected void assignToArray(Expression parent, Expression receiver, Expression index, Expression rhsValueLoader, boolean safe) {
ClassNode current = getController().getClassNode();
ClassNode arrayType = getController().getTypeChooser().resolveType(receiver, current);
ClassNode arrayComponentType = arrayType.getComponentType();
int operationType = getOperandType(arrayComponentType);
BinaryExpressionWriter bew = binExpWriter[operationType];
- if (bew.arraySet(true) && arrayType.isArray()) {
- super.assignToArray(parent, receiver, index, rhsValueLoader);
+ if (bew.arraySet(true) && arrayType.isArray() && !safe) {
+ super.assignToArray(parent, receiver, index, rhsValueLoader, safe);
} else {
/******
/ This code path is needed because ACG creates array access expressions
@@ -379,6 +380,8 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
"putAt",
ae
);
+
+ mce.setSafe(safe);
mce.setSourcePosition(parent);
visitor.visitMethodCallExpression(mce);
OperandStack operandStack = controller.getOperandStack();
http://git-wip-us.apache.org/repos/asf/groovy/blob/e058a848/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_02x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_02x.groovy b/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_02x.groovy
index b753cf0..3a91ac2 100644
--- a/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_02x.groovy
+++ b/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_02x.groovy
@@ -4,18 +4,44 @@ class SomeContainer {
public Object getAt(int i) {
return "123";
}
+
+ public void putAt(int i, Object obj) {
+ }
}
-@CompileStatic
-def cs() {
+def safe() {
List list = null;
- list?[1];
+ assert null == list?[1];
+ list?[1] = 'a';
+ assert null == list?[1];
Map map = null;
- map?[1];
+ assert null == map?[1];
+ map?[1] = 'a';
+ assert null == map?[1];
SomeContainer sc = null;
- sc?[1];
+ assert null == sc?[1];
+ sc?[1] = 'a';
+ assert null == sc?[1];
}
+safe();
+
+@CompileStatic
+def csSafe() {
+ List list = null;
+ assert null == list?[1];
+ list?[1] = 'a';
+ assert null == list?[1];
+
+ Map map = null;
+ assert null == map?[1];
+ map?[1] = 'a';
+ assert null == map?[1];
-cs()
+ SomeContainer sc = null;
+ assert null == sc?[1];
+ sc?[1] = 'a';
+ assert null == sc?[1];
+}
+csSafe();
http://git-wip-us.apache.org/repos/asf/groovy/blob/e058a848/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_03x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_03x.groovy b/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_03x.groovy
index ec800cd..320ed4f 100644
--- a/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_03x.groovy
+++ b/subprojects/groovy-antlr4-grammar/src/test/resources/core/SafeIndex_03x.groovy
@@ -10,6 +10,9 @@ def csObjArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 'c';
+ assert null == array?[1];
}
csObjArray();
@@ -22,6 +25,9 @@ def objArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 'c';
+ assert null == array?[1];
}
objArray();
@@ -35,6 +41,9 @@ def csBooleanArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = true;
+ assert null == array?[1];
}
csBooleanArray();
@@ -47,6 +56,9 @@ def booleanArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = true;
+ assert null == array?[1];
}
booleanArray();
@@ -60,6 +72,9 @@ def csCharArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 'c';
+ assert null == array?[1];
}
csCharArray();
@@ -72,6 +87,9 @@ def charArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 'c';
+ assert null == array?[1];
}
charArray();
@@ -85,6 +103,9 @@ def csByteArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3 as byte;
+ assert null == array?[1];
}
csByteArray();
@@ -97,31 +118,40 @@ def byteArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3 as byte;
+ assert null == array?[1];
}
byteArray();
@CompileStatic
def csShortArray() {
- short[] array = [1, 2];
- assert 2 == array?[1];
+ short[] array = [1 as short, 2 as short];
+ assert (2 as short) == array?[1];
- array?[1] = 3;
- assert 3 == array?[1];
+ array?[1] = 3 as short;
+ assert (3 as short) == array?[1];
array = null;
assert null == array?[1];
+
+ array?[1] = 3 as short;
+ assert null == array?[1];
}
csShortArray();
def shortArray() {
- short[] array = [1, 2];
- assert 2 == array?[1];
+ short[] array = [1 as short, 2 as short];
+ assert (2 as short) == array?[1];
- array?[1] = 3;
- assert 3 == array?[1];
+ array?[1] = 3 as short;
+ assert (3 as short) == array?[1];
array = null;
assert null == array?[1];
+
+ array?[1] = 3 as short;
+ assert null == array?[1];
}
shortArray();
@@ -135,6 +165,9 @@ def csIntArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3;
+ assert null == array?[1];
}
csIntArray();
@@ -147,6 +180,9 @@ def intArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3;
+ assert null == array?[1];
}
intArray();
@@ -160,6 +196,9 @@ def csLongArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3L;
+ assert null == array?[1];
}
csLongArray();
@@ -172,6 +211,9 @@ def longArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3L;
+ assert null == array?[1];
}
longArray();
@@ -185,6 +227,9 @@ def csFloatArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3.3f;
+ assert null == array?[1];
}
csFloatArray();
@@ -197,6 +242,9 @@ def floatArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3.3f;
+ assert null == array?[1];
}
floatArray();
@@ -210,6 +258,9 @@ def csDoubleArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3.3d;
+ assert null == array?[1];
}
csDoubleArray();
@@ -222,5 +273,8 @@ def doubleArray() {
array = null;
assert null == array?[1];
+
+ array?[1] = 3.3d;
+ assert null == array?[1];
}
doubleArray();
\ No newline at end of file