PageRenderTime 36ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/cappuccino_vm.js

https://github.com/hogeki/CappuccinoVM
JavaScript | 3353 lines | 2851 code | 341 blank | 161 comment | 254 complexity | 863a1e3f8076451b855c42e374b253f3 MD5 | raw file
  1. new function()
  2. {
  3. var debugPrint = function(str)
  4. {
  5. //document.write(str + "<br>");
  6. console.log(str);
  7. };
  8. var get16BitsSigned = function(value)
  9. {
  10. if(value & 0x8000)
  11. {
  12. value = (0x10000 - value) * -1;
  13. }
  14. return value;
  15. }
  16. var get8BitsSigned = function(value)
  17. {
  18. if(value & 0x80)
  19. {
  20. value = (0x100 - value) * -1;
  21. }
  22. return value;
  23. };
  24. var getParamLength = function(descriptor)
  25. {
  26. var paramLength = 0;
  27. var i = 0;
  28. if(descriptor.charAt(i) != "(")
  29. {
  30. throw Error("Method descriptor broken");
  31. }
  32. i++;
  33. loop: while(true)
  34. {
  35. switch(descriptor.charAt(i))
  36. {
  37. case ")":
  38. break loop;
  39. case "B":
  40. case "C":
  41. case "F":
  42. case "I":
  43. case "S":
  44. case "Z":
  45. paramLength++;
  46. i++;
  47. break;
  48. case "D":
  49. case "J":
  50. paramLength+=2;
  51. //paramLength++;
  52. i+=1;
  53. break;
  54. case "L":
  55. paramLength++;
  56. i++;
  57. while(descriptor.charAt(i) != ";")
  58. {
  59. i++;
  60. }
  61. i++;
  62. break;
  63. case "[":
  64. paramLength++;
  65. i++;
  66. while(true)
  67. {
  68. c = descriptor.charAt(i);
  69. if(c == "B" || c == "C" || c == "F" || c == "I" || c == "S" || c == "Z" || c == "D" || c == "J")
  70. {
  71. i++;
  72. break;
  73. }
  74. else if(c == "L")
  75. {
  76. i++;
  77. while(descriptor.charAt(i) != ";")
  78. {
  79. i++;
  80. }
  81. i++;
  82. break;
  83. }
  84. else
  85. {
  86. //[が続いているはず
  87. i++;
  88. }
  89. }
  90. break;
  91. }
  92. }
  93. return paramLength
  94. }
  95. const CONSTANT_CLASS = 7;
  96. const CONSTANT_FIELDREF = 9;
  97. const CONSTANT_METHODREF = 10;
  98. const CONSTANT_INTERFACEMETHODREF = 11;
  99. const CONSTANT_STRING = 8;
  100. const CONSTANT_INTEGER = 3;
  101. const CONSTANT_FLOAT = 4;
  102. const CONSTANT_LONG = 5;
  103. const CONSTANT_DOUBLE = 6;
  104. const CONSTANT_NAMEANDTYPE = 12;
  105. const CONSTANT_UTF8 = 1;
  106. const TYPE_INTEGER = 0x00;
  107. const TYPE_FLOAT = 0x01;
  108. const TYPE_DOUBLE = 0x02;
  109. const TYPE_LONG = 0x03;
  110. const TYPE_OBJECT = 0x04;
  111. const TYPE_DUMMY = 0x05;
  112. const TYPE_ARRAY = 0x10;
  113. var ConstEmpty = function() {}
  114. ConstEmpty.prototype.resolve = function(cpool) {
  115. this.value = "empty";
  116. }
  117. ConstEmpty.prototype.debugPrint = function()
  118. {
  119. debugPrint("Empty slot");
  120. }
  121. var ConstClass = function(tag, nameIndex)
  122. {
  123. this.tag = tag;
  124. this.nameIndex = nameIndex;
  125. }
  126. ConstClass.prototype.resolve = function(cpool)
  127. {
  128. this.value = cpool[this.nameIndex].value;
  129. }
  130. ConstClass.prototype.debugPrint = function()
  131. {
  132. debugPrint("Class " + this.value);
  133. }
  134. var ConstReferrence = function(tag, classIndex, nameAndTypeIndex)
  135. {
  136. this.tag = tag;
  137. this.classIndex = classIndex;
  138. this.nameAndTypeIndex = nameAndTypeIndex;
  139. }
  140. ConstReferrence.prototype.resolve = function(cpool)
  141. {
  142. var className = cpool[cpool[this.classIndex].nameIndex].value;
  143. var nameAndType = cpool[this.nameAndTypeIndex];
  144. var name = cpool[nameAndType.nameIndex].value;
  145. var descriptor = cpool[nameAndType.descriptorIndex].value;
  146. this.value = {className:className, name:name, descriptor:descriptor};
  147. }
  148. ConstReferrence.prototype.debugPrint = function()
  149. {
  150. debugPrint("Referrence " + this.value.className + " " + this.value.name + " " + this.value.descriptor);
  151. }
  152. var ConstFieldref = function()
  153. {
  154. ConstReferrence.apply(this, arguments);
  155. }
  156. ConstFieldref.prototype = new ConstReferrence();
  157. ConstFieldref.prototype.resolve = function()
  158. {
  159. ConstReferrence.prototype.resolve.apply(this, arguments);
  160. var desc = this.value.descriptor.charAt(0);
  161. switch(desc)
  162. {
  163. case "B":
  164. case "C":
  165. case "I":
  166. case "S":
  167. case "Z":
  168. //this.valueClass = ValueInteger;
  169. this.fieldType = TYPE_INTEGER;
  170. break;
  171. case "F":
  172. //this.valueClass = ValueFloat;
  173. this.fieldType = TYPE_FLOAT;
  174. break;
  175. case "D":
  176. //this.valueClass = ValueDouble;
  177. this.fieldType = TYPE_DOUBLE;
  178. break;
  179. case "J":
  180. //this.valueClass = ValueLong;
  181. this.fieldType = TYPE_LONG;
  182. break;
  183. case "L":
  184. case "[":
  185. //this.valueClass = ValueObject;
  186. this.fieldType = TYPE_OBJECT;
  187. break;
  188. default:
  189. //this.valueClass = ValueInteger;
  190. this.fieldType = TYPE_INTEGER;
  191. }
  192. }
  193. var ConstMethodref = function()
  194. {
  195. ConstReferrence.apply(this, arguments);
  196. }
  197. ConstMethodref.prototype = new ConstReferrence();
  198. ConstMethodref.prototype.resolve = function()
  199. {
  200. ConstReferrence.prototype.resolve.apply(this, arguments);
  201. this.paramLength = getParamLength(this.value.descriptor);
  202. }
  203. var ConstInterfaceMethodref = function()
  204. {
  205. ConstReferrence.apply(this, arguments);
  206. }
  207. ConstInterfaceMethodref.prototype = new ConstReferrence();
  208. var ConstString = function(tag, stringIndex)
  209. {
  210. this.tag = tag;
  211. this.stringIndex = stringIndex;
  212. }
  213. ConstString.prototype.resolve = function(cpool)
  214. {
  215. //this.value = cpool[this.stringIndex].value;
  216. this.value = createJavaString(cpool[this.stringIndex].value);
  217. }
  218. ConstString.prototype.debugPrint = function()
  219. {
  220. debugPrint("String " + this.value);
  221. }
  222. var ConstInteger = function(tag, bytes)
  223. {
  224. //debugPrint("ConstInteger:" + bytes);
  225. this.tag = tag;
  226. //this.value = get32BitsSigned(bytes);
  227. this.value = bytes;
  228. //this.value = new ValueInteger(bytes);
  229. }
  230. ConstInteger.prototype.resolve = function(cpool) {}
  231. ConstInteger.prototype.debugPrint = function()
  232. {
  233. debubPrint("Integer " + this.value);
  234. }
  235. var ConstLong = function(tag, high, low)
  236. {
  237. var tmp;
  238. this.tag = tag;
  239. //32bitずつhighとlowに分けて格納
  240. //符号はhighのbit32に持たせる(2の補数表現ではない)
  241. //オペランドスタック上ではhighが上でlowが下
  242. if(high & 0x80000000)
  243. {
  244. //負の数なので絶対値を取り出す
  245. //ビットを反転して1足す
  246. high = ~high >>> 0;
  247. low = ~low >>> 0;
  248. low = low + 1;
  249. if( low > 0xffffffff)
  250. {
  251. low = 0;
  252. high = high + 1;
  253. }
  254. high += Math.pow(2, 32);
  255. }
  256. this.high = high;
  257. this.low = low >>> 0;
  258. }
  259. ConstLong.prototype.resolve = function(cpool) {}
  260. ConstLong.prototype.debugPrint = function()
  261. {
  262. debugPrint("Long " + this.low);
  263. }
  264. var ConstFloat = function(tag, bytes)
  265. {
  266. this.tag = tag;
  267. var s = ((bytes >>> 31) == 1) ? -1 : 1;
  268. var e = (bytes >>> 23) & 0xff;
  269. var m = (e == 0) ? (bytes & 0x7fffff) << 1 : (bytes & 0x7fffff) | 0x800000;
  270. this.value = s * m * Math.pow(2, e-150);
  271. //this.value = new ValueFloat(s * m * Math.pow(2, e-150));
  272. }
  273. ConstFloat.prototype.resolve = function(cpool) {}
  274. ConstFloat.prototype.debugPrint = function()
  275. {
  276. debugPrint("Float " + this.value);
  277. }
  278. var ConstDouble = function(tag, highBytes, lowBytes)
  279. {
  280. this.tag = tag;
  281. var s = ((highBytes >>> 31) == 1) ? -1 : 1;
  282. var e = (highBytes >>> 20) & 0x7ff;
  283. var m;
  284. if(e == 0)
  285. {
  286. m = (highBytes & 0xfffff) * 8589934592.0 + lowBytes * 2.0;
  287. }
  288. else
  289. {
  290. m = ((highBytes & 0xfffff) | 0x100000) * 4294967296.0 + lowBytes;
  291. }
  292. //debugPrint("s=" + s + " e=" + e + " m=" + m);
  293. this.value = s * m * Math.pow(2, e-1075);
  294. //debugPrint("double value=" + this.value);
  295. //this.value = new ValueDouble(s * m * Math.pow(2, e-1075));
  296. }
  297. ConstDouble.prototype.resolve = function(cpool) {}
  298. ConstDouble.prototype.debugPrint = function()
  299. {
  300. debugPrint("Double " + this.value);
  301. }
  302. var ConstNameAndType = function(tag, nameIndex, descriptorIndex)
  303. {
  304. this.tag = tag;
  305. this.nameIndex = nameIndex;
  306. this.descriptorIndex = descriptorIndex;
  307. }
  308. ConstNameAndType.prototype.resolve = function(cpool)
  309. {
  310. var name = cpool[this.nameIndex].value;
  311. var descriptor = cpool[this.descriptorIndex].value;
  312. this.value = {name:name, descriptor:descriptor};
  313. }
  314. ConstNameAndType.prototype.debugPrint = function()
  315. {
  316. debugPrint("NameAndType " + this.value.name + " " + this.value.descriptor);
  317. }
  318. var ConstUtf8 = function(tag, length, str)
  319. {
  320. this.tag = tag;
  321. this.length = length;
  322. this.value = str;
  323. }
  324. ConstUtf8.prototype.resolve = function(cpool) {}
  325. ConstUtf8.prototype.debugPrint = function()
  326. {
  327. debugPrint("Utf8 " + this.value);
  328. }
  329. var Method = function(accessFlags, name, descriptor, $cappuccino)
  330. {
  331. this.accessFlags = accessFlags;
  332. this.name = name;
  333. this.descriptor = descriptor;
  334. this.paramLength = getParamLength(descriptor);
  335. this.$cappuccino = $cappuccino
  336. }
  337. Method.prototype.isStatic = function()
  338. {
  339. return(this.accessFlags & 0x0008);
  340. }
  341. Method.prototype.debugPrint = function()
  342. {
  343. debugPrint("Method " + this.name + " " + this.descriptor + " paramLength=" + this.paramLength);
  344. }
  345. Method.prototype.getCompiledMethod = function()
  346. {
  347. if(!this.compiledMethod)
  348. {
  349. this.compile();
  350. }
  351. return this.compiledMethod;
  352. }
  353. const NOP = 0x00;
  354. const ACONST_NULL = 0x01;
  355. const ICONST_M1 = 0x02;
  356. const ICONST_0 = 0x03;
  357. const ICONST_1 = 0x04;
  358. const ICONST_2 = 0x05;
  359. const ICONST_3 = 0x06;
  360. const ICONST_4 = 0x07;
  361. const ICONST_5 = 0x08;
  362. const LCONST_0 = 0x09;
  363. const LCONST_1 = 0x0a;
  364. const DCONST_0 = 0xe;
  365. const DCONST_1 = 0xf;
  366. const BIPUSH = 0x10;
  367. const SIPUSH = 0x11;
  368. const LDC = 0x12;
  369. const LDC2_W = 0x14;
  370. const ILOAD = 0x15;
  371. const LLOAD = 0x16;
  372. const FLOAD = 0x17;
  373. const DLOAD = 0x18;
  374. const ALOAD = 0x19;
  375. const ILOAD_0 = 0x1a;
  376. const ILOAD_1 = 0x1b;
  377. const ILOAD_2 = 0x1c;
  378. const ILOAD_3 = 0x1d;
  379. const LLOAD_0 = 0x1e;
  380. const LLOAD_1 = 0x1f;
  381. const LLOAD_2 = 0x20;
  382. const LLOAD_3 = 0x21;
  383. const FLOAD_0 = 0x22;
  384. const FLOAD_1 = 0x23;
  385. const FLOAD_2 = 0x24;
  386. const FLOAD_3 = 0x25;
  387. const DLOAD_0 = 0x26;
  388. const DLOAD_1 = 0x27;
  389. const DLOAD_2 = 0x28;
  390. const DLOAD_3 = 0x29;
  391. const ALOAD_0 = 0x2a;
  392. const ALOAD_1 = 0x2b;
  393. const ALOAD_2 = 0x2c;
  394. const ALOAD_3 = 0x2d;
  395. const IALOAD = 0x2e;
  396. const LALOAD = 0x2f;
  397. const FALOAD = 0x30;
  398. const DALOAD = 0x31;
  399. const AALOAD = 0x32;
  400. const ISTORE = 0x36;
  401. const LSTORE = 0x37;
  402. const FSTORE = 0x38;
  403. const DSTORE = 0x39;
  404. const ASTORE = 0x3a;
  405. const ISTORE_0 = 0x3b;
  406. const ISTORE_1 = 0x3c;
  407. const ISTORE_2 = 0x3d;
  408. const ISTORE_3 = 0x3e;
  409. const LSTORE_0 = 0x3f;
  410. const LSTORE_1 = 0x40;
  411. const LSTORE_2 = 0x41;
  412. const LSTORE_3 = 0x42;
  413. const FSTORE_0 = 0x43;
  414. const FSTORE_1 = 0x44;
  415. const FSTORE_2 = 0x45;
  416. const FSTORE_3 = 0x46;
  417. const DSTORE_0 = 0x47;
  418. const DSTORE_1 = 0x48;
  419. const DSTORE_2 = 0x49;
  420. const DSTORE_3 = 0x4a;
  421. const ASTORE_0 = 0x4b;
  422. const ASTORE_1 = 0x4c;
  423. const ASTORE_2 = 0x4d;
  424. const ASTORE_3 = 0x4e;
  425. const IASTORE = 0x4f;
  426. const LASTORE = 0x50;
  427. const FASTORE = 0x51;
  428. const DASTORE = 0x52;
  429. const AASTORE = 0x53;
  430. const POP = 0x57;
  431. const POP2 = 0x58;
  432. const DUP = 0x59;
  433. const DUP2 = 0x5c;
  434. const SWAP = 0x5f;
  435. const IADD = 0x60;
  436. const LADD = 0x61;
  437. const FADD = 0x62;
  438. const DADD = 0x63;
  439. const ISUB = 0x64;
  440. const LSUB = 0x65;
  441. const FSUB = 0x66;
  442. const DSUB = 0x67;
  443. const IMUL = 0x68;
  444. const LMUL = 0x69;
  445. const FMUL = 0x6a;
  446. const DMUL = 0x6b;
  447. const IDIV = 0x6c;
  448. const LDIV = 0x6d;
  449. const FDIV = 0x6e;
  450. const DDIV = 0x6f;
  451. const IREM = 0x70;
  452. const LREM = 0x71;
  453. const INEG = 0x74;
  454. const LNEG = 0x75;
  455. const FNEG = 0x76;
  456. const DNEG = 0x77;
  457. const ISHL = 0x78;
  458. const LSHL = 0x79;
  459. const ISHR = 0x7a;
  460. const LSHR = 0x7b;
  461. const IUSHR = 0x7c;
  462. const LUSHR = 0x7d;
  463. const IAND = 0x7e;
  464. const LAND = 0x7f;
  465. const IOR = 0x80;
  466. const LOR = 0x81;
  467. const IXOR = 0x82;
  468. const LXOR = 0x83;
  469. const IINC = 0x84;
  470. const I2L = 0x85;
  471. const I2F = 0x86;
  472. const I2D = 0x87;
  473. const L2I = 0x88;
  474. const L2F = 0x89;
  475. const L2D = 0x8a;
  476. const F2I = 0x8b;
  477. const F2L = 0x8c;
  478. const F2D = 0x8d;
  479. const D2I = 0x8e;
  480. const D2L = 0x8f;
  481. const D2F = 0x90;
  482. const I2B = 0x91;
  483. const I2C = 0x92;
  484. const I2S = 0x93;
  485. const LCMP = 0x94;
  486. const DCMPL = 0x97;
  487. const DCMPG = 0x98;
  488. const IFEQ = 0x99;
  489. const IFNE = 0x9a;
  490. const IFLT = 0x9b;
  491. const IFGE = 0x9c;
  492. const IFGT = 0x9d;
  493. const IFLE = 0x9e;
  494. const IF_ICMPEQ = 0x9f;
  495. const IF_ICMPNE = 0xa0;
  496. const IF_ICMPLT = 0xa1;
  497. const IF_ICMPGE = 0xa2;
  498. const IF_ICMPGT = 0xa3;
  499. const IF_ICMPLE = 0xa4;
  500. const IF_ACMPEQ = 0xa5;
  501. const IF_ACMPNE = 0xa6;
  502. const GOTO = 0xa7;
  503. const TABLESWITCH = 0xaa;
  504. const LOOKUPSWITCH = 0xab;
  505. const IRETURN = 0xac;
  506. const LRETURN = 0xad;
  507. const FRETURN = 0xae;
  508. const DRETURN = 0xaf;
  509. const ARETURN = 0xb0;
  510. const RETURN = 0xb1;
  511. const GETSTATIC = 0xb2;
  512. const PUTSTATIC = 0xb3;
  513. const GETFIELD = 0xb4;
  514. const PUTFIELD = 0xb5;
  515. const INVOKEVIRTUAL = 0xb6;
  516. const INVOKESPECIAL = 0xb7;
  517. const INVOKESTATIC = 0xb8;
  518. const INVOKEINTERFACE = 0xb9;
  519. const NEW = 0xbb;
  520. const NEWARRAY = 0xbc;
  521. const ANEWARRAY = 0xbd;
  522. const ARRAYLENGTH = 0xbe;
  523. const ATHROW = 0xbf;
  524. const MULTIANEWARRAY = 0xc5;
  525. const IFNULL = 0xc6;
  526. const IFNONNULL = 0xc7;
  527. Method.instTable = [];
  528. var notImplement = function(code, i, jsCodes, $cappuccino)
  529. {
  530. throw Error("Not implemented pc=" + i + " opcode=" + code[i]);
  531. }
  532. var i;
  533. for(i=0; i < 256; i++)
  534. Method.instTable[i] = notImplement;
  535. Method.instTable[NOP] = function(code, i, jsCodes)
  536. {
  537. return i + 1;
  538. }
  539. Method.instTable[ISTORE] = Method.instTable[ASTORE] = Method.instTable[FSTORE] = function(code, i, jsCodes)
  540. {
  541. jsCodes.push("vmStack[stackBase+" + code[i+1] + "] = vmStack[--thread.stackPtr];");
  542. return i + 2;
  543. }
  544. Method.instTable[DSTORE] = Method.instTable[LSTORE] = function(code, i, jsCodes)
  545. {
  546. jsCodes.push("thread.stackPtr-=2;");
  547. jsCodes.push("vmStack[stackBase+" + code[i+1] + "] = vmStack[thread.stackPtr];");
  548. jsCodes.push("vmStack[stackBase+" + (code[i+1] + 1) + "] = vmStack[thread.stackPtr+1];");
  549. return i + 2;
  550. }
  551. Method.instTable[ISTORE_0] = Method.instTable[ASTORE_0] = Method.instTable[FSTORE_0] = function(code, i, jsCodes)
  552. {
  553. jsCodes.push("vmStack[stackBase] = vmStack[--thread.stackPtr];");
  554. return i + 1;
  555. }
  556. Method.instTable[DSTORE_0] = Method.instTable[LSTORE_0] = function(code, i, jsCodes)
  557. {
  558. jsCodes.push("thread.stackPtr-=2");
  559. jsCodes.push("vmStack[stackBase] = vmStack[thread.stackPtr];");
  560. jsCodes.push("vmStack[stackBase+1] = vmStack[thread.stackPtr+1];");
  561. return i + 1;
  562. }
  563. Method.instTable[ISTORE_1] = Method.instTable[ASTORE_1] = Method.instTable[FSTORE_1] = function(code, i, jsCodes)
  564. {
  565. jsCodes.push("vmStack[stackBase+1] = vmStack[--thread.stackPtr];");
  566. return i + 1;
  567. }
  568. Method.instTable[DSTORE_1] = Method.instTable[LSTORE_1] = function(code, i, jsCodes)
  569. {
  570. jsCodes.push("thread.stackPtr-=2;");
  571. jsCodes.push("vmStack[stackBase+1] = vmStack[thread.stackPtr];");
  572. jsCodes.push("vmStack[stackBase+2] = vmStack[thread.stackPtr+1];");
  573. return i + 1;
  574. }
  575. Method.instTable[ISTORE_2] = Method.instTable[ASTORE_2] = Method.instTable[FSTORE_2] = function(code, i, jsCodes)
  576. {
  577. jsCodes.push("vmStack[stackBase+2] = vmStack[--thread.stackPtr];");
  578. return i + 1;
  579. }
  580. Method.instTable[DSTORE_2] = Method.instTable[LSTORE_2] = function(code, i, jsCodes)
  581. {
  582. jsCodes.push("thread.stackPtr-=2;");
  583. jsCodes.push("vmStack[stackBase+2] = vmStack[thread.stackPtr];");
  584. jsCodes.push("vmStack[stackBase+3] = vmStack[thread.stackPtr+1];");
  585. return i + 1;
  586. }
  587. Method.instTable[ISTORE_3] = Method.instTable[ASTORE_3] = Method.instTable[FSTORE_3] = function(code, i, jsCodes)
  588. {
  589. jsCodes.push("vmStack[stackBase+3] = vmStack[--thread.stackPtr];");
  590. return i + 1;
  591. }
  592. Method.instTable[DSTORE_3] = Method.instTable[LSTORE_3] = function(code, i, jsCodes)
  593. {
  594. jsCodes.push("thread.stackPtr-=2;");
  595. jsCodes.push("vmStack[stackBase+3] = vmStack[thread.stackPtr];");
  596. jsCodes.push("vmStack[stackBase+4] = vmStack[thread.stackPtr+1];");
  597. return i + 1;
  598. }
  599. Method.instTable[ILOAD] = Method.instTable[ALOAD] = Method.instTable[FLOAD] = function(code, i, jsCodes)
  600. {
  601. jsCodes.push("vmStack[thread.stackPtr++] = vmStack[stackBase+" + code[i+1] + "];");
  602. return i + 2;
  603. }
  604. Method.instTable[DLOAD] = Method.instTable[LLOAD] = function(code, i, jsCodes)
  605. {
  606. //jsCodes.push("vmStack.push(vmStack[stackTop+" + code[i+1] +"].duplicate());");
  607. //jsCodes.push("vmStack.push(CappuccinoVM.valueDummy);");
  608. jsCodes.push("vmStack[thread.stackPtr] = vmStack[stackBase+" + code[i+1] + "];");
  609. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[stackBase+" + (code[i+1]+1)+ "];");
  610. jsCodes.push("thread.stackPtr+=2;");
  611. return i + 2;
  612. }
  613. Method.instTable[ILOAD_0] = Method.instTable[ALOAD_0] = Method.instTable[FLOAD_0] = function(code, i, jsCodes)
  614. {
  615. jsCodes.push("vmStack[thread.stackPtr++] = vmStack[stackBase];");
  616. return i + 1;
  617. }
  618. Method.instTable[DLOAD_0] = Method.instTable[LLOAD_0] = function(code, i, jsCodes)
  619. {
  620. jsCodes.push("vmStack[thread.stackPtr] = vmStack[stackBase];");
  621. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[stackBase+1];");
  622. jsCodes.push("thread.stackPtr+=2;");
  623. return i + 1;
  624. }
  625. Method.instTable[ILOAD_1] = Method.instTable[ALOAD_1] = Method.instTable[FLOAD_1] = function(code, i, jsCodes)
  626. {
  627. jsCodes.push("vmStack[thread.stackPtr++] = vmStack[stackBase+1];");
  628. return i + 1;
  629. }
  630. Method.instTable[DLOAD_1] = Method.instTable[LLOAD_1] = function(code, i, jsCodes)
  631. {
  632. jsCodes.push("vmStack[thread.stackPtr] = vmStack[stackBase+1];");
  633. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[stackBase+2];");
  634. jsCodes.push("thread.stackPtr+=2;");
  635. return i + 1;
  636. }
  637. Method.instTable[ILOAD_2] = Method.instTable[ALOAD_2] = Method.instTable[FLOAD_2] = function(code, i, jsCodes)
  638. {
  639. jsCodes.push("vmStack[thread.stackPtr++] = vmStack[stackBase+2];");
  640. return i + 1;
  641. }
  642. Method.instTable[DLOAD_2] = Method.instTable[LLOAD_2] = function(code, i, jsCodes)
  643. {
  644. jsCodes.push("vmStack[thread.stackPtr] = vmStack[stackBase+2];");
  645. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[stackBase+3];");
  646. jsCodes.push("thread.stackPtr+=2;");
  647. return i + 1;
  648. }
  649. Method.instTable[ILOAD_3] = Method.instTable[ALOAD_3] = Method.instTable[FLOAD_3] = function(code, i, jsCodes)
  650. {
  651. jsCodes.push("vmStack[thread.stackPtr++] = vmStack[stackBase+3];");
  652. return i + 1;
  653. }
  654. Method.instTable[DLOAD_3] = Method.instTable[LLOAD_3] = function(code, i, jsCodes)
  655. {
  656. jsCodes.push("vmStack[thread.stackPtr] = vmStack[stackBase+3];");
  657. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[stackBase+4];");
  658. jsCodes.push("thread.stackPtr+=2;");
  659. return i + 1;
  660. }
  661. Method.instTable[IASTORE] = Method.instTable[AASTORE] = Method.instTable[FASTORE] = function(code, i, jsCodes)
  662. {
  663. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  664. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  665. jsCodes.push("obj = vmStack[--thread.stackPtr];");
  666. jsCodes.push("obj[operand1] = operand2;");
  667. return i + 1;
  668. }
  669. Method.instTable[DASTORE] = function(code, i, jsCodes)
  670. {
  671. jsCodes.push("--thread.stackPtr;");
  672. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  673. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  674. jsCodes.push("obj = vmStack[--thread.stackPtr];");
  675. jsCodes.push("obj[operand1] = operand2;");
  676. return i + 1;
  677. }
  678. Method.instTable[LASTORE] = function(code, i, jsCodes)
  679. {
  680. jsCodes.push("operand2 = {high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]};");
  681. jsCodes.push("operand1 = vmStack[thread.stackPtr-3];");
  682. jsCodes.push("obj = vmStack[thread.stackPtr-4];");
  683. jsCodes.push("obj[operand1] = operand2;");
  684. jsCodes.push("thread.stackPtr -= 4;");
  685. return i + 1;
  686. }
  687. Method.instTable[IALOAD] = Method.instTable[AALOAD] = Method.instTable[FALOAD] = function(code, i, jsCodes)
  688. {
  689. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  690. jsCodes.push("obj = vmStack[thread.stackPtr-1];");
  691. jsCodes.push("vmStack[thread.stackPtr-1] = obj[operand1];");
  692. return i + 1;
  693. }
  694. Method.instTable[DALOAD] = function(code, i, jsCodes)
  695. {
  696. jsCodes.push("operand1 = vmStack[thread.stackPtr-1];");
  697. jsCodes.push("obj = vmStack[thread.stackPtr-2];");
  698. jsCodes.push("vmStack[thread.stackPtr-2] = obj[operand1];");
  699. jsCodes.push("vmStack[thread.stackPtr-1] = 0;");
  700. return i + 1;
  701. }
  702. Method.instTable[LALOAD] = function(code, i, jsCodes)
  703. {
  704. jsCodes.push("operand1 = vmStack[thread.stackPtr-1];");
  705. jsCodes.push("obj = vmStack[thread.stackPtr-2];");
  706. jsCodes.push("vmStack[thread.stackPtr-2] = obj[operand1].low;");
  707. jsCodes.push("vmStack[thread.stackPtr-1] = obj[operand1].high;");
  708. return i + 1;
  709. }
  710. Method.instTable[POP] = function(code, i, jsCodes)
  711. {
  712. jsCodes.push("thread.stackPtr--;");
  713. return i + 1;
  714. }
  715. Method.instTable[POP2] = function(code, i, jsCodes)
  716. {
  717. jsCodes.push("thread.stackPtr-=2;");
  718. return i + 1;
  719. }
  720. Method.instTable[DUP] = function(code, i, jsCodes)
  721. {
  722. jsCodes.push("vmStack[thread.stackPtr] = vmStack[thread.stackPtr-1];");
  723. jsCodes.push("thread.stackPtr++;");
  724. return i + 1;
  725. }
  726. Method.instTable[DUP2] = function(code, i, jsCodes)
  727. {
  728. jsCodes.push("vmStack[thread.stackPtr] = vmStack[thread.stackPtr-2];");
  729. jsCodes.push("vmStack[thread.stackPtr+1] = vmStack[thread.stackPtr-1];");
  730. jsCodes.push("thread.stackPtr+=2;");
  731. return i + 1;
  732. }
  733. Method.instTable[SWAP] = function(code, i, jsCodes)
  734. {
  735. jsCodes.push("operand2 = vmStack[thread.stackPtr-1];");
  736. jsCodes.push("operand1 = vmStack[thread.stackPtr-2];");
  737. jsCodes.push("vmStack[thread.stackPtr-2] = operand2;");
  738. jsCodes.push("vmStack[thread.stackPtr-1] = operand1;");
  739. return i + 1;
  740. }
  741. Method.instTable[BIPUSH] = function(code, i, jsCodes)
  742. {
  743. jsCodes.push("vmStack[thread.stackPtr++] = " + get8BitsSigned(code[i+1]) + ";");
  744. return i + 2;
  745. }
  746. Method.instTable[SIPUSH] = function(code, i, jsCodes)
  747. {
  748. jsCodes.push("vmStack[thread.stackPtr++] = " + get16BitsSigned((code[i+1] << 8) + code[i+2]) + ";");
  749. return i + 3;
  750. }
  751. Method.instTable[ACONST_NULL] = function(code, i, jsCodes)
  752. {
  753. jsCodes.push("vmStack[thread.stackPtr++] = null;");
  754. return i + 1;
  755. }
  756. Method.instTable[ICONST_M1] = function(code, i, jsCodes)
  757. {
  758. jsCodes.push("vmStack[thread.stackPtr++] = -1;");
  759. return i + 1;
  760. }
  761. Method.instTable[ICONST_0] = function(code, i, jsCodes)
  762. {
  763. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  764. return i + 1;
  765. }
  766. Method.instTable[ICONST_1] = function(code, i, jsCodes)
  767. {
  768. jsCodes.push("vmStack[thread.stackPtr++] = 1;");
  769. return i + 1;
  770. }
  771. Method.instTable[ICONST_2] = function(code, i, jsCodes)
  772. {
  773. jsCodes.push("vmStack[thread.stackPtr++] = 2;");
  774. return i + 1;
  775. }
  776. Method.instTable[ICONST_3] = function(code, i, jsCodes)
  777. {
  778. jsCodes.push("vmStack[thread.stackPtr++] = 3;");
  779. return i + 1;
  780. }
  781. Method.instTable[ICONST_4] = function(code, i, jsCodes)
  782. {
  783. jsCodes.push("vmStack[thread.stackPtr++] = 4;");
  784. return i + 1;
  785. }
  786. Method.instTable[LCONST_0] = function(code, i, jsCodes)
  787. {
  788. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  789. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  790. return i + 1;
  791. }
  792. Method.instTable[LCONST_1] = function(code, i, jsCodes)
  793. {
  794. jsCodes.push("vmStack[thread.stackPtr++] = 1;");
  795. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  796. return i + 1;
  797. }
  798. Method.instTable[DCONST_0] = function(code, i, jsCodes)
  799. {
  800. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  801. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  802. return i + 1;
  803. }
  804. Method.instTable[DCONST_1] = function(code, i, jsCodes)
  805. {
  806. jsCodes.push("vmStack[thread.stackPtr++] = 1;");
  807. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  808. return i + 1;
  809. }
  810. Method.instTable[ICONST_5] = function(code, i, jsCodes)
  811. {
  812. jsCodes.push("vmStack[thread.stackPtr++] = 5;");
  813. return i + 1;
  814. }
  815. Method.instTable[IFEQ] = function(code, i, jsCodes)
  816. {
  817. var addr;
  818. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  819. jsCodes.push("if(operand1==0){");
  820. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  821. jsCodes.push("pc = " + addr + "; continue;}");
  822. return i + 3;
  823. }
  824. Method.instTable[IFNE] = function(code, i, jsCodes)
  825. {
  826. var addr;
  827. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  828. jsCodes.push("if(operand1!=0){");
  829. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  830. jsCodes.push("pc = " + addr + "; continue;}");
  831. return i + 3;
  832. }
  833. Method.instTable[IFLT] = function(code, i, jsCodes)
  834. {
  835. var addr;
  836. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  837. jsCodes.push("if(operand1<0){");
  838. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  839. jsCodes.push("pc = " + addr + "; continue;}");
  840. return i + 3;
  841. }
  842. Method.instTable[IFLE] = function(code, i, jsCodes)
  843. {
  844. var addr;
  845. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  846. jsCodes.push("if(operand1<=0){");
  847. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  848. jsCodes.push("pc = " + addr + "; continue;}");
  849. return i + 3;
  850. }
  851. Method.instTable[IFGT] = function(code, i, jsCodes)
  852. {
  853. var addr;
  854. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  855. jsCodes.push("if(operand1>0){");
  856. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  857. jsCodes.push("pc = " + addr + "; continue;}");
  858. return i + 3;
  859. }
  860. Method.instTable[IFGE] = function(code, i, jsCodes)
  861. {
  862. var addr;
  863. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  864. jsCodes.push("if(operand1>=0){");
  865. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  866. jsCodes.push("pc = " + addr + "; continue;}");
  867. return i + 3;
  868. }
  869. Method.instTable[IF_ICMPEQ] = Method.instTable[IF_ACMPEQ] = function(code, i, jsCodes)
  870. {
  871. var addr;
  872. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  873. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  874. jsCodes.push("if(operand1==operand2){");
  875. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  876. jsCodes.push("pc = " + addr + "; continue;}");
  877. return i + 3;
  878. }
  879. Method.instTable[IF_ICMPNE] = Method.instTable[IF_ACMPNE] = function(code, i, jsCodes)
  880. {
  881. var addr;
  882. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  883. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  884. jsCodes.push("if(operand1!=operand2){");
  885. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  886. jsCodes.push("pc = " + addr + "; continue;}");
  887. return i + 3;
  888. }
  889. Method.instTable[IF_ICMPLT] = function(code, i, jsCodes)
  890. {
  891. var addr;
  892. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  893. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  894. jsCodes.push("if(operand1<operand2){");
  895. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  896. jsCodes.push("pc = " + addr + "; continue;}");
  897. return i + 3;
  898. }
  899. Method.instTable[IF_ICMPLE] = function(code, i, jsCodes)
  900. {
  901. var addr;
  902. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  903. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  904. jsCodes.push("if(operand1<=operand2){");
  905. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  906. jsCodes.push("pc = " + addr + "; continue;}");
  907. return i + 3;
  908. }
  909. Method.instTable[IF_ICMPGT] = function(code, i, jsCodes)
  910. {
  911. var addr;
  912. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  913. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  914. jsCodes.push("if(operand1>operand2){");
  915. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  916. jsCodes.push("pc = " + addr + "; continue;}");
  917. return i + 3;
  918. }
  919. Method.instTable[IF_ICMPGE] = function(code, i, jsCodes)
  920. {
  921. var addr;
  922. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  923. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  924. jsCodes.push("if(operand1>=operand2){");
  925. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  926. jsCodes.push("pc = " + addr + "; continue;}");
  927. return i + 3;
  928. }
  929. Method.instTable[IFNULL] = function(code, i, jsCodes)
  930. {
  931. var addr;
  932. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  933. jsCodes.push("if(operand1 == null){");
  934. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  935. jsCodes.push("pc = " + addr + "; continue;}");
  936. return i + 3;
  937. }
  938. Method.instTable[IFNONNULL] = function(code, i, jsCodes)
  939. {
  940. var addr;
  941. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  942. jsCodes.push("if(operand1 != null){");
  943. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  944. jsCodes.push("pc = " + addr + "; continue;}");
  945. return i + 3;
  946. }
  947. Method.instTable[GOTO] = function(code, i, jsCodes)
  948. {
  949. var addr;
  950. addr = i + get16BitsSigned((code[i+1] << 8) + code[i+2]);
  951. jsCodes.push("pc = " + addr + "; continue;");
  952. return i + 3;
  953. }
  954. Method.instTable[TABLESWITCH] = function(code, i, jsCodes)
  955. {
  956. var _i, j, addr, defaddr, low, high;
  957. _i = i + (0x04 - (i & 0x03));
  958. defaddr = i + ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  959. _i += 4;
  960. low = ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  961. _i += 4;
  962. high = ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  963. _i += 4;
  964. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  965. for(j = low; j <= high; j++)
  966. {
  967. addr = i + ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  968. jsCodes.push("if(operand1 == " + j + "){pc =" + addr + "; continue;}");
  969. _i += 4;
  970. }
  971. jsCodes.push("pc=" + defaddr + "; continue;");
  972. return _i;
  973. }
  974. Method.instTable[LOOKUPSWITCH] = function(code, i, jsCodes)
  975. {
  976. var _i, j, addr, defaddr, npairs, match;
  977. _i = i + (0x04 - (i & 0x03));
  978. defaddr = i + ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  979. _i += 4;
  980. npairs = (code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3];
  981. _i += 4;
  982. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  983. for(j = 0; j < npairs; j++)
  984. {
  985. match = ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  986. _i += 4;
  987. addr = i + ((code[_i] << 24) + (code[_i+1] << 16) + (code[_i+2] << 8) + code[_i+3]);
  988. jsCodes.push("if(operand1==" + match + "){pc=" + addr + "; continue;}");
  989. _i += 4;
  990. }
  991. jsCodes.push("pc=" + defaddr + "; continue;");
  992. return _i;
  993. }
  994. Method.instTable[IINC] = function(code, i, jsCodes)
  995. {
  996. jsCodes.push("vmStack[stackBase+" + code[i+1] + "]+=" + get8BitsSigned(code[i+2]) + ";");
  997. return i + 3;
  998. }
  999. Method.instTable[IADD] = Method.instTable[FADD] = function(code, i, jsCodes)
  1000. {
  1001. jsCodes.push("vmStack[thread.stackPtr-2] += vmStack[thread.stackPtr-1];");
  1002. jsCodes.push("thread.stackPtr--;");
  1003. return i + 1;
  1004. }
  1005. Method.instTable[DADD] = function(code, i, jsCodes)
  1006. {
  1007. jsCodes.push("vmStack[thread.stackPtr-4] += vmStack[thread.stackPtr-2];");
  1008. jsCodes.push("thread.stackPtr-=2;");
  1009. return i + 1;
  1010. }
  1011. Method.instTable[LADD] = function(code, i, jsCodes)
  1012. {
  1013. jsCodes.push("obj=CappuccinoVM.doAddLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1014. jsCodes.push("vmStack[thread.stackPtr-4]=obj.low;");
  1015. jsCodes.push("vmStack[thread.stackPtr-3]=obj.high;");
  1016. jsCodes.push("thread.stackPtr-=2;");
  1017. return i + 1;
  1018. }
  1019. Method.instTable[ISUB] = Method.instTable[FSUB] = function(code, i, jsCodes)
  1020. {
  1021. jsCodes.push("vmStack[thread.stackPtr-2] -= vmStack[thread.stackPtr-1];");
  1022. jsCodes.push("thread.stackPtr--;");
  1023. return i + 1;
  1024. }
  1025. Method.instTable[DSUB] = function(code, i, jsCodes)
  1026. {
  1027. jsCodes.push("vmStack[thread.stackPtr-4] -= vmStack[thread.stackPtr-2];");
  1028. jsCodes.push("thread.stackPtr-=2;");
  1029. return i + 1;
  1030. }
  1031. Method.instTable[LSUB] = function(code, i, jsCodes)
  1032. {
  1033. jsCodes.push("obj=CappuccinoVM.doSubLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1034. jsCodes.push("vmStack[thread.stackPtr-4]=obj.low;");
  1035. jsCodes.push("vmStack[thread.stackPtr-3]=obj.high;");
  1036. jsCodes.push("thread.stackPtr-=2;");
  1037. return i + 1;
  1038. }
  1039. Method.instTable[IMUL] = Method.instTable[FMUL] = function(code, i, jsCodes)
  1040. {
  1041. jsCodes.push("vmStack[thread.stackPtr-2] *= vmStack[thread.stackPtr-1];");
  1042. jsCodes.push("thread.stackPtr--;");
  1043. return i + 1;
  1044. }
  1045. Method.instTable[DMUL] = function(code, i, jsCodes)
  1046. {
  1047. jsCodes.push("vmStack[thread.stackPtr-4] *= vmStack[thread.stackPtr-2];");
  1048. jsCodes.push("thread.stackPtr-=2;");
  1049. return i + 1;
  1050. }
  1051. Method.instTable[LMUL] = function(code, i, jsCodes)
  1052. {
  1053. jsCodes.push("obj=CappuccinoVM.doMulLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1054. jsCodes.push("vmStack[thread.stackPtr-4]=obj.low;");
  1055. jsCodes.push("vmStack[thread.stackPtr-3]=obj.high;");
  1056. jsCodes.push("thread.stackPtr-=2;");
  1057. return i + 1;
  1058. }
  1059. Method.instTable[IDIV] = Method.instTable[FDIV] = function(code, i, jsCodes)
  1060. {
  1061. jsCodes.push("vmStack[thread.stackPtr-2] = Math.floor(vmStack[thread.stackPtr-2]/vmStack[thread.stackPtr-1]);");
  1062. jsCodes.push("thread.stackPtr--;");
  1063. return i + 1;
  1064. }
  1065. Method.instTable[DDIV] = function(code, i, jsCodes)
  1066. {
  1067. jsCodes.push("vmStack[thread.stackPtr-4] /= vmStack[thread.stackPtr-2];");
  1068. jsCodes.push("thread.stackPtr-=2;");
  1069. return i + 1;
  1070. }
  1071. Method.instTable[LDIV] = function(code, i, jsCodes)
  1072. {
  1073. jsCodes.push("obj=CappuccinoVM.doDivLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1074. jsCodes.push("vmStack[thread.stackPtr-4]=obj.lowQuot;");
  1075. jsCodes.push("vmStack[thread.stackPtr-3]=obj.highQuot;");
  1076. jsCodes.push("thread.stackPtr-=2;");
  1077. return i + 1;
  1078. }
  1079. Method.instTable[IREM] = function(code, i, jsCodes)
  1080. {
  1081. jsCodes.push("vmStack[thread.stackPtr-2] %= vmStack[thread.stackPtr-1];");
  1082. jsCodes.push("thread.stackPtr--;");
  1083. return i + 1;
  1084. }
  1085. Method.instTable[LREM] = function(code, i, jsCodes)
  1086. {
  1087. jsCodes.push("obj=CappuccinoVM.doDivLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1088. jsCodes.push("vmStack[thread.stackPtr-4]=obj.lowMod;");
  1089. jsCodes.push("vmStack[thread.stackPtr-3]=obj.highMod;");
  1090. jsCodes.push("thread.stackPtr-=2;");
  1091. return i + 1;
  1092. }
  1093. Method.instTable[INEG] = Method.instTable[FNEG] = function(code, i, jsCodes)
  1094. {
  1095. jsCodes.push("vmStack[thread.stackPtr-1] *= -1;");
  1096. return i + 1;
  1097. }
  1098. Method.instTable[DNEG] = function(code, i, jsCodes)
  1099. {
  1100. jsCodes.push("vmStack[thread.stackPtr-2] *= -1;");
  1101. return i + 1;
  1102. }
  1103. Method.instTable[LNEG] = function(code, i, jsCodes)
  1104. {
  1105. jsCodes.push("obj=CappuccinoVM.doMulLong(vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2], Math.pow(2, 32), 1);");
  1106. jsCodes.push("vmStack[thread.stackPtr-2]=obj.low;");
  1107. jsCodes.push("vmStack[thread.stackPtr-1]=obj.high;");
  1108. return i + 1;
  1109. }
  1110. Method.instTable[LCMP] = function(code, i, jsCodes)
  1111. {
  1112. jsCodes.push("operand1=CappuccinoVM.doCmpLong(vmStack[thread.stackPtr-3], vmStack[thread.stackPtr-4], vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1113. jsCodes.push("vmStack[thread.stackPtr-4] = operand1")
  1114. jsCodes.push("thread.stackPtr-=3;");
  1115. return i + 1;
  1116. }
  1117. Method.instTable[DCMPL] = Method.instTable[DCMPG] = function(code, i, jsCodes)
  1118. {
  1119. jsCodes.push("thread.stackPtr--;");
  1120. jsCodes.push("operand2 = vmStack[--thread.stackPtr];");
  1121. jsCodes.push("thread.stackPtr--;");
  1122. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  1123. jsCodes.push("if(operand1 > operand2){vmStack[thread.stackPtr++] = 1;}")
  1124. jsCodes.push("else if(operand1 == operand2){vmStack[thread.stackPtr++] = 0;}");
  1125. jsCodes.push("else {vmStack[thread.stackPtr++] = -1;}");
  1126. return i + 1;
  1127. }
  1128. Method.instTable[ISHL] = function(code, i, jsCodes)
  1129. {
  1130. jsCodes.push("vmStack[thread.stackPtr-2] <<= vmStack[thread.stackPtr-1];");
  1131. jsCodes.push("thread.stackPtr--;");
  1132. return i + 1;
  1133. }
  1134. Method.instTable[LSHL] = function(code, i, jsCodes)
  1135. {
  1136. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-2], low:vmStack[thread.stackPtr-3]});");
  1137. jsCodes.push("operand2 = vmStack[thread.stackPtr-1];");
  1138. jsCodes.push("if(operand2 < 32) {");
  1139. jsCodes.push("mask = (~0 >>> 0) << (32-operand2);");
  1140. jsCodes.push("operand1.high = ((operand1.high << operand2) | ((operand1.low & mask) >>> (32-operand2))) >>> 0;");
  1141. jsCodes.push("operand1.low = (operand1.low << operand2) >>> 0;");
  1142. jsCodes.push("}else{");
  1143. jsCodes.push("operand1.high = (operand1.low << (operand2 - 32)) >>> 0;");
  1144. jsCodes.push("operand1.low = 0;");
  1145. jsCodes.push("}");
  1146. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1147. jsCodes.push("vmStack[thread.stackPtr-2] = operand1.high;");
  1148. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.low;");
  1149. jsCodes.push("thread.stackPtr--;");
  1150. return i + 1;
  1151. }
  1152. Method.instTable[ISHR] = function(code, i, jsCodes)
  1153. {
  1154. jsCodes.push("vmStack[thread.stackPtr-2] >>= vmStack[thread.stackPtr-1];");
  1155. jsCodes.push("thread.stackPtr--;");
  1156. return i + 1;
  1157. }
  1158. Method.instTable[LSHR] = function(code, i, jsCodes)
  1159. {
  1160. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-2], low:vmStack[thread.stackPtr-3]});");
  1161. jsCodes.push("operand2 = vmStack[thread.stackPtr-1];");
  1162. jsCodes.push("if(operand2 < 32) {");
  1163. jsCodes.push("mask = (~0 >>> 0) >>> (32-operand2);");
  1164. jsCodes.push("operand1.low = ((operand1.low >>> operand2) | ((operand1.high & mask) << (32-operand2))) >>> 0;");
  1165. jsCodes.push("operand1.high = (operand1.high >> operand2) >>> 0;");
  1166. jsCodes.push("}else{");
  1167. jsCodes.push("operand1.low = (operand1.high >> (operand2 - 32)) >>> 0;");
  1168. jsCodes.push("if(operand1.high & 0x80000000){operand1.high = 0xffffffff;}");
  1169. jsCodes.push("else{operand1.high = 0;}");
  1170. jsCodes.push("}");
  1171. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1172. jsCodes.push("vmStack[thread.stackPtr-2] = operand1.high;");
  1173. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.low;");
  1174. jsCodes.push("thread.stackPtr--;");
  1175. return i + 1;
  1176. }
  1177. Method.instTable[IUSHR] = function(code, i, jsCodes)
  1178. {
  1179. jsCodes.push("vmStack[thread.stackPtr-2] >>>= vmStack[thread.stackPtr-1];");
  1180. jsCodes.push("thread.stackPtr--;");
  1181. return i + 1;
  1182. }
  1183. Method.instTable[LUSHR] = function(code, i, jsCodes)
  1184. {
  1185. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-2], low:vmStack[thread.stackPtr-3]});");
  1186. jsCodes.push("operand2 = vmStack[thread.stackPtr-1];");
  1187. jsCodes.push("if(operand2 < 32) {");
  1188. jsCodes.push("mask = (~0 >>> 0) >>> (32-operand2);");
  1189. jsCodes.push("operand1.low = ((operand1.low >>> operand2) | ((operand1.high & mask) << (32-operand2))) >>> 0;");
  1190. jsCodes.push("operand1.high = (operand1.high >>> operand2) >>> 0;");
  1191. jsCodes.push("}else{");
  1192. jsCodes.push("operand1.low = (operand1.high >>> (operand2 - 32)) >>> 0;");
  1193. jsCodes.push("operand1.high = 0;");
  1194. jsCodes.push("}");
  1195. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1196. jsCodes.push("vmStack[thread.stackPtr-2] = operand1.high;");
  1197. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.low;");
  1198. jsCodes.push("thread.stackPtr--;");
  1199. return i + 1;
  1200. }
  1201. Method.instTable[IAND] = function(code, i, jsCodes)
  1202. {
  1203. jsCodes.push("vmStack[thread.stackPtr-2] &= vmStack[thread.stackPtr-1];");
  1204. jsCodes.push("thread.stackPtr--;");
  1205. return i + 1;
  1206. }
  1207. Method.instTable[LAND] = function(code, i, jsCodes)
  1208. {
  1209. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-3], low:vmStack[thread.stackPtr-4]});");
  1210. jsCodes.push("operand2 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]});");
  1211. jsCodes.push("operand1.low &= operand2.low;");
  1212. jsCodes.push("operand1.high &= operand2.high;");
  1213. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1214. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.high;");
  1215. jsCodes.push("vmStack[thread.stackPtr-4] = operand1.low;");
  1216. jsCodes.push("thread.stackPtr-=2;");
  1217. return i + 1;
  1218. }
  1219. Method.instTable[IOR] = function(code, i, jsCodes)
  1220. {
  1221. jsCodes.push("vmStack[thread.stackPtr-2] |= vmStack[thread.stackPtr-1];");
  1222. jsCodes.push("thread.stackPtr--;");
  1223. return i + 1;
  1224. }
  1225. Method.instTable[LOR] = function(code, i, jsCodes)
  1226. {
  1227. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-3], low:vmStack[thread.stackPtr-4]});");
  1228. jsCodes.push("operand2 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]});");
  1229. jsCodes.push("operand1.low |= operand2.low;");
  1230. jsCodes.push("operand1.high |= operand2.high;");
  1231. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1232. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.high;");
  1233. jsCodes.push("vmStack[thread.stackPtr-4] = operand1.low;");
  1234. jsCodes.push("thread.stackPtr-=2;");
  1235. return i + 1;
  1236. }
  1237. Method.instTable[IXOR] = function(code, i, jsCodes)
  1238. {
  1239. jsCodes.push("vmStack[thread.stackPtr-2] ^= vmStack[thread.stackPtr-1];");
  1240. jsCodes.push("thread.stackPtr--;");
  1241. return i + 1;
  1242. }
  1243. Method.instTable[LXOR] = function(code, i, jsCodes)
  1244. {
  1245. jsCodes.push("operand1 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-3], low:vmStack[thread.stackPtr-4]});");
  1246. jsCodes.push("operand2 = CappuccinoVM.getOpponentFromSign({high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]});");
  1247. jsCodes.push("operand1.low ^= operand2.low;");
  1248. jsCodes.push("operand1.high ^= operand2.high;");
  1249. jsCodes.push("operand1 = CappuccinoVM.getSignFromOpponent(operand1);");
  1250. jsCodes.push("vmStack[thread.stackPtr-3] = operand1.high;");
  1251. jsCodes.push("vmStack[thread.stackPtr-4] = operand1.low;");
  1252. jsCodes.push("thread.stackPtr-=2;");
  1253. return i + 1;
  1254. }
  1255. Method.instTable[I2C] = function(code, i, jsCodes)
  1256. {
  1257. //jsCodes.push("vmStack.push(vmStack.pop().toChar());");
  1258. jsCodes.push("vmStack[thread.stackPtr-1] &= 0xffff;");
  1259. return i + 1;
  1260. }
  1261. Method.instTable[I2B] = function(code, i, jsCodes)
  1262. {
  1263. //jsCodes.push("vmStack.push(vmStack.pop().toByte());");
  1264. jsCodes.push("vmStack[thread.stackPtr-1] &= 0xff;");
  1265. return i + 1;
  1266. }
  1267. Method.instTable[I2S] = function(code, i, jsCodes)
  1268. {
  1269. jsCodes.push("vmStack[thread.stackPtr-1] &= 0xffff;");
  1270. return i + 1;
  1271. }
  1272. Method.instTable[I2F] = function(code, i, jsCodes)
  1273. {
  1274. return i + 1;
  1275. }
  1276. Method.instTable[I2D] = function(code, i, jsCodes)
  1277. {
  1278. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  1279. return i + 1;
  1280. }
  1281. Method.instTable[I2L] = function(code, i, jsCodes)
  1282. {
  1283. jsCodes.push("obj = CappuccinoVM.getLongFromInt(vmStack[thread.stackPtr-1]);");
  1284. jsCodes.push("vmStack[thread.stackPtr-1] = obj.low;");
  1285. jsCodes.push("vmStack[thread.stackPtr++] = obj.high;");
  1286. return i + 1;
  1287. }
  1288. Method.instTable[F2I] = function(code, i, jsCodes)
  1289. {
  1290. jsCodes.push("vmStack[thread.stackPtr-1] = Math.floor(vmStack[thread.stackPtr-1]);");
  1291. return i + 1;
  1292. }
  1293. Method.instTable[F2D] = function(code, i, jsCodes)
  1294. {
  1295. jsCodes.push("vmStack[thread.stackPtr++] = 0;");
  1296. return i + 1;
  1297. }
  1298. Method.instTable[F2L] = function(code, i, jsCodes)
  1299. {
  1300. jsCodes.push("obj=CappuccinoVM.getLongFromDouble(vmStack[thread.stackPtr-1]);");
  1301. jsCodes.push("vmStack[thread.stackPtr-1] = obj.low;");
  1302. jsCodes.push("vmStack[thread.stackPtr++] = obj.high;");
  1303. return i + 1;
  1304. }
  1305. Method.instTable[L2I] = function(code, i, jsCodes)
  1306. {
  1307. jsCodes.push("operand1=CappuccinoVM.getDoubleFromLong(vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1308. jsCodes.push("vmStack[thread.stackPtr-2] = operand1;");
  1309. jsCodes.push("thread.stackPtr--;");
  1310. return i + 1;
  1311. }
  1312. Method.instTable[L2F] = function(code, i, jsCodes)
  1313. {
  1314. jsCodes.push("operand1=CappuccinoVM.getDoubleFromLong(vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1315. jsCodes.push("vmStack[thread.stackPtr-2] = operand1;");
  1316. jsCodes.push("thread.stackPtr--;");
  1317. return i + 1;
  1318. }
  1319. Method.instTable[L2D] = function(code, i, jsCodes)
  1320. {
  1321. jsCodes.push("operand1=CappuccinoVM.getDoubleFromLong(vmStack[thread.stackPtr-1], vmStack[thread.stackPtr-2]);");
  1322. jsCodes.push("vmStack[thread.stackPtr-2] = operand1;");
  1323. return i + 1;
  1324. }
  1325. Method.instTable[D2I] = function(code, i, jsCodes)
  1326. {
  1327. jsCodes.push("vmStack[thread.stackPtr-2] = Math.floor(vmStack[thread.stackPtr-2]);");
  1328. jsCodes.push("thread.stackPtr--;");
  1329. return i + 1;
  1330. }
  1331. Method.instTable[D2F] = function(code, i, jsCodes)
  1332. {
  1333. jsCodes.push("thread.stackPtr--;");
  1334. return i + 1;
  1335. }
  1336. Method.instTable[D2L] = function(code, i, jsCodes)
  1337. {
  1338. jsCodes.push("obj=CappuccinoVM.getLongFromDouble(vmStack[thread.stackPtr-2]);");
  1339. jsCodes.push("vmStack[thread.stackPtr-2] = obj.low;");
  1340. jsCodes.push("vmStack[thread.stackPtr-1] = obj.high;");
  1341. return i + 1;
  1342. }
  1343. ////Longの実装////
  1344. /*
  1345. memo:
  1346. highのbit32を符号bitとする
  1347. オペランドスタック上ではlowが下,highが上
  1348. */
  1349. var addAbsLong = function(highX, lowX, highY, lowY)
  1350. {
  1351. var highZ, lowZ;
  1352. var rad = Math.pow(2, 32)
  1353. lowZ = lowX + lowY;
  1354. highZ = highX + highY + Math.floor(lowZ / rad);
  1355. lowZ = lowZ % rad;
  1356. return {high:highZ, low:lowZ};
  1357. }
  1358. //X >= Yじゃないとダメ
  1359. var subAbsLong = function(highX, lowX, highY, lowY)
  1360. {
  1361. var highZ, lowZ;
  1362. var rad = Math.pow(2, 32);
  1363. lowX += rad;
  1364. lowZ = lowX - lowY;
  1365. highZ = highX - highY;
  1366. if(lowZ >= rad)
  1367. {
  1368. lowZ -= rad;
  1369. }
  1370. else
  1371. {
  1372. highZ--;
  1373. }
  1374. return {high:highZ, low:lowZ};
  1375. }
  1376. var cmpAbsLong = function(highX, lowX, highY, lowY)
  1377. {
  1378. if(highX > highY)
  1379. {
  1380. return 1;
  1381. }
  1382. else if(highX == highY)
  1383. {
  1384. if(lowX > lowY)
  1385. {
  1386. return 1;
  1387. }
  1388. else if(lowX == lowY)
  1389. {
  1390. return 0;
  1391. }
  1392. else
  1393. {
  1394. return -1;
  1395. }
  1396. }
  1397. else
  1398. {
  1399. return -1;
  1400. }
  1401. }
  1402. var doCmpLong = function(highX, lowX, highY, lowY)
  1403. {
  1404. var signX, signY;
  1405. var rad = Math.pow(2, 32);
  1406. signX = Math.floor(highX / rad) >>> 0;
  1407. highX = highX % rad >>> 0;
  1408. signY = Math.floor(highY / rad) >>> 0;
  1409. highY = highY % rad >>> 0;
  1410. if(signX == 0 && signY == 0)
  1411. {
  1412. return cmpAbsLong(highX, lowX, highY, lowY);
  1413. }
  1414. else if(signX == 0 && signY == 1)
  1415. {
  1416. return 1;
  1417. }
  1418. else if(signX == 1 && signY == 0)
  1419. {
  1420. return -1;
  1421. }
  1422. else
  1423. {
  1424. return cmpAbsLong(highX, lowX, highY, lowY) * -1;
  1425. }
  1426. }
  1427. var doAddLong = function(highX, lowX, highY, lowY)
  1428. {
  1429. var signX, signY;
  1430. var Z;
  1431. var res;
  1432. var rad = Math.pow(2, 32);
  1433. signX = Math.floor(highX / rad) >>> 0;
  1434. highX = highX % rad >>> 0;
  1435. signY = Math.floor(highY / rad) >>> 0;
  1436. highY = highY % rad >>> 0;
  1437. if(signX == signY)
  1438. {
  1439. Z = addAbsLong(highX, lowX, highY, lowY);
  1440. Z.high += rad * signX;
  1441. }
  1442. else
  1443. {
  1444. res = cmpAbsLong(highX, lowX, highY, lowY);
  1445. if(res == 1)
  1446. {
  1447. Z = subAbsLong(highX, lowX, highY, lowY);
  1448. Z.high += rad * signX;
  1449. }
  1450. else if(res == 0)
  1451. {
  1452. //符号が違って絶対値が等しければ答えは0
  1453. Z = {high:0, low:0};
  1454. }
  1455. else
  1456. {
  1457. Z = subAbsLong(highY, lowY, highX, lowX);
  1458. Z.high += rad * signY;
  1459. }
  1460. }
  1461. return Z;
  1462. }
  1463. var doSubLong = function(highX, lowX, highY, lowY)
  1464. {
  1465. var signX, signY;
  1466. var Z;
  1467. var res;
  1468. var rad = Math.pow(2, 32);
  1469. signX = Math.floor(highX / rad) >>> 0;
  1470. highX = highX % rad >>> 0;
  1471. signY = Math.floor(highY / rad) >>> 0;
  1472. highY = highY % rad >>> 0;
  1473. if(signX == 0)
  1474. {
  1475. if(signY == 0)
  1476. {
  1477. res = cmpAbsLong(highX, lowX, highY, lowY);
  1478. if(res == 1)
  1479. {
  1480. Z = subAbsLong(highX, lowX, highY, lowY);
  1481. }
  1482. else if(res == 0)
  1483. {
  1484. Z = {high:0, low:0};
  1485. }
  1486. else
  1487. {
  1488. Z = subAbsLong(highY, lowY, highX, lowX);
  1489. Z.high += rad;
  1490. }
  1491. }
  1492. else
  1493. {
  1494. Z = addAbsLong(highX, lowX, highY, lowY);
  1495. }
  1496. }
  1497. else
  1498. {
  1499. if(signY == 0)
  1500. {
  1501. Z = addAbsLong(highX, lowX, highY, lowY);
  1502. Z.high += rad;
  1503. }
  1504. else
  1505. {
  1506. res = cmpAbsLong(highX, lowX, highY, lowY);
  1507. if(res == 1)
  1508. {
  1509. Z = subAbsLong(highX, lowX, highY, lowY);
  1510. Z.high += rad;
  1511. }
  1512. else if(res == 0)
  1513. {
  1514. Z = {high:0, low:0};
  1515. }
  1516. else
  1517. {
  1518. Z = subAbsLong(highY, lowY, highX, lowX);
  1519. }
  1520. }
  1521. }
  1522. return Z;
  1523. }
  1524. var doMulLong = function(highX, lowX, highY, lowY)
  1525. {
  1526. var signX, signY;
  1527. var buffX = [];
  1528. var buffY = [];
  1529. var buffZ = [];
  1530. var i, j, tmp;
  1531. var Z = {high:0, low:0};
  1532. var rad = Math.pow(2, 32);
  1533. signX = Math.floor(highX / rad) >>> 0;
  1534. highX = highX % rad >>> 0;
  1535. signY = Math.floor(highY / rad) >>> 0;
  1536. highY = highY % rad >>> 0;
  1537. //16bitごとに分割
  1538. buffX[0] = (lowX & 0x0000ffff) >>> 0;
  1539. buffX[1] = lowX >>> 16;
  1540. buffX[2] = (highX & 0x0000ffff) >>> 0;
  1541. buffX[3] = highX >>> 16;
  1542. buffY[0] = (lowY & 0x0000ffff) >>> 0;
  1543. buffY[1] = lowY >>> 16;
  1544. buffY[2] = (highY & 0x0000ffff) >>> 0;
  1545. buffY[3] = highY >>> 16;
  1546. for(i=0; i<8; i++)
  1547. {
  1548. buffZ[i] = 0;
  1549. }
  1550. for(i=0; i<4; i++)
  1551. {
  1552. tmp = 0;
  1553. for(j=0; j<4; j++)
  1554. {
  1555. tmp += buffX[i] * buffY[j];
  1556. tmp += buffZ[i+j];
  1557. buffZ[i+j] = (tmp & 0x0000ffff) >>> 0;
  1558. tmp >>>= 16;
  1559. }
  1560. buffZ[i+j] = (tmp & 0x0000ffff) >>> 0;
  1561. }
  1562. Z.low = (buffZ[0] + (buffZ[1] << 16)) >>> 0;
  1563. Z.high = (buffZ[2] + (buffZ[3] << 16)) >>> 0;
  1564. if(signX != signY && (Z.low != 0 || Z.high != 0))
  1565. {
  1566. Z.high += rad;
  1567. }
  1568. return Z;
  1569. }
  1570. var cmpLongBuff = function(buffX, buffY)
  1571. {
  1572. var i;
  1573. for(i = 3; i >= 0; i--)
  1574. {
  1575. if(buffX[i] > buffY[i])
  1576. {
  1577. return 1;
  1578. }
  1579. else if(buffX[i] == buffY[i])
  1580. {
  1581. continue;
  1582. }
  1583. else
  1584. {
  1585. return -1;
  1586. }
  1587. return 0;
  1588. }
  1589. }
  1590. var subLongBuff = function(buffX, buffY)
  1591. {
  1592. var tmp;
  1593. var rad = Math.pow(2, 16);
  1594. var i;
  1595. tmp = 0;
  1596. for(i = 0; i < 4; i++)
  1597. {
  1598. tmp = rad + buffX[i] - buffY[i] - tmp;
  1599. buffX[i] = (tmp & 0xffff) >>> 0;
  1600. if(tmp & 0x10000)
  1601. {
  1602. tmp = 0;
  1603. }
  1604. else
  1605. {
  1606. tmp = 1;
  1607. }
  1608. }
  1609. }
  1610. var doDivLong = function(highX, lowX, highY, lowY)
  1611. {
  1612. var signX, signY;
  1613. var buffW = [];
  1614. var buffX = [];
  1615. var buffY = [];
  1616. var buffZ = [];
  1617. var sizeX, sizeY, sizeZ;
  1618. var i, j, tmp, q;
  1619. var rad = Math.pow(2, 32);
  1620. var ret = {highQuot:0, lowQuot:0, highMod:0, lowMod:0};
  1621. signX = Math.floor(highX / rad) >>> 0;
  1622. highX = highX % rad >>> 0;
  1623. signY = Math.floor(highY / rad) >>> 0;
  1624. highY = highY % rad >>> 0;
  1625. //16bitごとに分割
  1626. buffX[0] = (lowX & 0x0000ffff) >>> 0;
  1627. buffX[1] = lowX >>> 16;
  1628. buffX[2] = (highX & 0x0000ffff) >>> 0;
  1629. buffX[3] = highX >>> 16;
  1630. buffY[0] = (lowY & 0x0000ffff) >>> 0;
  1631. buffY[1] = lowY >>> 16;
  1632. buffY[2] = (highY & 0x0000ffff) >>> 0;
  1633. buffY[3] = highY >>> 16;
  1634. buffZ[0] = buffZ[1] = buffZ[2] = buffZ[3] = 0;
  1635. sizeX = 0;
  1636. for(i=3; i>=0; i--)
  1637. {
  1638. if(buffX[i] > 0)
  1639. {
  1640. sizeX = i + 1;
  1641. break;
  1642. }
  1643. }
  1644. if(sizeX == 0)
  1645. {
  1646. return {highQuot:0, lowQuot:0, highMod:0, lowMod:0};
  1647. }
  1648. sizeY = 0;
  1649. for(i=3; i>=0; i--)
  1650. {
  1651. if(buffY[i] > 0)
  1652. {
  1653. sizeY = i + 1;
  1654. break;
  1655. }
  1656. }
  1657. if(sizeY == 0)
  1658. {
  1659. throw Error("divide by 0(long)");
  1660. }
  1661. sizeZ = sizeX - sizeY + 1;
  1662. q = Math.floor(buffX[sizeX-1] / buffY[sizeY-1]);
  1663. if(q == 0)
  1664. {
  1665. if(sizeX >= 2)
  1666. {
  1667. q = Math.floor((((buffX[sizeX-1] << 16) + buffX[sizeX-2]) >>> 0) / buffY[sizeY-1]);
  1668. sizeZ--;
  1669. }
  1670. else
  1671. {
  1672. return {highQuot:0, lowQuot:0, highMod:highX, lowMod:lowX};
  1673. }
  1674. }
  1675. i = sizeZ - 1;
  1676. while(true)
  1677. {
  1678. while(true)
  1679. {
  1680. for(j = 0; j < 5; j++)
  1681. {
  1682. buffW[j] = 0;
  1683. }
  1684. if(q == 0)
  1685. {
  1686. break;
  1687. }
  1688. tmp = 0;
  1689. for(j=0; j < sizeY; j++)
  1690. {
  1691. tmp += buffY[j] * q;
  1692. buffW[j+i] = (tmp & 0x0000ffff) >>> 0;
  1693. tmp >>>= 16;
  1694. }
  1695. buffW[j+i] = tmp;
  1696. if(cmpLongBuff(buffX, buffW) != -1)
  1697. {
  1698. break;
  1699. }
  1700. q--;
  1701. }
  1702. buffZ[i--] = q;
  1703. subLongBuff(buffX, buffW);
  1704. if(i == -1)
  1705. {
  1706. break;
  1707. }
  1708. sizeX = 0;
  1709. for(j=3; j>=0; j--)
  1710. {
  1711. if(buffX[j] != 0)
  1712. {
  1713. sizeX = j + 1;
  1714. break;
  1715. }
  1716. }
  1717. if(sizeX >= 2)
  1718. {
  1719. q = Math.floor((((buffX[sizeX-1] << 16) + buffX[sizeX-2]) >>> 0) / buffY[sizeY-1]);
  1720. }
  1721. else if(sizeX == 1)
  1722. {
  1723. q = Math.floor(buffX[sizeX-1] / buffY[sizeY-1]);
  1724. }
  1725. else
  1726. {
  1727. break;
  1728. }
  1729. }
  1730. ret.highQuot = ((buffZ[3] << 16) + buffZ[2]) >>> 0;
  1731. ret.lowQuot = ((buffZ[1] << 16) + buffZ[0]) >>> 0;
  1732. ret.highMod = ((buffX[3] << 16) + buffX[2]) >>> 0;
  1733. ret.lowMod = ((buffX[1] << 16) + buffX[0]) >>> 0;
  1734. if(signX != signY && (ret.highQuot != 0 || ret.lowQuot != 0))
  1735. {
  1736. ret.highQuot += rad;
  1737. }
  1738. if(signX == 1 && (ret.highMod != 0 || ret.lowMod != 0))
  1739. {
  1740. ret.highMod += rad;
  1741. }
  1742. return ret;
  1743. }
  1744. var convLongStr = function(x)
  1745. {
  1746. var signX;
  1747. var ret;
  1748. var rad = Math.pow(2, 32);
  1749. signX = Math.floor(x.high / rad);
  1750. x.high = x.high % rad;
  1751. ret = x.low.toString(16);
  1752. while(ret.length < 8)
  1753. {
  1754. ret = "0" + ret;
  1755. }
  1756. ret = x.high.toString(16) + ret;
  1757. if(signX == 1)
  1758. {
  1759. ret = "-" + ret;
  1760. }
  1761. return ret;
  1762. }
  1763. var convLongStr10 = function(x)
  1764. {
  1765. var signX;
  1766. var y = {high:0, low:10};
  1767. var rad = Math.pow(2, 32);
  1768. var ret;
  1769. var str = "";
  1770. signX = Math.floor(x.high / rad);
  1771. x.high = x.high % rad;
  1772. do
  1773. {
  1774. ret = doDivLong(x.high, x.low, y.high, y.low);
  1775. str = ret.lowMod.toString() + str;
  1776. x = {high:ret.highQuot, low:ret.lowQuot};
  1777. }while(x.high != 0 || x.low != 0);
  1778. if(signX == 1)
  1779. {
  1780. str = "-" + str;
  1781. }
  1782. return str;
  1783. }
  1784. //符号+絶対値の形から2の補数表現へ変換
  1785. var getOpponentFromSign = function(x)
  1786. {
  1787. var high = x.high;
  1788. var low = x.low;
  1789. var sign;
  1790. var rad = Math.pow(2, 32);
  1791. sign = Math.floor(high / rad) >>> 0;
  1792. high = high % rad >>> 0;
  1793. low = low >>> 0;
  1794. if(sign == 1)
  1795. {
  1796. //ビットを反転して1足す
  1797. high = ~high >>> 0;
  1798. low = ~low >>> 0;
  1799. low = low + 1;
  1800. if( low > 0xffffffff)
  1801. {
  1802. low = 0;
  1803. high = high + 1;
  1804. }
  1805. }
  1806. return {high:high >>> 0, low:low >>> 0};
  1807. }
  1808. //2の補数表現から符号+絶対値の形へ変換
  1809. var getSignFromOpponent = function(x)
  1810. {
  1811. var high = x.high;
  1812. var low = x.low;
  1813. if(high & 0x80000000)
  1814. {
  1815. //負の数なので絶対値を取り出す
  1816. //ビットを反転して1足す
  1817. high = ~high >>> 0;
  1818. low = ~low >>> 0;
  1819. low = low + 1;
  1820. if( low > 0xffffffff)
  1821. {
  1822. low = 0;
  1823. high = high + 1;
  1824. }
  1825. high += Math.pow(2, 32);
  1826. }
  1827. return {high:high, low:low >>> 0}
  1828. }
  1829. var getLongFromInt = function(x)
  1830. {
  1831. var high = 0;
  1832. if(x < 0)
  1833. {
  1834. x*=-1;
  1835. high = Math.pow(2, 32);
  1836. }
  1837. return {high:high, low:x};
  1838. }
  1839. var getLongFromDouble = function(x)
  1840. {
  1841. var sign, high, low;
  1842. var rad = Math.pow(2, 32);
  1843. if(x < 0)
  1844. {
  1845. sign = 1;
  1846. x *= -1;
  1847. }
  1848. else
  1849. {
  1850. sign = 0;
  1851. }
  1852. x = Math.floor(x);
  1853. low = x % rad;
  1854. high = Math.floor(x / rad) % rad + rad * sign;
  1855. return {high:high, low:low};
  1856. }
  1857. var getDoubleFromLong = function(highX, lowX)
  1858. {
  1859. var rad = Math.pow(2, 32);
  1860. var ret, sign;
  1861. if(highX >= rad)
  1862. {
  1863. highX = highX % rad;
  1864. sign = 1;
  1865. }
  1866. else
  1867. {
  1868. sign = 0;
  1869. }
  1870. ret = (highX * rad + lowX);
  1871. if(sign == 1)
  1872. {
  1873. ret *= -1;
  1874. }
  1875. return ret;
  1876. }
  1877. Method.instTable[NEW] = function(code, i, jsCodes, $cappuccino)
  1878. {
  1879. var cindex = (code[i+1] << 8) + code[i+2];
  1880. var cname = $cappuccino.constantPool[cindex].value;
  1881. jsCodes.push("jclass = CappuccinoVM.getJavaClass('" + cname + "');");
  1882. jsCodes.push("if(jclass == null){return {action:'loadClass', className:'" + cname + "', pc:" + i + "}}");
  1883. jsCodes.push("vmStack[thread.stackPtr++] = new jclass();");
  1884. return i + 3;
  1885. }
  1886. Method.instTable[NEWARRAY] = function(code, i, jsCodes)
  1887. {
  1888. jsCodes.push("operand1 = vmStack[thread.stackPtr-1];");
  1889. jsCodes.push("vmStack[thread.stackPtr-1] = new Array(operand1);");
  1890. return i + 2;
  1891. }
  1892. Method.instTable[ANEWARRAY] = function(code, i, jsCodes)
  1893. {
  1894. jsCodes.push("operand1 = vmStack[thread.stackPtr-1];");
  1895. jsCodes.push("vmStack[thread.stackPtr-1] = new Array(operand1);");
  1896. return i + 3;
  1897. }
  1898. Method.instTable[ARRAYLENGTH] = function(code, i, jsCodes)
  1899. {
  1900. jsCodes.push("obj = vmStack[thread.stackPtr-1];");
  1901. jsCodes.push("vmStack[thread.stackPtr-1] = obj.length;");
  1902. return i + 1;
  1903. }
  1904. Method.instTable[ATHROW] = function(code, i, jsCodes)
  1905. {
  1906. jsCodes.push("throw Error('Exception is not implemented');");
  1907. return i + 1;
  1908. }
  1909. var makeArray = function(vmStack, stackPtr, dim)
  1910. {
  1911. var array = [];
  1912. if(dim >= 2)
  1913. {
  1914. var count = vmStack[stackPtr - dim];
  1915. for(var i = 0; i < count; i++)
  1916. {
  1917. array.push(makeArray(vmStack, stackPtr, dim-1));
  1918. }
  1919. }
  1920. return array;
  1921. }
  1922. Method.instTable[MULTIANEWARRAY] = function(code, i, jsCodes)
  1923. {
  1924. var j;
  1925. var dim = code[i+3];
  1926. jsCodes.push("obj = CappuccinoVM.makeArray(vmStack, thread.stackPtr, " + dim + ");");
  1927. jsCodes.push("thread.stackPtr -=" + (dim-1) + ";");
  1928. jsCodes.push("vmStack[thread.stackPtr-1] = obj;");
  1929. return i + 4;
  1930. }
  1931. Method.instTable[LDC] = function(code, i, jsCodes, $cappuccino)
  1932. {
  1933. var cindex = code[i+1];
  1934. jsCodes.push("vmStack[thread.stackPtr++] = $cappuccino.constantPool[" + cindex + "].value;");
  1935. return i + 2;
  1936. }
  1937. Method.instTable[LDC2_W] = function(code, i, jsCodes, $cappuccino)
  1938. {
  1939. var cindex = get16BitsSigned((code[i+1] << 8) + code[i+2]);
  1940. var tag = $cappuccino.constantPool[cindex].tag;
  1941. if(tag == CONSTANT_LONG)
  1942. {
  1943. jsCodes.push("vmStack[thread.stackPtr] = $cappuccino.constantPool[" + cindex + "].low >>> 0;");
  1944. jsCodes.push("vmStack[thread.stackPtr + 1] = $cappuccino.constantPool[" + cindex + "].high;");
  1945. }
  1946. else
  1947. {
  1948. jsCodes.push("vmStack[thread.stackPtr] = $cappuccino.constantPool[" + cindex + "].value;");
  1949. }
  1950. jsCodes.push("thread.stackPtr+=2;");
  1951. return i + 3;
  1952. }
  1953. Method.instTable[GETSTATIC] = function(code, i, jsCodes, $cappuccino)
  1954. {
  1955. var index = (code[i+1] << 8) + code[i+2];
  1956. var fieldType = $cappuccino.constantPool[index].fieldType;
  1957. jsCodes.push("refjclass = CappuccinoVM.getJavaClass($cappuccino.constantPool[" + index + "].value.className);");
  1958. jsCodes.push("if(refjclass == null){return {action:'loadClass', className: $cappuccino.constantPool[" + index + "].value.className, pc:" + i + "}}");
  1959. jsCodes.push("name = $cappuccino.constantPool[" + index + "].value.name;");
  1960. jsCodes.push("jclass = $cappuccino.findFieldOwner(name, refjclass);");
  1961. if(fieldType == TYPE_LONG)
  1962. {
  1963. jsCodes.push("vmStack[thread.stackPtr++] = jclass[name].low;");
  1964. jsCodes.push("vmStack[thread.stackPtr++] = jclass[name].high;");
  1965. }
  1966. else if(fieldType == TYPE_DOUBLE)
  1967. {
  1968. jsCodes.push("vmStack[thread.stackPtr++] = jclass[name];");
  1969. jsCodes.push("thread.stackPtr++;");
  1970. }
  1971. else
  1972. {
  1973. jsCodes.push("vmStack[thread.stackPtr++] = jclass[name];");
  1974. }
  1975. return i + 3;
  1976. }
  1977. Method.instTable[PUTSTATIC] = function(code, i, jsCodes, $cappuccino)
  1978. {
  1979. var index = (code[i+1] << 8) + code[i+2];
  1980. var fieldType = $cappuccino.constantPool[index].fieldType;
  1981. jsCodes.push("refjclass = CappuccinoVM.getJavaClass($cappuccino.constantPool[" + index + "].value.className);");
  1982. jsCodes.push("if(refjclass == null){return {action:'loadClass', className: $cappuccino.constantPool[" + index + "].value.className, pc:" + i + "}}");
  1983. jsCodes.push("name = $cappuccino.constantPool[" + index + "].value.name;");
  1984. jsCodes.push("jclass = $cappuccino.findFieldOwner(name, refjclass);");
  1985. if(fieldType == TYPE_LONG)
  1986. {
  1987. jsCodes.push("jclass[name] = {high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]};");
  1988. jsCodes.push("thread.stackPtr-=2;");
  1989. }
  1990. else if(fieldType == TYPE_DOUBLE)
  1991. {
  1992. jsCodes.push("jclass[name] = vmStack[thread.stackPtr-2];");
  1993. jsCodes.push("thread.stackPtr-=2;");
  1994. }
  1995. else
  1996. {
  1997. jsCodes.push("jclass[name]=vmStack[--thread.stackPtr];");
  1998. }
  1999. return i + 3;
  2000. }
  2001. Method.instTable[GETFIELD] = function(code, i, jsCodes, $cappuccino)
  2002. {
  2003. var index = (code[i+1] << 8) + code[i+2];
  2004. var fname = $cappuccino.constantPool[index].value.name;
  2005. var fieldType = $cappuccino.constantPool[index].fieldType;
  2006. jsCodes.push("obj = vmStack[thread.stackPtr-1];");
  2007. if(fieldType == TYPE_LONG)
  2008. {
  2009. jsCodes.push("vmStack[thread.stackPtr-1] = obj['" + fname + "'].low;");
  2010. jsCodes.push("vmStack[thread.stackPtr] = obj['" + fname + "'].high;");
  2011. jsCodes.push("thread.stackPtr++;");
  2012. }
  2013. else if(fieldType == TYPE_DOUBLE)
  2014. {
  2015. jsCodes.push("vmStack[thread.stackPtr-1] = obj['" + fname + "'];");
  2016. jsCodes.push("thread.stackPtr++;");
  2017. }
  2018. else
  2019. {
  2020. jsCodes.push("vmStack[thread.stackPtr-1] = obj['" + fname + "'];");
  2021. }
  2022. /*
  2023. jsCodes.push("vmStack[thread.stackPtr-1] = obj['" + fname + "'];");
  2024. if((fieldType == TYPE_DOUBLE) || (fieldType == TYPE_LONG))
  2025. {
  2026. jsCodes.push("thread.stackPtr++;");
  2027. }
  2028. */
  2029. return i + 3;
  2030. }
  2031. Method.instTable[PUTFIELD] = function(code, i, jsCodes, $cappuccino)
  2032. {
  2033. var index = (code[i+1] << 8) + code[i+2];
  2034. var fname = $cappuccino.constantPool[index].value.name;
  2035. var fieldType = $cappuccino.constantPool[index].fieldType;
  2036. if(fieldType == TYPE_LONG)
  2037. {
  2038. jsCodes.push("operand1 = {high:vmStack[thread.stackPtr-1], low:vmStack[thread.stackPtr-2]};");
  2039. jsCodes.push("obj = vmStack[thread.stackPtr-3];");
  2040. jsCodes.push("thread.stackPtr -= 3;");
  2041. }
  2042. else if(fieldType == TYPE_DOUBLE)
  2043. {
  2044. jsCodes.push("operand1 = vmStack[thread.stackPtr-2];");
  2045. jsCodes.push("obj = vmStack[thread.stackPtr-3];");
  2046. jsCodes.push("thread.stackPtr -= 3;");
  2047. }
  2048. else
  2049. {
  2050. jsCodes.push("operand1 = vmStack[thread.stackPtr-1];");
  2051. jsCodes.push("obj = vmStack[thread.stackPtr-2];");
  2052. jsCodes.push("thread.stackPtr -= 2;");
  2053. }
  2054. jsCodes.push("obj['" + fname + "'] = operand1;");
  2055. /*
  2056. if((fieldType == TYPE_DOUBLE) || (fieldType == TYPE_LONG))
  2057. {
  2058. jsCodes.push("thread.stackPtr--;");
  2059. }
  2060. jsCodes.push("operand1 = vmStack[--thread.stackPtr];");
  2061. jsCodes.push("obj = vmStack[--thread.stackPtr];");
  2062. jsCodes.push("obj['" + fname + "'] = operand1;");
  2063. */
  2064. return i + 3;
  2065. }
  2066. Method.instTable[INVOKESTATIC] = function(code, i, jsCodes)
  2067. {
  2068. var index;
  2069. index = (code[i+1] << 8) + code[i+2];
  2070. jsCodes.push("methodref = $cappuccino.constantPool[" + index + "];");
  2071. jsCodes.push("jclass = CappuccinoVM.getJavaClass(methodref.value.className);");
  2072. jsCodes.push("if(jclass == null){return {action:'loadClass', className: methodref.value.className, pc:" + i + "}}");
  2073. jsCodes.push("method = jclass.$cappuccino.findMethod(methodref.value.name, methodref.value.descriptor);");
  2074. jsCodes.push("return {action:'invoke', method:method, pc:" + (i+3) + "};");
  2075. return i + 3;
  2076. }
  2077. Method.instTable[INVOKEVIRTUAL] = function(code, i, jsCodes)
  2078. {
  2079. var index;
  2080. index = (code[i+1] << 8) + code[i+2];
  2081. jsCodes.push("methodref = $cappuccino.constantPool[" + index + "];");
  2082. jsCodes.push("sp = thread.stackPtr - methodref.paramLength - 1;");
  2083. //jsCodes.push("CappuccinoVM.debugPrint('invokevirtual');");
  2084. //jsCodes.push("CappuccinoVM.debugPrint(vmStack);");
  2085. //jsCodes.push("CappuccinoVM.debugPrint(stackBase);");
  2086. //jsCodes.push("CappuccinoVM.debugPrint(thread.stackPtr);");
  2087. jsCodes.push("method = vmStack[sp].constructor.$cappuccino.findMethod(methodref.value.name, methodref.value.descriptor);");
  2088. jsCodes.push("return {action:'invoke', method:method, pc:" + (i+3) + "};");
  2089. return i + 3;
  2090. }
  2091. Method.instTable[INVOKESPECIAL] = function(code, i, jsCodes)
  2092. {
  2093. var index;
  2094. index = (code[i+1] << 8) + code[i+2];
  2095. jsCodes.push("methodref = $cappuccino.constantPool[" + index + "];");
  2096. jsCodes.push("jclass = CappuccinoVM.getJavaClass(methodref.value.className);");
  2097. jsCodes.push("if(jclass == null){return {action:'loadClass', className: methodref.value.className, pc:" + i + "}}");
  2098. jsCodes.push("method = jclass.$cappuccino.findMethod(methodref.value.name, methodref.value.descriptor);");
  2099. jsCodes.push("return {action:'invoke', method:method, pc:" + (i+3) + "};");
  2100. return i + 3;
  2101. }
  2102. Method.instTable[RETURN] = function(code, i, jsCodes)
  2103. {
  2104. jsCodes.push("return {action:'return'};");
  2105. return i + 1;
  2106. }
  2107. Method.instTable[IRETURN] = Method.instTable[FRETURN] = Method.instTable[ARETURN] = function(code, i, jsCodes)
  2108. {
  2109. jsCodes.push("thread.stackPtr--;");
  2110. jsCodes.push("return {action:'returnValue', value:vmStack[thread.stackPtr]};");
  2111. return i + 1;
  2112. }
  2113. Method.instTable[DRETURN] = Method.instTable[LRETURN] = function(code, i, jsCodes)
  2114. {
  2115. jsCodes.push("thread.stackPtr-=2;");
  2116. jsCodes.push("return {action:'returnValueWide', value:{high:vmStack[thread.stackPtr+1], low:vmStack[thread.stackPtr]}};");
  2117. return i + 1;
  2118. }
  2119. Method.prototype.compile = function()
  2120. {
  2121. var jsCodes = [];
  2122. var i = 0;
  2123. var code = this.codeAttr.code;
  2124. /*
  2125. jsCodes.push("var vmStack = arguments[0];");
  2126. jsCodes.push("var stackTop = arguments[1];");
  2127. jsCodes.push("var pc = arguments[2];");
  2128. jsCodes.push("var $cappuccino = arguments[3];");
  2129. */
  2130. jsCodes.push("var thread = arguments[0];");
  2131. jsCodes.push("var vmStack = arguments[0].vmStack;");
  2132. jsCodes.push("var stackBase = arguments[0].stackBase;");
  2133. jsCodes.push("var pc = arguments[0].pc;");
  2134. jsCodes.push("var $cappuccino = arguments[0].currentMethod.$cappuccino;");
  2135. //jsCodes.push("CappuccinoVM.debugPrint(vmStack);");
  2136. //jsCodes.push("CappuccinoVM.debugPrint(stackTop);");
  2137. //jsCodes.push("CappuccinoVM.debugPrint(pc);");
  2138. //jsCodes.push("CappuccinoVM.debugPrint($cappuccino);");
  2139. jsCodes.push("var methodref, jclass, refjclass, method, name, sp, operand1, operand2, obj, mask;");
  2140. jsCodes.push("while(true){");
  2141. jsCodes.push("switch(pc){");
  2142. while(i < code.length)
  2143. {
  2144. jsCodes.push("case " + i + ":");
  2145. //jsCodes.push("CappuccinoVM.debugPrint('pc=" + i + "');");
  2146. i = Method.instTable[code[i]](code, i, jsCodes, this.$cappuccino);
  2147. }
  2148. jsCodes.push("default: throw Error('Invalid pc?');");
  2149. jsCodes.push("}}");
  2150. /*
  2151. debugPrint("//" + this.name);
  2152. for(i = 0; i < jsCodes.length; i++)
  2153. {
  2154. debugPrint(jsCodes[i]);
  2155. }
  2156. */
  2157. this.compiledMethod = new Function(jsCodes.join("\n"));
  2158. }
  2159. var Code = function(maxStack, maxLocals, code)
  2160. {
  2161. this.maxStack = maxStack;
  2162. this.maxLocals = maxLocals;
  2163. this.code = code;
  2164. }
  2165. var CVMInfo = function(thisClass)
  2166. {
  2167. this.methods = {}
  2168. this.thisClass = thisClass;
  2169. }
  2170. CVMInfo.prototype.addMethod = function(method)
  2171. {
  2172. if(this.methods[method.name] == null)
  2173. {
  2174. this.methods[method.name] = {};
  2175. }
  2176. this.methods[method.name][method.descriptor] = method;
  2177. }
  2178. CVMInfo.prototype.findMethod = function(name, descriptor)
  2179. {
  2180. if(this.methods[name] && this.methods[name][descriptor])
  2181. {
  2182. return this.methods[name][descriptor];
  2183. }
  2184. else
  2185. {
  2186. if(this.superClass)
  2187. {
  2188. return this.superClass.$cappuccino.findMethod(name, descriptor);
  2189. }
  2190. else
  2191. {
  2192. //superClassがnullということはこれはObjectクラス?
  2193. //あり得ない
  2194. throw Error("can't find method: " + name + " " + descriptor);
  2195. }
  2196. }
  2197. }
  2198. CVMInfo.prototype.findFieldOwner = function(name, jclass)
  2199. {
  2200. if(jclass[name] != undefined)
  2201. {
  2202. return jclass;
  2203. }
  2204. else if(jclass.$cappuccino.superClass)
  2205. {
  2206. return this.findFieldOwner(name, jclass.$cappuccino.superClass);
  2207. }
  2208. else
  2209. {
  2210. throw Error("static field " + name + " not found");
  2211. }
  2212. }
  2213. var getUnicodeString = function(classData, start, length)
  2214. {
  2215. var i = 0;
  2216. var str = "";
  2217. var byte1, byte2, byte3;
  2218. do
  2219. {
  2220. byte1 = classData[start+i];
  2221. //str = str + String.fromCharCode(byte1);
  2222. //i++;
  2223. if((byte1 & 0x80) == 0)
  2224. {
  2225. str = str + String.fromCharCode(byte1);
  2226. i++;
  2227. }
  2228. else if((byte1 & 0xe0) == 0xc0)
  2229. {
  2230. byte2 = classData[start+i+1];
  2231. str = str + String.fromCharCode(((byte1 & 0x1f) << 6) + (byte2 & 0x3f));
  2232. i+=2;
  2233. }
  2234. else if((byte1 & 0xf0) == 0xe0)
  2235. {
  2236. byte2 = classData[start+i+1];
  2237. byte3 = classData[start+i+2];
  2238. str = str + String.fromCharCode(((byte1 & 0x0f) << 12) + ((byte2 & 0x3f) << 6) + (byte3 & 0x3f));
  2239. i+=3;
  2240. }
  2241. else
  2242. {
  2243. //サロゲートペア非対応
  2244. i++;
  2245. }
  2246. }while(i < length);
  2247. return str;
  2248. }
  2249. var getClassfileURL = function(className)
  2250. {
  2251. //完全修飾名からURLを取得する
  2252. //とりあえず.classをつけるだけ
  2253. return className + ".class";
  2254. }
  2255. var loadJavaClass = function(classData)
  2256. {
  2257. var javaClass = function() {};
  2258. //VMのための様々な情報はここに詰め込む
  2259. //読み込むJavaのクラスに$cappuccinoという名前のメソッドやフィールドが存在する場合の対策が必要
  2260. //(prototypeとかにも同じことがいえる)
  2261. javaClass.$cappuccino = new CVMInfo(javaClass);
  2262. if(!(classData[0] == 0xca && classData[1] == 0xfe && classData[2] == 0xba && classData[3] == 0xbe))
  2263. {
  2264. throw Error("this is not Java Classfile!");
  2265. }
  2266. var i = 8;
  2267. var cpCount = classData[i+1] + (classData[i] << 8);
  2268. i += 2;
  2269. var cpool = [new ConstEmpty()];
  2270. var c;
  2271. var j;
  2272. var highBytes, lowBytes;
  2273. for(j = 0; j < cpCount - 1; j++)
  2274. {
  2275. switch(classData[i])
  2276. {
  2277. case CONSTANT_CLASS:
  2278. c = new ConstClass(classData[i], (classData[i+1] << 8) + classData[i+2]);
  2279. cpool.push(c);
  2280. i += 3;
  2281. break;
  2282. case CONSTANT_FIELDREF:
  2283. c = new ConstFieldref(classData[i], (classData[i+1] << 8) + classData[i+2], (classData[i+3] << 8) + classData[i+4]);
  2284. cpool.push(c);
  2285. i += 5;
  2286. break;
  2287. case CONSTANT_METHODREF:
  2288. c = new ConstMethodref(classData[i], (classData[i+1] << 8) + classData[i+2], (classData[i+3] << 8) + classData[i+4]);
  2289. cpool.push(c);
  2290. i += 5;
  2291. break;
  2292. case CONSTANT_INTERFACEMETHODREF:
  2293. c = new ConstInterfaceMethodref(classData[i], (classData[i+1] << 8) + classData[i+2], (classData[i+3] << 8) + classData[i+4]);
  2294. cpool.push(c);
  2295. i += 5;
  2296. break;
  2297. case CONSTANT_STRING:
  2298. c = new ConstString(classData[i], (classData[i+1] << 8) + classData[i+2])
  2299. cpool.push(c);
  2300. i += 3;
  2301. break;
  2302. case CONSTANT_INTEGER:
  2303. c = new ConstInteger(classData[i], (classData[i+1] << 24) + (classData[i+2] << 16) + (classData[i+3] << 8) + classData[i+4])
  2304. cpool.push(c);
  2305. i += 5;
  2306. break;
  2307. case CONSTANT_FLOAT:
  2308. c = new ConstFloat(classData[i], (classData[i+1] << 24) + (classData[i+2] << 16) + (classData[i+3] << 8) + classData[i+4])
  2309. cpool.push(c);
  2310. i +=5;
  2311. break;
  2312. case CONSTANT_LONG:
  2313. //c = new ConstLong(classData[i], (classData[i+1] << 56) + (classData[i+2] << 48) + (classData[i+3] << 40) + (classData[i+4] << 32) + (classData[i+5] << 24) + (classData[i+6] << 16) + (classData[i+7] << 8) + classData[i+8]);
  2314. highBytes = (classData[i+1] << 24) + (classData[i+2] << 16) + (classData[i+3] << 8) + classData[i+4];
  2315. lowBytes = (classData[i+5] << 24) + (classData[i+6] << 16) + (classData[i+7] << 8) + classData[i+8];
  2316. c = new ConstLong(classData[i], highBytes >>> 0, lowBytes >>> 0);
  2317. cpool.push(c);
  2318. //cpool.push(new ConstEmpty());
  2319. cpool.push(new ConstEmpty());
  2320. j++;
  2321. i += 9;
  2322. break;
  2323. case CONSTANT_DOUBLE:
  2324. highBytes = (classData[i+1] << 24) + (classData[i+2] << 16) + (classData[i+3] << 8) + classData[i+4];
  2325. lowBytes = (classData[i+5] << 24) + (classData[i+6] << 16) + (classData[i+7] << 8) + classData[i+8];
  2326. c = new ConstDouble(classData[i], highBytes >>> 0, lowBytes >>> 0);
  2327. cpool.push(c);
  2328. cpool.push(new ConstEmpty());
  2329. j++;
  2330. i += 9;
  2331. break;
  2332. case CONSTANT_NAMEANDTYPE:
  2333. c = new ConstNameAndType(classData[i], (classData[i+1] << 8) + classData[i+2], (classData[i+3] << 8) + classData[i+4]);
  2334. cpool.push(c);
  2335. i += 5;
  2336. break;
  2337. case CONSTANT_UTF8:
  2338. var tag = classData[i];
  2339. var length = (classData[i+1] << 8) + classData[i+2];
  2340. /*
  2341. var str = "";
  2342. for(var k=0; k < length; k++)
  2343. str = str + String.fromCharCode(classData[i+3+k]);
  2344. c = new ConstUtf8(tag, length, str);
  2345. */
  2346. c = new ConstUtf8(tag, length, getUnicodeString(classData, i+3, length));
  2347. cpool.push(c);
  2348. i += 3 + length;
  2349. break;
  2350. default:
  2351. throw Error("read constant pool error offset=" + i);
  2352. }
  2353. }
  2354. for(j = 0; j < cpCount; j ++)
  2355. {
  2356. cpool[j].resolve(cpool); //resolveしたあとはvalueが参照できる
  2357. //cpool[j].debugPrint();
  2358. }
  2359. //constant poolはコード生成のときに使う
  2360. javaClass.$cappuccino.constantPool = cpool;
  2361. javaClass.$cappuccino.accessFlags = (classData[i] << 8) + classData[i+1];
  2362. i += 2;
  2363. //debugPrint("accessFlags=" + javaClass.$cappuccino.accessFlags);
  2364. var thisClassIndex = (classData[i] << 8) + classData[i+1];
  2365. i += 2;
  2366. javaClass.$cappuccino.thisClassName = cpool[thisClassIndex].value;
  2367. //debugPrint("thisClassName=" + javaClass.$cappuccino.thisClassName);
  2368. var superClassIndex = (classData[i] << 8) + classData[i+1];
  2369. i += 2;
  2370. javaClass.$cappuccino.superClassName = cpool[superClassIndex].value;
  2371. //debugPrint("suerClassName=" + javaClass.$cappuccino.superClassName);
  2372. //javaClass.$cappuccino.superClass = getJavaClass(javaClass.$cappuccino.superClassName)
  2373. //Interfaceなんてどうでもいい気がするけど一応…
  2374. var interfacesCount = (classData[i] << 8) + classData[i + 1];
  2375. i += 2;
  2376. var interfaces = [];
  2377. for (j = 0; j < interfacesCount * 2; j++)
  2378. {
  2379. interfaces.push((classData[i+j] << 8) + classData[i+j+1]);
  2380. }
  2381. i += interfacesCount * 2;
  2382. javaClass.$cappuccino.interfaces = interfaces;
  2383. var fieldsCount = (classData[i] << 8) + classData[i+1];
  2384. i += 2;
  2385. var accessFlags;
  2386. var nameIndex;
  2387. var fieldName;
  2388. var attributesCount;
  2389. var attributeNameIndex;
  2390. var attributeLength;
  2391. var constatnValueIndex;
  2392. var k;
  2393. for(j = 0; j < fieldsCount; j ++)
  2394. {
  2395. accessFlags = (classData[i] << 8) + classData[i+1];
  2396. i += 2;
  2397. nameIndex = (classData[i] << 8) + classData[i+1];
  2398. i += 4; //descriptor_indexは読みとばす
  2399. attributesCount = (classData[i] << 8) + classData[i+1];
  2400. i += 2;
  2401. fieldName = cpool[nameIndex].value;
  2402. //とりあえず0で初期化しておく
  2403. if(accessFlags & 0x0008)
  2404. {
  2405. javaClass[fieldName] = 0;
  2406. }
  2407. for(k = 0; k < attributesCount; k++)
  2408. {
  2409. attributeNameIndex = (classData[i] << 8) + classData[i+1];
  2410. i += 2;
  2411. attributeLength = (classData[i] << 24) + (classData[i+1] << 16) + (classData[i+2] << 8) + classData[i+3];
  2412. i += 4;
  2413. if(accessFlags & 0x0008 && cpool[attributeNameIndex].value == "ConstantValue")
  2414. {
  2415. constantValueIndex = (classData[i] << 8) + classData[i+1];
  2416. javaClass[fieldName] = cpool[constantValueIndex].value;
  2417. }
  2418. i += attributeLength;
  2419. }
  2420. }
  2421. var methodsCount = (classData[i] << 8) + classData[i+1];
  2422. i += 2;
  2423. var method;
  2424. var descriptorIndex;
  2425. var maxStack;
  2426. var maxLocals;
  2427. var codeLength;
  2428. var code;
  2429. var l;
  2430. var codeAttr;
  2431. var exceptionTablesCount;
  2432. var exceptionTables;
  2433. var startPC;
  2434. var endPC;
  2435. var handlerPC;
  2436. var catchType;
  2437. for(j = 0; j < methodsCount; j++)
  2438. {
  2439. accessFlags = (classData[i] << 8) + classData[i+1];
  2440. i += 2;
  2441. nameIndex = (classData[i] << 8) + classData[i+1];
  2442. i += 2;
  2443. descriptorIndex = (classData[i] << 8) + classData[i+1];
  2444. i += 2;
  2445. method = new Method(accessFlags, cpool[nameIndex].value, cpool[descriptorIndex].value, javaClass.$cappuccino);
  2446. //method.debugPrint();
  2447. attributesCount = (classData[i] << 8) + classData[i+1];
  2448. i += 2;
  2449. for(k = 0; k < attributesCount; k++)
  2450. {
  2451. attributeNameIndex = (classData[i] << 8) + classData[i+1];
  2452. i += 2;
  2453. attributeLength = (classData[i] << 24) + (classData[i+1] << 16) + (classData[i+2] << 8) + classData[i+3];
  2454. i += 4;
  2455. if(cpool[attributeNameIndex].value == "Code")
  2456. {
  2457. maxStack = (classData[i] << 8) + classData[i+1];
  2458. i += 2;
  2459. maxLocals = (classData[i] << 8) + classData[i+1];
  2460. i += 2;
  2461. codeLength = (classData[i] << 24) + (classData[i+1] << 16) + (classData[i+2] << 8) + classData[i+3];
  2462. i += 4;
  2463. code = [];
  2464. for(l = 0; l < codeLength; l++)
  2465. {
  2466. code[l] = classData[i+l];
  2467. }
  2468. i += codeLength;
  2469. codeAttr = new Code(maxStack, maxLocals, code);
  2470. exceptionTablesCount = (classData[i] << 8) + classData[i+1];
  2471. i += 2;
  2472. exceptionTables = [];
  2473. for(l = 0; l < exceptionTablesCount; l++)
  2474. {
  2475. startPC = (classData[i] << 8) + classData[i+1];
  2476. i += 2;
  2477. endPC = (classData[i] << 8) + classData[i+1];
  2478. i += 2;
  2479. handlerPC = (classData[i] << 8) + classData[i+1];
  2480. i += 2;
  2481. catchType = (classData[i] << 8) + classData[i+1];
  2482. i += 2;
  2483. exceptionTables.push({startPC:startPC, endPC:endPC, handlerPC:handlerPC, catchType:catchType});
  2484. }
  2485. codeAttr.exceptionTables = exceptionTables;
  2486. //Codeの中のattributeは無視
  2487. i = ignoreAttributes(classData, i);
  2488. }
  2489. else
  2490. {
  2491. i += attributeLength;
  2492. }
  2493. }
  2494. method.codeAttr = codeAttr;
  2495. //method.debugPrint();
  2496. javaClass.$cappuccino.addMethod(method);
  2497. }
  2498. return javaClass;
  2499. }
  2500. var ignoreAttributes = function(classData, i)
  2501. {
  2502. var attributesCount = (classData[i] << 8) + classData[i+1];
  2503. var attributeLength;
  2504. i += 2;
  2505. for(var j = 0; j < attributesCount; j++)
  2506. {
  2507. i += 2;
  2508. attributeLength = (classData[i] << 24) + (classData[i+1] << 16) + (classData[i+2] << 8) + classData[i+3];
  2509. i += 4 + attributeLength;
  2510. }
  2511. return i;
  2512. }
  2513. var classHash = {};
  2514. var getJavaClass = function(className)
  2515. {
  2516. if(!classHash[className])
  2517. {
  2518. return null;
  2519. }
  2520. return classHash[className];
  2521. }
  2522. var loadClassfileAsync = function(className, javaThread, cbfunc, callMain, arg)
  2523. {
  2524. var xmlhttp = new XMLHttpRequest();
  2525. var url = getClassfileURL(className);
  2526. xmlhttp.open("GET", url, true);
  2527. xmlhttp.onreadystatechange = function()
  2528. {
  2529. var ab;
  2530. var ar;
  2531. var javaClass;
  2532. var superClass;
  2533. var mainMethod;
  2534. if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
  2535. {
  2536. ab = xmlhttp.response;
  2537. ar = new Uint8Array(ab, 0, ab.byteLength);
  2538. javaClass = loadJavaClass(ar);
  2539. if(callMain)
  2540. {
  2541. mainMethod = javaClass.$cappuccino.findMethod("main", "([Ljava/lang/String;)V");
  2542. javaThread.invoke(mainMethod, arg);
  2543. }
  2544. if(javaClass.$cappuccino.methods["<clinit>"] && javaClass.$cappuccino.methods["<clinit>"]["()V"])
  2545. {
  2546. //Threadをrunすると<clinit>が実行される
  2547. javaThread.invoke(javaClass.$cappuccino.methods["<clinit>"]["()V"]);
  2548. }
  2549. //debugPrint(javaClass.$cappuccino.thisClassName + " is loaded");
  2550. classHash[className] = javaClass;
  2551. superClass = getJavaClass(javaClass.$cappuccino.superClassName);
  2552. if(superClass)
  2553. {
  2554. javaClass.$cappuccino.superClass = superClass;
  2555. cbfunc();
  2556. }
  2557. else
  2558. {
  2559. //debugPrint(javaClass.$cappuccino.superClassName);
  2560. loadClassfileAsync(javaClass.$cappuccino.superClassName, function()
  2561. {
  2562. javaClass.$cappuccino.superClass = getJavaClass(javaClass.$cappuccino.superClassName);
  2563. cbfunc();
  2564. });
  2565. }
  2566. }
  2567. };
  2568. xmlhttp.responseType = "arraybuffer";
  2569. xmlhttp.send(null);
  2570. }
  2571. var JavaThread = function()
  2572. {
  2573. var i;
  2574. this.vmStack = [];
  2575. this.pc = 0;
  2576. this.stackBase = 0;
  2577. this.stackPtr = 0;
  2578. this.currentMethod = null;
  2579. this.firstMethod = null;
  2580. }
  2581. JavaThread.prototype.run = function()
  2582. {
  2583. var cfunc, ret, nextBase, numLocals, i, r, oldLength;
  2584. while(true)
  2585. {
  2586. //this.currentMethod.debugPrint();
  2587. cfunc = this.currentMethod.getCompiledMethod();
  2588. ret = cfunc(this);
  2589. //ret = cfunc(this.vmStack, this.stackTop, this.pc, this.currentMethod.$cappuccino);
  2590. if(ret.action == "invoke")
  2591. {
  2592. //debugPrint("invoke " + ret.method.name)
  2593. //debugPrint(ret.method.paramLength);
  2594. //debugPrint(ret.method.codeAttr.maxLocals);
  2595. //次のスタックが始まる位置
  2596. //nextTop = this.vmStack.length - ret.method.paramLength;
  2597. nextBase = this.stackPtr - ret.method.paramLength;
  2598. if(!ret.method.isStatic())
  2599. {
  2600. nextBase--;
  2601. }
  2602. //引数以外のローカル変数の数
  2603. numLocals = ret.method.codeAttr.maxLocals - ret.method.paramLength;
  2604. if(!ret.method.isStatic())
  2605. {
  2606. numLocals--;
  2607. }
  2608. /*
  2609. for(i = 0; i < numLocals; i++)
  2610. {
  2611. this.vmStack.push(null);
  2612. }
  2613. */
  2614. this.stackPtr += numLocals;
  2615. this.vmStack[this.stackPtr++] = this.currentMethod;
  2616. this.vmStack[this.stackPtr++] = this.stackBase;
  2617. //現在のスタックフレームのサイズを保存
  2618. this.vmStack[this.stackPtr] = this.stackPtr - ret.method.codeAttr.maxLocals - 2;
  2619. this.stackPtr++;
  2620. this.vmStack[this.stackPtr++] = ret.pc;
  2621. this.currentMethod = ret.method;
  2622. this.stackBase = nextBase;
  2623. this.pc = 0;
  2624. //debugPrint(this.vmStack);
  2625. //debugPrint(this.stackBase);
  2626. //debugPrint(this.stackPtr);
  2627. }
  2628. else if(ret.action == "return" || ret.action == "returnValue" || ret.action == "returnValueWide")
  2629. {
  2630. if(this.currentMethod == this.firstMethod)
  2631. {
  2632. //すべてのメソッドの終了が終わったのでスレッドを終了する
  2633. return;
  2634. }
  2635. else
  2636. {
  2637. r = this.stackBase + this.currentMethod.codeAttr.maxLocals;
  2638. this.currentMethod = this.vmStack[r];
  2639. this.stackBase = this.vmStack[r+1];
  2640. this.stackPtr = this.vmStack[r+2];
  2641. this.pc = this.vmStack[r+3];
  2642. if(ret.action == "returnValue")
  2643. {
  2644. this.vmStack[this.stackPtr] = ret.value;
  2645. this.stackPtr++;
  2646. }
  2647. if(ret.action == "returnValueWide")
  2648. {
  2649. this.vmStack[this.stackPtr] = ret.value.low;
  2650. this.vmStack[this.stackPtr+1] = ret.value.high;
  2651. this.stackPtr+=2;
  2652. }
  2653. }
  2654. }
  2655. else if(ret.action == "loadClass")
  2656. {
  2657. var javaThread = this;
  2658. this.pc = ret.pc;
  2659. loadClassfileAsync(ret.className, javaThread, function(){javaThread.run();});
  2660. return;
  2661. }
  2662. }
  2663. }
  2664. JavaThread.prototype.invoke = function(method)
  2665. {
  2666. var nextBase, numLocals, i;
  2667. if(!this.firstMethod)
  2668. {
  2669. this.firstMethod = method;
  2670. }
  2671. for(i=1; i < arguments.length; i++)
  2672. {
  2673. this.vmStack[this.stackPtr++] = arguments[i];
  2674. }
  2675. nextBase = this.stackPtr - method.paramLength;
  2676. if(!method.isStatic())
  2677. {
  2678. nextBase--;
  2679. }
  2680. //引数以外のローカル変数の数
  2681. numLocals = method.codeAttr.maxLocals - method.paramLength;
  2682. if(!method.isStatic())
  2683. {
  2684. numLocals--;
  2685. }
  2686. this.stackPtr += numLocals;
  2687. this.vmStack[this.stackPtr++] = this.currentMethod;
  2688. this.vmStack[this.stackPtr++] = this.stackBase;
  2689. //現在のスタックフレームのサイズを保存
  2690. this.vmStack[this.stackPtr] = this.vmStack.stackPtr - method.codeAttr.maxLocals - 2;
  2691. this.stackPtr++;
  2692. this.vmStack[this.stackPtr++] = this.pc;
  2693. this.currentMethod = method;
  2694. this.stackBase = nextBase;
  2695. this.pc = 0;
  2696. //debugPrint("invoking " + ret.method.name)
  2697. //for(i = 0; i < this.vmStack.length; i++)
  2698. // debugPrint(this.vmStack[i]);
  2699. //debugPrint("stackTop=" + nextTop);
  2700. }
  2701. //組み込みクラスの定義
  2702. //java/lang/Object
  2703. var JavaObject = function() {}
  2704. JavaObject.$cappuccino = new CVMInfo(JavaObject);
  2705. var objectInit = new Method(0x00, '<init>', '()V');
  2706. objectInit.codeAttr = new Code(0, 1, null);
  2707. objectInit.compiledMethod = function(javaThread)
  2708. {
  2709. //debugPrint("object init");
  2710. return {action: "return"};
  2711. }
  2712. JavaObject.$cappuccino.addMethod(objectInit);
  2713. classHash['java/lang/Object'] = JavaObject;
  2714. //java/io/PrintStrem
  2715. var PrintStream = function() {}
  2716. PrintStream.$cappuccino = new CVMInfo(PrintStream);
  2717. var printlnInt = new Method(0x00, 'println', '(I)V');
  2718. printlnInt.codeAttr = new Code(0, 2, null);
  2719. printlnInt.compiledMethod = function(javaThread)
  2720. {
  2721. var vmStack = javaThread.vmStack;
  2722. var stackBase = javaThread.stackBase;
  2723. debugPrint(vmStack[stackBase+1]);
  2724. return {action:"return"};
  2725. }
  2726. PrintStream.$cappuccino.addMethod(printlnInt);
  2727. var printlnString = new Method(0x00, "println", "(Ljava/lang/String;)V");
  2728. printlnString.codeAttr = new Code(0, 2, null);
  2729. printlnString.compiledMethod = function(javaThread)
  2730. {
  2731. var vmStack = javaThread.vmStack;
  2732. var stackBase = javaThread.stackBase;
  2733. debugPrint(vmStack[stackBase+1].toString());
  2734. return {action:"return"};
  2735. }
  2736. PrintStream.$cappuccino.addMethod(printlnString);
  2737. var printlnFloat = new Method(0x0000, "println", "(F)V");
  2738. printlnFloat.codeAttr = new Code(0, 2, null);
  2739. printlnFloat.compiledMethod = printlnInt.compiledMethod;
  2740. PrintStream.$cappuccino.addMethod(printlnFloat);
  2741. var printlnDouble = new Method(0x0000, "println", "(D)V");
  2742. printlnDouble.codeAttr = new Code(0, 3, null);
  2743. printlnDouble.compiledMethod = printlnInt.compiledMethod;
  2744. PrintStream.$cappuccino.addMethod(printlnDouble);
  2745. var printlnLong = new Method(0x0000, "println", "(J)V");
  2746. printlnLong.codeAttr = new Code(0, 3, null);
  2747. //printlnLong.compiledMethod = printlnInt.compiledMethod;
  2748. printlnLong.compiledMethod = function(javaThread)
  2749. {
  2750. var vmStack = javaThread.vmStack;
  2751. var stackBase = javaThread.stackBase;
  2752. debugPrint(convLongStr10({low:vmStack[stackBase+1], high:vmStack[stackBase+2]}));
  2753. return {action:"return"};
  2754. }
  2755. PrintStream.$cappuccino.addMethod(printlnLong);
  2756. classHash["java/io/PrintStream"] = PrintStream;
  2757. //java/lang/String
  2758. var JavaString = function() {}
  2759. JavaString.$cappuccino = new CVMInfo(JavaString);
  2760. //これはJavaのtoStringではなくJavaScriptのtoString(ややこしいな…)
  2761. JavaString.prototype.toString = function()
  2762. {
  2763. return this.str;
  2764. }
  2765. var stringInit = new Method(0x0000, "<init>", "(Ljava/lang/String;)V");
  2766. stringInit.codeAttr = new Code(0, 2, null);
  2767. stringInit.compiledMethod = function(javaThread)
  2768. {
  2769. var vmStack = javaThread.vmStack;
  2770. var stackBase = javaThread.stackBase;
  2771. var thisObj = vmStack[stackBase];
  2772. var arg = vmStack[stackBase+1];
  2773. thisObj.str = arg.str;
  2774. return {action:"return"};
  2775. }
  2776. JavaString.$cappuccino.addMethod(stringInit);
  2777. classHash['java/lang/String'] = JavaString;
  2778. var createJavaString = function(str)
  2779. {
  2780. var javaString = new JavaString();
  2781. javaString.str = str;
  2782. return javaString;
  2783. }
  2784. //java/lang/StringBuffer
  2785. var StringBuilder = function() {};
  2786. StringBuilder.$cappuccino = new CVMInfo(StringBuilder);
  2787. var sbInit = new Method(0x0000, "<init>", "()V");
  2788. sbInit.codeAttr = new Code(0, 1, null);
  2789. sbInit.compiledMethod = function(javaThread)
  2790. {
  2791. var vmStack = javaThread.vmStack;
  2792. var stackBase = javaThread.stackBase;
  2793. vmStack[stackBase].str = "";
  2794. return {action:"return"};
  2795. }
  2796. StringBuilder.$cappuccino.addMethod(sbInit);
  2797. var sbInitStr = new Method(0x0000, "<init>", "(Ljava/lang/String;)V");
  2798. sbInitStr.codeAttr = new Code(0, 2, null);
  2799. sbInitStr.compiledMethod = function(javaThread)
  2800. {
  2801. var vmStack = javaThread.vmStack;
  2802. var stackBase = javaThread.stackBase;
  2803. vmStack[stackBase].str = vmStack[stackBase+1].str;
  2804. return {action:"return"};
  2805. }
  2806. StringBuilder.$cappuccino.addMethod(sbInitStr);
  2807. var appendInt = new Method(0x000, "append", "(I)Ljava/lang/StringBuilder;");
  2808. appendInt.codeAttr = new Code(0, 2, null);
  2809. appendInt.compiledMethod = function(javaThread)
  2810. {
  2811. var vmStack = javaThread.vmStack;
  2812. var stackBase = javaThread.stackBase;
  2813. var thisObj = vmStack[stackBase];
  2814. var arg = vmStack[stackBase+1];
  2815. thisObj.str = thisObj.str + arg;
  2816. return {action:"returnValue", value:thisObj};
  2817. }
  2818. StringBuilder.$cappuccino.addMethod(appendInt);
  2819. var appendFloat = new Method(0x0000, "append", "(F)Ljava/lang/StringBuilder;");
  2820. appendFloat.codeAttr = new Code(0, 2, null);
  2821. appendFloat.compiledMethod = appendInt.compiledMethod;
  2822. StringBuilder.$cappuccino.addMethod(appendFloat);
  2823. var appendDouble = new Method(0x0000, "append", "(D)Ljava/lang/StringBuilder;");
  2824. appendDouble.codeAttr = new Code(0, 3, null);
  2825. appendDouble.compiledMethod = appendInt.compiledMethod;
  2826. StringBuilder.$cappuccino.addMethod(appendDouble);
  2827. var appendLong = new Method(0x0000, "append", "(J)Ljava/lang/StringBuilder;");
  2828. appendLong.codeAttr = new Code(0, 3, null);
  2829. appendLong.compiledMethod = function(javaThread)
  2830. {
  2831. var vmStack = javaThread.vmStack;
  2832. var stackBase = javaThread.stackBase;
  2833. var thisObj = vmStack[stackBase];
  2834. var arg = {high:vmStack[stackBase+2], low:vmStack[stackBase+1]};
  2835. thisObj.str = thisObj.str + convLongStr10(arg);
  2836. return {action:"returnValue", value:thisObj};
  2837. }
  2838. StringBuilder.$cappuccino.addMethod(appendLong);
  2839. var appendString = new Method(0x0000, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
  2840. appendString.codeAttr = new Code(0, 2, null);
  2841. appendString.compiledMethod = function(javaThread)
  2842. {
  2843. var vmStack = javaThread.vmStack;
  2844. var stackBase = javaThread.stackBase;
  2845. var thisObj = vmStack[stackBase];
  2846. var arg = vmStack[stackBase+1];
  2847. thisObj.str = thisObj.str + arg.str;
  2848. return {action:"returnValue", value:thisObj};
  2849. }
  2850. StringBuilder.$cappuccino.addMethod(appendString);
  2851. var sbToString = new Method(0x0000, "toString", "()Ljava/lang/String;");
  2852. sbToString.codeAttr = new Code(0, 1, null);
  2853. sbToString.compiledMethod = function(javaThread)
  2854. {
  2855. var vmStack = javaThread.vmStack;
  2856. var stackBase = javaThread.stackBase;
  2857. var javaString = createJavaString(vmStack[stackBase].str);
  2858. return {action:"returnValue", value:javaString};
  2859. }
  2860. StringBuilder.$cappuccino.addMethod(sbToString);
  2861. classHash["java/lang/StringBuilder"] = StringBuilder;
  2862. //java/lang/Math
  2863. var JavaMath = function() {}
  2864. JavaMath.$cappuccino = new CVMInfo(JavaMath);
  2865. JavaMath.PI = Math.PI;
  2866. var sqrt = new Method(0x0008, "sqrt", "(D)D");
  2867. sqrt.codeAttr = new Code(0, 2, null);
  2868. sqrt.compiledMethod = function(javaThread)
  2869. {
  2870. var vmStack = javaThread.vmStack;
  2871. var stackBase = javaThread.stackBase;
  2872. return {action: "returnValueWide", value: Math.sqrt(vmStack[stackBase])};
  2873. }
  2874. JavaMath.$cappuccino.addMethod(sqrt);
  2875. var random = new Method(0x0008, "random", "()D");
  2876. random.codeAttr = new Code(0, 2, null);
  2877. random.compiledMethod = function(javaThread)
  2878. {
  2879. var vmStack = javaThread.vmStack;
  2880. var stackBase = javaThread.stackBase;
  2881. return {action: "returnValueWide", value: Math.random()};
  2882. }
  2883. JavaMath.$cappuccino.addMethod(random);
  2884. var sin = new Method(0x0008, "sin", "(D)D");
  2885. sin.codeAttr = new Code(0, 2, null);
  2886. sin.compiledMethod = function(javaThread)
  2887. {
  2888. var vmStack = javaThread.vmStack;
  2889. var stackBase = javaThread.stackBase;
  2890. return {action: "returnValueWide", value: Math.sin(vmStack[stackBase])};
  2891. }
  2892. JavaMath.$cappuccino.addMethod(sin);
  2893. var min = new Method(0x0008, "min", "(II)I");
  2894. min.codeAttr = new Code(0, 2, null);
  2895. min.compiledMethod = function(javaThread)
  2896. {
  2897. var vmStack = javaThread.vmStack;
  2898. var stackBase = javaThread.stackBase;
  2899. var a = vmStack[stackBase];
  2900. var b = vmStack[stackBase+1];
  2901. if(a>b)
  2902. {
  2903. return {action: "returnValue", value: b};
  2904. }
  2905. else
  2906. {
  2907. return {action: "returnValue", value: a};
  2908. }
  2909. }
  2910. JavaMath.$cappuccino.addMethod(min);
  2911. var abs = new Method(0x0008, "abs", "(D)D");
  2912. abs.codeAttr = new Code(0, 2, null);
  2913. abs.compiledMethod = function(javaThread)
  2914. {
  2915. var vmStack = javaThread.vmStack;
  2916. var stackBase = javaThread.stackBase;
  2917. return {action: "returnValueWide", value: Math.abs(vmStack[stackBase])};
  2918. }
  2919. JavaMath.$cappuccino.addMethod(abs);
  2920. var absInt = new Method(0x0008, "abs", "(I)I");
  2921. absInt.codeAttr = new Code(0, 2, null);
  2922. absInt.compiledMethod = function(javaThread)
  2923. {
  2924. var vmStack = javaThread.vmStack;
  2925. var stackBase = javaThread.stackBase;
  2926. return {action: "returnValue", value: Math.abs(vmStack[stackBase])};
  2927. }
  2928. JavaMath.$cappuccino.addMethod(absInt);
  2929. classHash["java/lang/Math"] = JavaMath;
  2930. //java/lang/System
  2931. var System = function() {}
  2932. System.$cappuccino = new CVMInfo(System);
  2933. System.out = new PrintStream();
  2934. var currentTimeMillis = new Method(0x0008, "currentTimeMillis", "()J");
  2935. currentTimeMillis.codeAttr = new Code(0, 0, null);
  2936. currentTimeMillis.compiledMethod = function(javaThread)
  2937. {
  2938. var dd = new Date();
  2939. return {action: "returnValueWide", value:getLongFromDouble(dd.getTime())}
  2940. }
  2941. System.$cappuccino.addMethod(currentTimeMillis);
  2942. var getProperty = new Method(0x0008, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
  2943. getProperty.codeAttr = new Code(0, 1, null);
  2944. getProperty.compiledMethod = function(javaThread)
  2945. {
  2946. var propString = createJavaString("CappuccinoVM");
  2947. return {action: "returnValue", value: propString}
  2948. }
  2949. System.$cappuccino.addMethod(getProperty);
  2950. var arraycopy = new Method(0x0008, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V");
  2951. arraycopy.codeAttr = new Code(0, 5, null);
  2952. arraycopy.compiledMethod = function(javaThread)
  2953. {
  2954. var vmStack = javaThread.vmStack;
  2955. var stackBase = javaThread.stackBase;
  2956. var src = vmStack[stackBase];
  2957. var si = vmStack[stackBase + 1];
  2958. var dst = vmStack[stackBase + 2];
  2959. var di = vmStack[stackBase + 3];
  2960. var num = vmStack[stackBase + 4];
  2961. var i;
  2962. for (i = 0; i < num; i++)
  2963. {
  2964. dst[di + i] = src[si + i];
  2965. }
  2966. return {action: "return"};
  2967. }
  2968. System.$cappuccino.addMethod(arraycopy);
  2969. classHash["java/lang/System"] = System;
  2970. //グローバル名前空間オブジェクト
  2971. CappuccinoVM =
  2972. {
  2973. /*
  2974. startMain: function(className)
  2975. {
  2976. var javaClass = getJavaClass(className);
  2977. var mainMethod = javaClass.$cappuccino.findMethod("main", "([Ljava/lang/String;)V");
  2978. var i;
  2979. var args = [];
  2980. for (i=1; i < arguments.length; i++)
  2981. {
  2982. args[i-1] = new ValueObject(createJavaString(arguments[i]));
  2983. }
  2984. new JavaThread(mainMethod, [new ValueObject(args)]).run();
  2985. },
  2986. */
  2987. startMain: function(className)
  2988. {
  2989. var args = [];
  2990. var javaThread = new JavaThread();
  2991. for (i=1; i < arguments.length; i++)
  2992. {
  2993. args[i-1] = new createJavaString(arguments[i]);
  2994. }
  2995. loadClassfileAsync(className, javaThread, function(){javaThread.run();}, true, args);
  2996. },
  2997. debugPrint: debugPrint,
  2998. getJavaClass: getJavaClass,
  2999. makeArray: makeArray,
  3000. createJavaString: createJavaString,
  3001. doAddLong: doAddLong,
  3002. doSubLong: doSubLong,
  3003. doMulLong: doMulLong,
  3004. doDivLong: doDivLong,
  3005. doCmpLong: doCmpLong,
  3006. getOpponentFromSign: getOpponentFromSign,
  3007. getSignFromOpponent: getSignFromOpponent,
  3008. getLongFromInt: getLongFromInt,
  3009. getLongFromDouble: getLongFromDouble,
  3010. getDoubleFromLong: getDoubleFromLong
  3011. }
  3012. }