/* * Copyright 2014 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.dev.jjs.optimized; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.junit.DoNotRunWith; import com.google.gwt.junit.Platform; import java.util.Random; import jsinterop.annotations.JsPackage; import jsinterop.annotations.JsType; /** * Tests cast checks are optimized out when cast checking is disabled. */ @DoNotRunWith(Platform.Devel) public class CastOptimizationTest extends OptimizationTestBase { private static class TestObject { } @JsType(isNative = true) private interface JsTypeTestInterface { } private interface DualJsoTestInterface { } private static class JsoTestObject extends JavaScriptObject implements DualJsoTestInterface { protected JsoTestObject() { } } @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object") static class NativeObject { } @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Function") static class NativeFunction { } @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Array") static class NativeArray { } @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Number") static class NativeNumber { } @JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "String") static class NativeString { } private static Object field; private static double doubleField = new Random().nextDouble(); private static int randomNumber = new Random().nextInt(42); @Override protected void gwtSetUp() throws Exception { field = createField(); } private static Object createField() { // Makes sure that field type is not upgradable even the compiler becomes really smart and also // no types are pruned otherwise casts can be statically evaluated. switch (randomNumber) { case 0: return new TestObject(); case 1: return JavaScriptObject.createObject(); case 2: return new DualJsoTestInterface() { }; case 3: return "Some string"; default: return null; } } public static TestObject castOp() { return ((TestObject) field); } public static JavaScriptObject castOpJso() { return ((JavaScriptObject) field); } public static DualJsoTestInterface castOpDualJso() { return ((DualJsoTestInterface) field); } public static JavaScriptObject castOpJsType() { return ((JavaScriptObject) field); } public static String castOpString() { return ((String) field); } public static NativeFunction castNativeFunction() { return ((NativeFunction) field); } public static NativeObject castNativeObject() { return ((NativeObject) field); } public static NativeArray castNativeArray() { return ((NativeArray) field); } public static NativeNumber castNativeNumber() { return ((NativeNumber) field); } public static void castInt() { int num = ((int) doubleField); } private static native String getGeneratedCastFunctionDefinition() /*-{ return function() { @CastOptimizationTest::castOp()(); @CastOptimizationTest::castOpJso()(); @CastOptimizationTest::castOpDualJso()(); @CastOptimizationTest::castOpJsType()(); @CastOptimizationTest::castOpString()(); @CastOptimizationTest::castNativeFunction()(); @CastOptimizationTest::castNativeNumber()(); @CastOptimizationTest::castNativeArray()(); @CastOptimizationTest::castNativeObject()(); @CastOptimizationTest::castInt()(); }.toString(); }-*/; public void testCastsAreRemoved() throws Exception { String functionDef = getGeneratedCastFunctionDefinition(); assertFunctionMatches(functionDef, ""); } private static native String getGeneratedNullnessPropagationFunctionDefinition() /*-{ return function() { @CastOptimizationTest::castNonNullnessCheck()(); }.toString(); }-*/; public static void castNonNullnessCheck() { if ((String) (randomNumber == 1 ? "uniqueCastString" : new Object()) == null) { throw new RuntimeException(); } } public void testCastsPropagatesNullness() throws Exception { String functionDef = getGeneratedNullnessPropagationFunctionDefinition(); // Means that the function was inlined but the throw was optimized away. assertFunctionMatches(functionDef, "<obf>==1?'uniqueCastString':new<obf>()"); } }