XMLVM
最近、XMLVMを触ってる。
JavaバイトコードやCILを、XMLVMの名前通りXML形式の中間表現に変換し、それをXSLTなどでC/Objective-CやJavaScriptを出力している。
直近の日記がそればっかだけど、飽きずにaobenchを例にすると、Javaのコードが
void intersect(Intersection isect, Ray ray) { double d = -p.dot(n); double v = ray.dir.dot(n); if (Math.abs(v) < 1.0e-6) return; // the plane is parallel to the ray. double t = -(ray.org.dot(n) + d) / v; if ((t > 0) && (t < isect.t)) { isect.hit = true; isect.t = t; isect.n.set(n); isect.p.set(ray.org.x + t * ray.dir.x, ray.org.y + t * ray.dir.y, ray.org.z + t * ray.dir.z); } }
DalvikのXML表現で次のようになって
<vm:method name="intersect" signature="(Laobench/Intersection;Laobench/Ray;)V"> <vm:signature> <vm:parameter type="aobench.Intersection" /> <vm:parameter type="aobench.Ray" /> <vm:return type="void" /> </vm:signature> <dex:code register-size="14"> <dex:var name="this" register="11" type="aobench.Sphere" /> <dex:var name="var-register-12" register="12" param-index="0" type="aobench.Intersection" /> <dex:var name="var-register-13" register="13" param-index="1" type="aobench.Ray" /> <dex:const-wide-16 type="double" value="0.0" vx="8" vx-type="double" /> <dex:iget-object kind="field" class-type="aobench.Sphere" member-type="aobench.Vec" member-name="rs" vx="0" vx-type="aobench.Vec" vy="11" vy-type="aobench.Sphere" /> <dex:iget-object kind="field" class-type="aobench.Ray" member-type="aobench.Vec" member-name="org" vx="1" vx-type="aobench.Vec" vy="13" vy-type="aobench.Ray" /> <dex:iget-object kind="field" class-type="aobench.Sphere" member-type="aobench.Vec" member-name="center" vx="2" vx-type="aobench.Vec" vy="11" vy-type="aobench.Sphere" /> <dex:invoke-virtual class-type="aobench.Vec" method="sub" register="0"> <dex:parameters> <dex:parameter type="aobench.Vec" register="1" /> <dex:parameter type="aobench.Vec" register="2" /> <dex:return type="aobench.Vec" /> </dex:parameters> </dex:invoke-virtual> <dex:iget-object kind="field" class-type="aobench.Sphere" member-type="aobench.Vec" member-name="rs" vx="0" vx-type="aobench.Vec" vy="11" vy-type="aobench.Sphere" /> <dex:iget-object kind="field" class-type="aobench.Ray" member-type="aobench.Vec" member-name="dir" vx="1" vx-type="aobench.Vec" vy="13" vy-type="aobench.Ray" /> <!-- 省略 --> <dex:iget-object kind="field" class-type="aobench.Intersection" member-type="aobench.Vec" member-name="n" vx="0" vx-type="aobench.Vec" vy="12" vy-type="aobench.Intersection" /> <dex:invoke-virtual class-type="aobench.Vec" method="normalize" register="0"> <dex:parameters> <dex:return type="void" /> </dex:parameters> </dex:invoke-virtual> <dex:label id="112" /> <dex:return-void /> </dex:code> </vm:method>
これをこんなXSLTで変換して
<xsl:template match="dex:add-int|dex:add-int-2addr"> <xsl:text> _r</xsl:text> <xsl:value-of select="@vx"/> <xsl:text>.i = _r</xsl:text> <xsl:value-of select="@vy"/> <xsl:text>.i + _r</xsl:text> <xsl:value-of select="@vz"/> <xsl:text>.i; </xsl:text> </xsl:template>
最終的にこうなる
void aobench_Sphere_intersect___aobench_Intersection_aobench_Ray(JAVA_OBJECT me, JAVA_OBJECT n1, JAVA_OBJECT n2) { //XMLVM_BEGIN_WRAPPER[aobench_Sphere_intersect___aobench_Intersection_aobench_Ray] XMLVM_ENTER_METHOD("aobench.Sphere", "intersect", "?") XMLVMElem _r0; XMLVMElem _r1; XMLVMElem _r2; XMLVMElem _r3; XMLVMElem _r4; XMLVMElem _r5; XMLVMElem _r6; XMLVMElem _r7; XMLVMElem _r8; XMLVMElem _r9; XMLVMElem _r10; XMLVMElem _r11; XMLVMElem _r12; XMLVMElem _r13; _r11.o = me; _r12.o = n1; _r13.o = n2; _r8.d = 0.0; XMLVM_CHECK_NPE(11) _r0.o = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.rs_; XMLVM_CHECK_NPE(13) _r1.o = ((aobench_Ray*) _r13.o)->fields.aobench_Ray.org_; XMLVM_CHECK_NPE(11) _r2.o = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.center_; XMLVM_CHECK_NPE(0) aobench_Vec_sub___aobench_Vec_aobench_Vec(_r0.o, _r1.o, _r2.o); XMLVM_CHECK_NPE(11) _r0.o = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.rs_; XMLVM_CHECK_NPE(13) _r1.o = ((aobench_Ray*) _r13.o)->fields.aobench_Ray.dir_; XMLVM_CHECK_NPE(0) _r0.d = aobench_Vec_dot___aobench_Vec(_r0.o, _r1.o); XMLVM_CHECK_NPE(11) _r2.o = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.rs_; XMLVM_CHECK_NPE(11) _r3.o = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.rs_; XMLVM_CHECK_NPE(2) _r2.d = aobench_Vec_dot___aobench_Vec(_r2.o, _r3.o); XMLVM_CHECK_NPE(11) _r4.d = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.radius_; XMLVM_CHECK_NPE(11) _r6.d = ((aobench_Sphere*) _r11.o)->fields.aobench_Sphere.radius_; _r4.d = _r4.d * _r6.d; _r2.d = _r2.d - _r4.d; _r4.d = _r0.d * _r0.d; _r2.d = _r4.d - _r2.d; _r4.i = _r2.d > _r8.d ? 1 : (_r2.d == _r8.d ? 0 : -1); if (_r4.i <= 0) goto label112; _r0.d = -_r0.d; _r2.d = java_lang_Math_sqrt___double(_r2.d); _r5.d = _r0.d - _r2.d; _r0.i = _r5.d > _r8.d ? 1 : (_r5.d == _r8.d ? 0 : -1); // 省略 _r0.o = ((aobench_Intersection*) _r12.o)->fields.aobench_Intersection.n_; XMLVM_CHECK_NPE(0) aobench_Vec_normalize__(_r0.o); label112:; XMLVM_EXIT_METHOD() return; //XMLVM_END_WRAPPER }
実行してみると
$ time java -cp build/classes/ aobench.AO real 0m2.368s user 0m0.015s sys 0m0.015s $ time ./build/aobench.exe real 1m7.242s user 1m5.660s sys 0m0.233s $ cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 42 model name : Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz
実行速度はそれなり。
会社のJava資産をiOSに持っていけないかと実験したりパッチ投げたりしてるけど、全く枯れてなくて困るので皆さんもっと人柱になりましょう。