Closed2
j2cl wasm の出力を眺める
(なんか Bazel 5.4.0 だと動かなったので .bazelversion
を 6.4.0
にしたら大丈夫だった、7.0もダメそう)
// google/j2cl/samples/wasm/src/main/java/com/google/j2cl/samples/wasm/HelloWorld.java
package com.google.j2cl.samples.wasm;
class Animal {
String name;
Animal(String name) { this.name = name; }
void eat() { System.out.println(name + " is eating."); }
}
class Dog extends Animal {
Dog(String name) { super(name); }
String bark() { return "Woof! Woof!"; }
}
public class HelloWorld {
public static String getHelloWorld() {
Animal genericAnimal = new Animal("Generic Animal");
genericAnimal.eat();
System.out.println("---------------");
Dog myDog = new Dog("Buddy");
myDog.eat();
return myDog.bark();
}
}
$ cd samples/wasm
$ bazel build src/main/java/com/google/j2cl/samples/wasm:jsapp
$ cat bazel-out/darwin_arm64-fastbuild/bin/src/main/java/com/google/j2cl/samples/wasm/app.wat
;;; Code for com.google.j2cl.samples.wasm.Dog [type definition]
(type $com.google.j2cl.samples.wasm.Dog (sub $com.google.j2cl.samples.wasm.Animal (struct
(field $vtable (ref $com.google.j2cl.samples.wasm.Dog.vtable))
(field $itable (ref $itable))
(field $$systemIdentityHashCode@java.lang.Object (mut i32))
(field $name@com.google.j2cl.samples.wasm.Animal (mut (ref null $java.lang.String)))
))
)
(type $com.google.j2cl.samples.wasm.Dog.vtable (sub $com.google.j2cl.samples.wasm.Animal.vtable (struct
(field $$getClassImpl__java_lang_Class (ref $function.$getClassImpl__java_lang_Class))
(field $m_equals__java_lang_Object__boolean (ref $function.m_equals__java_lang_Object__boolean))
(field $m_getClass__java_lang_Class (ref $function.m_getClass__java_lang_Class))
(field $m_hashCode__int (ref $function.m_hashCode__int))
(field $m_toString__java_lang_String (ref $function.m_toString__java_lang_String))
(field $m_eat__void_$pp_com_google_j2cl_samples_wasm (ref $function.m_eat__void_$pp_com_google_j2cl_samples_wasm))
(field $m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm (ref $function.m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm))
))
)
;;; End of code for com.google.j2cl.samples.wasm.Dog [type definition]
;;; String HelloWorld.getHelloWorld()
(func $m_getHelloWorld__java_lang_String@com.google.j2cl.samples.wasm.HelloWorld
(result (ref null $java.lang.String))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:37:25
(local $genericAnimal (ref null $com.google.j2cl.samples.wasm.Animal))
(local $$qualifier (ref null $java.io.PrintStream))
(local $myDog (ref null $com.google.j2cl.samples.wasm.Dog))
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:37:41
(call $$clinit__void_<once>_@com.google.j2cl.samples.wasm.HelloWorld )
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:38:8
(local.set $genericAnimal (call $$create__java_lang_String@com.google.j2cl.samples.wasm.Animal (call $$getString_|Generic_Animal|__java_lang_String_<once>_@com.google.j2cl.samples.wasm.HelloWorld )))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:39:8
(call_ref $function.m_eat__void_$pp_com_google_j2cl_samples_wasm (ref.as_non_null (local.get $genericAnimal))(struct.get $com.google.j2cl.samples.wasm.Animal.vtable $m_eat__void_$pp_com_google_j2cl_samples_wasm (struct.get $com.google.j2cl.samples.wasm.Animal $vtable(local.get $genericAnimal))))
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:41:8
(local.set $$qualifier (block (result (ref null $java.io.PrintStream))
(call $$clinit__void_<once>_@java.lang.System )
(global.get $out@java.lang.System)
))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:41:8
(call_ref $function.m_println__java_lang_String__void (ref.as_non_null (local.get $$qualifier))(call $$getString_|_______________|__java_lang_String_<once>_@com.google.j2cl.samples.wasm.HelloWorld )(struct.get $java.io.PrintStream.vtable $m_println__java_lang_String__void (struct.get $java.io.PrintStream $vtable(local.get $$qualifier))))
)
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:43:8
(local.set $myDog (call $$create__java_lang_String@com.google.j2cl.samples.wasm.Dog (call $$getString_|Buddy|__java_lang_String_<once>_@com.google.j2cl.samples.wasm.HelloWorld )))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:44:8
(call_ref $function.m_eat__void_$pp_com_google_j2cl_samples_wasm (ref.as_non_null (local.get $myDog))(struct.get $com.google.j2cl.samples.wasm.Animal.vtable $m_eat__void_$pp_com_google_j2cl_samples_wasm (struct.get $com.google.j2cl.samples.wasm.Animal $vtable(local.get $myDog))))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:45:8
(return (call_ref $function.m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm (ref.as_non_null (local.get $myDog))(struct.get $com.google.j2cl.samples.wasm.Dog.vtable $m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm (struct.get $com.google.j2cl.samples.wasm.Dog $vtable(local.get $myDog)))))
)
)
このへん見ると分かるけど、Kotlin/Wasm と同様に各オブジェクトは vtable や itable へのインスタンスを持っている形。
(call_ref $function.m_eat__void_$pp_com_google_j2cl_samples_wasm (ref.as_non_null (local.get $myDog))(struct.get $com.google.j2cl.samples.wasm.Animal.vtable $m_eat__void_$pp_com_google_j2cl_samples_wasm (struct.get $com.google.j2cl.samples.wasm.Animal $vtable(local.get $myDog))))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:45:8
(return (call_ref $function.m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm (ref.as_non_null (local.get $myDog))(struct.get $com.google.j2cl.samples.wasm.Dog.vtable $m_bark__java_lang_String_$pp_com_google_j2cl_samples_wasm (struct.get $com.google.j2cl.samples.wasm.Dog $vtable(local.get $myDog)))))
https://zenn.dev/tanishiking/scraps/f5c9566bf67cad に少し書いたけど、j2clのinterface dispatchも似たような感じ
package com.google.j2cl.samples.wasm;
interface Animal {
public void sound();
}
class Cat implements Animal {
public void sound() {}
}
class Lion extends Cat implements Animal {
}
public class HelloWorld {
public static String getHelloWorld() {
Lion lion = new Lion();
doSound(lion);
return "hello";
}
private static void doSound(Animal animal) {
animal.sound();
}
}
これは
;;; Code for com.google.j2cl.samples.wasm.Animal [type definition]
(type $com.google.j2cl.samples.wasm.Animal.vtable (sub (struct
(field $m_sound__void (ref $function.m_sound__void))
))
)
;;; End of code for com.google.j2cl.samples.wasm.Animal [type definition]
Cat
;;; Code for com.google.j2cl.samples.wasm.Cat [type definition]
(type $com.google.j2cl.samples.wasm.Cat (sub $java.lang.Object (struct
(field $vtable (ref $com.google.j2cl.samples.wasm.Cat.vtable))
(field $itable (ref $com.google.j2cl.samples.wasm.Cat.itable))
(field $$systemIdentityHashCode@java.lang.Object (mut i32))
))
)
(type $com.google.j2cl.samples.wasm.Cat.vtable (sub $java.lang.Object.vtable (struct
(field $$getClassImpl__java_lang_Class (ref $function.$getClassImpl__java_lang_Class))
(field $m_equals__java_lang_Object__boolean (ref $function.m_equals__java_lang_Object__boolean))
(field $m_getClass__java_lang_Class (ref $function.m_getClass__java_lang_Class))
(field $m_hashCode__int (ref $function.m_hashCode__int))
(field $m_toString__java_lang_String (ref $function.m_toString__java_lang_String))
(field $m_sound__void (ref $function.m_sound__void))
))
)
(type $com.google.j2cl.samples.wasm.Cat.itable (sub $itable (struct
(field $slot0 (ref $com.google.j2cl.samples.wasm.Animal.vtable))
(field $slot1 (ref null struct))
(field $slot2 (ref null struct))
(field $slot3 (ref null struct))
(field $slot4 (ref null struct))
(field $slot5 (ref null struct))
(field $slot6 (ref null struct))
)))
;;; End of code for com.google.j2cl.samples.wasm.Cat [type definition]
HelloWorld
;;; String HelloWorld.getHelloWorld()
(func $m_getHelloWorld__java_lang_String@com.google.j2cl.samples.wasm.HelloWorld
(result (ref null $java.lang.String))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:30:25
(local $lion (ref null $com.google.j2cl.samples.wasm.Lion))
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:30:41
(call $$clinit__void_<once>_@com.google.j2cl.samples.wasm.HelloWorld )
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:31:8
(local.set $lion (call $$create__@com.google.j2cl.samples.wasm.Lion ))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:32:8
(call $m_doSound__com_google_j2cl_samples_wasm_Animal__void@com.google.j2cl.samples.wasm.HelloWorld (local.get $lion))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:33:8
(return (call $$getString_|hello|__java_lang_String_<once>_@com.google.j2cl.samples.wasm.HelloWorld ))
)
)
-
$$clinit__void_<once>_@com.google.j2cl.samples.wasm.HelloWorld
これはなんだろう、各クラスの何かの呼び出しの最初に実行されてそう。 -
$$create__@com.google.j2cl.samples.wasm.Lion
で Lion インスタンスを作る -
$m_doSound__com_google_j2cl_samples_wasm_Animal__void@com.google.j2cl.samples.wasm.HelloWorld
(名前長い!!!) をlocal.get $lion
を引数にして call - 文字列作ってreturn
;;; void HelloWorld.$clinit()
(func $$clinit__void_<once>_@com.google.j2cl.samples.wasm.HelloWorld
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:29:13
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:29:13
(if (global.get $$class-initialized@com.google.j2cl.samples.wasm.HelloWorld)
(then
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:29:13
(return )
)
)
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:29:13
(global.set $$class-initialized@com.google.j2cl.samples.wasm.HelloWorld (i32.const 1))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:29:13
(call $$clinit__void_<once>_@java.lang.Object )
)
)
なんだこれは? module initialize 的なやつが入るのかな?
Lion constructor
;;; Lion Lion.$create()
(func $$create__@com.google.j2cl.samples.wasm.Lion
(result (ref null $com.google.j2cl.samples.wasm.Lion))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(local $$instance (ref null $com.google.j2cl.samples.wasm.Lion))
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(call $$clinit__void_<once>_@com.google.j2cl.samples.wasm.Lion )
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(local.set $$instance (struct.new $com.google.j2cl.samples.wasm.Lion (ref.as_non_null (global.get $com.google.j2cl.samples.wasm.Lion.vtable)) (ref.as_non_null (global.get $com.google.j2cl.samples.wasm.Lion.itable)) (i32.const 0)))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(call $$ctor__void_$p_com_google_j2cl_samples_wasm_Lion@com.google.j2cl.samples.wasm.Lion (ref.as_non_null (local.get $$instance)))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(return (local.get $$instance))
)
)
$$instance
に struct.new ...
で vtable や itable などを追加して constructor を実行
;;; void Lion.$ctor()
(func $$ctor__void_$p_com_google_j2cl_samples_wasm_Lion@com.google.j2cl.samples.wasm.Lion
(param $this (ref null $com.google.j2cl.samples.wasm.Lion))
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(block
;;@ com/google/j2cl/samples/wasm/HelloWorld.java:26:6
(call $$ctor__void_$p_com_google_j2cl_samples_wasm_Cat@com.google.j2cl.samples.wasm.Cat (ref.as_non_null (local.get $this)))
)
)
interface dispatch
;;; void HelloWorld.doSound(Animal animal)
(func $m_doSound__com_google_j2cl_samples_wasm_Animal__void@com.google.j2cl.samples.wasm.HelloWorld
(param $animal (ref null $java.lang.Object))
(call_ref $function.m_sound__void
(ref.as_non_null (local.get $animal))
(struct.get
$com.google.j2cl.samples.wasm.Animal.vtable
$m_sound__void
(ref.cast
(ref $com.google.j2cl.samples.wasm.Animal.vtable)
(struct.get
$itable
$slot0
(struct.get
$java.lang.Object
$itable
(local.get $animal)
)
)
)
)
)
)
static interface は java.lang.Object になってる。ref.cast
で itable の slot を vtable に変換して call_ref
このスクラップは2024/01/05にクローズされました