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