1# Copyright (C) 2015 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# 15.class public LBoxUnbox; 16.super Ljava/lang/Object; 17 18.method public constructor <init>()V 19.registers 1 20 invoke-direct {p0}, Ljava/lang/Object;-><init>()V 21 return-void 22.end method 23 24.method public static run()V 25 .registers 0 26 27 invoke-static {}, LBoxUnbox;->testBox()V 28 invoke-static {}, LBoxUnbox;->testBoxEquality()V 29 invoke-static {}, LBoxUnbox;->testFailures()V 30 invoke-static {}, LBoxUnbox;->testFailures2()V 31 invoke-static {}, LBoxUnbox;->testFailures3()V 32 invoke-static {}, LBoxUnbox;->forceGC()V 33 34 return-void 35.end method 36 37#TODO: should use a closure type instead of ArtMethod. 38.method public static doHelloWorld(J)V 39 .registers 4 # 1 wide parameters, 2 locals 40 41 const-string v0, "(BoxUnbox) Hello boxing world! (0-args, no closure)" 42 43 sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream; 44 invoke-virtual {v1, v0}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 45 46 return-void 47.end method 48 49# Test boxing and unboxing; the same lambda should be invoked as if there was no box. 50.method private static testBox()V 51 .registers 3 52 53 create-lambda v0, LBoxUnbox;->doHelloWorld(J)V 54 box-lambda v2, v0 # v2 = box(v0) 55 unbox-lambda v0, v2, J # v0 = unbox(v2) 56 invoke-lambda v0, {} 57 58 return-void 59.end method 60 61# Test that boxing the same lambda twice yield the same object. 62.method private static testBoxEquality()V 63 .registers 6 # 0 parameters, 6 locals 64 65 create-lambda v0, LBoxUnbox;->doHelloWorld(J)V 66 box-lambda v2, v0 # v2 = box(v0) 67 box-lambda v3, v0 # v3 = box(v0) 68 69 # The objects should be not-null, and they should have the same reference 70 if-eqz v2, :is_zero 71 if-ne v2, v3, :is_not_equal 72 73 const-string v4, "(BoxUnbox) Boxing repeatedly yields referentially-equal objects" 74 goto :end 75 76:is_zero 77 const-string v4, "(BoxUnbox) Boxing repeatedly FAILED: boxing returned null" 78 goto :end 79 80:is_not_equal 81 const-string v4, "(BoxUnbox) Boxing repeatedly FAILED: objects were not same reference" 82 goto :end 83 84:end 85 sget-object v5, Ljava/lang/System;->out:Ljava/io/PrintStream; 86 invoke-virtual {v5, v4}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 87 return-void 88.end method 89 90# Test exceptions are thrown as expected when used opcodes incorrectly 91.method private static testFailures()V 92 .registers 4 # 0 parameters, 4 locals 93 94 const v0, 0 # v0 = null 95 const v1, 0 # v1 = null 96:start 97 unbox-lambda v2, v0, J 98 # attempting to unbox a null lambda will throw NPE 99:end 100 return-void 101 102:handler 103 const-string v2, "(BoxUnbox) Caught NPE for unbox-lambda" 104 sget-object v3, Ljava/lang/System;->out:Ljava/io/PrintStream; 105 invoke-virtual {v3, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 106 107 return-void 108 109 .catch Ljava/lang/NullPointerException; {:start .. :end} :handler 110.end method 111 112# Test exceptions are thrown as expected when used opcodes incorrectly 113.method private static testFailures2()V 114 .registers 4 # 0 parameters, 4 locals 115 116 const v0, 0 # v0 = null 117 const v1, 0 # v1 = null 118:start 119 box-lambda v2, v0 # attempting to box a null lambda will throw NPE 120:end 121 return-void 122 123 # TODO: refactor testFailures using a goto 124 125:handler 126 const-string v2, "(BoxUnbox) Caught NPE for box-lambda" 127 sget-object v3, Ljava/lang/System;->out:Ljava/io/PrintStream; 128 invoke-virtual {v3, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 129 130 return-void 131 132 .catch Ljava/lang/NullPointerException; {:start .. :end} :handler 133.end method 134 135# Test exceptions are thrown as expected when used opcodes incorrectly 136.method private static testFailures3()V 137 .registers 4 # 0 parameters, 4 locals 138 139 const-string v0, "This is not a boxed lambda" 140:start 141 # TODO: use \FunctionalType; here instead 142 unbox-lambda v2, v0, J 143 # can't use a string, expects a lambda object here. throws ClassCastException. 144:end 145 return-void 146 147 # TODO: refactor testFailures using a goto 148 149:handler 150 const-string v2, "(BoxUnbox) Caught ClassCastException for unbox-lambda" 151 sget-object v3, Ljava/lang/System;->out:Ljava/io/PrintStream; 152 invoke-virtual {v3, v2}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V 153 154 return-void 155 156 .catch Ljava/lang/ClassCastException; {:start .. :end} :handler 157.end method 158 159 160# Force a GC. Used to ensure our weak reference table of boxed lambdas is getting swept. 161.method private static forceGC()V 162 .registers 1 163 invoke-static {}, Ljava/lang/Runtime;->getRuntime()Ljava/lang/Runtime; 164 move-result-object v0 165 invoke-virtual {v0}, Ljava/lang/Runtime;->gc()V 166 167 return-void 168.end method 169