| /* |
| * 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>()"); |
| } |
| } |