diff --git a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java index 629656d..dbc07aa 100644 --- a/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/binary/BinaryModuleWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2021 Volker Berlin (i-net software) + * Copyright 2017 - 2022 Volker Berlin (i-net software) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1328,6 +1328,10 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod codeStream.writeVaruint32( i ); } break; + case BR_ON_NULL: + codeStream.writeOpCode( BR_ON_NULL ); + codeStream.writeVaruint32( (Integer)data ); + break; case LOOP: codeStream.writeOpCode( LOOP ); codeStream.writeValueType( ValueType.empty ); // void; the return type of the loop. currently we does not use it diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index 380d51a..c1d9478 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -514,6 +514,8 @@ public class TypeManager { WatCodeSyntheticFunctionName createInstanceOf() { return new WatCodeSyntheticFunctionName( // "instanceof", "local.get 0 " // THIS + + "ref.is_null if i32.const 0 return end " // NULL check + + "local.get 0 " // THIS + "struct.get java/lang/Object .vtable " // vtable is on index 0 + "local.tee 2 " // save the vtable location + "i32.load offset=" + TYPE_DESCRIPTION_INSTANCEOF_OFFSET + " align=4 " // get offset of instanceof inside vtable (int position 1, byte position 4) @@ -557,11 +559,14 @@ public class TypeManager { WatCodeSyntheticFunctionName createCast() { return new WatCodeSyntheticFunctionName( // "cast", "local.get 0 " // THIS + + "ref.is_null if local.get 0 return end " // NULL check + + "local.get 0 " // THIS + "local.get 1 " // the class index that we search + "call $.instanceof()V " // the synthetic signature of ArraySyntheticFunctionName - + "i32.eqz " // - + "local.get 0 " // THIS - + "return " // + + "if " // + + " local.get 0 " // THIS + + " return " // + + "end " // + "unreachable " // TODO throw a ClassCastException if exception handling is supported , valueOf( "java/lang/Object" ), ValueType.i32, null, valueOf( "java/lang/Object" ) ); } diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 5b41d14..3e5c46a 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 - 2021 Volker Berlin (i-net software) + * Copyright 2017 - 2022 Volker Berlin (i-net software) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -834,6 +834,9 @@ public class TextModuleWriter extends ModuleWriter { } name = builder.toString(); break; + case BR_ON_NULL: + name = "br_on_null " + data; + break; case LOOP: name = "loop"; insetAfter++; diff --git a/src/de/inetsoftware/jwebassembly/wasm/WasmBlockOperator.java b/src/de/inetsoftware/jwebassembly/wasm/WasmBlockOperator.java index 499f975..88c913d 100644 --- a/src/de/inetsoftware/jwebassembly/wasm/WasmBlockOperator.java +++ b/src/de/inetsoftware/jwebassembly/wasm/WasmBlockOperator.java @@ -1,5 +1,5 @@ /* - Copyright 2018 - 2019 Volker Berlin (i-net software) + Copyright 2018 - 2022 Volker Berlin (i-net software) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -32,6 +32,7 @@ public enum WasmBlockOperator { BR, BR_IF, BR_TABLE, + BR_ON_NULL, LOOP, UNREACHABLE, TRY, diff --git a/src/de/inetsoftware/jwebassembly/watparser/WatParser.java b/src/de/inetsoftware/jwebassembly/watparser/WatParser.java index ebb2f6b..5079e4e 100644 --- a/src/de/inetsoftware/jwebassembly/watparser/WatParser.java +++ b/src/de/inetsoftware/jwebassembly/watparser/WatParser.java @@ -1,5 +1,5 @@ /* - Copyright 2018 - 2021 Volker Berlin (i-net software) + Copyright 2018 - 2022 Volker Berlin (i-net software) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -272,6 +272,9 @@ public class WatParser extends WasmCodeBuilder { case "br_if": addBlockInstruction( WasmBlockOperator.BR_IF, getInt( tokens, ++i ), javaCodePos, lineNumber ); break; + case "br_on_null": + addBlockInstruction( WasmBlockOperator.BR_ON_NULL, getInt( tokens, ++i ), javaCodePos, lineNumber ); + break; case "throw": addBlockInstruction( WasmBlockOperator.THROW, null, javaCodePos, lineNumber ); break; diff --git a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java index 91b50df..e20ee39 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java +++ b/test/de/inetsoftware/jwebassembly/runtime/StructsNonGC.java @@ -61,7 +61,9 @@ public class StructsNonGC extends AbstractBaseTest { addParam( list, script, "instanceof1" ); addParam( list, script, "instanceof2" ); addParam( list, script, "instanceof3" ); - addParam( list, script, "cast" ); + addParam( list, script, "instanceof4" ); + addParam( list, script, "cast1" ); + addParam( list, script, "cast2" ); addParam( list, script, "objectClassName" ); addParam( list, script, "integerClassName" ); addParam( list, script, "classClassName" ); @@ -197,12 +199,25 @@ public class StructsNonGC extends AbstractBaseTest { } @Export - static int cast() { + static boolean instanceof4() { + Object obj = null; + return obj instanceof List; + } + + @Export + static int cast1() { Object obj = new Integer(42); Integer val = (Integer)obj; return val.intValue(); } + @Export + static Integer cast2() { + Object obj = null; + Integer val = (Integer)obj; + return val; + } + @Export static DOMString objectClassName() { Object obj = new Object();