Home | History | Annotate | Download | only in smali
      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