# Copyright (c) 2021-2022 Huawei Device Co., Ltd. # 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. definitions: - name: polymorphic-hdr template: | # .language PandaAssembly .record panda.Class .record panda.Object .record panda.Integer .record panda.Long .record panda.Short .record panda.String .record panda.invoke.MethodHandles .record panda.invoke.MethodHandles$Lookup .record panda.invoke.MethodHandle .record panda.invoke.VarHandle .record panda.invoke.MethodType .record panda.NullPointerException .record panda.reflect.Field .function panda.Object panda.reflect.Field.get(panda.reflect.Field a0, panda.Object a1) .function panda.reflect.Field panda.Class.getField(panda.Class a0, panda.String a1) .function panda.Class panda.Class.forName(panda.String a0) .function panda.invoke.MethodHandles$Lookup panda.invoke.MethodHandles.lookup() .function panda.invoke.MethodHandle panda.invoke.MethodHandles$Lookup.findStatic(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.invoke.MethodType a3) .function panda.invoke.MethodHandle panda.invoke.MethodHandles$Lookup.findVirtual(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.invoke.MethodType a3) .function panda.invoke.VarHandle panda.invoke.MethodHandles$Lookup.findVarHandle(panda.invoke.MethodHandles$Lookup a0, panda.Class a1, panda.String a2, panda.Class a3) .record W {} .record R { u1 f_boolean i8 f_byte u16 f_char i16 f_short i32 f_int i64 f_long f32 f_float f64 f_double } .record Q {} # returns int.class for panda.Integer, can be replaced with panda.Integer.TYPE .function panda.Class R.getPrimitiveType(panda.String a0) { call.short panda.Class.forName, a0 sta.obj v1 lda.str "TYPE" call.virt.acc.short panda.Class.getField, v1, 1 mov.null v0 call.virt.acc.short panda.reflect.Field.get, v0, 0 return.obj } .function i32 main() { call.short R.test return } tests: - file-name: 'call.polymorphic.range' isa: title: Polymorphic calls description: > TODO commands: - file-name: 'syntax' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check call.polymorphic.range syntax. runner-options: [use-pa, compile-failure, ] tags: ['irtoc_ignore'] header-template: [polymorphic-hdr] code-template: | .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, R a2, R a3) .function i32 R.test() { call.polymorphic.range %s check-type: exit-positive cases: - values: - 'panda.invoke.MethodHandle.invoke, v0, v1, v2, v3' - values: - 'panda.invoke.MethodHandle.invoke, v253' runner-options: [use-pa, verifier-failure, verifier-config, ] tags: [verifier] bugid: ['7636'] ignore: true - values: - 'panda.invoke.MethodHandle.invoke, v254' runner-options: [use-pa, verifier-failure, verifier-config, ] tags: [verifier] bugid: ['7636'] ignore: true - values: - 'panda.invoke.MethodHandle.invoke, v255' runner-options: [use-pa, verifier-failure, verifier-config, ] tags: [verifier] bugid: ['7636'] ignore: true - values: - 'panda.invoke.MethodHandle.invoke, v256' - values: - 'panda.invoke.MethodHandle.invoke, v32768' - values: - 'panda.invoke.MethodHandle.invoke, v65536' - values: - 'panda.invoke.MethodHandle.invoke, v252' runner-options: [use-pa, compile-only, ] - file-name: 'uninitialized_regs' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that verifier reports an error on unitialized registers. runner-options: [use-pa, verifier-failure, verifier-config, ] tags: ['verifier', 'irtoc_ignore'] header-template: [polymorphic-hdr] code-template: | .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, R a2, R a3) .function i32 R.test() { %s call.polymorphic.range panda.invoke.MethodHandle.invoke, %s check-type: exit-positive cases: - values: # v0, v1, v2, v3 are not initialized - '' - v0 bugid: ['7636'] ignore: true - values: # v103 is not initilized - | # newobj v100, R newobj v101, R newobj v102, R - v100 bugid: ['7636'] ignore: true - values: # all regs are initialized - | # newobj v252, R newobj v253, R newobj v254, R newobj v255, R - v252 runner-options: [use-pa, verifier-only, verifier-config, ] - file-name: 'npe' isa: exceptions: [x_null] description: Check that NullPointerException is thrown if v1 is null. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7637'] ignore: true header-template: [polymorphic-hdr] code-template: | .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1) .function i32 R.test() { mov.null v4 newobj v5, R try_begin: call.polymorphic.range panda.invoke.MethodHandle.invoke, v4 ldai 4 return try_end: catch_begin: ldai 0 return catch_end: .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end } check-type: empty - file-name: 'call_1s' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for static function with one argument. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) %s .function i32 R.inc32(i32 a0) { inci a0, 1 lda a0 return } .function i32 R.inc64(i64 a0) { ldai.64 2 add2.64 a0 i64toi32 return } .function i32 R.inc16(i16 a0) { inci a0, 3 lda a0 return } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.str "panda.Integer" sta.obj v1 call.short R.getPrimitiveType, v1 sta.obj v1 lda.str "%s" sta.obj v2 call.short R.getPrimitiveType, v2 sta.obj v2 call.short panda.invoke.MethodType.methodType, v1, v2 sta.obj v1 # MethodType object for (i32)i32 lda.type R sta.obj v2 lda.str "%s" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1 sta.obj v4 # MethodHandle object %s call.polymorphic.range panda.invoke.MethodHandle.invoke, v4 movi v1, 42 jeq v1, ok ldai 1 return ok: ldai 0 return } check-type: empty cases: - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i32 a1) - panda.Integer - inc32 - movi v5, 41 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i64 a1) - panda.Long - inc64 - movi.64 v5, 40 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i16 a1) - panda.Short - inc16 - movi v5, 39 - file-name: 'call_3s' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for static function with three arguments. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class[] a1) %s .function i32 R.sum32(i32 a0, i32 a1, i32 a2) { add a0, a1 add2 a2 return } .function i32 R.sum64(i64 a0, i64 a1, i64 a2) { lda.64 a0 add2.64 a1 add2.64 a2 i64toi32 return } .function i32 R.sum16(i16 a0, i16 a1, i16 a2) { add a0, a1 add2 a2 return } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.str "panda.Integer" sta.obj v1 call.short R.getPrimitiveType, v1 sta.obj v1 lda.str "%s" sta.obj v2 call.short R.getPrimitiveType, v2 movi v3, 3 # 3 arguments newarr v2, v3, panda.Class[] movi v4, 0 starr.obj v2, v4 inci v4, 1 starr.obj v2, v4 inci v4, 1 starr.obj v2, v4 call panda.invoke.MethodType.methodType, v1, v2 sta.obj v1 # MethodType object for (i32, i32, i32)i32 lda.type R sta.obj v2 lda.str "%s" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1 sta.obj v252 # MethodHandle object %s call.polymorphic.range panda.invoke.MethodHandle.invoke, v252 movi v1, 42 jeq v1, ok ldai 1 return ok: ldai 0 return } check-type: empty cases: - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i32 a1, i32 a2, i32 a3) - panda.Integer - sum32 - | # movi v253, 22 movi v254, 15 movi v255, 5 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i64 a1, i64 a2, i64 a3) - panda.Long - sum64 - | # movi.64 v253, -500 movi.64 v254, 1042 movi.64 v255, -500 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, i16 a1, i16 a2, i16 a3) - panda.Short - sum16 - | # movi v253, 1 movi v254, 2 movi v255, 39 - file-name: 'call_1v' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for virtual function with one argument. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) %s .function i32 R.inc32(R a0, i32 a1) { inci a1, 1 lda a1 return } .function i32 R.inc64(R a0, i64 a1) { ldai.64 2 add2.64 a1 i64toi32 return } .function i32 R.inc16(R a0, i16 a1) { inci a1, 3 lda a1 return } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.str "panda.Integer" sta.obj v1 call.short R.getPrimitiveType, v1 sta.obj v1 lda.str "%s" sta.obj v2 call.short R.getPrimitiveType, v2 sta.obj v2 call.short panda.invoke.MethodType.methodType, v1, v2 sta.obj v1 # MethodType object for (i32)i32 lda.type R sta.obj v2 lda.str "%s" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findVirtual, v0, v2, v3, v1 sta.obj v4 # MethodHandle object newobj v5, R %s call.polymorphic.range panda.invoke.MethodHandle.invoke, v4 movi v1, 42 jeq v1, ok ldai 1 return ok: ldai 0 return } check-type: empty cases: - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i32 a2) - panda.Integer - inc32 - movi v6, 41 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i64 a2) - panda.Long - inc64 - movi.64 v6, 40 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i16 a2) - panda.Short - inc16 - movi v6, 39 - file-name: 'call_2v' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for virtual function with two arguments. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class[] a1) %s .function i32 R.sum32(R a0, i32 a1, i32 a2) { add a1, a2 return } .function i32 R.sum64(R a0, i64 a1, i64 a2) { lda.64 a1 add2.64 a2 i64toi32 return } .function i32 R.sum16(R a0, i16 a1, i16 a2) { add a1, a2 return } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.str "panda.Integer" sta.obj v1 call.short R.getPrimitiveType, v1 sta.obj v1 lda.str "%s" sta.obj v2 call.short R.getPrimitiveType, v2 movi v3, 2 # 2 arguments newarr v2, v3, panda.Class[] movi v4, 0 starr.obj v2, v4 inci v4, 1 starr.obj v2, v4 call.short panda.invoke.MethodType.methodType, v1, v2 sta.obj v1 # MethodType object for (i32, i32)i32 lda.type R sta.obj v2 lda.str "%s" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findVirtual, v0, v2, v3, v1 sta.obj v4 # MethodHandle object newobj v5, R %s call.polymorphic.range panda.invoke.MethodHandle.invoke, v4 movi v1, 42 jeq v1, ok ldai 1 return ok: ldai 0 return } check-type: empty cases: - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i32 a2, i32 a3) - panda.Integer - sum32 - | # movi v6, 0x800000000039 movi v7, 0x7ffffffffff1 - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i64 a2, i64 a3) - panda.Long - sum64 - | # movi.64 v6, 0x800000000000002b movi.64 v7, 0x7fffffffffffffff - values: - .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1, i16 a2, i16 a3) - panda.Short - sum16 - | # movi v6, 0 movi v7, 42 - file-name: 'call_all_regs_v' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for virtual function with all register arguments used. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class[] a1) .function i32 panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, R a1%s) .function i32 R.sum32(R a0%s) { ldai 0 %s return } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.str "panda.Integer" sta.obj v1 call.short R.getPrimitiveType, v1 sta.obj v1 movi v5, 254 # array size newarr v2, v5, panda.Class[] # fill array from 0 to 253 movi v4, 0 # array index loop: lda.obj v1 starr.obj v2, v4 inci v4, 1 lda v4 jlt v5, loop call.short panda.invoke.MethodType.methodType, v1, v2 sta.obj v1 # MethodType object for (i32, i32, ...)i32 lda.type R sta.obj v2 lda.str "sum32" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findVirtual, v0, v2, v3, v1 sta.obj v0 # MethodHandle object newobj v1, R %s call.polymorphic.range panda.invoke.MethodHandle.invoke, v0 movi v1, 32639 jeq v1, ok ldai 1 return ok: ldai 0 return } check-type: empty cases: - values: - "#{[*2..255].map do |i| \", i32 a#{i}\" end .join}" - "#{[*1..254].map do |i| \", i32 a#{i}\" end .join}" - "#{[*1..254].map do |i| \" add2 a#{i}\\n\" end .join}" - "#{[*2..255].map do |i| \" movi v#{i}, #{i}\\n\" end .join}" - file-name: 'call_obj' isa: exceptions: [x_call] description: Check that polymorphic call throws right exception on invalid arguments. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | .function panda.invoke.MethodType panda.invoke.MethodType.methodType(panda.Class a0, panda.Class a1) .function R panda.invoke.MethodHandle.invoke(panda.invoke.MethodHandle a0, %s a1) .record panda.Exception .record E {} .record panda.ClassCastException .function R R.throwE(R a0) { newobj v0, E throw v0 lda.obj a0 return.obj } .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.type R sta.obj v1 call.short panda.invoke.MethodType.methodType, v1, v1 sta.obj v1 # MethodType object for (R)R lda.type R sta.obj v2 lda.str "throwE" sta.obj v3 call.virt panda.invoke.MethodHandles$Lookup.findStatic, v0, v2, v3, v1 sta.obj v5 # MethodHandle object newobj v6, %s try_begin: call.polymorphic.range panda.invoke.MethodHandle.invoke, v5 ldai 1 return try_end: catch_begin: ldai 0 return catch_end: %s } check-type: empty cases: - values: - E - E - .catch panda.ClassCastException, try_begin, try_end, catch_begin, catch_end - values: - W - W - .catch panda.ClassCastException, try_begin, try_end, catch_begin, catch_end - values: - R - R - .catch E, try_begin, try_end, catch_begin, catch_end - values: - Q - Q - .catch E, try_begin, try_end, catch_begin, catch_end - file-name: 'call_vh' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call is performed for field access. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | %s .function i32 R.test() { call.short panda.invoke.MethodHandles.lookup sta.obj v0 # MethodHandles.Lookup object lda.type R sta.obj v2 lda.str "%s" sta.obj v3 lda.str "%s" sta.obj v4 call.short R.getPrimitiveType, v4 sta.obj v4 call.virt panda.invoke.MethodHandles$Lookup.findVarHandle, v0, v2, v3, v4 sta.obj v5 # VarHandle object %s ldai 0 return fail: ldai 1 return } check-type: empty cases: - values: - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R a1, i32 a2) - f_int - panda.Integer - | # newobj v6, R movi v7, 42 call.polymorphic.range panda.invoke.VarHandle.set, v5 lda.null ldobj v6, R.f_int jne v7, fail - values: - .function i32 panda.invoke.VarHandle.get(panda.invoke.VarHandle a0, R a1) - f_int - panda.Integer - | # newobj v6, R movi v7, 42 lda v7 stobj v6, R.f_int lda.null call.polymorphic.range panda.invoke.VarHandle.get, v5 jne v7, fail - values: - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R a1, f64 a2) - f_double - panda.Double - | # newobj v6, R fmovi.64 v7, 42.4242 call.polymorphic.range panda.invoke.VarHandle.set, v5 lda.null ldobj.64 v6, R.f_double fcmpg.64 v7 jnez fail - values: - .function f64 panda.invoke.VarHandle.get(panda.invoke.VarHandle a0, R a1) - f_double - panda.Double - | # newobj v6, R fmovi.64 v7, 42.4242 lda.64 v7 stobj.64 v6, R.f_double lda.null call.polymorphic.range panda.invoke.VarHandle.get, v5 fcmpg.64 v7 jnez fail - values: - .function f32 panda.invoke.VarHandle.getAndSet(panda.invoke.VarHandle a0, R a1, f32 a2) - f_float - panda.Float - | # newobj v6, R fmovi v8, 3.141593 # initial value lda v8 stobj v6, R.f_float fmovi v7, 2.718282 # value to set by getAndSet lda.null call.polymorphic.range panda.invoke.VarHandle.getAndSet, v5 fcmpg v8 jnez fail ldobj v6, R.f_float fcmpg v7 jnez fail - values: - .function i64 panda.invoke.VarHandle.getAndAdd(panda.invoke.VarHandle a0, R a1, i64 a2) - f_long - panda.Long - | # newobj v6, R movi.64 v8, 0x7ffffffffffffffe # initial value lda.64 v8 stobj.64 v6, R.f_long movi.64 v7, 1 # value to add by getAndAdd lda.null call.polymorphic.range panda.invoke.VarHandle.getAndAdd, v5 cmp.64 v8 jnez fail ldobj.64 v6, R.f_long sub2.64 v7 cmp.64 v8 jnez fail - values: - .function i32 panda.invoke.VarHandle.getAndBitwiseOr(panda.invoke.VarHandle a0, R a1, i32 a2) - f_int - panda.Integer - | # newobj v6, R movi v8, 0xf0f0f0f0 # initial value lda v8 stobj v6, R.f_int movi v7, 0xa5a5a5a5 # value to OR by getAndBitwiseOr lda.null call.polymorphic.range panda.invoke.VarHandle.getAndBitwiseOr, v5 jne v8, fail or2 v7 sta v9 ldobj v6, R.f_int jne v9, fail - values: - .function i16 panda.invoke.VarHandle.getAndBitwiseAnd(panda.invoke.VarHandle a0, R a1, i16 a2) - f_short - panda.Short - | # newobj v6, R movi v8, 0x5a5a # initial value lda v8 stobj v6, R.f_short movi v7, 0x0f0f # value to AND by getAndBitwiseAnd lda.null call.polymorphic.range panda.invoke.VarHandle.getAndBitwiseAnd, v5 jne v8, fail and2 v7 sta v9 ldobj v6, R.f_short jne v9, fail - values: - .function i8 panda.invoke.VarHandle.getAndBitwiseXor(panda.invoke.VarHandle a0, R a1, i8 a2) - f_byte - panda.Byte - | # newobj v6, R ldai 0x35 # initial value i32toi8 sta v8 stobj v6, R.f_byte ldai 0x1f # value to XOR by getAndBitwiseXor i32toi8 sta v7 lda.null call.polymorphic.range panda.invoke.VarHandle.getAndBitwiseXor, v5 jne v8, fail xor2 v7 sta v9 ldobj v6, R.f_byte jne v9, fail - file-name: 'call_vh_exc' isa: instructions: - sig: call.polymorphic.range method_id, v:in:top prefix: PandaAssembly acc: out:top format: [pref_op_v_8_id_16] description: Check that polymorphic call of VarHandle is throwing exceptions as expected. runner-options: [use-pa, ] tags: ['irtoc_ignore'] bugid: ['7634'] header-template: [polymorphic-hdr] code-template: | %s .function panda.invoke.VarHandle panda.invoke.MethodHandles.arrayElementVarHandle(panda.Class a0) .function i32 R.test() { lda.type R[] sta.obj v1 call.short panda.invoke.MethodHandles.arrayElementVarHandle, v1 sta.obj v1 # VarHandle object movi v3, 3 # array size newarr v2, v3, R[] movi v3, 1 # element index newobj v4, R # object to set in R[1] try_begin: %s try_end: ldai 1 return catch_begin: ldai 0 return catch_end: } %s check-type: empty cases: - values: # no exceptions case, set R into R[] - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) - | # call.polymorphic.range panda.invoke.VarHandle.set, v1 ldai 0 ldarr.obj v2 jnez.obj try_end ldai 1 ldarr.obj v2 jeqz.obj try_end isinstance R jeqz try_end ldai 2 ldarr.obj v2 jeqz.obj catch_begin - '' - values: # no exceptions case. set Q into R[], Q extends R - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) - | # newobj v4, Q call.polymorphic.range panda.invoke.VarHandle.set, v1 ldai 0 ldarr.obj v2 jnez.obj try_end ldai 1 ldarr.obj v2 jeqz.obj try_end isinstance R jeqz try_end ldai 2 ldarr.obj v2 jeqz.obj catch_begin - '' - values: # ClassCastException is expected, set W into R[], W is not R - | .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, W a3) .record panda.ClassCastException - | # newobj v4, W call.polymorphic.range panda.invoke.VarHandle.set, v1 - .catch panda.ClassCastException, try_begin, try_end, catch_begin, catch_end - values: # NPE is expected, VarHandle ref is null - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) - | # mov.null v1 call.polymorphic.range panda.invoke.VarHandle.set, v1 - .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end - values: # NPE is expected, target array is null - .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) - | # mov.null v2 call.polymorphic.range panda.invoke.VarHandle.set, v1 - .catch panda.NullPointerException, try_begin, try_end, catch_begin, catch_end - values: # WrongMethodTypeException is expected - | .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2) .record panda.invoke.WrongMethodTypeException - | # call.polymorphic.range panda.invoke.VarHandle.set, v1 - .catch panda.invoke.WrongMethodTypeException, try_begin, try_end, catch_begin, catch_end - values: # ArrayIndexOutOfBoundsException is expected - | .function void panda.invoke.VarHandle.set(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) .record panda.ArrayIndexOutOfBoundsException - | # movi v3, 100 call.polymorphic.range panda.invoke.VarHandle.set, v1 - .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_begin, catch_end - values: # UnsupportedOperationException is expected - | .function void panda.invoke.VarHandle.getAndBitwiseAnd(panda.invoke.VarHandle a0, R[] a1, i32 a2, R a3) .record panda.UnsupportedOperationException - | # call.polymorphic.range panda.invoke.VarHandle.getAndBitwiseAnd, v1 - .catch panda.UnsupportedOperationException, try_begin, try_end, catch_begin, catch_end