K.Sasada's Home Page

Diary - 2005 June

研究日記

水無月

_30(Thu)

評価の合間に読んでいたハリーポッターを読みきってしまった orz


明示的に変数(の値)の生存範囲を指定できればいいのに。現在ではこれをやるために

{
  VALUE v = x;
  ...
}
{
  VALUE v = y;
  ...
}

と、ブロックを切ってやってるんだけど、gcc はそれぞれ別の領域を割り当ててしまう。つまり、上記ブロックが大量に、1000個くらいあると、1000個の領域をスタックから取ってしまう。

だけど、

VALUE v;
{
  v = x;
}
{
  v = y;
}

にすると、コンパイラの最適化が難しくなりそうな気がするんだけれど。きちんと代入によって分けてくれるかな。


あれ、単純な例だと再現しない。


よくよく調べてみると、きちんと共有できるところは共有してた。

[[-1220, [["epc:(1,11)", 109], ["epc:(1,11)", 109]]],
 [-1216,
  [["len:(0,1)", 7987],
   ["len:(0,1)", 8068],
   ["len:(0,1)", 8149],
   ["len:(0,1)", 8230]]],
 [-1212,
  [["iseqobj:(55,21)", 108],
   ["len:(0,1)", 831],
   ["len:(0,1)", 7906],
   ["iseqobj:(55,21)", 108]]],
 [-1200, [["cont_sp:(1,11)", 109], ["cont_sp:(1,11)", 109]]],
 [-1196, [["cont:(1,11)", 109], ["cont:(1,11)", 109]]],
 [-1192, [["catch_iseq:(2,1)", 107], ["catch_iseq:(2,1)", 107]]],
 [-1188, [["val_1:(2,1)", 22789], ["val_1:(2,1)", 22789]]],
 [-1184, [["val_1:(2,1)", 22723], ["val_1:(2,1)", 22723]]],
 [-1180, [["val_1:(2,1)", 22657], ["val_1:(2,1)", 22657]]],
 [-1176, [["val_1:(2,1)", 22591], ["val_1:(2,1)", 22591]]],
 [-1172, [["val_1:(2,1)", 22525], ["val_1:(2,1)", 22525]]],
 [-1168,
  [["prev_lfp:(2,13)", 15088],
   ["prev_lfp:(2,13)", 15088],
   ["prev_lfp:(2,13)", 15088]]],
 [-1164,
  [["prev_dfp:(2,13)", 15088],
   ["prev_dfp:(2,13)", 15088],
   ["prev_dfp:(2,13)", 15088]]],
 [-1160,
  [["iseq:(2,1)", 15087], ["iseq:(2,1)", 15087], ["iseq:(2,1)", 15087]]],
 [-1156,
  [["prev_lfp:(2,13)", 14994],
   ["prev_lfp:(2,13)", 14994],
   ["prev_lfp:(2,13)", 14994]]],
 [-1152,
  [["prev_dfp:(2,13)", 14994],
   ["prev_dfp:(2,13)", 14994],
   ["prev_dfp:(2,13)", 14994]]],
 [-1148,
  [["iseq:(2,1)", 14993], ["iseq:(2,1)", 14993], ["iseq:(2,1)", 14993]]],
 [-1144,
  [["prev_lfp:(2,13)", 14900],
   ["prev_lfp:(2,13)", 14900],
   ["prev_lfp:(2,13)", 14900]]],
 [-1140,
  [["prev_dfp:(2,13)", 14900],
   ["prev_dfp:(2,13)", 14900],
   ["prev_dfp:(2,13)", 14900]]],
 [-1136,
  [["iseq:(2,1)", 14899], ["iseq:(2,1)", 14899], ["iseq:(2,1)", 14899]]],
 [-1132,
  [["prev_lfp:(2,13)", 14807],
   ["prev_lfp:(2,13)", 14807],
   ["prev_lfp:(2,13)", 14807]]],
 [-1128,
  [["prev_dfp:(2,13)", 14807],
   ["prev_dfp:(2,13)", 14807],
   ["prev_dfp:(2,13)", 14807]]],
 [-1124,
  [["iseq:(2,1)", 14806], ["iseq:(2,1)", 14806], ["iseq:(2,1)", 14806]]],
 [-1120,
  [["prev_lfp:(2,13)", 14714],
   ["prev_lfp:(2,13)", 14714],
   ["prev_lfp:(2,13)", 14714]]],
 [-1116,
  [["prev_dfp:(2,13)", 14714],
   ["prev_dfp:(2,13)", 14714],
   ["prev_dfp:(2,13)", 14714]]],
 [-1112,
  [["iseq:(2,1)", 14713], ["iseq:(2,1)", 14713], ["iseq:(2,1)", 14713]]],
 [-1108,
  [["clear_local_size:(0,1)", 14213],
   ["clear_local_size:(0,1)", 14213],
   ["clear_local_size:(0,1)", 14213]]],
 [-1104,
  [["opt_pc:(0,1)", 14212], ["opt_pc:(0,1)", 14212], ["opt_pc:(0,1)", 14212]]],
 [-1100,
  [["newiseq:(2,1)", 14210],
   ["newiseq:(2,1)", 14210],
   ["newiseq:(2,1)", 14210]]],
 [-1096,
  [["niseqobj:(55,21)", 14209],
   ["niseqobj:(55,21)", 14209],
   ["niseqobj:(55,21)", 14209]]],
 [-1092,
  [["num:(1,11)", 14008],
   ["num:(1,11)", 14008],
   ["num:(1,11)", 14008],
   ["num:(1,11)", 14008]]],
 [-1088,
  [["block_ptr:(51,5)", 14007],
   ["block_ptr:(51,5)", 14007],
   ["block_ptr:(51,5)", 14007],
   ["block_ptr:(51,5)", 14007]]],
 [-1084,
  [["klass:(2,1)", 14006],
   ["klass:(2,1)", 14006],
   ["klass:(2,1)", 14006],
   ["klass:(2,1)", 14006]]],
 [-1080,
  [["procblock:(2,1)", 14005],
   ["procblock:(2,1)", 14005],
   ["procblock:(2,1)", 14005],
   ["procblock:(2,1)", 14005]]],
 [-1076,
  [["recv:(2,1)", 14004],
   ["recv:(2,1)", 14004],
   ["recv:(2,1)", 14004],
   ["recv:(2,1)", 14004]]],
 [-1072,
  [["id:(2,2)", 13986],
   ["id:(2,2)", 13986],
   ["id:(2,2)", 13986],
   ["id:(2,2)", 13986]]],
 [-1068,
  [["block:(2,1)", 13984],
   ["block:(2,1)", 13984],
   ["block:(2,1)", 13984],
   ["block:(2,1)", 13984]]],
 [-1064,
  [["ic:(55,29)", 13982],
   ["ic:(55,29)", 13982],
   ["ic:(55,29)", 13982],
   ["ic:(55,29)", 13982]]],
 [-1060,
  [["clear_local_size:(0,1)", 13805],
   ["clear_local_size:(0,1)", 13805],
   ["clear_local_size:(0,1)", 13805]]],
 [-1056,
  [["opt_pc:(0,1)", 13804], ["opt_pc:(0,1)", 13804], ["opt_pc:(0,1)", 13804]]],
 [-1052,
  [["newiseq:(2,1)", 13802],
   ["newiseq:(2,1)", 13802],
   ["newiseq:(2,1)", 13802]]],
 [-1048,
  [["niseqobj:(55,21)", 13801],
   ["niseqobj:(55,21)", 13801],
   ["niseqobj:(55,21)", 13801]]],
 [-1044,
  [["num:(1,11)", 13600],
   ["num:(1,11)", 13600],
   ["num:(1,11)", 13600],
   ["num:(1,11)", 13600]]],
 [-1040,
  [["block_ptr:(51,5)", 13599],
   ["block_ptr:(51,5)", 13599],
   ["block_ptr:(51,5)", 13599],
   ["block_ptr:(51,5)", 13599]]],
 [-1036,
  [["klass:(2,1)", 13598],
   ["klass:(2,1)", 13598],
   ["klass:(2,1)", 13598],
   ["klass:(2,1)", 13598]]],
 [-1032,
  [["procblock:(2,1)", 13597],
   ["procblock:(2,1)", 13597],
   ["procblock:(2,1)", 13597],
   ["procblock:(2,1)", 13597]]],
 [-1028,
  [["recv:(2,1)", 13596],
   ["recv:(2,1)", 13596],
   ["recv:(2,1)", 13596],
   ["recv:(2,1)", 13596]]],
 [-1024,
  [["id:(2,2)", 13578],
   ["id:(2,2)", 13578],
   ["id:(2,2)", 13578],
   ["id:(2,2)", 13578]]],
 [-1020,
  [["block:(2,1)", 13576],
   ["block:(2,1)", 13576],
   ["block:(2,1)", 13576],
   ["block:(2,1)", 13576]]],
 [-1016,
  [["ic:(55,29)", 13574],
   ["ic:(55,29)", 13574],
   ["ic:(55,29)", 13574],
   ["ic:(55,29)", 13574]]],
 [-1012,
  [["clear_local_size:(0,1)", 13397],
   ["clear_local_size:(0,1)", 13397],
   ["clear_local_size:(0,1)", 13397]]],
 [-1008,
  [["opt_pc:(0,1)", 13396], ["opt_pc:(0,1)", 13396], ["opt_pc:(0,1)", 13396]]],
 [-1004,
  [["newiseq:(2,1)", 13394],
   ["newiseq:(2,1)", 13394],
   ["newiseq:(2,1)", 13394]]],
 [-1000,
  [["niseqobj:(55,21)", 13393],
   ["niseqobj:(55,21)", 13393],
   ["niseqobj:(55,21)", 13393]]],
 [-996,
  [["num:(1,11)", 13192],
   ["num:(1,11)", 13192],
   ["num:(1,11)", 13192],
   ["num:(1,11)", 13192]]],
 [-992,
  [["block_ptr:(51,5)", 13191],
   ["block_ptr:(51,5)", 13191],
   ["block_ptr:(51,5)", 13191],
   ["block_ptr:(51,5)", 13191]]],
 [-988,
  [["klass:(2,1)", 13190],
   ["klass:(2,1)", 13190],
   ["klass:(2,1)", 13190],
   ["klass:(2,1)", 13190]]],
 [-984,
  [["procblock:(2,1)", 13189],
   ["procblock:(2,1)", 13189],
   ["procblock:(2,1)", 13189],
   ["procblock:(2,1)", 13189]]],
 [-980,
  [["recv:(2,1)", 13188],
   ["recv:(2,1)", 13188],
   ["recv:(2,1)", 13188],
   ["recv:(2,1)", 13188]]],
 [-976,
  [["id:(2,2)", 13170],
   ["id:(2,2)", 13170],
   ["id:(2,2)", 13170],
   ["id:(2,2)", 13170]]],
 [-972,
  [["block:(2,1)", 13168],
   ["block:(2,1)", 13168],
   ["block:(2,1)", 13168],
   ["block:(2,1)", 13168]]],
 [-968,
  [["ic:(55,29)", 13166],
   ["ic:(55,29)", 13166],
   ["ic:(55,29)", 13166],
   ["ic:(55,29)", 13166]]],
 [-964,
  [["clear_local_size:(0,1)", 12990],
   ["clear_local_size:(0,1)", 12990],
   ["clear_local_size:(0,1)", 12990]]],
 [-960,
  [["opt_pc:(0,1)", 12989], ["opt_pc:(0,1)", 12989], ["opt_pc:(0,1)", 12989]]],
 [-956,
  [["newiseq:(2,1)", 12987],
   ["newiseq:(2,1)", 12987],
   ["newiseq:(2,1)", 12987]]],
 [-952,
  [["niseqobj:(55,21)", 12986],
   ["niseqobj:(55,21)", 12986],
   ["niseqobj:(55,21)", 12986]]],
 [-948,
  [["num:(1,11)", 12785],
   ["num:(1,11)", 12785],
   ["num:(1,11)", 12785],
   ["num:(1,11)", 12785]]],
 [-944,
  [["block_ptr:(51,5)", 12784],
   ["block_ptr:(51,5)", 12784],
   ["block_ptr:(51,5)", 12784],
   ["block_ptr:(51,5)", 12784]]],
 [-940,
  [["klass:(2,1)", 12783],
   ["klass:(2,1)", 12783],
   ["klass:(2,1)", 12783],
   ["klass:(2,1)", 12783]]],
 [-936,
  [["procblock:(2,1)", 12782],
   ["procblock:(2,1)", 12782],
   ["procblock:(2,1)", 12782],
   ["procblock:(2,1)", 12782]]],
 [-932,
  [["recv:(2,1)", 12781],
   ["recv:(2,1)", 12781],
   ["recv:(2,1)", 12781],
   ["recv:(2,1)", 12781]]],
 [-928,
  [["id:(2,2)", 12763],
   ["id:(2,2)", 12763],
   ["id:(2,2)", 12763],
   ["id:(2,2)", 12763]]],
 [-924,
  [["block:(2,1)", 12761],
   ["block:(2,1)", 12761],
   ["block:(2,1)", 12761],
   ["block:(2,1)", 12761]]],
 [-920,
  [["ic:(55,29)", 12759],
   ["ic:(55,29)", 12759],
   ["ic:(55,29)", 12759],
   ["ic:(55,29)", 12759]]],
 [-916, [["pack_size:(0,1)", 12610], ["pack_size:(0,1)", 12610]]],
 [-912,
  [["opt_pc:(0,1)", 12582], ["opt_pc:(0,1)", 12582], ["opt_pc:(0,1)", 12582]]],
 [-908,
  [["newiseq:(2,1)", 12580],
   ["newiseq:(2,1)", 12580],
   ["newiseq:(2,1)", 12580]]],
 [-904,
  [["niseqobj:(55,21)", 12579],
   ["niseqobj:(55,21)", 12579],
   ["niseqobj:(55,21)", 12579]]],
 [-900,
  [["num:(1,11)", 12378],
   ["num:(1,11)", 12378],
   ["num:(1,11)", 12378],
   ["num:(1,11)", 12378],
   ["num:(1,11)", 12378],
   ["num:(1,11)", 12378],
   ["num:(1,11)", 12378]]],
 [-896,
  [["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377],
   ["block_ptr:(51,5)", 12377]]],
 [-892,
  [["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376],
   ["klass:(2,1)", 12376]]],
 [-888,
  [["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375],
   ["procblock:(2,1)", 12375]]],
 [-884,
  [["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374],
   ["recv:(2,1)", 12374]]],
 [-880,
  [["id:(2,2)", 12356],
   ["id:(2,2)", 12356],
   ["id:(2,2)", 12356],
   ["id:(2,2)", 12356],
   ["id:(2,2)", 12356],
   ["id:(2,2)", 12356],
   ["id:(2,2)", 12356]]],
 [-876,
  [["block:(2,1)", 12354],
   ["block:(2,1)", 12354],
   ["block:(2,1)", 12354],
   ["block:(2,1)", 12354],
   ["block:(2,1)", 12354],
   ["block:(2,1)", 12354],
   ["block:(2,1)", 12354]]],
 [-872,
  [["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352],
   ["ic:(55,29)", 12352]]],
 [-868, [["module:(2,1)", 12131], ["module:(2,1)", 12131]]],
 [-864, [["module_iseq:(2,1)", 12115], ["module_iseq:(2,1)", 12115]]],
 [-860, [["module:(2,1)", 12034], ["module:(2,1)", 12034]]],
 [-856, [["module_iseq:(2,1)", 12018], ["module_iseq:(2,1)", 12018]]],
 [-852, [["module:(2,1)", 11937], ["module:(2,1)", 11937]]],
 [-848, [["module_iseq:(2,1)", 11921], ["module_iseq:(2,1)", 11921]]],
 [-844, [["module:(2,1)", 11840], ["module:(2,1)", 11840]]],
 [-840, [["module_iseq:(2,1)", 11824], ["module_iseq:(2,1)", 11824]]],
 [-836, [["module:(2,1)", 11743], ["module:(2,1)", 11743]]],
 [-832, [["module_iseq:(2,1)", 11726], ["module_iseq:(2,1)", 11726]]],
 [-828, [["klass:(2,1)", 11494], ["klass:(2,1)", 11494]]],
 [-824, [["super:(2,1)", 11480], ["super:(2,1)", 11480]]],
 [-820, [["klass_iseq:(2,1)", 11477], ["klass_iseq:(2,1)", 11477]]],
 [-816, [["klass:(2,1)", 11391], ["klass:(2,1)", 11391]]],
 [-812, [["super:(2,1)", 11377], ["super:(2,1)", 11377]]],
 [-808, [["klass_iseq:(2,1)", 11374], ["klass_iseq:(2,1)", 11374]]],
 [-804, [["klass:(2,1)", 11288], ["klass:(2,1)", 11288]]],
 [-800, [["super:(2,1)", 11273], ["super:(2,1)", 11273]]],
 [-796, [["klass_iseq:(2,1)", 11270], ["klass_iseq:(2,1)", 11270]]],
 [-792, [["klass:(2,1)", 11184], ["klass:(2,1)", 11184]]],
 [-788, [["super:(2,1)", 11169], ["super:(2,1)", 11169]]],
 [-784, [["klass_iseq:(2,1)", 11166], ["klass_iseq:(2,1)", 11166]]],
 [-780, [["id:(2,2)", 11063], ["id:(2,2)", 11063]]],
 [-776, [["klass_iseq:(2,1)", 11062], ["klass_iseq:(2,1)", 11062]]],
 [-772,
  [["needstr:(2,1)", 10984],
   ["needstr:(2,1)", 10984],
   ["needstr:(2,1)", 10984]]],
 [-768, [["val:(2,1)", 10982], ["val:(2,1)", 10982], ["val:(2,1)", 10982]]],
 [-764,
  [["needstr:(2,1)", 10905],
   ["needstr:(2,1)", 10905],
   ["needstr:(2,1)", 10905]]],
 [-760, [["val:(2,1)", 10903], ["val:(2,1)", 10903], ["val:(2,1)", 10903]]],
 [-756,
  [["needstr:(2,1)", 10826],
   ["needstr:(2,1)", 10826],
   ["needstr:(2,1)", 10826]]],
 [-752, [["val:(2,1)", 10824], ["val:(2,1)", 10824], ["val:(2,1)", 10824]]],
 [-748,
  [["needstr:(2,1)", 10748],
   ["needstr:(2,1)", 10748],
   ["needstr:(2,1)", 10748]]],
 [-744, [["val:(2,1)", 10746], ["val:(2,1)", 10746], ["val:(2,1)", 10746]]],
 [-740,
  [["needstr:(2,1)", 10670],
   ["needstr:(2,1)", 10670],
   ["needstr:(2,1)", 10670]]],
 [-736, [["val:(2,1)", 10668], ["val:(2,1)", 10668], ["val:(2,1)", 10668]]],
 [-732,
  [["klass:(2,1)", 10256], ["klass:(2,1)", 10256], ["klass:(2,1)", 10256]]],
 [-728, [["id:(2,2)", 10243], ["id:(2,2)", 10243], ["id:(2,2)", 10243]]],
 [-724,
  [["klass:(2,1)", 10193], ["klass:(2,1)", 10193], ["klass:(2,1)", 10193]]],
 [-720, [["id:(2,2)", 10180], ["id:(2,2)", 10180], ["id:(2,2)", 10180]]],
 [-716,
  [["klass:(2,1)", 10130], ["klass:(2,1)", 10130], ["klass:(2,1)", 10130]]],
 [-712, [["id:(2,2)", 10117], ["id:(2,2)", 10117], ["id:(2,2)", 10117]]],
 [-708,
  [["klass:(2,1)", 10067], ["klass:(2,1)", 10067], ["klass:(2,1)", 10067]]],
 [-704, [["id:(2,2)", 10054], ["id:(2,2)", 10054], ["id:(2,2)", 10054]]],
 [-700,
  [["klass:(2,1)", 10004], ["klass:(2,1)", 10004], ["klass:(2,1)", 10004]]],
 [-696, [["id:(2,2)", 9990], ["id:(2,2)", 9990], ["id:(2,2)", 9990]]],
 [-692, [["id:(2,2)", 9934], ["id:(2,2)", 9934]]],
 [-688, [["id:(2,2)", 9878], ["id:(2,2)", 9878]]],
 [-684, [["id:(2,2)", 9822], ["id:(2,2)", 9822]]],
 [-680, [["id:(2,2)", 9766], ["id:(2,2)", 9766]]],
 [-676, [["id:(2,2)", 9710], ["id:(2,2)", 9710]]],
 [-672, [["num:(1,11)", 8447]]],
 [-668, [["val:(2,1)", 8445]]],
 [-664, [["num:(1,11)", 8408]]],
 [-660, [["val:(2,1)", 8406]]],
 [-656, [["num:(1,11)", 8369]]],
 [-652, [["val:(2,1)", 8367]]],
 [-648, [["num:(1,11)", 8331]]],
 [-644, [["val:(2,1)", 8329]]],
 [-640, [["num:(1,11)", 8293]]],
 [-636, [["val:(2,1)", 8291]]],
 [-632, [["holdnum:(0,3)", 8264]]],
 [-628, [["flag:(2,1)", 8212], ["flag:(2,1)", 8212]]],
 [-624, [["holdnum:(0,3)", 8183]]],
 [-620, [["flag:(2,1)", 8131], ["flag:(2,1)", 8131]]],
 [-616, [["holdnum:(0,3)", 8102]]],
 [-612, [["flag:(2,1)", 8050], ["flag:(2,1)", 8050]]],
 [-608, [["holdnum:(0,3)", 8021]]],
 [-604, [["flag:(2,1)", 7969], ["flag:(2,1)", 7969]]],
 [-600, [["holdnum:(0,3)", 7940]]],
 [-596, [["flag:(2,1)", 7887], ["flag:(2,1)", 7887]]],
 [-592, [["num:(1,11)", 7266]]],
 [-588, [["val:(2,1)", 7264]]],
 [-584, [["num:(1,11)", 7228]]],
 [-580, [["val:(2,1)", 7226]]],
 [-576, [["num:(1,11)", 7190]]],
 [-572, [["val:(2,1)", 7188]]],
 [-568, [["num:(1,11)", 7153]]],
 [-564, [["val:(2,1)", 7151]]],
 [-560, [["num:(1,11)", 7116]]],
 [-556, [["val:(2,1)", 7114]]],
 [-552, [["val:(2,1)", 5900], ["val:(2,1)", 5900]]],
 [-548, [["id:(2,2)", 5899], ["id:(2,2)", 5899]]],
 [-544, [["val:(2,1)", 5862], ["val:(2,1)", 5862]]],
 [-540, [["id:(2,2)", 5861], ["id:(2,2)", 5861]]],
 [-536, [["val:(2,1)", 5824], ["val:(2,1)", 5824]]],
 [-532, [["id:(2,2)", 5823], ["id:(2,2)", 5823]]],
 [-528, [["val:(2,1)", 5786], ["val:(2,1)", 5786]]],
 [-524, [["id:(2,2)", 5785], ["id:(2,2)", 5785]]],
 [-520, [["val:(2,1)", 5747], ["val:(2,1)", 5747]]],
 [-516, [["id:(2,2)", 5746], ["id:(2,2)", 5746]]],
 [-512, [["val_1:(2,1)", 3752], ["val_1:(2,1)", 3752]]],
 [-508,
  [["prev_lfp:(2,13)", 2195],
   ["prev_lfp:(2,13)", 2195],
   ["prev_lfp:(2,13)", 2195]]],
 [-504,
  [["prev_dfp:(2,13)", 2195],
   ["prev_dfp:(2,13)", 2195],
   ["prev_dfp:(2,13)", 2195]]],
 [-500, [["iseq:(2,1)", 2194], ["iseq:(2,1)", 2194], ["iseq:(2,1)", 2194]]],
 [-496, [["pack_size:(0,1)", 1969], ["pack_size:(0,1)", 1969]]],
 [-492,
  [["opt_pc:(0,1)", 1941], ["opt_pc:(0,1)", 1941], ["opt_pc:(0,1)", 1941]]],
 [-488,
  [["newiseq:(2,1)", 1939], ["newiseq:(2,1)", 1939], ["newiseq:(2,1)", 1939]]],
 [-484,
  [["niseqobj:(55,21)", 1938],
   ["niseqobj:(55,21)", 1938],
   ["niseqobj:(55,21)", 1938]]],
 [-480,
  [["num:(1,11)", 1737],
   ["num:(1,11)", 1737],
   ["num:(1,11)", 1737],
   ["num:(1,11)", 1737],
   ["num:(1,11)", 1737],
   ["num:(1,11)", 1737],
   ["num:(1,11)", 1737]]],
 [-476,
  [["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736],
   ["block_ptr:(51,5)", 1736]]],
 [-472,
  [["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735],
   ["klass:(2,1)", 1735]]],
 [-468,
  [["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734],
   ["procblock:(2,1)", 1734]]],
 [-464,
  [["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733],
   ["recv:(2,1)", 1733]]],
 [-460,
  [["id:(2,2)", 1715],
   ["id:(2,2)", 1715],
   ["id:(2,2)", 1715],
   ["id:(2,2)", 1715],
   ["id:(2,2)", 1715],
   ["id:(2,2)", 1715],
   ["id:(2,2)", 1715]]],
 [-456,
  [["block:(2,1)", 1713],
   ["block:(2,1)", 1713],
   ["block:(2,1)", 1713],
   ["block:(2,1)", 1713],
   ["block:(2,1)", 1713],
   ["block:(2,1)", 1713],
   ["block:(2,1)", 1713]]],
 [-452,
  [["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711],
   ["ic:(55,29)", 1711]]],
 [-448, [["module:(2,1)", 1602], ["module:(2,1)", 1602]]],
 [-444, [["module_iseq:(2,1)", 1585], ["module_iseq:(2,1)", 1585]]],
 [-440, [["id:(2,2)", 1452], ["id:(2,2)", 1452]]],
 [-436, [["klass_iseq:(2,1)", 1451], ["klass_iseq:(2,1)", 1451]]],
 [-432,
  [["needstr:(2,1)", 1373], ["needstr:(2,1)", 1373], ["needstr:(2,1)", 1373]]],
 [-428, [["val:(2,1)", 1371], ["val:(2,1)", 1371], ["val:(2,1)", 1371]]],
 [-424, [["klass:(2,1)", 1251], ["klass:(2,1)", 1251], ["klass:(2,1)", 1251]]],
 [-420, [["id:(2,2)", 1237], ["id:(2,2)", 1237], ["id:(2,2)", 1237]]],
 [-416, [["id:(2,2)", 1181], ["id:(2,2)", 1181]]],
 [-412, [["num:(1,11)", 894]]],
 [-408, [["val:(2,1)", 892]]],
 [-404, [["holdnum:(0,3)", 865]]],
 [-400, [["flag:(2,1)", 812], ["flag:(2,1)", 812]]],
 [-396, [["num:(1,11)", 657]]],
 [-392, [["val:(2,1)", 655]]],
 [-388, [["val:(2,1)", 382], ["val:(2,1)", 382]]],
 [-384, [["id:(2,2)", 381], ["id:(2,2)", 381]]],
 [-380, [["state:(0,1)", 57]]],
 [-376, [["throwed:(2,1)", 55]]],
 [-372, [["reg_cfp:(2,13)", 52]]],
 [-368, [["reg_dfp:(2,13)", 51]]],
 [-364, [["reg_lfp:(2,13)", 50]]],
 [-360, [["reg_sp:(2,13)", 49]]],
 [-356, [["reg_b:(2,1)", 28]]],
 [-352, [["reg_a:(2,1)", 27]]],
 [-348, [["th:(1,4)", 20]]],
 [-344, [["val:(2,1)", 16868], ["val:(2,1)", 16868]]],
 [-340, [["val:(2,1)", 16826], ["val:(2,1)", 16826]]],
 [-336, [["val:(2,1)", 16784], ["val:(2,1)", 16784]]],
 [-332, [["val:(2,1)", 16742], ["val:(2,1)", 16742]]],
 [-328, [["val:(2,1)", 16700], ["val:(2,1)", 16700]]],
 [-324,
  [["newbody:(55,18)", 10257],
   ["newbody:(55,18)", 10257],
   ["newbody:(55,18)", 10257]]],
 [-320,
  [["newbody:(55,18)", 10194],
   ["newbody:(55,18)", 10194],
   ["newbody:(55,18)", 10194]]],
 [-316,
  [["newbody:(55,18)", 10131],
   ["newbody:(55,18)", 10131],
   ["newbody:(55,18)", 10131]]],
 [-312,
  [["newbody:(55,18)", 10068],
   ["newbody:(55,18)", 10068],
   ["newbody:(55,18)", 10068]]],
 [-308,
  [["newbody:(55,18)", 10005],
   ["newbody:(55,18)", 10005],
   ["newbody:(55,18)", 10005]]],
 [-304, [["val:(2,1)", 2599], ["val:(2,1)", 2599]]],
 [-300,
  [["newbody:(55,18)", 1252],
   ["newbody:(55,18)", 1252],
   ["newbody:(55,18)", 1252]]],
 [-296,
  [["cmi:(51,10)", 12519],
   ["cmi:(51,10)", 14149],
   ["cmi:(51,10)", 13741],
   ["cmi:(51,10)", 13333],
   ["cmi:(51,10)", 12926],
   ["cmi:(51,10)", 1878],
   ["cmi:(51,10)", 1878],
   ["cmi:(51,10)", 12926],
   ["cmi:(51,10)", 13333],
   ["cmi:(51,10)", 13741],
   ["cmi:(51,10)", 14149],
   ["cmi:(51,10)", 12519]]],
 [-280, [["_tag:(1,14)", 58]]],
 [-28, [["reg_pc_store:(61,1)=B(2,13)", 34]]]]

スタックの利用方法。tag が意外にでかい。

で、なんか沢山あるのは、ブロック間で goto していて、それで解析がおっつかなかった(解析しても不可能?)だったからみたい。まとめれば半分くらいになるかしらん。

あれれ、よくよくよくよく見てみると、もっと共有できるはず。

変数名が違うと駄目なんだろうか。

関数で変数宣言は一箇所にしちゃったほうがいいんだろうか。


各VM命令ごとの機械語命令数を数えてみた(x86)。本当にこれが正しいかはパーサ次第なんだけど。

send_SC_xx_ax 2770
send 2748
send_SC_ba_ax 2191
send_SC_ab_ax 2191
send_SC_bx_ax 2188
send_SC_ax_ax 2180
expandarray_SC_ba_xx 802
expandarray_SC_ab_xx 802
expandarray_SC_ax_xx 766
expandarray_SC_bx_xx 766
expandarray 747
expandarray_SC_xx_xx 747
defined_SC_ba_ax 542
defined_SC_ab_ax 542
defined_SC_ax_ax 531
defined_SC_bx_ax 531
defined 519
defined_SC_xx_ax 499
singletonmethoddef_SC_bx_xx 420
singletonmethoddef_SC_ba_bx 420
singletonmethoddef_SC_ax_xx 420
singletonmethoddef_SC_ab_ax 420
singletonmethoddef_SC_xx_xx 413
singletonmethoddef 413
opt_plus 273
opt_plus_SC_bx_ax 262
opt_plus_SC_ax_ax 262
opt_plus_SC_xx_ax 253
opt_plus_SC_ab_ax 249
opt_plus_SC_ba_ax 249
opt_ltlt_SC_bx_ax 219
opt_ltlt_SC_ax_ax 219
opt_ltlt 212
getspecial_SC_ab_ba 212
getspecial_SC_ba_ab 212
UNIFIED_putnil_end_SC_ab_ba 212
end 210
setclassvariable 208
setclassvariable_SC_xx_xx 208
opt_ltlt_SC_ba_ax 208
opt_ltlt_SC_ab_ax 208
UNIFIED_putnil_end_SC_ba_ab 206
opt_mult 203
getspecial 200
opt_regexpmatch2 198
methoddef 195
methoddef_SC_ab_ab 195
methoddef_SC_ba_ba 195
methoddef_SC_ax_ax 195
methoddef_SC_bx_bx 195
methoddef_SC_xx_xx 195
opt_ltlt_SC_xx_ax 192
end_SC_xx_ax 190
opt_minus 189
concatstrings_SC_ab_ax 188
concatstrings_SC_ba_ax 188
UNIFIED_putnil_end 188
opt_mult_SC_bx_ax 186
opt_regexpmatch2_SC_ab_ax 186
opt_regexpmatch2_SC_ba_ax 186
opt_mult_SC_ax_ax 186
opt_mult_SC_xx_ax 185
setclassvariable_SC_ab_ax 183
setclassvariable_SC_ax_xx 183
setclassvariable_SC_ba_bx 183
setclassvariable_SC_bx_xx 183
newhash_SC_ba_ax 182
newhash_SC_ab_ax 182
opt_regexpmatch2_SC_ax_ax 181
opt_regexpmatch2_SC_bx_ax 181
getspecial_SC_ax_ab 180
getspecial_SC_xx_ax 180
getspecial_SC_bx_ba 180
UNIFIED_putnil_end_SC_ax_ab 180
UNIFIED_putnil_end_SC_bx_ba 180
UNIFIED_putnil_end_SC_xx_ax 180
opt_regexpmatch2_SC_xx_ax 178
concatstrings_SC_bx_ax 177
concatstrings_SC_ax_ax 177
end_SC_bx_ax 175
end_SC_ab_ax 175
opt_minus_SC_bx_ax 174
opt_minus_SC_ax_ax 174
end_SC_ax_ax 169
end_SC_ba_ax 169
opt_minus_SC_xx_ax 167
newhash_SC_bx_ax 167
newhash_SC_ax_ax 167
opt_mult_SC_ba_ax 165
opt_mult_SC_ab_ax 165
yield_SC_ba_ax 158
yield_SC_ab_ax 158
opt_minus_SC_ab_ax 149
opt_minus_SC_ba_ax 149
yield_SC_bx_ax 141
yield_SC_ax_ax 141
concatstrings_SC_xx_ax 141
concatstrings 140
newhash_SC_xx_ax 139
newhash 134
yield 126
getclassvariable_SC_ab_ba 119
getclassvariable_SC_ba_ab 119
dupn_SC_ab_xx 117
dupn_SC_ba_xx 117
yield_SC_xx_ax 115
setconstant_SC_ax_xx 111
setconstant_SC_bx_xx 111
alias_SC_ba_ba 110
alias_SC_ab_ab 110
alias 110
alias_SC_xx_xx 110
alias_SC_bx_bx 110
alias_SC_ax_ax 110
getclassvariable 107
setconstant_SC_xx_xx 106
dupn_SC_bx_xx 106
dupn_SC_ax_xx 106
setconstant 104
newarray_SC_ba_ax 103
newarray_SC_ab_ax 103
opt_case_dispatch_SC_ba_xx 102
opt_case_dispatch_SC_ab_xx 102
undef_SC_bx_bx 100
undef_SC_ax_ax 100
undef 100
undef_SC_ab_ab 100
undef_SC_xx_xx 100
undef_SC_ba_ba 100
UNIFIED_getlocal_getlocal_SC_ab_ab 98
UNIFIED_getlocal_getlocal_SC_ba_ba 98
opt_lt 97
opt_lt_SC_bx_ax 97
opt_lt_SC_ax_ax 97
getconstant 93
setconstant_SC_ba_xx 92
setconstant_SC_ab_xx 92
newarray_SC_ax_ax 92
newarray_SC_bx_ax 92
opt_case_dispatch_SC_xx_xx 91
opt_case_dispatch 91
UNIFIED_putstring_putstring_SC_ab_ab 90
UNIFIED_putstring_putstring_SC_ba_ba 90
opt_lt_SC_xx_ax 87
getclassvariable_SC_bx_ba 87
getclassvariable_SC_ax_ab 87
getclassvariable_SC_xx_ax 87
UNIFIED_getlocal_getlocal_SC_ax_ba 87
UNIFIED_getlocal_getlocal_SC_bx_ab 87
setspecial_SC_xx_xx 85
setspecial 85
UNIFIED_getlocal_putobject_SC_ba_ba 85
UNIFIED_getlocal_putobject_SC_ab_ab 85
toregexp 83
getdynamic_SC_ba_ab 81
getdynamic_SC_ab_ba 81
UNIFIED_putobject_putstring_SC_ab_ab 80
UNIFIED_putstring_putobject_SC_ab_ab 80
UNIFIED_putobject_putstring_SC_ba_ba 80
UNIFIED_putstring_putobject_SC_ba_ba 80
getinlinecache_SC_ab_ba 79
getconstant_SC_xx_ax 79
getinlinecache_SC_ba_ab 79
UNIFIED_putstring_putstring_SC_ax_ba 79
UNIFIED_putstring_putstring_SC_bx_ab 79
setinlinecache 74
dupn 74
dupn_SC_xx_xx 74
UNIFIED_getlocal_putobject_SC_ax_ba 74
UNIFIED_getlocal_putobject_SC_bx_ab 74
UNIFIED_getlocal_getlocal 74
opt_lt_SC_ba_ax 72
opt_lt_SC_ab_ax 72
getinstancevariable_SC_ab_ba 72
getinstancevariable_SC_ba_ab 72
UNIFIED_putobject_putobject_SC_ba_ba 72
UNIFIED_putobject_putobject_SC_ab_ab 72
topn_SC_ba_ax 71
topn_SC_ab_ax 71
setdynamic_SC_xx_xx 70
setdynamic 70
opt_case_dispatch_SC_bx_xx 70
opt_case_dispatch_SC_ax_xx 70
newrange 70
toregexp_SC_xx_ax 69
newrange_SC_ax_ax 69
newrange_SC_bx_ax 69
newarray 69
getdynamic 69
UNIFIED_putstring_putobject_SC_ax_ba 69
UNIFIED_putobject_putstring_SC_bx_ab 69
UNIFIED_putobject_putstring_SC_ax_ba 69
UNIFIED_putstring_putobject_SC_bx_ab 69
newrange_SC_xx_ax 68
UNIFIED_putstring_putstring 68
opt_regexpmatch1 67
getinlinecache 67
topn_SC_bx_ax 66
tostring 66
setinstancevariable_SC_xx_xx 65
setinstancevariable 65
getdynamic_OP__WC__0_SC_ab_ba 65
getdynamic_OP__WC__0_SC_ba_ab 65
getlocal_SC_ab_ba 65
getlocal_SC_ba_ab 65
setspecial_SC_bx_xx 64
setspecial_SC_ab_ax 64
setspecial_SC_ax_xx 64
setspecial_SC_ba_bx 64
getconstant_SC_ab_ab 64
getconstant_SC_ax_ax 64
getconstant_SC_bx_ax 64
getconstant_SC_ba_ba 64
setinlinecache_SC_xx_ax 63
UNIFIED_putobject_putobject_SC_bx_ab 61
UNIFIED_putobject_putobject_SC_ax_ba 61
UNIFIED_getlocal_putobject 61
topn_SC_ax_ax 60
putstring_SC_ba_ab 60
putstring_SC_ab_ba 60
newarray_SC_xx_ax 60
getglobal_SC_ba_ab 60
getglobal_SC_ab_ba 60
getinstancevariable 60
duparray_SC_ab_ba 60
duparray_SC_ba_ab 60
UNIFIED_putstring_setdynamic_SC_xx_xx 60
UNIFIED_dup_setlocal_SC_xx_ax 60
UNIFIED_putstring_setdynamic_SC_bx_bx 60
UNIFIED_putstring_setdynamic 60
UNIFIED_putstring_setdynamic_SC_ab_ab 60
UNIFIED_putstring_setdynamic_SC_ba_ba 60
UNIFIED_putstring_setdynamic_SC_ax_ax 60
opt_regexpmatch1_SC_xx_ax 59
UNIFIED_dup_setlocal 59
getdynamic_OP_1_0_SC_ba_ab 58
getlocal_OP_3_SC_ba_ab 58
getlocal_OP_2_SC_ba_ab 58
getlocal_OP_3_SC_ab_ba 58
getdynamic_OP_1_0_SC_ab_ba 58
getlocal_OP_2_SC_ab_ba 58
putself_SC_ba_ab 57
putself_SC_ab_ba 57
swap_SC_bx_ab 56
putnot_SC_xx_ax 56
UNIFIED_putobject_putstring 56
UNIFIED_putstring_putobject 56
reput_SC_ab_ax 55
putnot 55
dup_SC_ba_ab 55
dup_SC_ab_ba 55
UNIFIED_getlocal_getlocal_SC_xx_ab 55
topn 54
setlocal_SC_xx_xx 54
setlocal 54
putobject_OP_INT2FIX_O_1_C__SC_ba_ab 54
putobject_OP_Qtrue_SC_ab_ba 54
putnil_SC_ba_ab 54
putobject_OP_Qtrue_SC_ba_ab 54
putobject_OP_INT2FIX_O_0_C__SC_ab_ba 54
putobject_OP_INT2FIX_O_1_C__SC_ab_ba 54
putnil_SC_ab_ba 54
putobject_OP_INT2FIX_O_0_C__SC_ba_ab 54
swap_SC_xx_ab 53
setglobal_SC_xx_xx 53
setglobal 53
getlocal 53
getdynamic_OP__WC__0 53
tostring_SC_xx_ax 52
putobject_SC_ab_ba 52
putobject_SC_ba_ab 52
swap 51
putobject_OP_Qfalse_SC_ba_ab 51
putobject_OP_Qfalse_SC_ab_ba 51
dup_SC_xx_ab 50
unless 49
unless_SC_xx_xx 49
setdynamic_SC_ba_bx 49
setdynamic_SC_bx_xx 49
setdynamic_SC_ax_xx 49
setdynamic_SC_ab_ax 49
if 49
if_SC_xx_xx 49
getdynamic_SC_bx_ba 49
getdynamic_SC_ax_ab 49
getdynamic_SC_xx_ax 49
toregexp_SC_ba_ba 48
toregexp_SC_ax_ax 48
toregexp_SC_bx_ax 48
toregexp_SC_ab_ab 48
singletonclassdef 48
putstring 48
newrange_SC_ab_ax 48
newrange_SC_ba_ax 48
getglobal 48
duparray 48
UNIFIED_putobject_putobject 48
setlocal_OP_2 47
setlocal_OP_2_SC_xx_xx 47
setlocal_OP_3_SC_xx_xx 47
setlocal_OP_3 47
getinlinecache_SC_ax_ab 47
getinlinecache_SC_bx_ba 47
getinlinecache_SC_xx_ax 47
UNIFIED_putstring_putstring_SC_xx_ab 47
getlocal_OP_3 46
getdynamic_OP_1_0 46
getlocal_OP_2 46
dup 46
UNIFIED_putobject_setdynamic_SC_ab_ab 46
UNIFIED_putobject_setdynamic_SC_bx_bx 46
UNIFIED_putobject_setdynamic 46
UNIFIED_putobject_setdynamic_SC_ba_ba 46
UNIFIED_putobject_setdynamic_SC_ax_ax 46
UNIFIED_putobject_setdynamic_SC_xx_xx 46
putself 45
setinstancevariable_SC_bx_xx 44
setinstancevariable_SC_ab_ax 44
swap_SC_ax_ab 44
setinstancevariable_SC_ba_bx 44
singletonclassdef_SC_xx_ax 44
setinstancevariable_SC_ax_xx 44
reput_SC_xx_ax 44
reput_SC_ba_ax 43
setinlinecache_SC_bx_ax 42
UNIFIED_getlocal_putobject_SC_xx_ab 42
putobject_OP_INT2FIX_O_1_C_ 41
putobject_OP_Qfalse 41
putobject_OP_Qtrue 41
putobject_OP_INT2FIX_O_0_C_ 41
putnil 41
putobject 40
getinstancevariable_SC_bx_ba 40
getinstancevariable_SC_ax_ab 40
getinstancevariable_SC_xx_ax 40
UNIFIED_putstring_setlocal_SC_bx_bx 40
UNIFIED_putstring_setlocal_SC_ax_ax 40
UNIFIED_putstring_setlocal 40
UNIFIED_putstring_setlocal_SC_xx_xx 40
UNIFIED_putstring_setlocal_SC_ba_ba 40
UNIFIED_putstring_setlocal_SC_ab_ab 40
UNIFIED_dup_setlocal_SC_bx_ax 39
reput 38
opt_regexpmatch1_SC_bx_ax 38
opt_regexpmatch1_SC_ax_ax 38
opt_regexpmatch1_SC_ba_ba 38
opt_regexpmatch1_SC_ab_ab 38
UNIFIED_putobject_putstring_SC_xx_ab 37
UNIFIED_putstring_putobject_SC_xx_ab 37
setinlinecache_SC_ab_ab 36
setinlinecache_SC_ax_ax 36
setinlinecache_SC_ba_ba 36
swap_SC_ab_ab 35
putnot_SC_ab_ab 35
putnot_SC_bx_ax 35
putnot_SC_ax_ax 35
putnot_SC_ba_ba 35
topn_SC_xx_ax 34
setlocal_SC_ax_xx 33
setlocal_SC_bx_xx 33
setlocal_SC_ba_bx 33
setlocal_SC_ab_ax 33
pop 33
pop_SC_xx_xx 33
getdynamic_OP__WC__0_SC_bx_ba 33
getlocal_SC_bx_ba 33
getlocal_SC_xx_ax 33
getlocal_SC_ax_ab 33
getdynamic_OP__WC__0_SC_xx_ax 33
getdynamic_OP__WC__0_SC_ax_ab 33
UNIFIED_dup_setlocal_SC_ba_ba 33
UNIFIED_dup_setlocal_SC_ab_ab 33
UNIFIED_dup_setlocal_SC_ax_ax 33
setglobal_SC_ba_bx 32
setglobal_SC_bx_xx 32
setglobal_SC_ax_xx 32
setglobal_SC_ab_ax 32
tostring_SC_ba_ba 31
tostring_SC_bx_ax 31
tostring_SC_ab_ab 31
tostring_SC_ax_ax 31
UNIFIED_putobject_setlocal_SC_xx_xx 30
UNIFIED_putobject_setlocal_SC_ab_ab 30
UNIFIED_putobject_setlocal 30
UNIFIED_putobject_setlocal_SC_ba_ba 30
UNIFIED_putobject_setlocal_SC_ax_ax 30
UNIFIED_putobject_setlocal_SC_bx_bx 30
unless_SC_ba_bx 29
unless_SC_bx_xx 29
unless_SC_ab_ax 29
unless_SC_ax_xx 29
if_SC_bx_xx 29
if_SC_ax_xx 29
if_SC_ba_bx 29
if_SC_ab_ax 29
UNIFIED_putobject_putobject_SC_xx_ab 29
popcref_SC_ax_ax 28
popcref_SC_ab_ab 28
popcref 28
popcref_SC_xx_xx 28
putstring_SC_ax_ab 28
popcref_SC_bx_bx 28
putstring_SC_bx_ba 28
putstring_SC_xx_ax 28
popcref_SC_ba_ba 28
getglobal_SC_ax_ab 28
getglobal_SC_xx_ax 28
getglobal_SC_bx_ba 28
duparray_SC_ax_ab 28
duparray_SC_xx_ax 28
duparray_SC_bx_ba 28
setlocal_OP_2_SC_ba_bx 26
setlocal_OP_2_SC_bx_xx 26
setlocal_OP_2_SC_ax_xx 26
setlocal_OP_3_SC_bx_xx 26
setlocal_OP_3_SC_ab_ax 26
setlocal_OP_2_SC_ab_ax 26
setlocal_OP_3_SC_ax_xx 26
setlocal_OP_3_SC_ba_bx 26
getlocal_OP_3_SC_ax_ab 26
getlocal_OP_2_SC_bx_ba 26
getdynamic_OP_1_0_SC_bx_ba 26
getlocal_OP_2_SC_ax_ab 26
getlocal_OP_2_SC_xx_ax 26
getlocal_OP_3_SC_bx_ba 26
getdynamic_OP_1_0_SC_xx_ax 26
getlocal_OP_3_SC_xx_ax 26
getdynamic_OP_1_0_SC_ax_ab 26
putself_SC_ax_ab 25
putself_SC_bx_ba 25
putself_SC_xx_ax 25
reput_SC_bx_ax 23
dup_SC_bx_ab 23
dup_SC_ax_ab 23
singletonclassdef_SC_ab_ab 22
singletonclassdef_SC_bx_ax 22
singletonclassdef_SC_ba_ba 22
singletonclassdef_SC_ax_ax 22
putobject_OP_INT2FIX_O_0_C__SC_xx_ax 22
putnil_SC_ax_ab 22
putobject_OP_INT2FIX_O_0_C__SC_bx_ba 22
putobject_OP_Qtrue_SC_xx_ax 22
putnil_SC_xx_ax 22
putobject_OP_INT2FIX_O_1_C__SC_ax_ab 22
putobject_OP_INT2FIX_O_0_C__SC_ax_ab 22
putnil_SC_bx_ba 22
putobject_OP_Qtrue_SC_bx_ba 22
putobject_OP_INT2FIX_O_1_C__SC_xx_ax 22
putobject_OP_INT2FIX_O_1_C__SC_bx_ba 22
putobject_OP_Qtrue_SC_ax_ab 22
putobject_SC_bx_ba 20
putobject_SC_xx_ax 20
putobject_SC_ax_ab 20
putobject_OP_Qfalse_SC_xx_ax 19
putobject_OP_Qfalse_SC_ax_ab 19
putobject_OP_Qfalse_SC_bx_ba 19
jump 19
jump_SC_ax_ax 19
jump_SC_bx_bx 19
jump_SC_ab_ab 19
jump_SC_xx_xx 19
jump_SC_ba_ba 19
swap_SC_ba_ab 11
reput_SC_ax_ax 11
pop_SC_ax_xx 11
pop_SC_ab_ax 11
pop_SC_ba_bx 11
pop_SC_bx_xx 11
nop_SC_ab_ab 11
nop 11
nop_SC_ax_ax 11
nop_SC_bx_bx 11
nop_SC_xx_xx 11
nop_SC_ba_ba 11

total: 58451

send でかすぎ。

ちょっと修正。


if(COND1){
  if(COND1_1){
    body1;
  }
  else if(COND1_2){
    body2;
  }
  else{
    elsebody;
  }
}
else{
  elsebody;
}

さて、elsebody がダブってる。もっと綺麗でカッコイイ書き方は無いものか。

ちなみに、goto を使っちゃった。


Ruby の場合、CLASS_OF(obj) == klass よりも !SPECIAL_CONST_P(obj) && RBASIC(obj)->klass == klass のほうが速い。


send_SC_xx_ax 2770
send 2748
send_SC_ba_ax 2191
send_SC_ab_ax 2191
send_SC_bx_ax 2188
send_SC_ax_ax 2180
send_OP__WC__1_Qfalse_0__WC__SC_ba_ax 1630
send_OP__WC__2_Qfalse_0__WC__SC_ab_ax 1630
send_OP__WC__3_Qfalse_0__WC__SC_ba_ax 1630
send_OP__WC__2_Qfalse_0__WC__SC_ba_ax 1630
send_OP__WC__3_Qfalse_0__WC__SC_ab_ax 1630
send_OP__WC__1_Qfalse_0__WC__SC_ab_ax 1630
send_OP__WC___WC__Qfalse_0__WC__SC_ba_ax 1629
send_OP__WC___WC__Qfalse_0__WC__SC_ab_ax 1629
send_OP__WC__0_Qfalse_0__WC__SC_ba_ax 1627
send_OP__WC__0_Qfalse_0__WC__SC_ab_ax 1627
send_OP__WC___WC__Qfalse_0__WC__SC_ax_ax 1618
send_OP__WC___WC__Qfalse_0__WC__SC_bx_ax 1618
send_OP__WC__2_Qfalse_0__WC__SC_ax_ax 1617
send_OP__WC__3_Qfalse_0__WC__SC_ax_ax 1617
send_OP__WC__1_Qfalse_0__WC__SC_bx_ax 1617
send_OP__WC__2_Qfalse_0__WC__SC_bx_ax 1617
send_OP__WC__3_Qfalse_0__WC__SC_bx_ax 1617
send_OP__WC__1_Qfalse_0__WC__SC_ax_ax 1617
send_OP__WC__0_Qfalse_0__WC__SC_ax_ax 1614
send_OP__WC__0_Qfalse_0__WC__SC_bx_ax 1614
send_OP__WC___WC__Qfalse_0__WC_ 1606
send_OP__WC__1_Qfalse_0__WC_ 1605
send_OP__WC__3_Qfalse_0__WC_ 1605
send_OP__WC__2_Qfalse_0__WC_ 1605
send_OP__WC__0_Qfalse_0__WC_ 1602
send_OP__WC__1_Qfalse_0__WC__SC_xx_ax 1589
send_OP__WC__3_Qfalse_0__WC__SC_xx_ax 1589
send_OP__WC__2_Qfalse_0__WC__SC_xx_ax 1589
send_OP__WC__0_Qfalse_0__WC__SC_xx_ax 1586
send_OP__WC___WC__Qfalse_0__WC__SC_xx_ax 1586
expandarray_SC_ba_xx 802
expandarray_SC_ab_xx 802
expandarray_SC_ax_xx 766
expandarray_SC_bx_xx 766
expandarray_SC_xx_xx 747
expandarray 747
defined_SC_ba_ax 542
defined_SC_ab_ax 542
defined_SC_bx_ax 531
defined_SC_ax_ax 531
defined 519
defined_SC_xx_ax 499
classdef_SC_bx_ax 465
classdef_SC_ax_ax 459
classdef_SC_ab_ax 442
classdef_SC_xx_ax 442
classdef_SC_ba_ax 442
classdef 436
singletonmethoddef_SC_ba_bx 420
singletonmethoddef_SC_ab_ax 420
singletonmethoddef_SC_bx_xx 420
singletonmethoddef_SC_ax_xx 420
singletonmethoddef 413
singletonmethoddef_SC_xx_xx 413
moduledef_SC_xx_ax 406
moduledef 406
moduledef_SC_ab_ax 391
moduledef_SC_bx_ax 391
moduledef_SC_ba_ax 391
moduledef_SC_ax_ax 391
opt_plus 273
opt_plus_SC_bx_ax 262
opt_plus_SC_ax_ax 262
opt_plus_SC_xx_ax 253
opt_plus_SC_ab_ax 249
opt_plus_SC_ba_ax 249
opt_ltlt_SC_ax_ax 219
opt_ltlt_SC_bx_ax 219
opt_ltlt 212
getspecial_SC_ab_ba 212
getspecial_SC_ba_ab 212
UNIFIED_putnil_end_SC_ab_ba 212
end 210
setclassvariable_SC_xx_xx 208
setclassvariable 208
opt_ltlt_SC_ab_ax 208
opt_ltlt_SC_ba_ax 208
UNIFIED_putnil_end_SC_ba_ab 206
opt_mult 203
end_OP_5 201
getspecial 200
opt_regexpmatch2 198
methoddef_SC_ax_ax 195
methoddef_SC_ab_ab 195
methoddef_SC_ba_ba 195
methoddef 195
methoddef_SC_xx_xx 195
methoddef_SC_bx_bx 195
throw_SC_xx_xx 192
throw 192
opt_ltlt_SC_xx_ax 192
end_SC_xx_ax 190
opt_minus 189
concatstrings_SC_ab_ax 188
concatstrings_SC_ba_ax 188
UNIFIED_putnil_end 188
end_OP_5_SC_xx_ax 187
opt_mult_SC_bx_ax 186
opt_mult_SC_ax_ax 186
opt_regexpmatch2_SC_ba_ax 186
opt_regexpmatch2_SC_ab_ax 186
opt_mult_SC_xx_ax 185
setclassvariable_SC_ax_xx 183
setclassvariable_SC_ba_bx 183
setclassvariable_SC_bx_xx 183
setclassvariable_SC_ab_ax 183
newhash_SC_ba_ax 182
newhash_SC_ab_ax 182
opt_regexpmatch2_SC_bx_ax 181
opt_regexpmatch2_SC_ax_ax 181
getspecial_SC_xx_ax 180
getspecial_SC_ax_ab 180
getspecial_SC_bx_ba 180
UNIFIED_putnil_end_SC_ax_ab 180
UNIFIED_putnil_end_SC_bx_ba 180
UNIFIED_putnil_end_SC_xx_ax 180
opt_regexpmatch2_SC_xx_ax 178
throw_SC_ax_xx 177
throw_SC_bx_xx 177
throw_SC_ba_bx 177
throw_SC_ab_ax 177
concatstrings_SC_ax_ax 177
concatstrings_SC_bx_ax 177
end_SC_bx_ax 175
end_SC_ab_ax 175
opt_minus_SC_ax_ax 174
opt_minus_SC_bx_ax 174
end_OP_5_SC_bx_ax 172
end_SC_ba_ax 169
end_SC_ax_ax 169
opt_minus_SC_xx_ax 167
newhash_SC_ax_ax 167
newhash_SC_bx_ax 167
end_OP_5_SC_ab_ax 166
opt_mult_SC_ba_ax 165
opt_mult_SC_ab_ax 165
end_OP_5_SC_ax_ax 160
end_OP_5_SC_ba_ax 160
yield_SC_ab_ax 158
yield_SC_ba_ax 158
opt_minus_SC_ab_ax 149
opt_minus_SC_ba_ax 149
yield_SC_bx_ax 141
yield_SC_ax_ax 141
concatstrings_SC_xx_ax 141
concatstrings 140
newhash_SC_xx_ax 139
newhash 134
yield 126
getclassvariable_SC_ba_ab 119
getclassvariable_SC_ab_ba 119
dupn_SC_ab_xx 117
dupn_SC_ba_xx 117
yield_SC_xx_ax 115
setconstant_SC_bx_xx 111
setconstant_SC_ax_xx 111
alias_SC_ab_ab 110
alias 110
alias_SC_ax_ax 110
alias_SC_bx_bx 110
alias_SC_ba_ba 110
alias_SC_xx_xx 110
getclassvariable 107
setconstant_SC_xx_xx 106
dupn_SC_ax_xx 106
dupn_SC_bx_xx 106
setconstant 104
newarray_SC_ba_ax 103
newarray_SC_ab_ax 103
opt_case_dispatch_SC_ba_xx 102
opt_case_dispatch_SC_ab_xx 102
undef_SC_bx_bx 100
undef_SC_ab_ab 100
undef_SC_ba_ba 100
undef_SC_ax_ax 100
undef_SC_xx_xx 100
undef 100
UNIFIED_getlocal_getlocal_SC_ba_ba 98
UNIFIED_getlocal_getlocal_SC_ab_ab 98
opt_lt_SC_ax_ax 97
opt_lt_SC_bx_ax 97
opt_lt 97
getconstant 93
setconstant_SC_ab_xx 92
setconstant_SC_ba_xx 92
newarray_SC_bx_ax 92
newarray_SC_ax_ax 92
opt_case_dispatch 91
opt_case_dispatch_SC_xx_xx 91
UNIFIED_putstring_putstring_SC_ba_ba 90
UNIFIED_putstring_putstring_SC_ab_ab 90
opt_lt_SC_xx_ax 87
getclassvariable_SC_xx_ax 87
getclassvariable_SC_bx_ba 87
getclassvariable_SC_ax_ab 87
UNIFIED_getlocal_getlocal_SC_ax_ba 87
UNIFIED_getlocal_getlocal_SC_bx_ab 87
setspecial 85
setspecial_SC_xx_xx 85
UNIFIED_getlocal_putobject_SC_ab_ab 85
UNIFIED_getlocal_putobject_SC_ba_ba 85
toregexp 83
getdynamic_SC_ba_ab 81
getdynamic_SC_ab_ba 81
UNIFIED_putobject_putstring_SC_ba_ba 80
UNIFIED_putobject_putstring_SC_ab_ab 80
UNIFIED_putstring_putobject_SC_ba_ba 80
UNIFIED_putstring_putobject_SC_ab_ab 80
getconstant_SC_xx_ax 79
getinlinecache_SC_ab_ba 79
getinlinecache_SC_ba_ab 79
UNIFIED_putstring_putstring_SC_ax_ba 79
UNIFIED_putstring_putstring_SC_bx_ab 79
setinlinecache 74
dupn 74
dupn_SC_xx_xx 74
UNIFIED_getlocal_getlocal 74
UNIFIED_getlocal_putobject_SC_ax_ba 74
UNIFIED_getlocal_putobject_SC_bx_ab 74
opt_lt_SC_ba_ax 72
opt_lt_SC_ab_ax 72
getinstancevariable_SC_ba_ab 72
getinstancevariable_SC_ab_ba 72
UNIFIED_putobject_putobject_SC_ab_ab 72
UNIFIED_putobject_putobject_SC_ba_ba 72
topn_SC_ab_ax 71
topn_SC_ba_ax 71
setdynamic 70
setdynamic_SC_xx_xx 70
opt_case_dispatch_SC_bx_xx 70
opt_case_dispatch_SC_ax_xx 70
newrange 70
toregexp_SC_xx_ax 69
newarray 69
newrange_SC_bx_ax 69
newrange_SC_ax_ax 69
getdynamic 69
UNIFIED_putobject_putstring_SC_bx_ab 69
UNIFIED_putobject_putstring_SC_ax_ba 69
UNIFIED_putstring_putobject_SC_ax_ba 69
UNIFIED_putstring_putobject_SC_bx_ab 69
newrange_SC_xx_ax 68
UNIFIED_putstring_putstring 68
opt_regexpmatch1 67
getinlinecache 67
tostring 66
topn_SC_bx_ax 66
setinstancevariable 65
setinstancevariable_SC_xx_xx 65
getdynamic_OP__WC__0_SC_ab_ba 65
getlocal_SC_ab_ba 65
getdynamic_OP__WC__0_SC_ba_ab 65
getlocal_SC_ba_ab 65
setspecial_SC_ba_bx 64
setspecial_SC_bx_xx 64
setspecial_SC_ax_xx 64
setspecial_SC_ab_ax 64
getconstant_SC_ax_ax 64
getconstant_SC_bx_ax 64
getconstant_SC_ba_ba 64
getconstant_SC_ab_ab 64
setinlinecache_SC_xx_ax 63
super_SC_ba_ax 62
super_SC_ab_ax 62
UNIFIED_putobject_putobject_SC_bx_ab 61
UNIFIED_getlocal_putobject 61
UNIFIED_putobject_putobject_SC_ax_ba 61
topn_SC_ax_ax 60
putstring_SC_ba_ab 60
putstring_SC_ab_ba 60
newarray_SC_xx_ax 60
getglobal_SC_ab_ba 60
getglobal_SC_ba_ab 60
getinstancevariable 60
duparray_SC_ab_ba 60
duparray_SC_ba_ab 60
UNIFIED_putstring_setdynamic_SC_xx_xx 60
UNIFIED_putstring_setdynamic_SC_ba_ba 60
UNIFIED_putstring_setdynamic_SC_bx_bx 60
UNIFIED_dup_setlocal_SC_xx_ax 60
UNIFIED_putstring_setdynamic_SC_ab_ab 60
UNIFIED_putstring_setdynamic 60
UNIFIED_putstring_setdynamic_SC_ax_ax 60
opt_regexpmatch1_SC_xx_ax 59
UNIFIED_dup_setlocal 59
getlocal_OP_2_SC_ab_ba 58
getdynamic_OP_1_0_SC_ba_ab 58
getlocal_OP_3_SC_ba_ab 58
getlocal_OP_2_SC_ba_ab 58
getlocal_OP_3_SC_ab_ba 58
getdynamic_OP_1_0_SC_ab_ba 58
zsuper_SC_ba_ax 57
zsuper_SC_ab_ax 57
putself_SC_ba_ab 57
putself_SC_ab_ba 57
swap_SC_bx_ab 56
putnot_SC_xx_ax 56
UNIFIED_putstring_putobject 56
UNIFIED_putobject_putstring 56
reput_SC_ab_ax 55
putnot 55
dup_SC_ba_ab 55
dup_SC_ab_ba 55
UNIFIED_getlocal_getlocal_SC_xx_ab 55
topn 54
setlocal 54
setlocal_SC_xx_xx 54
putobject_OP_Qtrue_SC_ab_ba 54
putnil_SC_ab_ba 54
putobject_OP_Qtrue_SC_ba_ab 54
putobject_OP_INT2FIX_O_1_C__SC_ba_ab 54
putobject_OP_INT2FIX_O_0_C__SC_ab_ba 54
putnil_SC_ba_ab 54
putobject_OP_INT2FIX_O_1_C__SC_ab_ba 54
putobject_OP_INT2FIX_O_0_C__SC_ba_ab 54
swap_SC_xx_ab 53
setglobal 53
setglobal_SC_xx_xx 53
getlocal 53
getdynamic_OP__WC__0 53
tostring_SC_xx_ax 52
putobject_SC_ab_ba 52
putobject_SC_ba_ab 52
super_SC_ax_ax 51
swap 51
super_SC_bx_ax 51
putobject_OP_Qfalse_SC_ab_ba 51
putobject_OP_Qfalse_SC_ba_ab 51
dup_SC_xx_ab 50
unless 49
unless_SC_xx_xx 49
setdynamic_SC_bx_xx 49
setdynamic_SC_ba_bx 49
setdynamic_SC_ax_xx 49
setdynamic_SC_ab_ax 49
if_SC_xx_xx 49
if 49
getdynamic_SC_xx_ax 49
getdynamic_SC_bx_ba 49
getdynamic_SC_ax_ab 49
toregexp_SC_ab_ab 48
toregexp_SC_bx_ax 48
toregexp_SC_ba_ba 48
toregexp_SC_ax_ax 48
singletonclassdef 48
putstring 48
newrange_SC_ba_ax 48
newrange_SC_ab_ax 48
getglobal 48
duparray 48
UNIFIED_putobject_putobject 48
setlocal_OP_2_SC_xx_xx 47
setlocal_OP_2 47
setlocal_OP_3 47
setlocal_OP_3_SC_xx_xx 47
getinlinecache_SC_ax_ab 47
getinlinecache_SC_bx_ba 47
getinlinecache_SC_xx_ax 47
endvmloop_SC_xx_ax 47
endvmloop 47
UNIFIED_putstring_putstring_SC_xx_ab 47
zsuper_SC_bx_ax 46
zsuper_SC_ax_ax 46
getlocal_OP_2 46
getlocal_OP_3 46
getdynamic_OP_1_0 46
dup 46
UNIFIED_putobject_setdynamic_SC_ab_ab 46
UNIFIED_putobject_setdynamic_SC_ba_ba 46
UNIFIED_putobject_setdynamic_SC_ax_ax 46
UNIFIED_putobject_setdynamic_SC_bx_bx 46
UNIFIED_putobject_setdynamic 46
UNIFIED_putobject_setdynamic_SC_xx_xx 46
putself 45
swap_SC_ax_ab 44
setinstancevariable_SC_ax_xx 44
setinstancevariable_SC_ba_bx 44
setinstancevariable_SC_bx_xx 44
singletonclassdef_SC_xx_ax 44
setinstancevariable_SC_ab_ax 44
reput_SC_xx_ax 44
reput_SC_ba_ax 43
setinlinecache_SC_bx_ax 42
UNIFIED_getlocal_putobject_SC_xx_ab 42
putnil 41
putobject_OP_Qtrue 41
putobject_OP_INT2FIX_O_1_C_ 41
putobject_OP_INT2FIX_O_0_C_ 41
putobject_OP_Qfalse 41
putobject 40
getinstancevariable_SC_xx_ax 40
getinstancevariable_SC_bx_ba 40
getinstancevariable_SC_ax_ab 40
UNIFIED_putstring_setlocal_SC_ba_ba 40
UNIFIED_putstring_setlocal_SC_bx_bx 40
UNIFIED_putstring_setlocal_SC_xx_xx 40
UNIFIED_putstring_setlocal 40
UNIFIED_putstring_setlocal_SC_ax_ax 40
UNIFIED_putstring_setlocal_SC_ab_ab 40
UNIFIED_dup_setlocal_SC_bx_ax 39
reput 38
opt_regexpmatch1_SC_bx_ax 38
opt_regexpmatch1_SC_ba_ba 38
opt_regexpmatch1_SC_ax_ax 38
opt_regexpmatch1_SC_ab_ab 38
UNIFIED_putstring_putobject_SC_xx_ab 37
UNIFIED_putobject_putstring_SC_xx_ab 37
setinlinecache_SC_ab_ab 36
setinlinecache_SC_ba_ba 36
setinlinecache_SC_ax_ax 36
swap_SC_ab_ab 35
putnot_SC_ax_ax 35
putnot_SC_ab_ab 35
putnot_SC_bx_ax 35
putnot_SC_ba_ba 35
topn_SC_xx_ax 34
setlocal_SC_ax_xx 33
setlocal_SC_ba_bx 33
setlocal_SC_ab_ax 33
setlocal_SC_bx_xx 33
pop_SC_xx_xx 33
pop 33
getlocal_SC_ax_ab 33
getdynamic_OP__WC__0_SC_bx_ba 33
getdynamic_OP__WC__0_SC_ax_ab 33
getlocal_SC_bx_ba 33
getdynamic_OP__WC__0_SC_xx_ax 33
getlocal_SC_xx_ax 33
UNIFIED_dup_setlocal_SC_ba_ba 33
UNIFIED_dup_setlocal_SC_ab_ab 33
UNIFIED_dup_setlocal_SC_ax_ax 33
setglobal_SC_ba_bx 32
setglobal_SC_ab_ax 32
setglobal_SC_bx_xx 32
setglobal_SC_ax_xx 32
tostring_SC_ab_ab 31
tostring_SC_ax_ax 31
tostring_SC_ba_ba 31
tostring_SC_bx_ax 31
super 31
UNIFIED_putobject_setlocal 30
UNIFIED_putobject_setlocal_SC_ax_ax 30
UNIFIED_putobject_setlocal_SC_xx_xx 30
UNIFIED_putobject_setlocal_SC_ab_ab 30
UNIFIED_putobject_setlocal_SC_bx_bx 30
UNIFIED_putobject_setlocal_SC_ba_ba 30
unless_SC_bx_xx 29
unless_SC_ab_ax 29
unless_SC_ax_xx 29
unless_SC_ba_bx 29
if_SC_ab_ax 29
if_SC_bx_xx 29
if_SC_ax_xx 29
if_SC_ba_bx 29
UNIFIED_putobject_putobject_SC_xx_ab 29
popcref 28
putstring_SC_xx_ax 28
putstring_SC_bx_ba 28
popcref_SC_ba_ba 28
popcref_SC_ax_ax 28
popcref_SC_ab_ab 28
putstring_SC_ax_ab 28
popcref_SC_bx_bx 28
popcref_SC_xx_xx 28
getglobal_SC_ax_ab 28
getglobal_SC_xx_ax 28
getglobal_SC_bx_ba 28
duparray_SC_ax_ab 28
duparray_SC_bx_ba 28
duparray_SC_xx_ax 28
zsuper 26
setlocal_OP_2_SC_bx_xx 26
setlocal_OP_3_SC_bx_xx 26
setlocal_OP_2_SC_ba_bx 26
setlocal_OP_3_SC_ax_xx 26
setlocal_OP_2_SC_ax_xx 26
setlocal_OP_2_SC_ab_ax 26
setlocal_OP_3_SC_ab_ax 26
setlocal_OP_3_SC_ba_bx 26
getdynamic_OP_1_0_SC_bx_ba 26
getlocal_OP_2_SC_bx_ba 26
getlocal_OP_3_SC_bx_ba 26
getlocal_OP_3_SC_ax_ab 26
getlocal_OP_2_SC_xx_ax 26
getdynamic_OP_1_0_SC_xx_ax 26
getdynamic_OP_1_0_SC_ax_ab 26
getlocal_OP_3_SC_xx_ax 26
getlocal_OP_2_SC_ax_ab 26
endvmloop_SC_ab_ax 26
endvmloop_SC_ax_ax 26
endvmloop_SC_bx_ax 26
endvmloop_SC_ba_ax 26
putself_SC_ax_ab 25
putself_SC_xx_ax 25
putself_SC_bx_ba 25
reput_SC_bx_ax 23
dup_SC_bx_ab 23
dup_SC_ax_ab 23
singletonclassdef_SC_ab_ab 22
singletonclassdef_SC_ba_ba 22
singletonclassdef_SC_ax_ax 22
singletonclassdef_SC_bx_ax 22
putnil_SC_ax_ab 22
putobject_OP_INT2FIX_O_1_C__SC_bx_ba 22
putobject_OP_INT2FIX_O_1_C__SC_ax_ab 22
putobject_OP_INT2FIX_O_1_C__SC_xx_ax 22
putobject_OP_Qtrue_SC_xx_ax 22
putobject_OP_INT2FIX_O_0_C__SC_ax_ab 22
putobject_OP_Qtrue_SC_bx_ba 22
putobject_OP_INT2FIX_O_0_C__SC_xx_ax 22
putobject_OP_INT2FIX_O_0_C__SC_bx_ba 22
putnil_SC_bx_ba 22
putnil_SC_xx_ax 22
putobject_OP_Qtrue_SC_ax_ab 22
opt_call_native_compiled_SC_ax_ax 21
opt_call_native_compiled_SC_ba_ba 21
opt_call_native_compiled_SC_ab_ab 21
opt_call_native_compiled 21
opt_call_native_compiled_SC_bx_bx 21
opt_call_native_compiled_SC_xx_xx 21
putobject_SC_xx_ax 20
putobject_SC_bx_ba 20
putobject_SC_ax_ab 20
super_SC_xx_ax 19
putobject_OP_Qfalse_SC_bx_ba 19
putobject_OP_Qfalse_SC_xx_ax 19
putobject_OP_Qfalse_SC_ax_ab 19
jump_SC_ab_ab 19
jump_SC_ba_ba 19
jump 19
jump_SC_xx_xx 19
jump_SC_bx_bx 19
jump_SC_ax_ax 19
zsuper_SC_xx_ax 14
swap_SC_ba_ab 11
reput_SC_ax_ax 11
pop_SC_ab_ax 11
pop_SC_ax_xx 11
pop_SC_ba_bx 11
pop_SC_bx_xx 11
nop_SC_ab_ab 11
nop 11
nop_SC_ax_ax 11
nop_SC_bx_bx 11
nop_SC_xx_xx 11
nop_SC_ba_ba 11

total: 114917

わーい。

_しゅ(Thu Jun 30 15:05:03 JST 2005)

 やっぱり、Etrl先生達がどうやって解決してるのかを調べないと。待ってまーす。

_ささだ(Thu Jun 30 15:36:23 JST 2005)

 Etrl先生の場合、各命令の粒度が大変小さいため、この辺は問題にならないんじゃないかと考えます。

_29(Wed)

グラフ化。

yarvspeedup


MRTG で HDD 温度を監視するようにしてみた。


MRTG でメールのトラフィックを見てみるようにした。自分の分だけだけど。


apcupsd が落ちてた。sarge にしたとき、デフォルトでオフになっていたみたい。

_28(Tue)

OSC-DO は実は結構迷ってたんですが、再投稿の締め切り間際なのでざっくりとダメポ。


なんか、色々とショックなことがあったらしい。


YARV の処理系生成の、かなりしょうもないながらも新規性として挙げられるであろう、stack caching コードの自動生成は、2004 年の論文でやられていました orz

ショックすぎる。

M. Anton Ertl, et al. Combining Stack Caching with Dynamic Superinstructions SIGPLAN 2004 Workshop on Interpreters, Virtual Machines, and Emulators (IVME ’04) Proceedings, pages 7-14

Ertl さん働きすぎだよ!

しかも dynamic superinstruction と混ぜてるし、命令数を少なくする方法も提案してるし(X 命令があった場合、Y state の stack caching で X*Y 個の命令が出来るから、命令数は膨大になる)。

うぅ、ショックだ。

そういえば、こんなタイトル見たんだよなあ。でも、1年経たないと公開されないから、待ってたんだよねえ。

あー。ショックだ。


そうだよなぁ。論文書くためなら Forth くらいの処理系が簡単でいいよな。処理系の最適かもかなり効くし、効果がはっきりするから。

やっぱ ruby (の処理系の開発)じゃ論文書けないんだろうか。


いや、どっちも出来る能力があるのが一番なんですけどねぇ。


暑い。暑すぎる。


自宅に警察の人が来た。近所の駅で殺人事件が2月にあって、その調査でどうにも証拠がなくて、近所の20代後半から30代前半までの男性をしらみつぶしで回ってるらしい。

さすが日本の警察。

で、そんな不在証明できるわけもなかったんだけど、IRCのログが残ってたから、それを言ったら写真を撮って帰っていった。うーん、証拠能力あるのかなあ。


トライ&エラーの観点で考えると、やはりインタプリタのサンプルとして Ruby を取り上げたのは複雑過ぎだったなぁ、と思ったけど、フレームの構造とかはやっぱり Ruby を考慮しないと駄目駄目だな。


久々に評価した結果。

Ruby non SC SC Ruby/SC nonSC/SC
array 19.672 10.984 10.734 1.83 1.02
block 1.328 0.265 0.235 5.65 1.13
const 9 1.032 0.672 13.39 1.54
ensure 0.64 0.094 0.078 8.21 1.21
factorial 14.234 10.609 10.563 1.35 1.00
fib 4.953 0.906 0.766 6.47 1.18
lists 0.25 0.156 0.141 1.77 1.11
method 4.094 1.313 1.156 3.54 1.14
poly_method 5.219 1.86 1.563 3.34 1.19
proc 2.61 0.438 0.36 7.25 1.22
reccount 0.063 0.032 0.031 2.03 1.03
regexp 1.469 0.86 0.828 1.77 1.04
rescue 7.016 0.844 0.484 14.50 1.74
rescue2 2.688 1.641 1.609 1.67 1.02
simpleiter 0.515 0.188 0.203 2.54 0.93
simplereturn 0.984 0.234 0.156 6.31 1.50
so_ackermann 1.203 0.265 0.219 5.49 1.21
so_array 12.969 6.375 6.11 2.12 1.04
so_concatenate 0.391 0.172 0.187 2.09 0.92
so_count_words 0.657 0.641 0.687 0.96 0.93
so_exception 11.922 8.25 8.344 1.43 0.99
so_matrix 4.016 1.625 1.515 2.65 1.07
so_nested_loop 11.109 4.094 3.687 3.01 1.11
so_object 16.64 14.938 14.703 1.13 1.02
so_random 3.735 1.844 1.766 2.11 1.04
so_sieve 2.656 0.656 0.5 5.31 1.31
strconcat 8.781 8.11 7.969 1.10 1.02
super 13.984 4.204 3.781 3.70 1.11
swap 17.172 1.016 0.594 28.91 1.71
tak 17.641 3 2.688 6.56 1.12
tarai 14.375 3.375 2.985 4.82 1.13
times 3.922 1.719 1.719 2.28 1.00
unif1 11.188 2.125 1.578 7.09 1.35
whileloop 16.5 2.14 1.266 13.03 1.69
zsuper 17.078 4.266 3.891 4.39 1.10

SC しても、あんまり速くなってない場合が。そればかりか、遅くなってる場合がある。まぁ、どれも小さい値なので、誤差という可能性もあるな。


もうちょっと詳しく。

Ruby no opt basic basic+inline basic+inline+unif basic+unif+SC
array 19.453 12.859 10.844 10.922 10.89 10.594
block 1.328 0.5 0.297 0.282 0.281 0.234
const 8.937 3.031 1.047 1.031 0.984 0.657
ensure 0.625 0.281 0.094 0.094 0.079 0.063
factorial 14.094 10.515 10.484 10.422 10.485 10.5
fib 4.891 2.062 0.984 0.891 0.828 0.75
lists 0.25 0.187 0.172 0.156 0.156 0.156
method 4.078 1.656 1.469 1.297 1.204 1.078
poly_method 5.172 2.031 1.844 1.844 1.672 1.469
proc 2.594 0.672 0.454 0.438 0.407 0.36
reccount 0.031 0 0.015 0 0 0
regexp 1.469 1.172 0.859 0.859 0.86 0.828
rescue 6.953 2.859 0.844 0.844 0.765 0.453
rescue2 2.641 1.625 1.625 1.625 1.64 1.594
simpleiter 0.532 0.188 0.172 0.204 0.203 0.187
simplereturn 0.953 0.437 0.219 0.218 0.204 0.172
so_ackermann 1.156 0.39 0.266 0.266 0.219 0.188
so_array 12.906 7.297 7.39 6.312 6.063 5.735
so_concatenate 0.422 0.188 0.172 0.172 0.156 0.172
so_count_words 0.594 0.656 0.625 0.625 0.594 0.625
so_exception 11.782 8.329 8.312 8.218 8.188 8.157
so_matrix 3.969 2.109 1.703 1.609 1.562 1.469
so_nested_loop 10.985 5.391 3.922 4.078 4.063 3.578
so_object 16.5 14.75 14.813 14.813 14.687 14.532
so_random 3.688 2.109 1.891 1.828 1.797 1.688
so_sieve 2.656 1.344 0.688 0.641 0.61 0.485
strconcat 8.672 8.422 7.953 7.984 7.969 7.89
super 13.875 6.453 4.547 4.172 3.969 3.515
swap 17.032 3.062 0.984 1 0.938 0.563
tak 17.468 6.031 3.375 3 2.86 2.641
tarai 14.25 4.859 3.735 3.359 3.125 2.89
times 3.875 1.75 1.75 1.719 1.703 1.704
unif1 11.094 4.297 2.297 2.11 1.828 1.454
whileloop 16.391 7.922 2.125 2.125 1.969 1.141
zsuper 16.938 6.5 4.547 4.234 4.062 3.594
ruby/ no opt ruby/ basic ruby/ basic+inline ruby/ basic+inline+unif ruby/ basic+unif+SC
array 1.51 1.79 1.78 1.79 1.84
block 2.66 4.47 4.71 4.73 5.68
const 2.95 8.54 8.67 9.08 13.60
ensure 2.22 6.65 6.65 7.91 9.92
factorial 1.34 1.34 1.35 1.34 1.34
fib 2.37 4.97 5.49 5.91 6.52
lists 1.34 1.45 1.60 1.60 1.60
method 2.46 2.78 3.14 3.39 3.78
poly_method 2.55 2.80 2.80 3.09 3.52
proc 3.86 5.71 5.92 6.37 7.21
reccount #DIV/0! 2.07 #DIV/0! #DIV/0! #DIV/0!
regexp 1.25 1.71 1.71 1.71 1.77
rescue 2.43 8.24 8.24 9.09 15.35
rescue2 1.63 1.63 1.63 1.61 1.66
simpleiter 2.83 3.09 2.61 2.62 2.84
simplereturn 2.18 4.35 4.37 4.67 5.54
so_ackermann 2.96 4.35 4.35 5.28 6.15
so_array 1.77 1.75 2.04 2.13 2.25
so_concatenate 2.24 2.45 2.45 2.71 2.45
so_count_words 0.91 0.95 0.95 1.00 0.95
so_exception 1.41 1.42 1.43 1.44 1.44
so_matrix 1.88 2.33 2.47 2.54 2.70
so_nested_loop 2.04 2.80 2.69 2.70 3.07
so_object 1.12 1.11 1.11 1.12 1.14
so_random 1.75 1.95 2.02 2.05 2.18
so_sieve 1.98 3.86 4.14 4.35 5.48
strconcat 1.03 1.09 1.09 1.09 1.10
super 2.15 3.05 3.33 3.50 3.95
swap 5.56 17.31 17.03 18.16 30.25
tak 2.90 5.18 5.82 6.11 6.61
tarai 2.93 3.82 4.24 4.56 4.93
times 2.21 2.21 2.25 2.28 2.27
unif1 2.58 4.83 5.26 6.07 7.63
whileloop 2.07 7.71 7.71 8.32 14.37
zsuper 2.61 3.73 4.00 4.17 4.71

融合系はあんまり効果がないなぁ。あんまりまじめに融合命令の選別をしていないからか。融合命令を自動的に選別する方法作らないと。

inline はインラインメソッドキャッシュ。ものによってはきちんと効果が出ている。

グラフ化は家に帰ったらやろう。って、帰れるのか・・・。


というか、評価の値が小さすぎるな。もうちょっと沢山計算させないと。

あと、評価自動化するやつかかないと。手作業でやってみたんだけど、面倒くさすぎ。

_shiro(Tue Jun 28 05:35:15 JST 2005)

「ruby特有の事情」を使えば論文になると思います。つまり、「rubyには他の言語に無いかくかくしかじかの特徴があり、それを効率的にサポートするためにこれこれの工夫をした」と。

こういうのはちょっとズルいと言えなくはないですが (変な仕様が多いほどたくさん論文が書けるから; rubyが、っていうんでなくて一般的な意味で)、本当に画期的な論文なんてそうそう書けるものではないので、自分から見て多少なりとも面白い結果が出たら訓練のつもりで書いてみる方がいいんじゃないかと思います。

_まつもと(Tue Jun 28 08:50:39 JST 2005)

 私はその手を使わないと論文書けません

_ささだ(Tue Jun 28 13:10:09 JST 2005)

 「Ruby特有の〜」というのは承知しているんですが、どうにも一般化したいという欲求と単純なトライ&エラーのサイクルと、それからそもそも私に「〜特有の理由において、本方式の利点は〜」を見つける能力の欠如が・・・。

_しゅ(Tue Jun 28 14:24:50 JST 2005)

 それは経験豊富な共同研究者(前田さん?まつもとさん?(み)先生?)がサポートしやすい部分なんじゃないかと>見つける能力

_27(Mon)

お腹すいたよウワーン。


VS.NET インストールに数時間かかってしまった。


命令融合は、命令記述から以下のようなコードを生成するんですが、変数名が重ならないように、次のような処理をします。

a = X;
{
  ...; /* a を利用したコード */
}
a = Y;
{
  ...; /* a を利用したコード */
}
#=>

a_1 = X;
a_2 = Y;
{
#define a a_1
  ...; /* a を利用したコード */
#undef a
}
{
#define a a_2
  ...; /* a を利用したコード */
#undef a
}

ここで問題になるのが、構造体のメンバに a という文字列があった場合、st->a が st-a_1 になってコンパイルエラーになってしまう。

なんとかこれを回避することは出来ないものか。

って、これだけなら各ブロックで a を宣言しなおせばいいだけだな。

ここで問題になるのが、a の値を次のブロックに伝播する可能性があるということ。

a_1 = X;
{
#define a a_1
  ...; /* a を利用したコード */
  a = Y;
  ...;
#undef a
}
{
#define a a_1
  ...; /* a を利用したコード */
#undef a
}

こんなのも生成する場合がある。

で、こういう場合、

a_1 = X;
{
  VALUE a = a_1;
  ...; /* a を利用したコード */
  a = Y;
  ...;
  a_1 = a;
}
{
  const VALUE a = a_1;
  ...; /* a を利用したコード */
}

こんなふうにコード生成するしか手はないかなー。

で。そうしたときに、きちんと無駄な代入とかは除去されるんだろうか。

naming convention で何とかする、って手もあるけれど、うーむ。


ちなみに、const な変数を利用するのと、define で即値を埋め込むの、どっちが最適化しやすいんだろう。直感的には define による即値埋め込みが圧倒的に有利(最適化しやすそう)と思うが、となると、const な変数がどれだけ最適化されるか、という話になるんだろうか。


代入をするようにしたら、やっぱりちょっと遅くなってしまった。ので、名前を気をつける、という方針で行こう(弱)。


gcc 3.3.3 だと、きちんと (?) jmp は一回で済んでいるな。

どうにもわからないので、gcc の中の人に聞いてみるか...。英語書けないよ...。

その前に gcc4.0 で試したいな。誰か持ってないだろうか。


色々と考えたけど、やっぱり可読性だろう、ということでインライン関数にしておっきなブロックを分けようと、リファクタリングしようとしたら、根本的にうまくいかないことに今更ながら気づく。どうしよう。

根本的なところを作り変えたくてしょうがないんだけど、それをやってる場合でもない。しくしく。


現実逃避に、-Wall で数千個あった warning を 100 以下にする。warning 96行に削減成功。printf のフォーマットとか、その辺がかなり。


RubyConf のホテル、こんなに少なくていいのかな? そういえば荻野さんどうするんだろ。


しょうがないので、インラインアセンブラで無理やり飛ばしてみた。そうしたら、whileloop で 1.5倍速くなった。

で、これが出来なくてはまった。

insnA:
  body...
  asm(jmp);

insnB:
  body...
  asm(jmp);
...

とやったんだけど、コンパイルは勿論通るが、動かない。動かない(segv)。

かなり、間抜けなミスだったんだけど、わかりますか?


で、こいつにはまって3時間。今日もその日に家に帰れなかった。

_babie(Mon Jun 27 08:57:35 JST 2005)

 いいなぁ、アカデミック価格。

_KM(Mon Jun 27 20:18:18 JST 2005)

 自分の機械,FC4 に上げたから GCC4 だよ.gcc --version すると gcc (GCC) 4.0.0 20050519 (Red Hat 4.0.0-8) な感じ

_ささだ(Mon Jun 27 20:40:18 JST 2005)

 YARV コンパイルして〜。

_26(Sun)

建て増しに建て増しを繰り返してきた結果、とてもスパゲッティー。誰か助けて。


命令を1500命令くらいにして、C の 1 関数が 7万行くらいにしたら、コンパイラが弱音を吐いた。

どうするべきか。

あ、アセンブラか? まぁ、デバッグ情報出せネーヨ、ということだったので、いいのかな。


ノートの電池で心配することがなくなったので、作業ができる喫茶店探しをしている。なかなか落ち着いて集中できるところがない。

府中近辺で知ってるところがあったら教えてください。


現実逃避に chm を沢山作ってしまった。orz。


サーバのバックアップ用ドライブがすぐに一杯になってしまう。どうしようかな。

でかいと思ったのは(使っていない) ximapd だった。

_まつもと(Sun Jun 26 02:13:10 JST 2005)

 私が助けてほしい

_25(Sat)

るびまの一番大きな宣伝は、Matz にっきだと思うんですが、今月はタイミングが合わず(http://www.rubyist.net/~matz/20050621.html#p03)。残念。

毎月(無駄に?)頑張ってるんで、良ければ見てください、って、この日記を見てる人はるびまは見ているような気がする。

ちなみに,投票もよろしく。


NX bit test:

int func(int a, int b){
  return a + b;
}

int main(){
  int (*fp1)(int a, int b);
  int (*fp2)(int a, int b);
  char buff[0x100];
  fp1 = (void *) buff;
  fp2 = (void *)malloc(0x100);
  memcpy(fp1, func, 0x100);
  memcpy(fp2, func, 0x100);

  printf("%d\n", fp1(1, 2));
  printf("%d\n", fp2(1, 2));
  return 0;
}
#include <sys/mman.h>

int func(int a, int b){
  return a + b;
}

void dump(int *p){
  int i;
  for(i=0; i<5; i++){
    printf("%4d: %08x\n", i, p[i]);
  }
}

void *memalloc(int size){
  void *p;
  int prot = PROT_EXEC | PROT_WRITE;// | PROT_READ | PROT_WRITE;
  int flags= MAP_PRIVATE | MAP_ANONYMOUS;
  if(1){
    p = malloc(size);
    printf("mprotect: %d\n", mprotect(p, size, prot));
  }
  else{
    p = mmap(0, 0x100, prot, flags, 0, 0);
  }
  return p;
}

int main(){
  int (*fp1)(int a, int b);
  fp1 = memalloc(0x100);
  memcpy(fp1, func, 0x100);
  dump((int*)fp1);
  printf("%d\n", fp1(1, 2));
  return 0;
}

mmap version doesn't work. hmm.


Skype doesn't work on DEP (Data Execution Prevent) mode of Windows XP.


512MB 増設メモリキター (http://www.adtec.co.jp/products/adf3200m-_/index.html)。

1024GB MB メモリなんて初めて。凄い凄い。

なんというか、ますます俺の持っているどのデスクトップマシンよりも高性能だ。


a = []
while true
  s = a.size
  b = [1, 2, 3]
  a << s % 10 == 0 ? b : nil
  p s if s % 1024 == 0
end

とりあえずこんなのを動かしてるんだけど、終わらない終わらない。熱い熱い。


T4、キーボードが打ちづらい...。性能を重視したとはいえ、これに慣れるのは結構つらい。ひとつのキーを大きくするためにいわゆる普通のキーボードとちょっと違って。


cross jumping の問題再発。

出現コード:

Ljmp:
  jmp *%eax

...
  Insn1:
    ...
    jmp Ljmp
  Insn2:
    ...
    jmp Ljmp
  ...
  InsnN:
    ...
    jmp Ljmp

ジャンプ先がジャンプ命令なんだから、けちるなよ!

んー、gcc 3.4 にしたからかなぁ (gcc (GCC) 3.4.4 (cygming special))。3.3 だったら平気だったような気がしたんだけど。

どうしたもんだか。最適化オプションに何かあるのかなぁ。


オペランド統合した命令に対しても命令統合の対象にしたら、命令数が案の定爆発した。

命令 I について、オペランド統合した命令(Io1, Io2, ...)があって、命令 I と J を統合するという支持があるとする。

I_J という命令のほかに、Io1_J, Io2_J, ... という命令が作られる。

で、スタックキャッシングのためにその命令数は単純に5倍になる。簡単に命令数は爆発する。

ちょっとやっただけで、50命令が 700命令になってしまった。

どうやって減らすか、というのもテーマになるのか。これは試行によって出来そうな気はするが。

とりあえず、Io1_J, ... は生成しないようにした。

(ほかにもバグがある、という理由もあるのだけれど)。

てゆーか、まさにこれが前田さんのあの論文のテーマだった気がする。


大体バグの原因はわかっていて、ここを全部こう書き直せばいい、ってのはわかってるんだけど、そうやりたいところが沢山あって、泣ける。

_しゅ(Sat Jun 25 13:57:19 JST 2005)

Linux (少なくとも 2.6 ,2.4 / x86) だと、mprotect(2) の第一引数(ポインタ)がページのサイズに整列されていないと、エラー(invalid argument)になってしまうようです。 参考:http://www.shudo.net/diary/2004may.html#20040517

_こーのいけ(Sat Jun 25 18:26:56 JST 2005)

 それはすごい>1TBメモリ

_ (Sat Jun 25 22:10:51 JST 2005)

 USBキーボード使ってみれば?

_ささだ(Sat Jun 25 23:03:28 JST 2005)

 これ以上かさばるのはいやだなぁ。

_24(Fri)

久しぶりに頭(本業の研究の)を使って疲れすぎた。


昨日は未踏・千葉滋先生プロジェクトの飲み会懇談会だった。

(関連リンクhttp://d.hatena.ne.jp/masataka_k/20050623#1119535301

なんと、私が一番若いらしい。いろいろ説教ありがたいお話を伺うことができた。

Ruby はもっと日本人がいろいろやるべきだ、Rails なんかにのってちゃ駄目だよ、とは栗原さんの弁。そういう見方もあるかもしれないけど、俺はあの辺あんまり興味ないからなぁ。

あと、YARV 以外のプログラムを作るな、と釘をさされてしまった。


今回(の流れ)が大変大きなチャンスであることは自覚しております。

実は、何度かチャンスを頂いていたのに甘く見てしまってものにできなかった、というのは何回かあるんだけれど、今回はそのようなことが無いように(同じ轍を踏まないように)頑張ります。


しかし、技術的な話をやっぱりもっと知りたかった。

そういえば、キックオフはオープンでやるらしいですよ。興味のある方は良かったら見に来てください。


しかし、千葉先生の進捗管理の方法が面白い。


(YARV ネタで)OOPSLA でポスターを出そうと思っている、と相談をしたら、「行っても誰も相手にしてくれないよ」とはっきりと言われた。正直落ち込む orz

でもその上で「とりあえず勉強に(叩かれに)行ってくれば」と更に言う千葉先生が凄いと思った。


ふと思い出したけど、kmori さんは gcc のソースを読まないらしい。うーん、なるほど。


javac の吐くコードは大変わかりやすく、悪く言うと全然最適化されていないんだが、それは後で JIT compiler が解析しやすくするためで、それを考えないで bytecode を生成しても遅くなるだけだ、ということを聞いて、ああ、なるほど、と感心してしまった。

しかし、それはなんとなく本末転倒な気がするんだけれど・・・。属性かなんかでフローの情報とか渡しちゃえばいいのに。まぁ、クラスファイルを小さくするというのは一つの目標ではあったんだろうけれども。

.NET ruby でどっか一箇所が異様に速かったのはこれが理由か?


英語が無いなぁ。


そういえば、ACM ICPC からきたメールで、コーチ連中全員に Cc で送ってきたのはいかがなものか。

_ (Fri Jun 24 11:54:16 JST 2005)

 くわしく >進捗管理

_babie(Fri Jun 24 12:16:10 JST 2005)

 同じく、くわしく。秘密&だるくなければ。>進捗管理

_KM(Fri Jun 24 13:00:27 JST 2005)

 javac・JIT → .NET ruby って流れが読めないのですが?

_ささだ(Fri Jun 24 15:58:36 JST 2005)

 (秘密にする必要があるかどうかは知らないんだけど)秘密。

_23(Thu)

T4 がきてうれしすぎて数時間インストール作業をやってしまった orz

そんな余裕無いのに...。

さー、論文書く(準備)するぞー。


現状はスタックをコントロール部分と値部分を混ぜ混ぜにして作ってるけど、制御スタックと値スタックを別に作ったらどうなるんだろう。設計がすげぇシンプルになるような気はする。

で、何が一番いいか、って GC 時に maybe (保守的GC なので、ポインタ値であった場合、それが Ruby の値かどうかをチェックしなければならない)を利用しなくていい点である。うーん、一度そういうのに作り変えてみたい。

なんだか、今考えてみればみるほどそっちのほうがいいような気がする。

デメリットはスタックを積んだときのオーバーフローチェックがスタックが二つになるので2回になること。でも、そんなもん気にしちゃ駄目かななぁ。

まぁ、この2回、というのもひとつの領域で上に進むように利用するスタックと下に進むように利用するスタック、両方やればいいんだが。

あと他にももうちょっとオーバーヘッドがある何かがあったような気がする。

しかし、今のスパゲッティがなんとかなると思うと、ちょっとやりたくなる。

ブロックをどこで作るのか、という問題があるんだなぁ。

_maeda(Thu Jun 23 15:33:44 JST 2005)

 オーバーフローチェックって、メソッド呼び出しごとに一回ですまない?

_ささだ(Thu Jun 23 16:05:46 JST 2005)

 すみます。だから、そこで悩むのはあほだなぁ、とか思い始めています。というわけで、本当は作り変えてみたいんですが、なんか色々とあって・・・。

_22(Wed)

Thunderbird で、未読のフォルダを上に、未読がないフォルダを隠す機能は無いものか。機能拡張でできるのかな。

フォルダ数が 100 個くらいになってしまって使いづらい。


雨止んだかな。


凌霄花(のうぜんかずら)。

a trumpet creeper.


YARV の論文書いてるんだけど、章立てするために内容を分けようと思っても、うまくいかない。

たとえば、命令融合はコンパイル時にそのための処理を走らせるけど、実行する命令は自動生成されて評価器に組み込まれる。

最適化、という章でいいのか? それとも、処理系の自動生成という章にするか。


Ruby用仮想マシンYARVの実装と評価

  1. はじめに
    1. オブジェクト指向スクリプト言語Ruby
    2. 既存のRuby処理系の問題点
  2. YARV: Yet Another RubyVMの概観
    1. 全体像
    2. 処理の流れ
    3. 命令セット
    4. 計算モデル
      1. スタックフレーム
  3. 処理系の最適化
    1. コンパイラ
      1. 覗き穴最適化
      2. オペランド・命令融合
    2. 実行部
      1. スレッデッドコード
      2. インラインキャッシュ
      3. スタックキャッシング
  4. 処理系の自動生成
    1. 融合命令の生成
    2. スタックキャッシング命令の生成
  5. 評価
    1. 何しよう?
  6. 関連研究
    1. 何書こう?
  7. まとめ

プラグマによって利用する最適化手法を変えるというのはよくある手だが、さて Ruby の場合どんな手法があるだろう?

  • 記法
  • 通知すべき情報

It is a common scheme to notice optimize options to a compiler with "pragma". How to do it on Ruby?

  • Notation
  • Optimize Information

今考えてるのは、特殊なメソッドを用意して、なんだけれども。

A Current Idea.

def fixnumadd a, b
  __OPTIMIZE_OPTION(:var_type, :a, :Fixnum)
  __OPTIMIZE_OPTION(:var_type, :b, :Fixnum)
  a + b
end

def floatingadd a, b
  __OPTIMIZE_OPTION(:var_type, :a, :Float)
  __OPTIMIZE_OPTION(:var_type, :b, :Float)
  a + b
end

def stringconcat a, b
  __OPTIMIZE_OPTION(:var_type, :a, :String)
  __OPTIMIZE_OPTION(:var_type, :b, :String)
  a + b
end

うーん、全然うれしくないな。


スタックキャッシングで、各命令の次のスタックキャッシュの状態を計算する手法は自明か?


T4 キター。

_なかだ(Wed Jun 22 22:57:18 JST 2005)
def fixnumadd a, b
  # -*- optimize: var_type(a, Fixnum) -*-
  # -*- optimize: var_type(b, String) -*-
  a + b
end

def floatingadd a, b
  # -*- optimize: var_type(a, Float); optimize: var_type(b, Float) -*-
  a + b
end

def stringconcat a, b
  # -*- optimize: var_type(a, String), var_type(b, String) -*-
  a + b
end

とか。

_21(Tue)

クビシメロマンチスト読了。



struct link{
  struct link *prev;
  struct link *next;
  int type;
};

struct anchor{
  struct link link;
  struct link *last;
};

main(){
  struct anchor anc = {
    {0, 0, 0},
    &anc.link};

  printf("%x, %x, %x, %x\n", anc.link.prev, anc.link.next, anc.link.type, anc.last);
  return 0;
}

main 関数でやってる anc の初期化は、C の仕様で完全に準拠してる?


IPA:未踏ソフトウェア創造事業:2005年上期未踏ソフト 公募結果

今年も未踏で支援していただくことが出来ました。YARV を Yet Another で無くすよう、努力する次第であります。今後ともご指導ご鞭撻のほどをよろしくお願いいたします。


えーと、英語でなんていうんだ。

I got fund on "Exploratory Software Project (ESP)" from IPA (Information-technology Promotion Agency, Japan). Last year, I had also got a fund on "ESP youth".

Project title is "Innovation of Ruby Interpreter".


うぅ、コンパイラ作り変えやっと終わった...。これから評価。


6 倍に

遅くなった orz


えーと、問題は GC だった。コンパイル時、毎回 1MB のメモリをアロケートしてるんだけど、それで GC が頻発する。

そして、YARV が用意するスタックは、全部毎回 mark するという駄目なやり方なので、遅い。

コンパイル時確保する量を 1KB にすると、5倍ほど速くなった。

4万行のソース
ruby 0m0.700s
yarv 0m1.160s 1KB
yarv 0m5.369s old
yarv 0m9.508s 1MB

10万行のソース
ruby 0m2.270s
yarv 0m4.244s 1KB
yarv 0m10.279s old

というわけで、1KB スタートで倍に確保していくようにしよう。

GC の速度は課題。

コンパイラの速度向上は、まぁ、こんなもんでいいかな。


後どの辺がボトルネックなのかな。

Function Clockticks % (108)
iseq_compile_each 27.34
set_sequence 13.15
compile_array 11.07
compile_data_alloc 9.34
new_insn_body 6.92
insn_optimize 6.23
new_unified_insn 5.54
new_insn_core 3.81
insn_set_sc_state 2.42
ADD_LINKED_LIST 2.08
insn_len 2.08
compile_data_alloc_insn 1.73
set_sequence_stackcaching 1.73
iseq_optimize 1.38
iseq_translate_direct_threaded_code 1.38
iseq_insns_unification 1.04
insn_ret_num 0.69
insn_data_length 0.35
insn_op_types 0.35
iseq_compile 0.35
iseq_mark 0.35
rb_check_type 0.35
rb_node_newnode 0.35

compile_array はなんとかなりそうだなぁ。

_なかだ(Tue Jun 21 14:53:26 JST 2005)

 ANSI-CならOKのはず

_mput(Tue Jun 21 15:17:06 JST 2005)

 しかしポインタと整数のサイズが違うこともあるから、printfの行が正しくない。正確には"%p"を使うべし(さもなくばキャスト)

_MenTaLguY(Wed Jun 22 02:21:37 JST 2005)

 Rather than "I got [a] fund on...", it's probably better to say "I received a grant for...".

_20(Mon)

Book:

  • Guin Saga 99

論文が条件付採録で返って来たんだけど、条件が多すぎるよウワーン。

まぁ、reject じゃなかっただけ良かったんだけれども、自分でも納得できていない部分を、しっかりと指摘してもらって、かなり凹む。本当に、よく条件付でも生かしておいてもらえたものだ orz。

まぁ、手法のアイデアや目を付けるところはあながち間違っていなかったんだ、と思って頑張ろう。

_19(Sun)

HSP となでしこの話を大変興味深く伺いました。

その話はとても面白かったんだけど、周りからの突っ込みも面白かった。


Rubyist Magazine Vol.7 was RELEASED!

Read and Enjoy.


"Should Integer have 'times' method?"

3.times{
  ...
}

Above code is very simple, and easy to write.

But there are some objection that Integer shouldn't have the "times" method (because of semantics).

If we have this method, do you use it?

def repeat cnt
  cnt.times{|x|
    yield x
  }
end

repeat 10 do |i|
  p i
end
_ogino.(Sun Jun 19 04:54:35 JST 2005)

 てゆーかなんかもうしわけない気持ちになりました。でもともかく面白かった〜。いい企画でしたね。

_なかだ(Sun Jun 19 11:23:25 JST 2005)

 くー、風邪さえ引かなければ。

_arton(Sun Jun 19 15:22:22 JST 2005)

 行きたかった(ぼそ)

_mput(Mon Jun 20 02:26:11 JST 2005)

and this code won't run:

a = 10

repeat a {|i|
   p i
}

I'd rather use a.times, which runs great (just as we use today).

_MenTaLguY(Tue Jun 21 06:36:09 JST 2005)

 That will run with parenthesis.

_18(Sat)

Today is RHG (Ruby Haching Guide) Reading session.

_17(Fri)

MS-Office がどうの、と言っていた人に OOo を使わせる。さて、どうなることやら。

_yam@(Fri Jun 17 22:09:03 JST 2005)

MS-Officeがどうのと言っているものの一人です。 個人的には互換性を無視すれば、

  • Writerは、問題なし。でもTeX使いたい。
  • Calcはもうちょっとグラフのテンプレ欲しい。
  • ImpressよりPower Point の方がアニメーション作りやすい。

※ OOo 1.1.3を使用した場合の個人的な感想。客観性無視。OOo2.0はこれから調査。

コストを考えれば充分過ぎるかな、という感じです。 逆にMSはあれだけ金とるならせめて変に図がずれたり、Excellで別ディレクトリ、同一ファイル名のファイルを開けるようにしろと言いたいです。

フリーな物が充分な機能を持てば懐が暖かくて良いなぁと手前勝手に考えております。

_ささだ(Fri Jun 17 23:09:30 JST 2005)

 君の場合は、MS-Office よりも MS がどうの、というような。今回の場合、MS-Office がどうの、というのは、MS-Office を寄越せーと言っている人に「そんな金なんかねー」と言ったというお話です。Excelって同一ファイル名のファイル開けないんだ。へー。

_16(Thu)

箪笥の取っ手が折れた。不吉な・・・。

_15(Wed)

Rainy day.


Comic:

  • Twin Spica vol.8

なんか納豆クレープを食え、という指令が来たような気がしたので食った。なんか普通。


SEGV x 2...

_ (Wed Jun 15 13:43:25 JST 2005)

 Oh! What a difficult English phrase!

_しゅ(Wed Jun 15 22:11:43 JST 2005)

 納豆サンド(パン)はうまいですよー。納豆ご飯より好き。

_14(Tue)

クビキリサイクル読了。


http://pc8.2ch.net/test/read.cgi/tech/1094825807/525

各記事の最後にでも関連サイトへのリンクをガシガシ張ってくれるとありがたいのですが無理ですかそうですか

貼ってる記事は貼ってると思うんだけど、まだ足りませんかそうですか。

例えばこの記事にこのリンクは、とか、そういう指摘があれば、今後気をつけやすいんだけれど。


http://pc8.2ch.net/test/read.cgi/tech/1094825807/527

全記事一覧を一ページにまとめてくれるとありがたいのですが無理ですかそうですか

誰かやってくれませんか。いや、やろうとは思ってるんだけど。やろうという計画は去年からあったんだけど、色々とあって...。


こんなことを書くと、お前いつも 2ch 見てるのかよ、とか言われるのかな。

すみません、るるりんからリンクあるところはたいてい見てます。

見てるけど、反応するかどうか、ってのは別問題か。


googlec bot: メーリングリスト(232,000), メーリス(2,970), メーリン(990)

googlec bot: メーリグ(4), メリーグー(2), メーリング -リスト(12,300)

メーリンは少数派らしい。


英語で全然書いて無いじゃん。


Books:

  • Life, the Universe, and Everything (邦題:宇宙クリケット大戦争)

_13(Mon)

もちろん 2ch のスレを見て思い出したんですが、別に ML でまつもとさんに提案したわけではなく(誤解された方すみません)、RHG 読書会の時か IRC かで、誰かに言ったら誰かにリジェクトされたような覚えがあるんですが、覚えてないのですよね。

なんだったかなぁ。提案自体はしてなくて、NaHi さんの投稿を見て、とかかなぁ。でも誰かに言った覚えはあるんだけど。

Gauche の場合、まさに値を返す p が #?= というリーダーマクロがあって便利です。まぁ、S式という構造に非常にマッチしているというのがあるんですが。

他の言語だとどうなんでしょうね。


そもそも、"p" というメソッド名は如何なものか、という意見もある気がする。Proc オブジェクトは p というローカル変数に入れたい。

中田さんの p? がいいのかしらん。


Method name "p" considered harmful because we can't use local variable name "p" which I want to use with Proc object.


Google Top "considered harmful":

  1. Hyper-Threading considered harmful
  2. Go To Statement Considered Harmful
  3. "Reply-To" Munging Considered Harmful
  4. Csh Programming Considered Harmful -
  5. Recursive Make Considered Harmful
  6. Sending XHTML as text/html Considered Harmful
  7. mktexlsr は有害だ (mktexlsr Considered Harmful)
  8. W* Effect Considered Harmful
  9. Address Munging Considered Harmful
  10. Slashdot | Aspect-Oriented Programming Considered Harmful

The best harmful scheme seems like Hyper-Threading.

My research theme in laboratory is (not Ruby) Hyper-Threading (HT is only a commercial word. Simultaneous Multi-Threading is technology name). sigh.


あ、p? は self を返すのか。うーん。


そういうわけで、今回の RHG のゲストも凄いです。HSP ですよ、なでしこですよ。日本で相当有名なプログラミング言語の開発者さんですよ。

楽しみです。


本当は nadoka 0.7.0 は先週末に出したかったんだけどなぁ。


なんというか、マナーの悪さに辟易。


  • "ruby considered harmful" => (0)
  • "perl considered harmful" => (19)
  • "python considered harmful" => (32)

Google results.

If you write "ruby considered harmful", you can get first document of this opinion :P


ウワーン、戯言にされてしまった。


asahi.com: 東大名誉教授の後藤英一さん死去&nbsp;-&nbsp;おくやみ

先日 codefest でちょうど後藤先生のお話を伺ったばかりでした。ご冥福をお祈りいたします。

_なかだ(Mon Jun 13 08:35:59 JST 2005)

 もう単純なローカル変数とメソッド名の衝突はなくなったはず。

_ささだ(Mon Jun 13 08:47:02 JST 2005)

 あ、いや。無意識にメソッド名と同じローカル変数を避けてたんですが、考えてみれば(引数をつけるメソッドなら)同じ名前でも問題ないんですね。しかし、p=nil; p p は気持ち悪いなぁ。

_なかだ(Mon Jun 13 11:50:29 JST 2005)

 pにこだわらないなら Kernel#me? とか。

_び(Tue Jun 14 00:15:29 JST 2005)

 後藤先生は残念でした。情報処理学会のパイオニアのページ http://www.ipsj.or.jp/katsudou/museum/pioneer/gotou.html の和田英一先生の文章も必見。ちなみに、同日、倉橋由美子も逝去してたのね…。

_Eric Hodel(Tue Jun 14 02:52:25 JST 2005)

 I've gotten a 25% performance boost from HTT with Ruby on my web servers. Can't be all that bad.

_I(Thu Jun 16 15:06:13 JST 2005)

 In all fairness, the "Hypertheading Considered Harmful" article refers to a specific security vulnerability in HT as currently implemented in Intel processors. There's nothing wrong with HT in theory, only as Intel currently implements it. Keep on hacking, Sasada-san! :-)

_12(Sun)

クビキリサイクルを借りようとしたら,図書館に置いてなかった。どうしようかな。


Should "Kernel.p" return an argument? I love this behaviour, but when I proposed it, it's rejected. But I can't remember that reason. What do you think about it?


Books:

  • Guin Saga 98
  • Harry Potter and the Order of the Phoenix (in Japanese)
  • Twin Spica 6, 7
_こーのいけ(Sun Jun 12 21:53:41 JST 2005)

 全部あるけど。貸そうか?

_なかだ(Sun Jun 12 22:53:24 JST 2005)

 「軛recycle」ってなんじゃ?と思った。

_ささだ(Sun Jun 12 23:51:54 JST 2005)

 貸して欲しいかも。

_I(Thu Jun 16 15:15:23 JST 2005)

 In functional programming languages like Scheme, a function usually creates a side-effect (like printing to the screen), or returns a useful value, but not both. This is to prevent people from relying on side-effect-producing functions for their return values. For example, a call to the function ( def foo; "Hello, world!" ; end ) is "referentially transparent", and can be computed at compile-time (which should interest someone who is working on compilation to a Ruby VM ;-). The function ( def bar; p "Hello"; "Hello"; end ) cannot be eliminated at compile-time, because the program is expecting the side-effect of ( p "Hello" ). This is why they are ideally kept separate. :)

_11(Sat)

Books:

  • Futatsu no Spica 4, 5
  • Guin Saga 96, 97

_10(Fri)

Few days ago, I upgraded woody machine (atdot.net) to sarge. I only used "apt-get update" and "apt-get dist-upgrade". There was no problem eerily.


The reason why I write this diary in English is simple, to learn English.

_Chris(Fri Jun 10 11:56:40 JST 2005)

 and we (English speaking rubyists) are happy to help teach the person who brings us YARV!

_gab(Fri Jun 10 20:14:01 JST 2005)

 and we, non native english neither japanese speakers are happy to learn both :)

_9(Thu)

comics.

  • Futatsu no Spica 2, 3

2bit あれば、(考えたうちでは)効率的なロックが実現できそうな気がするんだが、かなり駄目な欠陥がある。そのロック取得者の情報を保存しない、という欠陥。つまり、ロック取得者がなんか死んじゃったとしたら、そのロックを解法することが出来ない。

さて、「ロック獲得中のスレッドが死んじゃうことはあり得るのか?」

Ruby レベルにこの機構を出したら、十分あり得るが、C 拡張ライブラリレベルで「気をつけてね☆ミ」というだけなら現実的、なんだろうか。必ず開放することを、C レベルで保証することは可能なんだろうか。

せめて、あるスレッドが何個ロックを抱えてるかを数えておいて、スレッド終了処理中にカウンタが 1 以上だったらシステムを終了させちゃうくらいの面倒は見るべきかもしれない。

果たして、意図しないスレッドの終了はあり得るだろうか? とりあえず、思いつかないんだけど、でもスレッドだからなぁ。


Lock aquire scheme with 2 bit and CAS instruction:

lock_acquire:
  lock_info = LOCK_INFO_OF(obj);
  if(UNLOCKED(lock_info)){
    old_info = CAS(obj, lock_info, lock_info | LOCKED_BIT);
    if(!(UNLOCKED(old)){
      old_info = CAS(obj, old_info, old_info | WATING_BIT);
      // check
      goto wait;
    }
  }
  else{
  wait:
    THREAD_LOCK();
    REGIST_WAITING_THREAD_WITH(obj);
    THREAD_UNLOCK_AND_WAIT();
    goto lock_acquire;
  }

lock_release:
  lock_info = LOCK_INFO_OB(obj);
  if(NO_WAITING_THREAD(obj)){
    CAS(...);
  }
  else{
    invoke...
  }

If there are no conflicts to aquire lock, above scheme is light-weight enough. If conflicts occuer, VM should have some overhead.


ロックビットと、ウェイトビットがあって、ロックビットがたっていなければロックされていない。もしされている場合、ウェイトビットをたてて、待つ。待つとき、VM に自分はどのオブジェクトで待っているかを登録しておく。

ロック解法時、ウェイトビットが立っていれば、そのオブジェクトのロック解法を待っているスレッドを VM に聞きに行って、そこで再開させる。

各ビット操作は CAS などを使いアトミックに行なう。

というシナリオなんだけど、何か抜けは・・・。

殆どの場合ロックは競合しないことを前提としているため、もし競合したときはかなり重い。


表にすると。

wait bit 0 wait bit 1
lock bit 0 ロックもしていないし、待ちスレッドも無い あり得ない(バグ)
lock bit 1 ロックされているが、誰も待ってない ロックされていて、誰かが待っている(要開放)

って、よく考えるとこんなことしなくても、どうせコンフリクトするんだったら(そして、コンフリクト時に苦労していいんだったら) busy wait でいいぢゃないか。しょぼーん。

Java なんかは busy wait を使っていないような気がするが、どうなんだろうな。実装みてないからなんもいえないが。


YARV commit lines count (diff lines count).

-r 1:2 2004-05-11 398
-r 2:3 2004-05-12 250
-r 3:4 2004-05-14 162
-r 4:5 2004-05-14 163
-r 5:6 2004-05-16 1580
-r 6:7 2004-05-17 553
-r 7:8 2004-05-17 695
-r 8:9 2004-05-17 155
-r 9:10 2004-05-17 46
-r 10:11 2004-05-17 66
-r 11:12 2004-05-17 30
-r 12:13 2004-05-18 281
-r 13:14 2004-05-18 346
-r 14:15 2004-05-18 28
-r 15:16 2004-05-18 106
-r 16:17 2004-05-19 711
-r 17:18 2004-05-19 256
-r 18:19 2004-05-19 123
-r 19:20 2004-05-20 544
-r 20:21 2004-05-20 107
-r 21:22 2004-05-22 265
-r 22:23 2004-06-01 772
-r 23:24 2004-08-18 366
-r 24:25 2004-08-25 1185
-r 25:26 2004-08-25 180
-r 26:27 2004-08-27 1025
-r 27:28 2004-08-27 219
-r 28:29 2004-08-27 69
-r 29:30 2004-08-27 79
-r 30:31 2004-08-28 847
-r 31:32 2004-08-28 163
-r 32:33 2004-08-28 234
-r 33:34 2004-08-28 113
-r 34:35 2004-08-28 182
-r 35:36 2004-08-29 361
-r 36:37 2004-09-01 599
-r 37:38 2004-09-01 428
-r 38:39 2004-09-01 151
-r 39:40 2004-09-03 421
-r 40:41 2004-09-08 773
-r 41:42 2004-09-12 664
-r 42:43 2004-09-13 202
-r 43:44 2004-09-13 349
-r 44:45 2004-09-13 249
-r 45:46 2004-09-16 271
-r 46:47 2004-09-29 1926
-r 47:48 2004-09-29 148
-r 48:49 2004-10-02 719
-r 49:50 2004-10-10 833
-r 50:51 2004-10-25 43
-r 51:52 2004-11-01 936
-r 52:53 2004-11-01 13
-r 53:54 2004-11-03 238
-r 54:55 2004-11-10 235
-r 55:56 2004-11-13 308
-r 56:57 2004-11-13 145
-r 57:58 2004-11-15 452
-r 58:59 2004-11-19 374
-r 59:60 2004-11-19 298
-r 60:61 2004-11-21 510
-r 61:62 2004-11-22 724
-r 62:63 2004-11-22 513
-r 63:64 2004-11-26 676
-r 64:65 2004-11-27 110
-r 65:66 2004-11-29 784
-r 66:67 2004-11-30 833
-r 67:68 2004-11-30 98
-r 68:69 2004-11-30 498
-r 69:70 2004-11-30 107
-r 70:71 2004-11-30 99
-r 71:72 2004-12-01 418
-r 72:73 2004-12-02 849
-r 73:74 2004-12-02 35
-r 74:75 2004-12-03 90
-r 75:76 2004-12-03 359
-r 76:77 2004-12-03 156
-r 77:78 2004-12-05 757
-r 78:79 2004-12-05 323
-r 79:80 2004-12-06 771
-r 80:81 2004-12-06 40
-r 81:82 2004-12-06 323
-r 82:83 2004-12-06 55
-r 83:84 2004-12-07 707
-r 84:85 2004-12-07 290
-r 85:86 2004-12-08 80
-r 86:87 2004-12-11 379
-r 87:88 2004-12-11 178
-r 88:89 2004-12-13 46
-r 89:90 2004-12-14 526
-r 90:91 2004-12-14 177
-r 91:92 2004-12-14 374
-r 92:93 2004-12-15 151
-r 93:94 2004-12-17 184
-r 94:95 2005-01-01 1036
-r 95:96 2005-01-01 269
-r 96:97 2005-01-01 670
-r 97:98 2005-01-01 619
-r 98:99 2005-01-01 209
-r 99:100 2005-01-01 139
-r 100:101 2005-01-02 43
-r 101:102 2005-01-02 232
-r 102:103 2005-01-02 129
-r 103:104 2005-01-03 231
-r 104:105 2005-01-04 775
-r 105:106 2005-01-04 335
-r 106:107 2005-01-04 66
-r 107:108 2005-01-04 30
-r 108:109 2005-01-04 254
-r 109:110 2005-01-05 436
-r 110:111 2005-01-06 468
-r 111:112 2005-01-08 1141
-r 112:113 2005-01-08 470
-r 113:114 2005-01-08 385
-r 114:115 2005-01-08 91
-r 115:116 2005-01-09 819
-r 116:117 2005-01-09 191
-r 117:118 2005-01-09 1032
-r 118:119 2005-01-09 13482
-r 119:120 2005-01-10 31
-r 120:121 0
-r 121:122 0
-r 122:123 0
-r 123:124 2005-01-25 1807
-r 124:125 2005-01-25 213
-r 125:126 2005-01-25 72
-r 126:127 2005-02-09 200
-r 127:128 2005-02-09 69
-r 128:129 2005-02-11 121
-r 129:130 2005-02-12 529
-r 130:131 2005-02-14 306
-r 131:132 2005-02-16 2017
-r 132:133 2005-02-16 244
-r 133:134 2005-02-18 911
-r 134:135 2005-02-18 230
-r 135:136 2005-02-18 60
-r 136:137 2005-02-18 638
-r 137:138 2005-02-18 769
-r 138:139 2005-02-18 160
-r 139:140 2005-02-19 49
-r 140:141 2005-02-19 21
-r 141:142 0
-r 142:143 2005-02-21 201
-r 143:144 2005-02-21 595
-r 144:145 2005-02-23 128
-r 145:146 2005-02-24 295
-r 146:147 2005-02-24 33
-r 147:148 2005-02-24 221
-r 148:149 2005-02-26 656
-r 149:150 2005-03-01 589
-r 150:151 2005-03-03 751
-r 151:152 2005-03-03 77
-r 152:153 2005-03-03 29
-r 153:154 2005-03-04 73
-r 154:155 0
-r 155:156 2005-03-04 57
-r 156:157 2005-03-04 113
-r 157:158 2005-06-03 123
-r 158:159 2005-06-04 301
-r 159:160 2005-06-04 545
-r 160:161 2005-06-04 165
-r 161:162 2005-06-04 547
-r 162:163 2005-06-04 50
-r 163:164 2005-06-06 625
-r 164:165 2005-06-07 1617
-r 165:166 2005-06-07 43
-r 166:167 2005-06-08 25
-r 167:168 206

久々に gauche のドキュメントを更新しようと思ったら見つからない。どうしようかな。


コミットに非常にムラがあるのがばれてしまう。

別にコミットしてない期間、作業をしていなかったわけではないので・・・。


Today's Trap:

p 'aaa'.split('a')  # ?
p 'aaab'.split('a') # ?
p 'baaa'.split('a') # ?
p 'baab'.split('a') # ?
p '   b'.split(' ') # ?
p 'b  b'.split(' ') # ?

Can you asnwer all outputs?

_shiro(Thu Jun 09 15:01:54 JST 2005)

 threadのcancellationに対応すればいいだけなら、pthread_cleanup_push/popみたいなメカニズムが使えるのでは。cleanupも走らないようなシチュエーションってのはかなり何かが壊れている状態だと思いますが、cleanup中にSEGVったりしたらどうなるかなあ。

_ささだ(Thu Jun 09 15:33:23 JST 2005)

 自分がどのロックを持ってるかどうかという情報も持ってないので、celanup ができないというのがこの話の前提ですた。cancelling ですが、プログラマが明示的にキャンセルしない限り、起こることはないですよね。その保証があるのかなー、というのが上記の話ではあります。

_shiro(Thu Jun 09 20:16:17 JST 2005)

んー、pthread_cleanup_push/popって、ロックを獲得するコードを囲むレキシカルなスコープで使いますよね。そしたらどのロックを扱っているか情報はそこに静的にあるんじゃないかという気がするのですが、何か勘違いしているかしら。ああもちろん、ロックプリミティブをC APIとして見せているならpthread_cleanup_push/popを使うのもC拡張コードを書く人の責任になるんで、「気をつけてね☆ミ」ってのはそういうことなのか。 (そうだとしても、通常のmutexでも同じことなので悪くはないと思いますが)

cancellingは確かに、アプリケーション中に明示的にそういうコードがない限りは起こらなさそうですね。

_8(Wed)

In this diary, I write entries with my original wiki like form. In especially, syntax of specify code region is very useful for me.

#code [specify end tag. default: end]
hogehoge
#end

Now, I hit the idea of new table syntax.

#table [specify column separator. default: \t], [specify end tag. default: end]
a	b	c
a	b	c
a	b	c
#end

It seems good (for me).


I found out above table syntax. If I select "," as column separator, it conflict with end specifier.

#table ,, endtable
...
#endtable

Quote column separator?

#table ",", endtable
...
#endtable

It seems bad...

Usually, to specify end tag is rare case. So put it as first parameter isn't good idea.

Introduction of keyword parameter?


Quote column specifier seems good in above ideas.


Today's trap:

a = {:foo => 'bar'}
...
if b = a[:foo] && b.respond_to?(:split)
  p b # what is the output here?
end

Nadoka 0.7.0 will be released soon.


If we don't have nil (or false) in Ruby, what was happen? What's a disadvantage on lack of nil? Beauty of language design?


P2P を、って言うとアレじゃないかな。P2P ファイルシステムを、ならわかるんだけど。

ajax で分散計算ってありましたね。


ToDo: memory management system for compilation


多分、GC 時間がでかいので・・・。やっぱり Array を利用するのは速度的にかなりまずい感じ。でも、20% しか削減できないな。半分くらいにならないかな。

ほんとは今やることじゃない気もする。


中田先生のコンパイラ(1981)を見てみると、先日の論理式の最適化の話が出てきてるんだけど、P-198 の表 9.3 を見てみると、何をやってるかわからなかったんだけれど、理解してみると(そもそも、この T(e, bool, label) の式を理解すると)、なるほど、と思う。けど、この表は非常にわかりづらい。T(e, then_label, else_label) という式にすると、非常にわかりやすくなる。YARV はまさにこれをそのまま実装した。

・・・とかえらそうに書くことじゃないな。


で、中田先生の本を見ていて、また気づく。

  eval(A)
  if   L1
  jump L2
L1:
  ...
L2:

という命令列は、

  eval(A)
  unless L2
L1:
  ...
L2:

で済む。うわぁ、間抜け。しかし、これをどうやって除去するか。

見てみると、

  1. if or unless の次の命令が jump である
  2. if or unless の飛び先 L1 が jump の次である

このとき、最初の if or unless を jump のとび先 L2 だったとき、unless or if に反転して L2 に飛ばせばよい。

もっと簡単な規則にならないかな。


  if   L1
  jump L2
L1:
  ...
L2:

があったときに、L1 と L2 を交換して、

  unless L2
  jump   L1
L1:
  ...
L2:

とやれば、jump L1 が無駄命令ということがわかるので消せる! と思ったのだけれど、次の命令への jump を除去するのはもっと前にやっていた。

どうしたもんかなぁ。


Gauche を見てみる。

gosh>
(disasm (lambda (x y z)
          (if (or (and x y) z)
              1 2)))
main_code (name=#f, code=0x80e6eb0, size=18, const=0, stack=0):
args: #f
     0 LREF2                    ; x
     1 BF 11
     3 LREF1                    ; y
     4 BF 8
     6 JUMP 12
     8 LREF0                    ; z
     9 JUMP 12
    11 LREF0                    ; z
    12 BF 16                    ; (if (or (and x y) z) 1 2)
    14 CONSTI(1)
    15 RET
    16 CONSTI(2)
    17 RET
#<undef>

うおー、z の参照がコピーされてる。

YARV で上記の最適化を付けたもの。

0000 getlocal_SC_xx_ax4
0002 unless_SC_ax_xx 8
0004 getlocal_SC_xx_ax3
0006 if_SC_ax_xx     11
0008 getlocal_OP_2_SC_xx_ax
0009 unless_SC_ax_xx 14
0011 putobject_OP_INT2FIX_O_1_C__SC_xx_ax
0012 end_SC_ax_ax    6
0014 putobject_SC_xx_ax2
0016 end_SC_ax_ax    6

しかしなぁ。


BTW, javac's case:

  int t(boolean a, boolean b, boolean c){
    if((a && b) || (c)){
      return 1;
    }
    else{
      return 2;
    }
  }

#=>
   0:	iload_1
   1:	ifeq	8
   4:	iload_2
   5:	ifne	12
   8:	iload_3
   9:	ifeq	14
   12:	iconst_1
   13:	ireturn
   14:	iconst_2
   15:	ireturn

It's same as generated code by yarv completely.


sample table data:

a b c
d e f

sampe 2:

0000 getlocal_SC_xx_ax4
0002 unless_SC_ax_xx 8
0004 getlocal_SC_xx_ax3
0006 if_SC_ax_xx 11
0008 getlocal_OP_2_SC_xx_ax
0009 unless_SC_ax_xx 14
0011 putobject_OP_INT2FIX_O_1_C__SC_xx_ax
0012 end_SC_ax_ax 6
0014 putobject_SC_xx_ax2
0016 end_SC_ax_ax 6

sample 3:

0: iload_1
1: ifeq 8
4: iload_2
5: ifne 12
8: iload_3
9: ifeq 14
12: iconst_1
13: ireturn
14: iconst_2
15: ireturn

sample 4:

Function Clockticks % (104)
iseq_compile_each 19.49
iseq_array_to_linkedlist_each 10.92
insn_alloc 10.92
compile_array 10.49
set_sequence 8.78
insn_optimize 8.35
new_insn 5.57
insn_init 5.35
iseq_insns_unification 3.85
insn_set_sc_state 1.93
iseq_translate_direct_threaded_code 1.71
ADD_LINKED_LIST 1.71
yarv_free 1.07
insn_mark 1.07
new_unified_insn 1.07
rb_ary_push 1.07
set_sequence_stackcaching 1.07
insn_op_types 0.86
iseq_mark 0.86
rb_check_type 0.43
insn_len 0.43
insn_data_length 0.43
iseq_optimize 0.43
_MenTaLguY(Wed Jun 08 06:44:29 JST 2005)

 Will the column or end separators contain whitespace? If they won't contain whitespace, would be better to use whitespace rather than a comma?

_ko1(Wed Jun 08 07:33:02 JST 2005)

 whitespace has possibility to apear on that.

_Gyoung-Yoon Noh(Wed Jun 08 08:31:48 JST 2005)

 Oops.. it should have raised NameError?

_ko1(Wed Jun 08 11:43:14 JST 2005)

 You can try it.

_KM(Wed Jun 08 17:24:29 JST 2005)

自分のライブラリにこんな,ブロック引数をとるメソッド

def do_while; while r = yield do end; r end

があるけど,これの return value で,一応 nil か false かで 1bit の情報を返せる.使ってないけど

_ko1(Wed Jun 08 17:33:18 JST 2005)

 Yes. I know that we can use nil and false as different value. But is it useful? Is it good program?

_shiro(Wed Jun 08 18:24:23 JST 2005)

あーそこは枝が単純な式の場合のみコピーされます > Gaucheの場合。 zを(foo z)とかにすると違ってきます。 具体的な条件は src/compile.scm の pass2/$IF の上のコメントに書いてあります。

今のコードだと、アドレス6のJUMP 12 で飛んだ先でまた BF が出てくるのが 冗長なんですよねー。

_ささだ(Wed Jun 08 18:44:13 JST 2005)

 and/or で (x) みたいにして確認してました。多分そうなんだろうな、と。

_ささだ(Wed Jun 08 18:49:51 JST 2005)

 ちなみに、jump -> bf が冗長なんですか? bf->jump じゃなくて。

_maeda(Wed Jun 08 20:23:51 JST 2005)

 「無条件ジャンプを飛び越す条件ジャンプ」を「逆条件ジャンプ」に。condition reversalといいます。ピープホール最適化の定番。「if L1;jump L2;L1:」というパターンを見つけて書き換えればよい。あと「jump L; L:」も同様。ラベルは、ラベルへの参照がなくなれば消す。連続したラベルは一つにマージする。どのルールもヒットしなくなるまで何度も繰り返す。

_ささだ(Wed Jun 08 21:00:15 JST 2005)

 ラベルは自分への参照を管理していないのですよねぇ。どうしよ。リファレンスカウンタみたいにしたほうがいいのかしらん(現状ではラベルはスキップして次の命令とかにアクセスしてます)。とりあえず、そんな感じで力技で上記二つは実装しました。

_MenTaLguY(Thu Jun 09 00:19:27 JST 2005)

 I've used true, false, and nil together in situations where a "tristate" made sense. In such cases, nil generally meaning "unknown" or "undefined" rather than "known to be false".

_MenTaLguY(Thu Jun 09 01:37:29 JST 2005)

Hmm. If I must get rid of one, I would keep "nil" rather than "false". Having to use false to mean "NULL object" seems strange to me.

Actually we have precedent for this -- LISP has no "false", only t and nil. However, later LISP-influenced language designers seem to have consistently felt this was a bad idea; for example, Scheme has #t, #f, and nil like Ruby. Smalltalk also has true, false, and nil, but it does not permit nil (or any non-boolean types) to be used as a boolean (so Matz preferred Scheme over Smalltalk in this regard).

In languages where any type can be used as a boolean (and nil can be false), why have booleans at all?

True is required so that the results of boolean operators can make sense (notably, what "!nil" means).

False is not required, but there seems to be an evolutionary pressure towards adopting it. I think this is because it aids clarity and avoids ambiguity when interfacing with languages that do completely separate boolean and non-boolean types.

As I noted earlier, sometimes false is also useful to contrast with nil for "tristate" purposes.

_7(Tue)

Yesterday, I and Mr.Ikeda Mr.Ikeda and I went to eat the sushi. It's was my 3rd experience to eat of eating the sushi in the a sushi-bar.


I measured compile time again.

test code 1:

if false
if false
  m(1, 2, 3)
  ...         # repeat it
  m(1, 2, 3)
end

if false
  m(1, 2, 3)
  ...         # repeat it
  m(1, 2, 3)
end

... # repeat it. about 100k lines
end

result:

ruby        0m 1.457s
yarv(array) 0m14.881s
yarv(list)  0m11.778s

test data 2:

if false
  def m
    m(1, 2, 3)
    ...         # repeat it
    m(1, 2, 3)
  end

  def m
    m(1, 2, 3)
    ...         # repeat it
    m(1, 2, 3)
  end

... # repeat it. about 100k lines
end

result:

ruby        0m1.806s
yarv(array) 0m24.428s
yarv(list)  0m10.101s

New version of yarv (using list data structure) is faster than old one. But new version is 5 times slower than current ruby.


疲れたので日本語で。

Gauche のバイトコードをディスアセンブルしてみていると、(and a b c) の表現で dup を使っていない。あれ、スタックマシンだったよなぁ、と思ってよく見てみると、条件の値をスタックに残したままにするものとしないものがある? うーむ、そうしたほうがいいのだろうか。うむむ。


branch condition optimization:

a = b = 1
if (a and b) && (a or b) || (!a and b)
  p :then
else
  p :else
end

#=> (old verision)
0000 putobject
0001 dup
0002 setlocal
0003 setlocal        3
0005 getlocal        3
0007 dup
0008 unless          23
0010 pop
0011 getlocal
0012 dup
0013 unless          23
0015 pop
0016 getlocal        3
0018 dup
0019 if              23
0021 pop
0022 getlocal
0023 dup
0024 if              35
0026 pop
0027 getlocal        3
0029 putnot
0030 dup
0031 unless          35
0033 pop
0034 getlocal
0035 unless          46
0037 putself
0038 putobject       :then
0040 send            :p, 1, <ic>
0044 end             4
0046 putself
0047 putobject       :else
0049 send            :p, 1, <ic>
0053 end             4

#=> new version

0000 putobject
0001 dup
0002 setlocal
0003 setlocal        3
0005 getlocal        3
0007 unless          23
0009 getlocal
0010 unless          23
0012 getlocal        3
0014 unless          18
0016 jump            32
0018 getlocal
0019 unless          23
0021 jump            32
0023 getlocal        3
0025 unless          29
0027 jump            41
0029 getlocal
0030 unless          41
0032 putself
0033 putobject       :then
0035 send            :p, 1, <ic>
0039 end             4
0041 putself
0042 putobject       :else
0044 send            :p, 1, <ic>
0048 end             4

Benchmark result:

i=0
while i<1000000
  a = b = 10
  while a < 10 and b < 5
    a = b = a+1
  end
  i+=1
end

#=>
ruby  1.672000   0.000000   1.672000 (  1.717000)
yarv  0.250000   0.000000   0.250000 (  0.253000) # old version
yarv  0.203000   0.016000   0.219000 (  0.207000) # new version

diff output becomes 1600 lines over...


構造体宣言、というものがあることをはじめて知った。


よくよく考えてみると、知っていたような記憶があるが、頭に全然無かった。知らなかったといって差し支えないと思う。


Today's expense: 150000 yen. Tax and Automobile insurance and IPAX exhibition fee.


Mac が Intel の CPU を使うって。mac mini はどうなるんだって? mac imini になるんですよ。そういえば、Apple の頭文字は a だ。つまり、mac iminai ということだったんだよ(略。


いや、できれば mac mini 欲しいんですけど。買えるかなぁ・・・。


あんまり、コンパイル時間にこだわる気はないんですが、ちょっと時間を。VTune らくちん。

Function	Clockticks % (104)
iseq_compile_each	19.49
iseq_array_to_linkedlist_each	10.92
insn_alloc	10.92
compile_array	10.49
set_sequence	8.78
insn_optimize	8.35
new_insn	5.57
insn_init	5.35
iseq_insns_unification	3.85
insn_set_sc_state	1.93
iseq_translate_direct_threaded_code	1.71
ADD_LINKED_LIST	1.71
yarv_free	1.07
insn_mark	1.07
new_unified_insn	1.07
rb_ary_push	1.07
set_sequence_stackcaching	1.07
insn_op_types	0.86
iseq_mark	0.86
rb_check_type	0.43
insn_len	0.43
insn_data_length	0.43
iseq_optimize	0.43

関数名と実行時間の割合ですが。命令オブジェクトの割り付けがでかいのが意外。GC してんのかなー。命令オブジェクトは Ruby のオブジェクトとしてバイトコード1命令づつ作ってます。ちょっと無駄が多いので自分で malloc するべきか。

insn_optimize は jump 先の最適化のためだけにやってるんだけど、遅い。パスを一回通るごとにかなりのオーバーヘッドということか。まぁ、10万行のスクリプトを対象にしているのでキャッシュミスが頻発しているだけな気もするけど、どうなんだろう。

高速化のためには自分でメモリ管理しないと駄目なんだろうなぁ。

_shiro(Tue Jun 07 05:17:37 JST 2005)
  • eat the sushi -> eat sushi (unless you meant a specific sushi, such as
  • "the famous one I was always talking", or "my favorite one, oo-toro, you know".)
  • in the sushi-bar -> in a sushi bar (unless you meant a specific sushi-bar
  • you've mentioned earlier. If it's the case, this sentence means it was the third time you ate there but doesn't tell whether you've been to other sushi bars many times or not.)

And probably this is a personal preference but I'd say "Yesterday, I and Mr. Ikeda went out to eat sushi. It was my 3rd experience of eating sushi in a sushi bar."

_ko1(Tue Jun 07 05:54:11 JST 2005)

 Thank you a lot for your correction.

_maeda(Tue Jun 07 13:39:12 JST 2005)

 Re:dup Many stack-based VMs have branch-cond-pop and branch-cond-nopop variants. And number of conditions is diverse (false and true, type predicates, arithmetic comparison, etc.) I'd prefer to leave branches as simple as possible, and optimize them using superinstructions if neccesary. E.g: dup-and-branch-true (which is essentially equivalent to branch-true-nopop), dup-and-<-and-branch-false etc.

_shiro(Tue Jun 07 17:27:54 JST 2005)

 Gaucheは値レジスタをひとつ持ってます。条件分岐は値レジスタを見て判断します。

_ささだ(Tue Jun 07 19:47:09 JST 2005)

 そういえばそうでした。結局その辺の検討を十分にしてないなぁ。たしか、スタックキャッシングで頑張れば十分それ以上のメリットが得られる(んじゃないか)と思って今の実装にしたような気がする。

_c0zydoll(Wed Jun 08 01:45:51 JST 2005)

 mac mini かぁ・・・スッパ と 本 の ご褒美代わりにプレゼントするかなぁ・・・

_Chris(Wed Jun 08 06:03:05 JST 2005)

 it's better form to place the name of your companion first: "Yesterday, Mr. Ikeda and I went..."

_ko1(Wed Jun 08 09:25:51 JST 2005)

 chris: thank you.

_6(Mon)

Today's RubyManiacQuiz:

p((nil && true) == (false && true))

What value will be printed?


YARV compiler doesn't use Graph data structure to represent instruction sequence. It's only Array of Ruby.

The idea is very easy to implement, but it's too bad idea to optimize it. So I must re-implement this to use graph (linked-list) data structure.

For example, I tried to optimize unused jump elimination. But on Array data structure, it's too difficult to do it.


疲れたので日本語で。

今は、ネストした Array を作って、一本のArray(flattenして)を作って、そして YARV 命令列に最終的にしている。

これを、途中で便利なために連結リストにしたい。そこで、連結リストを何時作るかが問題になる。

  1. NODE から変換するときに、すでに連結リストを作っていく
  2. ネストした Array を作ってから連結リストを作る

前者のほうが配列生成コストが無くなって軽くなる。

後者のほうは、NODE 木をパースする部分は手をつけなくていいから楽。




struct iseq_link_element{
  int type;
  struct iseq_link_element *next;
};

struct iseq_linked_seq{
  struct iseq_link_element first;
  struct iseq_link_element *last;
};


struct iseq_linked_seq *new_seq(){
  struct iseq_linked_seq *seq = malloc(sizeof(struct iseq_linked_seq));
  
  seq->last = &seq->first;
  seq->first.next = 0;
  return seq;
}

struct iseq_link_element *new_elem(int type){
  struct iseq_link_element *e = malloc(sizeof(struct iseq_link_element));
  e->type = type;
  e->next = 0;
  return e;
}

void ADD_SEQ(struct iseq_linked_seq *s1, struct iseq_linked_seq *s2){
  s1->last->next = s2->first.next;
  s1->last = s2->last;
}

void ADD_ELEM(struct iseq_linked_seq *s, struct iseq_link_element *e){
  s->last->next = e;
  s->last = e;
}



main(){
  struct iseq_linked_seq *s1 = new_seq();
  struct iseq_linked_seq *s2 = new_seq();
  struct iseq_link_element *e;
  ADD_ELEM(s1, new_elem(1));
  ADD_ELEM(s1, new_elem(2));
  ADD_ELEM(s1, new_elem(3));
  
  ADD_ELEM(s2, new_elem(5));
  ADD_ELEM(s2, new_elem(6));

  ADD_SEQ(s1, s2);
  
  for(e = s1->first.next; e; e = e->next){
    printf("%d\n", e->type);
  }
}

Is above code abnormal?

Unak pointed out that iseq_linked_seq.first is very bad name because this name cause mistake.

What name is suitable for this code?


DirectX NotePad 0.98beta is EXCELLENT!!


I decided that once creating nested ruby array and then translate it to linked list.

It's easy way to implement. If compile time is a problem, then I change this method.


BTW, the trigger of re-structuring of compile time insn sequence representation is to try optimization that remove unused jump instruction.

         * unused jump elimination
         *
         * case 1: jump to next insn
         *
         *     jump LABEL
         *   LABEL:
         *
         *   => this jump instruction should be elimination
         *
         *
         * case 2: jump to jump insn
         *
         *     jump LABEL1
         *     ...
         *   LABEL2:
         *     jump LABEL2
         *
         *   => in this case, first jump instruction should jump tp
         *      LABEL2 directly

After re-structuring, dead code elimination can be applied.


舵手伝い。


I'm tired. Can I finish this change?


えーと、もともと最初は if などの条件文に関して、and / or / not の最適化を行おうと思っていたのだった。

Ruby の and などは値を持って、たとえば (A and B) は、もし A が偽なら A、そうでなかったら B の値を返す。そのために、少し面倒な処理(命令でいうと dup)が必要になる。

だけど、条件節では返り値は真か偽かしか興味ないためその辺を省略できます。

単純な例だと、

if !A
else
end

#=>
  eval(A)
  not
  unless ELSE
  ...
  jump END
ELSE:
  ...
END:

#=> 最適化
  eval(A)
  if ELSE
  ...
  jump END
ELSE:
  ...
END:

となる。

if A and B とか if A and (B or C) とか if (!A and B) or C とか、同様。


なんか、not の例って not if を unless に変更するだけでいいような気がしてきた。

後で加えよう。

_mput(Mon Jun 06 09:20:02 JST 2005)

But on Array data structure, it's too difficult to do it

Why? I can see no difficulties in it (or I miss something). Perhaps that's simply a matter of performance?

_ko1(Mon Jun 06 09:49:52 JST 2005)

In current YARV, compiler uses Array as Instruction sequence.

 0 -> InsnA
 1 -> InsnB
 2 -> InsnC
 3 -> jump Label
 ...
 L -> Label
 M -> InsnM
 ...
 N -> end

(0-N means Array index)

If you want to know the next instruction of Label (InsnM), Label must know its own index L. But resolving Label position is final stage of compilation.

_shiro(Mon Jun 06 16:52:23 JST 2005)

LabelがArrayの一要素を占めてるのがよくわからない。Labelってインストラクションがあるわけじゃないんだよねえ。LabelはArrayのindexを指すものなんじゃないのかしらん。

「jumpの先がjump」とか「jumpの先がreturn」とかをoptimizeするのはArrayのままでもできますね(Gaucheではコンパイルの最終段階で、コードベクタを生成した後でやってます)。中間のjumpがdead codeになる可能性があるから、それを消したかったら別の表現がいいんだろうけど、ソース読んでコンパイルして即実行、っていうスクリプト言語処理系においてdead code eliminationはそんなに神経質にやらなくてもいいんじゃないかって気はします。disassembleを眺めてて気持ち悪いのは確かだけど。

「jump先が次のインストラクション」というのはどういうシチュエーションで出てくるんでしょ。Gaucheのコンパイラではそのパターンは見ないような気がする。

_ささだ(Mon Jun 06 17:23:11 JST 2005)

Label は Array の index を指してもいいんですが、命令を追加したりとか除いたり入れ替えたりしたときに、今の構造のほうが便利なのでそうやっています。消すのとか入れ替えるのはまだいいのか。命令を追加するのが、つまり index をずらす操作が必要なときにまずくなるような気がします。

たしかに、命令を追加するごとにindexを再計算するようにすれば出来るといえば出来るんですが、コストの問題ですね。やっぱり。

うーん、どっちが一般的なのかな。ほかのコンパイラを見ていないからよくわからない。

あ、jump 先が return を忘れていたなぁ。

あと、もう一個かなり実装よりのうれしい話があるんですが、省略。

「jump先が次のインストラクション」というのはどういうシチュエーションで出てくるんでしょ

どこで出てきたか覚えてないんですが、出てきました。どこだったかなぁ。

で、コンパイラの処理を最適化のためにちょっと変えて、

if true
end

#=>

0000 putobject_OP_Qtrue_SC_xx_ax                                      (  12)
0001 unless_SC_ax_xx 8
0003 jump_SC_xx_xx   5 ## 無駄
0005 putnil_SC_xx_ax 
0006 jump_SC_ax_ax   9                                                (  12)
0008 putnil_SC_xx_ax 
0009 end_SC_ax_ax    2

こんなのが出るようにしました。無駄な jump があるのがわかると思います。そもそもこんなコード吐かせるほうが駄目、ということかもしれませんが、他にいい方法が思いつかなくてそうしました。

_ささだ(Mon Jun 06 17:31:46 JST 2005)

 ちなみに、配列のほうがいい、積極的に配列にするべき理由ってありますか。命令列をたどる時に高速、という利点はあるかも。でもなぁ、結局配列の各要素はポインタなので、ポインタをたどるとキャッシュとか考えると同じ気がする。

_shiro(Mon Jun 06 18:25:09 JST 2005)

ああ、配列にした後でインストラクション列をいじるのかあ。うーん、要素の挿入や削除があるならリンクトリストの方が圧倒的に楽じゃないですか。そしたらラベルはリスト要素へのポインタで持ってればいいし。むしろ敢えて配列にする必要がわからない。gccも最終段階はインストラクションの双方向リンクトリストにしてたような気がします。2.xの頃ですが。

でも、最終段階のpeephole最適化はともかく、他の最適化はもすこし構造を持っといた方がいいんじゃないでしょうか。GaucheではS式をANFに近い内部形式にしていろいろ最適化をかけて、一番最後にえいやと配列に落としてます。配列に落とす段階でやるのは複合インストラクションの導入とjump先のoptimizationです。どっちにせよインストラクションの列というのは非常に抽象度が低いので、最適化も微視的なものになっちゃいますよね。もし動的なコード再構成とかやるとしても、多分抽象度の高い内部形式を持っといてそれをいじることにすると思います。配列部分は再生成ってことです。

実行時の持ち方がリストが良いか配列が良いかについては、Gaucheのコンパイラを書き直す段階で試す機会があった (以前のGaucheのコンパイラがdirected graphを吐いていたので、それを配列にpackして実行するという中間段階があった) のですが、実行時間の差はほとんど見られなかったです。ただコンパイル結果をダンプしておくのは配列の方が簡単ですね。

あ、それと、この式:

if test end

に相当するSchemeプログラムは書けません。then部に必ず式が必要なので。 ただ、cond式でテストの結果がスルーするという場合があって:

(let ((test 'ok)) (cond (test))) => ok

このパターンは中間表現の段階で検出して最適化をかけてます。

_ささだ(Tue Jun 07 01:33:50 JST 2005)

何も考えないで配列でやってました。なので、

むしろ敢えて配列にする必要がわからない。

私もわかりません orz とりあえず配列でいいや、と。一番最初に全部を配列で作ってしまったので、そのようになっていました。


不勉強で ANF というのを知りません。せっかくなので、yarv-dev で。

_5(Sun)

爆睡してしまった。


うーむ、市民税、都民税をこんなに取られるのか。


とりあえず、ちょこっと正規表現だけで ruby のスキャナーを書いてみようかと思ったんだけど、あまりに面倒くさそうだったのでやめた。

%q(...), %W(...#{..}...)

とかを実現するにはどうすればいいんだろう。正規表現の動的な生成が必要だよねぇ。

逆に言うと、動的な生成さえきちんとサポートすれば、(ヒアドキュメント以外は)すぐに書けるんじゃなかろうか。


というわけで、そんな感じで rucheme を弄ると良かったりするんだろうか。

多分、scheme の場合はざっくりと行くような気がする。


ばっさりといかなかった。

radix ごとに正規表現を用意すればいいんだろうか。つまり、num2、num8、num10、num16を。

そうすればばっさり。しかし、書くのが面倒くさい。


I'll try to write some entries of this diary in English because fetty hope it.

How many entries can I write?


svn の認証方法を変更。こりゃ楽でいいや。

_4(Sat)

i=0
while i<1000000
  i+=1
  case :a
  when :x
  when :y
  when :z
  end
end

ruby  3.815000   0.010000   3.825000 (  3.893000)
yarv  1.231000   0.000000   1.231000 (  1.247000) old
yarv  0.370000   0.010000   0.380000 (  0.385000) new
i=0
while i<1000000
  i+=1
  case :x
  when :x
  when :y
  when :z
  end
end

ruby  2.864000   0.010000   2.874000 (  3.056000)
yarv  0.560000   0.010000   0.570000 (  0.571000) old
yarv  0.380000   0.010000   0.390000 (  0.399000) new

かなり速くなったと思っていいんじゃないだろうか。コミット。


しかし、一晩紆余曲折した結果でこれか・・・。


i=0
while i<100000
  i+=1
  case 'xxx'
  when 'aaa'
  when 'bbb'
  when 'ccc'
  when 'ddd'
  when 'eee'
  when 'fff'
  when 'ggg'
  when 'hhh'
  when 'iii'
  when 'jjj'
  when 'kkk'
  when 'lll'
  when 'mmm'
  when 'nnn'
  else
  end
end
--
      user     system      total        real
ruby  3.625000   0.010000   3.635000 (  3.680000)
yarv  0.140000   0.010000   0.150000 (  0.149000)

Ruby で書いた VM を動かした結果。

ruby  8.953000   0.020000   8.973000 (  9.100000) 
yarv  4.356000   0.010000   4.366000 (  4.458000) # old case/when
yarv  3.164000   0.000000   3.164000 (  3.244000) # new case/when

#
# RubiMaVM
#

module RubiMaVM
  class Instruction
    def initialize code, opts
      @code = code
      @opts = opts
    end
    attr_reader :code, :opts

    def inspect
      "#{code} <#{opts.join ', '}>"
    end
  end

  class Label
    @@id = 0
    def initialize label
      @label = label
      @pos = -1
      @id  = @@id+=1
    end
    attr_accessor :pos

    def inspect
      "#{@label} <#{@id}@#{@pos}>"
    end
    alias to_s inspect
  end
  
  class Evaluator
    def initialize
      @stack = []
      @pc    = 0
    end
    
    def evaluate sequence
      while insn = sequence[@pc]
        dispatch insn
      end
      @stack[0]
    end

    def dispatch insn
      case insn.code
      when :nop
        
      when :push
        push insn.opts[0]
        
      when :pop
        pop

      when :dup
        popped = pop
        push popped
        push popped
        
      when :add
        push pop + pop
        
      when :sub
        push pop - pop
        
      when :mul
        push pop * pop
        
      when :div
        push pop / pop
        
      when :not
        push !pop
        
      when :smaller
        push pop < pop
        
      when :bigger
        push pop > pop
        
      when :getlocal
        getlocal insn.opts[0]
      when :goto
        @pc = insn.opts[0].pos
        return
        
      when :if
        if pop
          @pc = insn.opts[0].pos
          return
        end

      when :send
        args = []
        insn.opts[1].times{
          args << pop
        }
        pop.__send__ *args

      else
        raise "Unknown Opcode: #{insn}"

      end

      @pc += 1
    end

    def push obj
      @stack.push obj
    end
    
    def pop
      @stack.pop
    end
  end
  
  class Parser
    def self.parse program
      pc     = 0
      labels = {}
      program.map{|line|
        p line
        line = line.strip
        insn = []
        
        if /\A:\w+\z/ =~ line
          label = $~[0].intern
          unless lobj = labels[label]
            lobj  = ::RubiMaVM::Label.new label
            labels[label] = lobj
          end
          next lobj
        end
        
        while line.size > 0
          case line
          when /\A:[a-z]+/
            # label
            label = $~[0].intern
            unless lobj = labels[label]
              lobj = ::RubiMaVM::Label.new label
              labels[label] = lobj
            end
            insn << lobj
            
          when /\A\s+/, /\A\#.*/
            # ignore
            
          when /\A[a-z]+/
            insn << $~[0].intern
            
          when /\A\d+/
            insn << $~[0].to_i
            
          else
            raise "Parse Error: #{line}"
            
          end
          line = $~.post_match
        end
        
        insn.size > 0 ? insn : nil
      }.compact.map{|insn|
        if insn.kind_of? ::RubiMaVM::Label
          insn.pos = pc
          nil
        else
          pc += 1
          ::RubiMaVM::Instruction.new insn[0], insn[1..-1]
        end
      }.compact
    end
  end
end


if $0 == __FILE__
  program = <<-EOP
    #
    push 1
  :label
    push 1
    add
    dup
    push 100000
    bigger
    if :label
  EOP

  parsed_program = RubiMaVM::Parser.parse program
  parsed_program.each_with_index{|insn, idx|
    puts "#{'%04d' % idx}\t#{insn.inspect}"
  }
  
  result = RubiMaVM::Evaluator.new.evaluate parsed_program
  puts result
end

_3(Fri)

case/when の高速化を考えてみる。

現在の case/when は、必ず === メソッド呼び出しの

case X
when A
  ...
when B
  ...
when C
  ...
else
  ...
end

のときには、

  v = eval X
  if A.===(v)
    ...
  elsif B.===(v)
    ...
  elsif C.===(v)
    ...
  else
    ...
  end

のようになる。

毎回これだと色々と悲しい気がするのでなんとかならないかとちょっと考えてみた。A, B, C が全部定数リテラル(=== が自明)だったとする。

コンパイル時の処理:

  h = {A => posA, B => posB, C => posC}

実行時の処理:

  pos = h.fetch(COND, posElse)
  goto pos
posA:
  ...
posB:
  ...
posC:
  ...
posElse:
  ...

実際には、定数リテラルの === が再定義されている可能性があるため、

  if redefined_eqq
    今までどおりの case/when
  else
    Hash を利用した case/when
  end

のようにすればよい。そうすると、ちょっと長い case/when、たとえば when が 10個くらい連なっていて、それぞれ文字列比較を行なうようなものに比べ、その部分の処理は10倍くらい速くなることが期待できる。あれ、期待値は5倍か?

すべてが定数リテラルであるという条件は、結構ありそうな例である。自分が作っても、when には文字列かシンボル、ときどき数値ということは多い。

ちょっと痛いのは、定数(Constant)がwhenに指定されているとこの最適化が一切適用されないことである。これは結構悲しい。文字列やシンボルはあまり困らないが、数値の場合は定数に格納されている場合が多そうだからである。

定数はコンパイル時に決まるように言語仕様が変わったらどれだけ幸せになれることだろう。でも、無理だろうなぁ。


ところで、YARV ではコンパイル時にローカル変数を自前で定義して利用する、ということを一切していないのだけれど、いくつかの処理にはそれが楽ちんな気がしてきた。でも、それをやり出すと際限なくローカル変数が追加されるかもしれないんだよな。変数の有効範囲をきっちり記録していかないと。


case X
when A
  ABody
when B
  BBody
else
  ElseBody
end

#=>

  eval X
  dup
  opt_case_dispatch hash
  dup
  if    A.=== pop
    goto posA
  dup
  elsif B.=== pop
    goto posB
  else
posElse:
  pop
  ElseBody
  goto posEnd
posB:
  pop
  eval B
  goto posEnd
posA:
  pop
  eval A 
posEnd:

こんなふうになるか。hash の位置を確定するフェーズが必要になるんだなぁ。どうやって登録したもんか。まぁ、なんとかなるか。

こう見てみると、opt_case_dispatch があるかないかしか違わない。こりゃ楽でいいな。


と思ったけど、stack caching と混ぜると自明じゃなかった。しくしく。


  eval X
  opt_case_dispatch hash, posElse, _$1
  eval A
  getlocal _$1
  send ===, 1
  if posA
  eval B
  getlocal _$1
  send ===, 1
  if posB
posElse:
  eval ElseBody
  jump posEnd
posB:
  eval BBody
  goto posEnd
posA:
  eval ABody
posEnd:

のほうが、自然だし短いし、SC 考えなくていいし(2-level なら)、いいかなぁ。

SC はジャンプ先とジャンプ前と値とレジスタの関係を同一にしないといけないのが面倒だなぁ。


instruction opt_case_dispatch(hash, elsePos, id)
  cond = pop
  if redefined_some_eqq?
    set_local(id, cond)
  else
    jump hash.fetch(cond, elsePos)
  end
end

みんな正規表現の場合、/#{A}|#{B}|#{C}/ みたいなのでどかっとやるのがよかったりするんだろうか。


地元の図書館でインターネット予約受付ができるようになっている。大変素晴らしい。


小金井図書館内情報コンセントは不正な使用があったため使用を禁止します。今後は無線LANをご利用下さい。 

何があったんだろう。まぁ、何も制限かけてなかったからなぁ。


体の調子が悪い。もつだろうか・・・。


なんか普段知らないような人ばっかりだ。

朝までもつだろうか。


temporary 変数を利用するようにしようとしたら、意外に難しいことを発見した。 とくに、eval のときの処置。

svar を使うのもアレだしな。

_なかだ(Fri Jun 03 09:07:31 JST 2005)

 正規表現は?

_ささだ(Fri Jun 03 09:10:34 JST 2005)

 正規表現は無理ですね。=== が自明なもの(シンボル、文字列、数値だけ?)のみ対象。

_2(Thu)

なんとなく、色々やる。

screen をなんとなく ^a のままだったので、 ^t に変えておく。^a は便利なんだけど、やっぱり行頭まで飛ばすとき困るね。


patch -p0 を教えてもらう。前も教えてもらったらしい。ごめんなさい。


そういえば、昨日ので、SPECIAL_CONST_P の分岐を一個にまとめたほうが速い、という指摘があった。

#define IMMEDIATE_MASK 0x03
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))

if(!SPECIAL_CONST_P(x)){
  ...
}
#=> このとき、x86 命令だと分岐は2個できたらしい

ちょっとだけ考えたんだけれど、いい方法思いつかなかった。


ざっくりと略。


詳しくない人のために補足。

int SPECIAL_CONST_P(VALUE x){
  if(x == 0    ||
     x == 0x04 ||
     (x & 0x03)){
    return 1;
  else{
    return 0;
  }
}

をどれだけ効率的に書けるか、という話です。で、最近のプロセッサでは分岐があると性能が極端に落ちてしまう可能性があるため、分岐がどこまで削れるか、という話。


なんというか、素直にやったらとても素直になった。

static inline int SPECIAL_CONST_P(VALUE x){
  VALUE a, b;
  a = !(x & ~Qnil);
  b = (x | (x >> 1)) & 0x01;
  return a | b;
}
  if(!SPECIAL_CONST_P(v)){
    r = 3;
  }

#=>
	testl	$-5, %eax
	sete	%cl
	movl	%eax, %edx
	sarl	%edx
	orl	%edx, %eax
	orl	%ecx, %eax
	testb	$1, %al
	jne	L4
	movl	$3, -8(%ebp)
L4:

typedef long VALUE;

#define Qnil 4
#define IMMEDIATE_MASK 0x03
#define IMMEDIATE_P(x) ((VALUE)(x) & IMMEDIATE_MASK)
#define RTEST(v) (((VALUE)(v) & ~Qnil) != 0)
#define SPECIAL_CONST_P(x) (IMMEDIATE_P(x) || !RTEST(x))

static inline int SPECIAL_CONST_P_NEW(VALUE x){
  VALUE a, b;
  a = !(x & ~Qnil);
  b = (x | (x >> 1)) & 0x01;
  return a | b;
}

int check(VALUE x){
  if(SPECIAL_CONST_P(x) != SPECIAL_CONST_P_NEW(x)){
    printf("Error: %8x\n", x);
  }
  return 0;
}

int main(){
  unsigned long x;

  check(0);
  for(x=1; x!=0; x++){
    check((VALUE)x);
  }
}

テストコード。


ちなみに、従来のマクロだと。

	testb	$3, %al
	jne	L7
	andl	$-5, %eax
	je	L7
	movl	$3, -4(%ebp)
L7:

単純計算で命令数が2倍。分岐命令は1/2倍。どっちが速いのかな。


static inline int SPECIAL_CONST_P_NEW(VALUE x){
  VALUE a, b;
  a = !(x & ~Qnil);
  b = !!(x & 0x03);//(x | (x >> 1)) & 0x01;
  return a | b;
}

#=>
	testl	$-5, %eax
	sete	%dl
	testb	$3, %al
	setne	%al
	orl	%edx, %eax
	testb	$1, %al
	jne	L7
	movl	$3, -4(%ebp)

もっと単純でよかった。


static inline int SPECIAL_CONST_P_NEW(VALUE x){
  VALUE a;
  a = !(x & ~Qnil);
  return (x|a) & 0x03;
}

#=>
	xorl	%edx, %edx
	testl	$-5, %eax
	sete	%dl
	orl	%edx, %eax
	testb	$3, %al
	jne	L6
	movl	$10, -8(%ebp)

もうちょっとうまくいった。

しかし、%edx の初期化は要るんだろうか。なんとかなりそうなんだけどなぁ。ah は最後に 0x03 で and とるから要らない。で、short でやればいいのか、とか思ってやってみたら、かわらなかった。しょぼん。


return (!(x & ~Qnil)) | (x & 0x03);

こういうふうにまとめてもかわらんなぁ、と思ったら変わった。分岐が増えてしまった。なるほどなぁ。


まとめ。マクロ SPECIAL_CONST_P は、以下のようなインライン関数に変更してみませんか?

static inline int SPECIAL_CONST_P_NEW(VALUE x){
  VALUE false_val, const_val;
  false_val = !(x & ~Qnil);
  const_val = x & 0x03;
  return false_val | const_val;
}

評価は後ほど。


うぇ、遅くなりました orz @ Pen3 500Mhz。

real    0m5.598s // 従来
real    0m6.626s // 新しいの

デスクトップでやりなおしてみよ。


デスクトップでも遅くなりました orz @ Celeron 1.7Ghz

もちろん環境にも寄るんでしょうが。分岐予測器をなめんじゃねー、ということでしょうか。


査定金額なんてあるんですね。そして、ざっくりと削られておりました orz

仕事は削れないんだろうか。


今は、while などのコード生成が、

while COND
  A
end

#=>
start:
  v = eval cond
  if v goto end_label
  eval A
  goto start
end_label

なんだけど、

  goto check_cond
while_body:
  eval A
check_cond:
  v = eval COND
  if v goto while_body

にするくらい考え直さないとなあ。まだまだやることは沢山ある。しかし、ruby への逆変換が面倒そう。


よく、

  v = eval COND
  unless v goto while_end
while_body:
  eval A
  v = eval COND
  if v goto while_body
while_end:

にしているのもあるけれど、どっちがいいのかなぁ。最初の goto が消えてハッピーというのはわかるんだが、コード量が増えてキャッシュ効率が云々(これは I-cache じゃなくて D-cache に載せるから)とか思うと。そんなこと考えた時点で負けかも。


javac はどうかな、と見てみたところ、

    while(i<100){
      i+=1;
    }

#=>
   2:	iload_1
   3:	bipush	100
   5:	if_icmpge	14
   8:	iinc	1, 1
   11:	goto	2
   14:   ...

ありゃりゃ。なんでだろう。なんか勘違いしてるのかな。


while i<50000000
  i+=1
end

yarv  3.141000   0.000000   3.141000 (  3.132000) # old
yarv  2.953000   0.000000   2.953000 (  2.953000) # new

まぁ、ちょっとは速くなったからいいとしよう。

_wo(Thu Jun 02 22:05:15 JST 2005)

return (((x+1)>>1)-3)>>31; で、どうですかね?

ただ、上だと、0xffffffffの時にも1になるので、そういう時は、 return ((((x+1)>>1)-3)&~x)>>31; ですかね。

_wo(Thu Jun 02 22:35:12 JST 2005)

う、すいません、勘違いしてました…

return ((((x>>2)-2) | (~((x&0x3)-1))) >> 31) ですかね

_ささだ(Fri Jun 03 00:29:53 JST 2005)

 すみません、わからにゃい。

_wo(Fri Jun 03 00:59:36 JST 2005)

えーと、

xが0か4の時は、((x>>2)-2)が負で、

(x&0x3) != 0 のときは、((x&0x3)-1)が正だから、~((x&0x3)-1)が負。

で、符号ビットのorをとれば、上のSPECIAL_CONST_Pが条件分岐無しで可能なんじゃないかなー、ていうネタです…わかりにくくてすいません。

あと、(~((x&0x3)-1)) はコンパイラさんが -(x&0x3) に最適化してくれてました。

_1(Wed)

ximapd の ML で2ゲットしてしまったので、インストールしようとして、いろいろ入れる。いろいろ野良ビルド。

で、bdb がダウンロードできない。どうしたもんかなぁ。


なぜかさっくり出来た。謎だ。

ximapd のテストも通った。さて、4万通の import にどれくらい時間がかかるか。これは rast の性能なんだろうなぁ。


投票については御大からの指令です。当初は違うものを考えていたんだけど。


PRO 研究会。まつもとさんの発表はいろんな意味で盛り上がっていた。

今回は、話がわかりやすいものばかりだったので助かった。


そして Linux cafe でまったり。いいなぁ、こういうの。なんとなく背筋がしゃんとするし。

・・・やな客だな。


(あんまり波風を立ててもアレなので消去)


いつの間にか待望の Gauche 0.8.4 がリリースされていたようなので、インストール。

すげぇなぁ。


そういえば、SWoPP のプログラムが流れている。うーむ、この時間か。いっそのこと初日朝とか、人のこなさそうなところだったらよかったのに。

しかし、PRO は絶対パラレルでやると思ったのに、きちんと PRO は一本だった。すげえ。


家に帰ってきたが、まだ届いてなかった。しょぼーん。

Sasada Koichi / sasada@namikilab.tuat.ac.jp
$Date: 2003/04/28 10:27:51 $