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