Tue, 03 Dec 2019 08:29:04 +0100
8234617: C1: Incorrect result of field load due to missing narrowing conversion
Summary: Emit an explicit conversion to get the correct field value after the write.
Reviewed-by: vlivanov, mdoerr, phh, andrew
1.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 29 05:41:50 2020 +0100 1.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Tue Dec 03 08:29:04 2019 +0100 1.3 @@ -1705,6 +1705,23 @@ 1.4 Value replacement = !needs_patching ? _memory->load(load) : load; 1.5 if (replacement != load) { 1.6 assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); 1.7 + // Writing an (integer) value to a boolean, byte, char or short field includes an implicit narrowing 1.8 + // conversion. Emit an explicit conversion here to get the correct field value after the write. 1.9 + BasicType bt = field->type()->basic_type(); 1.10 + switch (bt) { 1.11 + case T_BOOLEAN: 1.12 + case T_BYTE: 1.13 + replacement = append(new Convert(Bytecodes::_i2b, replacement, as_ValueType(bt))); 1.14 + break; 1.15 + case T_CHAR: 1.16 + replacement = append(new Convert(Bytecodes::_i2c, replacement, as_ValueType(bt))); 1.17 + break; 1.18 + case T_SHORT: 1.19 + replacement = append(new Convert(Bytecodes::_i2s, replacement, as_ValueType(bt))); 1.20 + break; 1.21 + default: 1.22 + break; 1.23 + } 1.24 push(type, replacement); 1.25 } else { 1.26 push(type, append(load));
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/compiler/conversions/Conversion.jasm Tue Dec 03 08:29:04 2019 +0100 2.3 @@ -0,0 +1,130 @@ 2.4 +/* 2.5 + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +package compiler/conversions; 2.28 + 2.29 +public class Conversion 2.30 + version 52:0 2.31 +{ 2.32 + Field booleanFld:Z; 2.33 + Field byteFld:B; 2.34 + Field charFld:C; 2.35 + Field shortFld:S; 2.36 + Field intFld:I; 2.37 + 2.38 + public Method "<init>":"()V" 2.39 + stack 1 locals 1 2.40 + { 2.41 + aload_0; 2.42 + invokespecial Method java/lang/Object."<init>":"()V"; 2.43 + return; 2.44 + } 2.45 + 2.46 + public Method testBooleanConst:"()I" 2.47 + stack 5 locals 1 2.48 + { 2.49 + aload_0; 2.50 + ldc_w int 2; // 2^1 (maximum boolean value is 1) 2.51 + putfield Field booleanFld:"Z"; 2.52 + aload_0; 2.53 + getfield Field booleanFld:"Z"; 2.54 + ireturn; 2.55 + } 2.56 + 2.57 + public Method testBoolean:"(I)I" 2.58 + stack 5 locals 2 2.59 + { 2.60 + aload_0; 2.61 + iload_1; 2.62 + putfield Field booleanFld:"Z"; 2.63 + aload_0; 2.64 + getfield Field booleanFld:"Z"; 2.65 + ireturn; 2.66 + } 2.67 + 2.68 + public Method testByteConst:"()I" 2.69 + stack 5 locals 1 2.70 + { 2.71 + aload_0; 2.72 + ldc_w int 256; // 2^8 (maximum byte value is 2^7-1) 2.73 + putfield Field byteFld:"B"; 2.74 + aload_0; 2.75 + getfield Field byteFld:"B"; 2.76 + ireturn; 2.77 + } 2.78 + 2.79 + public Method testByte:"(I)I" 2.80 + stack 5 locals 2 2.81 + { 2.82 + aload_0; 2.83 + iload_1; 2.84 + putfield Field byteFld:"B"; 2.85 + aload_0; 2.86 + getfield Field byteFld:"B"; 2.87 + ireturn; 2.88 + } 2.89 + 2.90 + public Method testCharConst:"()I" 2.91 + stack 5 locals 1 2.92 + { 2.93 + aload_0; 2.94 + ldc_w int 131072; // 2^17 (maximum char value is 2^16-1) 2.95 + putfield Field charFld:"C"; 2.96 + aload_0; 2.97 + getfield Field charFld:"C"; 2.98 + ireturn; 2.99 + } 2.100 + 2.101 + public Method testChar:"(I)I" 2.102 + stack 5 locals 2 2.103 + { 2.104 + aload_0; 2.105 + iload_1; 2.106 + putfield Field charFld:"C"; 2.107 + aload_0; 2.108 + getfield Field charFld:"C"; 2.109 + ireturn; 2.110 + } 2.111 + 2.112 + public Method testShortConst:"()I" 2.113 + stack 5 locals 1 2.114 + { 2.115 + aload_0; 2.116 + ldc_w int 65536; // 2^16 (maximum short value is 2^15-1) 2.117 + putfield Field shortFld:"S"; 2.118 + aload_0; 2.119 + getfield Field shortFld:"S"; 2.120 + ireturn; 2.121 + } 2.122 + 2.123 + public Method testShort:"(I)I" 2.124 + stack 5 locals 2 2.125 + { 2.126 + aload_0; 2.127 + iload_1; 2.128 + putfield Field shortFld:"S"; 2.129 + aload_0; 2.130 + getfield Field shortFld:"S"; 2.131 + ireturn; 2.132 + } 2.133 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/compiler/conversions/TestPrimitiveConversions.java Tue Dec 03 08:29:04 2019 +0100 3.3 @@ -0,0 +1,60 @@ 3.4 +/* 3.5 + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +package compiler.conversions; 3.28 + 3.29 +import com.oracle.java.testlibrary.Asserts; 3.30 + 3.31 +/* 3.32 + * @test 3.33 + * @bug 8234617 3.34 + * @summary Test implicit narrowing conversion of primivite values at putfield. 3.35 + * @library /testlibrary 3.36 + * @compile Conversion.jasm 3.37 + * @run main/othervm -Xbatch -XX:CompileCommand=dontinline,compiler.conversions.Conversion::* 3.38 + * compiler.conversions.TestPrimitiveConversions 3.39 + */ 3.40 +public class TestPrimitiveConversions { 3.41 + 3.42 + public static void main(String[] args) { 3.43 + Conversion conv = new Conversion(); 3.44 + for (int i = 0; i < 100_000; ++i) { 3.45 + int res = conv.testBooleanConst(); 3.46 + Asserts.assertEquals(res, 0); 3.47 + res = conv.testBoolean(2); // 2^1 (maximum boolean value is 1) 3.48 + Asserts.assertEquals(res, 0); 3.49 + res = conv.testByteConst(); 3.50 + Asserts.assertEquals(res, 0); 3.51 + res = conv.testByte(256); // 2^8 (maximum byte value is 2^7-1) 3.52 + Asserts.assertEquals(res, 0); 3.53 + res = conv.testCharConst(); 3.54 + Asserts.assertEquals(res, 0); 3.55 + res = conv.testChar(131072); // 2^17 (maximum char value is 2^16-1) 3.56 + Asserts.assertEquals(res, 0); 3.57 + res = conv.testShortConst(); 3.58 + Asserts.assertEquals(res, 0); 3.59 + res = conv.testShort(65536); // 2^16 (maximum short value is 2^15-1) 3.60 + Asserts.assertEquals(res, 0); 3.61 + } 3.62 + } 3.63 +}