yanoshiです。計算機との対話を10年以上続けていますが未だにうまくできた試しがありません。デレ期はいつ来ますか?
さて、計算機の世界には最適化という便利な概念があります。
思考停止ワードとして有名ですが、「計算機が真の力を発揮してくれれば…きっとうまくやってくれる!」という人間の願望がこもった素晴らしい言葉だと思いませんか?(白目
人間のために作ったはずの最適化も、時には人間に牙をむくこともあります。計算機との対話はいつもうまく行きません。人間の意図をちゃんと汲みとってくれるとは限りませんからね。
今日はそんな話。
経緯
TLを眺めていたらきくらげ氏が面白そうなおもちゃを見つけていました。
おもしろい。 pic.twitter.com/Fe3zs4hIeO
— きくらげ (@Kiikurage) 2016年6月21日
当たり前ですが、
typeof null === "undefined";
はfalse
になるはずです。ってことでこれは明らかにおかしい。
ちなみに枚方氏情報によるとNode.jsでも同じ症状が出るっぽい。ってことでやっぱり原因はV8かな。
— 枚方 (@cympfh) 2016年6月21日
遊ぶ
楽しそうだから私も遊んでみたんだなぁ。
ほんとになった。 https://t.co/8N18uiHWM0 pic.twitter.com/s2gzdWNESH
— yanoshi (@yanoshi) 2016年6月21日
@Kiikurage nullの解釈の問題では?って思ったけど、違いそうだなぁ…そもそもこれでも同じ挙動になるんだね。 pic.twitter.com/XoCZcLHiIw
— yanoshi (@yanoshi) 2016年6月21日
@Kiikurage ちゃんと出るね… pic.twitter.com/wtO4BL3DAx
— yanoshi (@yanoshi) 2016年6月21日
@Kiikurage 「諦める」気を削ぐようなコードにしたら、最後までfalseになった。 pic.twitter.com/WLOlIAfpCv
— yanoshi (@yanoshi) 2016年6月21日
@Kiikurage ちなみに諦めたくなるコードを書いてみたら、見事に諦めた!やったぁ! pic.twitter.com/KK4uCSUe7f
— yanoshi (@yanoshi) 2016年6月21日
V8の懺悔。楽しい(確信 pic.twitter.com/nx8dGBRu6j
— yanoshi (@yanoshi) 2016年6月21日
console.logはV8にとって「意味のある命令ではない」説。
— yanoshi (@yanoshi) 2016年6月21日
そうなるとconsole.logに渡される引数は容赦のない最適化の対象となるわけで、同じ出力が連続しているループにおいて一定数回数以上はサボることになったとかそういうあれかな?
予想に反して処理を諦めやがった… https://t.co/lY7ULfEG8R pic.twitter.com/5Ogh7UByER
— yanoshi (@yanoshi) 2016年6月21日
この場合だと諦めない。 pic.twitter.com/yOpPEJFSau
— yanoshi (@yanoshi) 2016年6月21日
これだと諦めた! pic.twitter.com/d2YAgVKjVr
— yanoshi (@yanoshi) 2016年6月21日
ということで、最適化がやっぱり原因っぽいねって感じ。演算子の数を増やすと処理をサボらなくなるしね。
結論
答えというかバグフィックス部分https://t.co/vPkolIdmHk
— きくらげ (@Kiikurage) 2016年6月21日
v8の二段階に分ける最適化のせいで、最初のうちは正しく実行されていたものが途中からバグったっぽい
— きくらげ (@Kiikurage) 2016年6月21日
ということでバグでしたとさ。そして既にV8の最新版では修正済み。
まとめ
「このバグを踏むなら今のうち!!」
for(var i=0; i<10000; i++) { document.write("私はバグってます:" + ((typeof null === "undefined")?"YES!<br />":"NO...<br />")); }
for(var i=0; i<100000; ++i) console.log(typeof null === "undefined");
闇だ…
やはりJavaScriptはアセンブラなのでは…()
— yanoshi (@yanoshi) 2016年6月21日