QEMU.js: ಈಗ ಗಂಭೀರವಾಗಿದೆ ಮತ್ತು WASM ಜೊತೆಗೆ

ಒಮ್ಮೆ ನಾನು ವಿನೋದಕ್ಕಾಗಿ ನಿರ್ಧರಿಸಿದೆ ಪ್ರಕ್ರಿಯೆಯ ಹಿಮ್ಮುಖತೆಯನ್ನು ಸಾಬೀತುಪಡಿಸಿ ಮತ್ತು ಯಂತ್ರ ಕೋಡ್‌ನಿಂದ JavaScript (ಹೆಚ್ಚು ನಿಖರವಾಗಿ, Asm.js) ಅನ್ನು ಹೇಗೆ ರಚಿಸುವುದು ಎಂಬುದನ್ನು ತಿಳಿಯಿರಿ. ಪ್ರಯೋಗಕ್ಕಾಗಿ QEMU ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲಾಯಿತು, ಮತ್ತು ಸ್ವಲ್ಪ ಸಮಯದ ನಂತರ ಹಬ್ರ್ನಲ್ಲಿ ಲೇಖನವನ್ನು ಬರೆಯಲಾಯಿತು. ಕಾಮೆಂಟ್‌ಗಳಲ್ಲಿ ನಾನು ವೆಬ್‌ಅಸೆಂಬ್ಲಿಯಲ್ಲಿ ಯೋಜನೆಯನ್ನು ರೀಮೇಕ್ ಮಾಡಲು ಸಲಹೆ ನೀಡಿದ್ದೇನೆ ಮತ್ತು ನನ್ನನ್ನೇ ತ್ಯಜಿಸುತ್ತೇನೆ ಬಹುತೇಕ ಪೂರ್ಣಗೊಂಡಿದೆ ನಾನು ಹೇಗಾದರೂ ಯೋಜನೆಯನ್ನು ಬಯಸಲಿಲ್ಲ ... ಕೆಲಸ ನಡೆಯುತ್ತಿದೆ, ಆದರೆ ಬಹಳ ನಿಧಾನವಾಗಿ, ಮತ್ತು ಈಗ, ಇತ್ತೀಚೆಗೆ ಆ ಲೇಖನದಲ್ಲಿ ಕಾಣಿಸಿಕೊಂಡಿದೆ ವ್ಯಾಖ್ಯಾನ ವಿಷಯದ ಮೇಲೆ "ಹಾಗಾದರೆ ಅದು ಹೇಗೆ ಕೊನೆಗೊಂಡಿತು?" ನನ್ನ ವಿವರವಾದ ಉತ್ತರಕ್ಕೆ ಪ್ರತಿಕ್ರಿಯೆಯಾಗಿ, "ಇದು ಲೇಖನದಂತೆ ತೋರುತ್ತದೆ" ಎಂದು ನಾನು ಕೇಳಿದೆ. ಸರಿ, ನಿಮಗೆ ಸಾಧ್ಯವಾದರೆ, ಒಂದು ಲೇಖನ ಇರುತ್ತದೆ. ಬಹುಶಃ ಯಾರಾದರೂ ಅದನ್ನು ಉಪಯುಕ್ತವಾಗಿ ಕಾಣುತ್ತಾರೆ. ಅದರಿಂದ ಓದುಗರು QEMU ಕೋಡ್ ಉತ್ಪಾದನೆಯ ಬ್ಯಾಕೆಂಡ್‌ಗಳ ವಿನ್ಯಾಸದ ಬಗ್ಗೆ ಕೆಲವು ಸಂಗತಿಗಳನ್ನು ಕಲಿಯುತ್ತಾರೆ, ಹಾಗೆಯೇ ವೆಬ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಾಗಿ ಜಸ್ಟ್-ಇನ್-ಟೈಮ್ ಕಂಪೈಲರ್ ಅನ್ನು ಹೇಗೆ ಬರೆಯುವುದು.

ಕಾರ್ಯಗಳನ್ನು

ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್‌ಗೆ QEMU ಅನ್ನು "ಹೇಗಾದರೂ" ಪೋರ್ಟ್ ಮಾಡುವುದು ಹೇಗೆ ಎಂದು ನಾನು ಈಗಾಗಲೇ ಕಲಿತಿದ್ದರಿಂದ, ಈ ಬಾರಿ ಅದನ್ನು ಬುದ್ಧಿವಂತಿಕೆಯಿಂದ ಮಾಡಲು ನಿರ್ಧರಿಸಲಾಯಿತು ಮತ್ತು ಹಳೆಯ ತಪ್ಪುಗಳನ್ನು ಪುನರಾವರ್ತಿಸಬಾರದು.

ದೋಷ ಸಂಖ್ಯೆ ಒಂದು: ಪಾಯಿಂಟ್ ಬಿಡುಗಡೆಯಿಂದ ಶಾಖೆ

ಅಪ್‌ಸ್ಟ್ರೀಮ್ ಆವೃತ್ತಿ 2.4.1 ರಿಂದ ನನ್ನ ಆವೃತ್ತಿಯನ್ನು ಫೋರ್ಕ್ ಮಾಡುವುದು ನನ್ನ ಮೊದಲ ತಪ್ಪು. ನಂತರ ನನಗೆ ಇದು ಒಳ್ಳೆಯದು ಎಂದು ತೋರುತ್ತದೆ: ಪಾಯಿಂಟ್ ಬಿಡುಗಡೆಯು ಅಸ್ತಿತ್ವದಲ್ಲಿದ್ದರೆ, ಅದು ಬಹುಶಃ ಸರಳ 2.4 ಗಿಂತ ಹೆಚ್ಚು ಸ್ಥಿರವಾಗಿರುತ್ತದೆ ಮತ್ತು ಇನ್ನೂ ಹೆಚ್ಚಿನ ಶಾಖೆ master. ಮತ್ತು ನನ್ನ ಸ್ವಂತ ದೋಷಗಳನ್ನು ಸಾಕಷ್ಟು ಪ್ರಮಾಣದಲ್ಲಿ ಸೇರಿಸಲು ನಾನು ಯೋಜಿಸಿದ್ದರಿಂದ, ನನಗೆ ಬೇರೆಯವರ ಅಗತ್ಯವಿರಲಿಲ್ಲ. ಬಹುಶಃ ಅದು ಹೇಗೆ ಬದಲಾಯಿತು. ಆದರೆ ಇಲ್ಲಿ ವಿಷಯ ಇಲ್ಲಿದೆ: QEMU ಇನ್ನೂ ನಿಲ್ಲುವುದಿಲ್ಲ, ಮತ್ತು ಕೆಲವು ಹಂತದಲ್ಲಿ ಅವರು ರಚಿಸಿದ ಕೋಡ್‌ನ ಆಪ್ಟಿಮೈಸೇಶನ್ ಅನ್ನು 10 ಪ್ರತಿಶತದಷ್ಟು ಘೋಷಿಸಿದರು. "ಹೌದು, ಈಗ ನಾನು ಫ್ರೀಜ್ ಮಾಡಲಿದ್ದೇನೆ," ನಾನು ಯೋಚಿಸಿದೆ ಮತ್ತು ಮುರಿದುಬಿಟ್ಟೆ. ಇಲ್ಲಿ ನಾವು ವ್ಯತಿರಿಕ್ತತೆಯನ್ನು ಮಾಡಬೇಕಾಗಿದೆ: QEMU.js ನ ಏಕ-ಥ್ರೆಡ್ ಸ್ವಭಾವದಿಂದಾಗಿ ಮತ್ತು ಮೂಲ QEMU ಬಹು-ಥ್ರೆಡಿಂಗ್ ಅನುಪಸ್ಥಿತಿಯನ್ನು ಸೂಚಿಸುವುದಿಲ್ಲ (ಅಂದರೆ, ಹಲವಾರು ಸಂಬಂಧವಿಲ್ಲದ ಕೋಡ್ ಮಾರ್ಗಗಳನ್ನು ಏಕಕಾಲದಲ್ಲಿ ನಿರ್ವಹಿಸುವ ಸಾಮರ್ಥ್ಯ, ಮತ್ತು ಕೇವಲ "ಎಲ್ಲಾ ಕರ್ನಲ್‌ಗಳನ್ನು ಬಳಸಿ") ಇದಕ್ಕೆ ನಿರ್ಣಾಯಕವಾಗಿದೆ, ಥ್ರೆಡ್‌ಗಳ ಮುಖ್ಯ ಕಾರ್ಯಗಳನ್ನು ನಾನು ಹೊರಗಿನಿಂದ ಕರೆ ಮಾಡಲು "ಅದನ್ನು ಹೊರಹಾಕಬೇಕು". ಇದು ವಿಲೀನದ ಸಮಯದಲ್ಲಿ ಕೆಲವು ನೈಸರ್ಗಿಕ ಸಮಸ್ಯೆಗಳನ್ನು ಸೃಷ್ಟಿಸಿತು. ಆದಾಗ್ಯೂ, ಶಾಖೆಯಿಂದ ಕೆಲವು ಬದಲಾವಣೆಗಳು ಎಂದು ವಾಸ್ತವವಾಗಿ master, ನಾನು ನನ್ನ ಕೋಡ್ ಅನ್ನು ವಿಲೀನಗೊಳಿಸಲು ಪ್ರಯತ್ನಿಸಿದಾಗ, ಪಾಯಿಂಟ್ ಬಿಡುಗಡೆಯಲ್ಲಿ (ಮತ್ತು ಆದ್ದರಿಂದ ನನ್ನ ಶಾಖೆಯಲ್ಲಿ) ಚೆರ್ರಿಯನ್ನು ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ, ಬಹುಶಃ ಅನುಕೂಲವನ್ನು ಸೇರಿಸುತ್ತಿರಲಿಲ್ಲ.

ಸಾಮಾನ್ಯವಾಗಿ, ಮೂಲಮಾದರಿಯನ್ನು ಹೊರಹಾಕಲು, ಭಾಗಗಳಿಗೆ ಡಿಸ್ಅಸೆಂಬಲ್ ಮಾಡಲು ಮತ್ತು ಹೊಸದನ್ನು ಆಧರಿಸಿ ಮೊದಲಿನಿಂದ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ನಿರ್ಮಿಸಲು ಇನ್ನೂ ಅರ್ಥವಿದೆ ಎಂದು ನಾನು ನಿರ್ಧರಿಸಿದೆ ಮತ್ತು ಈಗ master.

ತಪ್ಪು ಸಂಖ್ಯೆ ಎರಡು: TLP ವಿಧಾನ

ಮೂಲಭೂತವಾಗಿ, ಇದು ತಪ್ಪಲ್ಲ, ಸಾಮಾನ್ಯವಾಗಿ, ಇದು "ಎಲ್ಲಿ ಮತ್ತು ಹೇಗೆ ಚಲಿಸಬೇಕು?" ಮತ್ತು ಸಾಮಾನ್ಯವಾಗಿ "ನಾವು ಅಲ್ಲಿಗೆ ಹೋಗುತ್ತೇವೆಯೇ?" ಎರಡರ ಸಂಪೂರ್ಣ ತಪ್ಪುಗ್ರಹಿಕೆಯ ಪರಿಸ್ಥಿತಿಗಳಲ್ಲಿ ಯೋಜನೆಯನ್ನು ರಚಿಸುವ ಒಂದು ವೈಶಿಷ್ಟ್ಯವಾಗಿದೆ. ಈ ಪರಿಸ್ಥಿತಿಗಳಲ್ಲಿ ನಾಜೂಕಿಲ್ಲದ ಪ್ರೋಗ್ರಾಮಿಂಗ್ ಸಮರ್ಥನೀಯ ಆಯ್ಕೆಯಾಗಿದೆ, ಆದರೆ, ಸ್ವಾಭಾವಿಕವಾಗಿ, ನಾನು ಅದನ್ನು ಅನಗತ್ಯವಾಗಿ ಪುನರಾವರ್ತಿಸಲು ಬಯಸುವುದಿಲ್ಲ. ಈ ಬಾರಿ ನಾನು ಅದನ್ನು ಬುದ್ಧಿವಂತಿಕೆಯಿಂದ ಮಾಡಲು ಬಯಸುತ್ತೇನೆ: ಪರಮಾಣು ಕಮಿಟ್‌ಗಳು, ಪ್ರಜ್ಞಾಪೂರ್ವಕ ಕೋಡ್ ಬದಲಾವಣೆಗಳು (ಮತ್ತು "ಅದು ಕಂಪೈಲ್ ಮಾಡುವವರೆಗೆ (ಎಚ್ಚರಿಕೆಗಳೊಂದಿಗೆ) ಯಾದೃಚ್ಛಿಕ ಅಕ್ಷರಗಳನ್ನು ಒಟ್ಟಿಗೆ ಸೇರಿಸುವುದಿಲ್ಲ", ವಿಕಿಕೋಟ್ ಪ್ರಕಾರ ಲಿನಸ್ ಟೊರ್ವಾಲ್ಡ್ಸ್ ಒಮ್ಮೆ ಯಾರೊಬ್ಬರ ಬಗ್ಗೆ ಹೇಳಿದಂತೆ), ಇತ್ಯಾದಿ.

ತಪ್ಪು ಸಂಖ್ಯೆ ಮೂರು: ಫೋರ್ಡ್ ತಿಳಿಯದೆ ನೀರಿಗೆ ಬರುವುದು

ನಾನು ಇನ್ನೂ ಇದನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ತೊಡೆದುಹಾಕಿಲ್ಲ, ಆದರೆ ಈಗ ನಾನು ಕನಿಷ್ಠ ಪ್ರತಿರೋಧದ ಹಾದಿಯನ್ನು ಅನುಸರಿಸದಿರಲು ನಿರ್ಧರಿಸಿದ್ದೇನೆ ಮತ್ತು ಅದನ್ನು “ವಯಸ್ಕನಂತೆ” ಮಾಡಲು ನಿರ್ಧರಿಸಿದೆ, ಅಂದರೆ, ನನ್ನ TCG ಬ್ಯಾಕೆಂಡ್ ಅನ್ನು ಮೊದಲಿನಿಂದ ಬರೆಯಿರಿ. ನಂತರ ಹೇಳಲು, "ಹೌದು, ಇದು ಸಹಜವಾಗಿ, ನಿಧಾನವಾಗಿ, ಆದರೆ ನಾನು ಎಲ್ಲವನ್ನೂ ನಿಯಂತ್ರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ - TCI ಅನ್ನು ಹೀಗೆ ಬರೆಯಲಾಗಿದೆ..." ಇದಲ್ಲದೆ, ಇದು ಆರಂಭದಲ್ಲಿ ಸ್ಪಷ್ಟ ಪರಿಹಾರದಂತೆ ತೋರುತ್ತಿತ್ತು ನಾನು ಬೈನರಿ ಕೋಡ್ ಅನ್ನು ರಚಿಸುತ್ತೇನೆ. ಅವರು ಹೇಳುವಂತೆ, “ಘೆಂಟ್ ಸಂಗ್ರಹಿಸಿದರುу, ಆದರೆ ಅದು ಅಲ್ಲ”: ಕೋಡ್, ಸಹಜವಾಗಿ, ಬೈನರಿ, ಆದರೆ ನಿಯಂತ್ರಣವನ್ನು ಸರಳವಾಗಿ ವರ್ಗಾಯಿಸಲಾಗುವುದಿಲ್ಲ - ಸಂಕಲನಕ್ಕಾಗಿ ಅದನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಬ್ರೌಸರ್‌ಗೆ ತಳ್ಳಬೇಕು, ಇದರ ಪರಿಣಾಮವಾಗಿ JS ಪ್ರಪಂಚದಿಂದ ಒಂದು ನಿರ್ದಿಷ್ಟ ವಸ್ತುವು ಇನ್ನೂ ಅಗತ್ಯವಿದೆ. ಎಲ್ಲೋ ಉಳಿಸಿ. ಆದಾಗ್ಯೂ, ಸಾಮಾನ್ಯ RISC ಆರ್ಕಿಟೆಕ್ಚರ್‌ಗಳಲ್ಲಿ, ನಾನು ಅರ್ಥಮಾಡಿಕೊಂಡಂತೆ, ಪುನರುತ್ಪಾದಿಸಲಾದ ಕೋಡ್‌ಗಾಗಿ ಸೂಚನಾ ಸಂಗ್ರಹವನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಮರುಹೊಂದಿಸುವ ಅವಶ್ಯಕತೆಯಿದೆ - ಇದು ನಮಗೆ ಅಗತ್ಯವಿಲ್ಲದಿದ್ದರೆ, ಯಾವುದೇ ಸಂದರ್ಭದಲ್ಲಿ, ಅದು ಹತ್ತಿರದಲ್ಲಿದೆ. ಹೆಚ್ಚುವರಿಯಾಗಿ, ನನ್ನ ಕೊನೆಯ ಪ್ರಯತ್ನದಿಂದ, ಅನುವಾದ ಬ್ಲಾಕ್‌ನ ಮಧ್ಯಭಾಗಕ್ಕೆ ನಿಯಂತ್ರಣವು ವರ್ಗಾವಣೆಯಾಗುವುದಿಲ್ಲ ಎಂದು ನಾನು ಕಲಿತಿದ್ದೇನೆ, ಆದ್ದರಿಂದ ನಮಗೆ ಯಾವುದೇ ಆಫ್‌ಸೆಟ್‌ನಿಂದ ಬೈಟ್‌ಕೋಡ್ ಅನ್ನು ಅರ್ಥೈಸುವ ಅಗತ್ಯವಿಲ್ಲ ಮತ್ತು ನಾವು ಅದನ್ನು TB ಯಲ್ಲಿನ ಕಾರ್ಯದಿಂದ ಸರಳವಾಗಿ ರಚಿಸಬಹುದು. .

ಅವರು ಬಂದು ಒದ್ದರು

ಜುಲೈನಲ್ಲಿ ನಾನು ಕೋಡ್ ಅನ್ನು ಪುನಃ ಬರೆಯಲು ಪ್ರಾರಂಭಿಸಿದರೂ, ಒಂದು ಮ್ಯಾಜಿಕ್ ಕಿಕ್ ಗಮನಿಸದೆ ಹರಿದಾಡಿತು: ಸಾಮಾನ್ಯವಾಗಿ GitHub ನಿಂದ ಪತ್ರಗಳು ಸಮಸ್ಯೆಗಳಿಗೆ ಪ್ರತಿಕ್ರಿಯೆಗಳ ಕುರಿತು ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ವಿನಂತಿಗಳನ್ನು ಎಳೆಯಿರಿ, ಆದರೆ ಇಲ್ಲಿ, ಇದ್ದಕ್ಕಿದ್ದಂತೆ ಥ್ರೆಡ್ನಲ್ಲಿ ಉಲ್ಲೇಖಿಸಿ ಕ್ವಿಮು ಬ್ಯಾಕೆಂಡ್ ಆಗಿ ಬೈನರೇನ್ ಸನ್ನಿವೇಶದಲ್ಲಿ, "ಅವನು ಹಾಗೆ ಮಾಡಿದ್ದಾನೆ, ಬಹುಶಃ ಅವನು ಏನಾದರೂ ಹೇಳಬಹುದು." ನಾವು ಎಂಸ್ಕ್ರಿಪ್ಟನ್‌ನ ಸಂಬಂಧಿತ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸುವ ಬಗ್ಗೆ ಮಾತನಾಡುತ್ತಿದ್ದೆವು ಬೈನರೇನ್ WASM JIT ರಚಿಸಲು. ಸರಿ, ನೀವು ಅಲ್ಲಿ Apache 2.0 ಪರವಾನಗಿಯನ್ನು ಹೊಂದಿದ್ದೀರಿ ಎಂದು ನಾನು ಹೇಳಿದೆ ಮತ್ತು ಒಟ್ಟಾರೆಯಾಗಿ QEMU ಅನ್ನು GPLv2 ಅಡಿಯಲ್ಲಿ ವಿತರಿಸಲಾಗಿದೆ ಮತ್ತು ಅವುಗಳು ಹೆಚ್ಚು ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ಇದ್ದಕ್ಕಿದ್ದಂತೆ ಪರವಾನಗಿ ಆಗಿರಬಹುದು ಎಂದು ಬದಲಾಯಿತು ಹೇಗಾದರೂ ಸರಿಪಡಿಸಿ (ನನಗೆ ಗೊತ್ತಿಲ್ಲ: ಬಹುಶಃ ಅದನ್ನು ಬದಲಾಯಿಸಬಹುದು, ಬಹುಶಃ ಡ್ಯುಯಲ್ ಪರವಾನಗಿ, ಬಹುಶಃ ಬೇರೆ ಏನಾದರೂ ...). ಇದು ನನಗೆ ಸಂತೋಷವನ್ನುಂಟುಮಾಡಿತು, ಏಕೆಂದರೆ ಆ ಹೊತ್ತಿಗೆ ನಾನು ಈಗಾಗಲೇ ಹತ್ತಿರದಿಂದ ನೋಡಿದೆ ಬೈನರಿ ಸ್ವರೂಪ WebAssembly, ಮತ್ತು ನಾನು ಹೇಗಾದರೂ ದುಃಖಿತನಾಗಿದ್ದೆ ಮತ್ತು ಗ್ರಹಿಸಲಾಗಲಿಲ್ಲ. ಟ್ರಾನ್ಸಿಶನ್ ಗ್ರಾಫ್‌ನೊಂದಿಗೆ ಮೂಲ ಬ್ಲಾಕ್‌ಗಳನ್ನು ಕಬಳಿಸುವ, ಬೈಟ್‌ಕೋಡ್ ಅನ್ನು ಉತ್ಪಾದಿಸುವ ಮತ್ತು ಅಗತ್ಯವಿದ್ದರೆ ಅದನ್ನು ಇಂಟರ್ಪ್ರಿಟರ್‌ನಲ್ಲಿ ಚಲಾಯಿಸುವ ಗ್ರಂಥಾಲಯವೂ ಇತ್ತು.

ನಂತರ ಹೆಚ್ಚು ಇತ್ತು ಒಂದು ಪತ್ರ QEMU ಮೇಲಿಂಗ್ ಪಟ್ಟಿಯಲ್ಲಿ, ಆದರೆ ಇದು "ಹೇಗಾದರೂ ಯಾರಿಗೆ ಬೇಕು?" ಎಂಬ ಪ್ರಶ್ನೆಗೆ ಸಂಬಂಧಿಸಿದೆ. ಮತ್ತು ಇದು ಇದ್ದಕ್ಕಿದ್ದಂತೆ, ಇದು ಅಗತ್ಯ ಎಂದು ಬದಲಾಯಿತು. ಕನಿಷ್ಠ, ನೀವು ಹೆಚ್ಚು ಅಥವಾ ಕಡಿಮೆ ವೇಗವಾಗಿ ಕೆಲಸ ಮಾಡಿದರೆ, ಕೆಳಗಿನ ಬಳಕೆಯ ಸಾಧ್ಯತೆಗಳನ್ನು ಒಟ್ಟಿಗೆ ಸ್ಕ್ರ್ಯಾಪ್ ಮಾಡಬಹುದು:

  • ಯಾವುದೇ ಅನುಸ್ಥಾಪನೆಯಿಲ್ಲದೆ ಶೈಕ್ಷಣಿಕ ಏನನ್ನಾದರೂ ಪ್ರಾರಂಭಿಸುವುದು
  • ಐಒಎಸ್‌ನಲ್ಲಿ ವರ್ಚುವಲೈಸೇಶನ್, ಅಲ್ಲಿ, ವದಂತಿಗಳ ಪ್ರಕಾರ, ಫ್ಲೈನಲ್ಲಿ ಕೋಡ್ ಉತ್ಪಾದಿಸುವ ಹಕ್ಕನ್ನು ಹೊಂದಿರುವ ಏಕೈಕ ಅಪ್ಲಿಕೇಶನ್ JS ಎಂಜಿನ್ ಆಗಿದೆ (ಇದು ನಿಜವೇ?)
  • ಮಿನಿ-ಓಎಸ್ನ ಪ್ರದರ್ಶನ - ಏಕ-ಫ್ಲಾಪಿ, ಅಂತರ್ನಿರ್ಮಿತ, ಎಲ್ಲಾ ರೀತಿಯ ಫರ್ಮ್ವೇರ್, ಇತ್ಯಾದಿ ...

ಬ್ರೌಸರ್ ರನ್ಟೈಮ್ ವೈಶಿಷ್ಟ್ಯಗಳು

ನಾನು ಈಗಾಗಲೇ ಹೇಳಿದಂತೆ, QEMU ಅನ್ನು ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್‌ಗೆ ಜೋಡಿಸಲಾಗಿದೆ, ಆದರೆ ಬ್ರೌಸರ್ ಅದನ್ನು ಹೊಂದಿಲ್ಲ. ಸರಿ, ಅಂದರೆ, ಇಲ್ಲ ... ಮೊದಲಿಗೆ ಅದು ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲ, ನಂತರ ವೆಬ್‌ವರ್ಕರ್‌ಗಳು ಕಾಣಿಸಿಕೊಂಡರು - ನಾನು ಅರ್ಥಮಾಡಿಕೊಂಡಂತೆ, ಇದು ಸಂದೇಶ ರವಾನಿಸುವಿಕೆಯ ಆಧಾರದ ಮೇಲೆ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಆಗಿದೆ ಹಂಚಿಕೆಯ ಅಸ್ಥಿರಗಳಿಲ್ಲದೆ. ಸ್ವಾಭಾವಿಕವಾಗಿ, ಹಂಚಿಕೆಯ ಮೆಮೊರಿ ಮಾದರಿಯ ಆಧಾರದ ಮೇಲೆ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೋಡ್ ಅನ್ನು ಪೋರ್ಟ್ ಮಾಡುವಾಗ ಇದು ಗಮನಾರ್ಹ ಸಮಸ್ಯೆಗಳನ್ನು ಸೃಷ್ಟಿಸುತ್ತದೆ. ನಂತರ ಸಾರ್ವಜನಿಕರ ಒತ್ತಡಕ್ಕೆ ಮಣಿದು ಹೆಸರಿಟ್ಟು ಜಾರಿಗೆ ತರಲಾಯಿತು SharedArrayBuffers. ಇದನ್ನು ಕ್ರಮೇಣ ಪರಿಚಯಿಸಲಾಯಿತು, ಅವರು ವಿವಿಧ ಬ್ರೌಸರ್‌ಗಳಲ್ಲಿ ಅದರ ಉಡಾವಣೆಯನ್ನು ಆಚರಿಸಿದರು, ನಂತರ ಅವರು ಹೊಸ ವರ್ಷವನ್ನು ಆಚರಿಸಿದರು, ಮತ್ತು ನಂತರ ಮೆಲ್ಟ್‌ಡೌನ್ ... ಅದರ ನಂತರ ಅವರು ಸಮಯದ ಅಳತೆಯನ್ನು ಒರಟಾದ ಅಥವಾ ಒರಟಾದ ಎಂದು ತೀರ್ಮಾನಕ್ಕೆ ಬಂದರು, ಆದರೆ ಹಂಚಿಕೆಯ ಸ್ಮರಣೆಯ ಸಹಾಯದಿಂದ ಮತ್ತು a ಥ್ರೆಡ್ ಕೌಂಟರ್ ಅನ್ನು ಹೆಚ್ಚಿಸುತ್ತದೆ, ಅದು ಒಂದೇ ಆಗಿರುತ್ತದೆ ಇದು ಸಾಕಷ್ಟು ನಿಖರವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ. ಆದ್ದರಿಂದ ನಾವು ಹಂಚಿಕೊಂಡ ಮೆಮೊರಿಯೊಂದಿಗೆ ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದೇವೆ. ಅವರು ನಂತರ ಅದನ್ನು ಮತ್ತೆ ಆನ್ ಮಾಡಿದ್ದಾರೆ ಎಂದು ತೋರುತ್ತದೆ, ಆದರೆ, ಮೊದಲ ಪ್ರಯೋಗದಿಂದ ಸ್ಪಷ್ಟವಾದಂತೆ, ಅದು ಇಲ್ಲದೆ ಜೀವನವಿದೆ, ಮತ್ತು ಹಾಗಿದ್ದಲ್ಲಿ, ನಾವು ಮಲ್ಟಿಥ್ರೆಡಿಂಗ್ ಅನ್ನು ಅವಲಂಬಿಸದೆ ಅದನ್ನು ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತೇವೆ.

ಎರಡನೆಯ ವೈಶಿಷ್ಟ್ಯವು ಸ್ಟಾಕ್ನೊಂದಿಗೆ ಕಡಿಮೆ-ಮಟ್ಟದ ಮ್ಯಾನಿಪ್ಯುಲೇಷನ್ಗಳ ಅಸಾಧ್ಯತೆಯಾಗಿದೆ: ನೀವು ಸರಳವಾಗಿ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಿಲ್ಲ, ಪ್ರಸ್ತುತ ಸಂದರ್ಭವನ್ನು ಉಳಿಸಿ ಮತ್ತು ಹೊಸ ಸ್ಟಾಕ್ನೊಂದಿಗೆ ಹೊಸದಕ್ಕೆ ಬದಲಿಸಿ. ಕರೆ ಸ್ಟಾಕ್ ಅನ್ನು JS ವರ್ಚುವಲ್ ಯಂತ್ರದಿಂದ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ. ಮೊದಲಿನ ಹರಿವನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಹಸ್ತಚಾಲಿತವಾಗಿ ನಿರ್ವಹಿಸಲು ನಾವು ಇನ್ನೂ ನಿರ್ಧರಿಸಿದ್ದರಿಂದ ಸಮಸ್ಯೆ ಏನು ಎಂದು ತೋರುತ್ತದೆ? ವಾಸ್ತವವಾಗಿ, QEMU ನಲ್ಲಿ I/O ಬ್ಲಾಕ್ ಅನ್ನು ಕೊರೊಟೀನ್‌ಗಳ ಮೂಲಕ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುತ್ತದೆ ಮತ್ತು ಇಲ್ಲಿಯೇ ಕಡಿಮೆ-ಮಟ್ಟದ ಸ್ಟಾಕ್ ಮ್ಯಾನಿಪ್ಯುಲೇಷನ್‌ಗಳು ಸೂಕ್ತವಾಗಿ ಬರುತ್ತವೆ. ಅದೃಷ್ಟವಶಾತ್, Emscipten ಈಗಾಗಲೇ ಅಸಮಕಾಲಿಕ ಕಾರ್ಯಾಚರಣೆಗಳ ಕಾರ್ಯವಿಧಾನವನ್ನು ಹೊಂದಿದೆ, ಎರಡು ಸಹ: ಅಸಿನ್ಸಿಫೈ и ಎಂಟರ್‌ಪ್ರೆಟರ್. ಮೊದಲನೆಯದು ರಚಿತವಾದ JavaScript ಕೋಡ್‌ನಲ್ಲಿ ಗಮನಾರ್ಹವಾದ ಉಬ್ಬುವಿಕೆಯ ಮೂಲಕ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಮತ್ತು ಇನ್ನು ಮುಂದೆ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಎರಡನೆಯದು ಪ್ರಸ್ತುತ "ಸರಿಯಾದ ಮಾರ್ಗ" ಮತ್ತು ಸ್ಥಳೀಯ ಇಂಟರ್ಪ್ರಿಟರ್ಗಾಗಿ ಬೈಟ್ಕೋಡ್ ಉತ್ಪಾದನೆಯ ಮೂಲಕ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಇದು ನಿಧಾನವಾಗಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ, ಆದರೆ ಇದು ಕೋಡ್ ಅನ್ನು ಉಬ್ಬುವುದಿಲ್ಲ. ನಿಜ, ಈ ಕಾರ್ಯವಿಧಾನಕ್ಕೆ ಕೊರೊಟೀನ್‌ಗಳಿಗೆ ಬೆಂಬಲವನ್ನು ಸ್ವತಂತ್ರವಾಗಿ ನೀಡಬೇಕಾಗಿತ್ತು (ಅಸಿನ್ಸಿಫೈಗಾಗಿ ಈಗಾಗಲೇ ಕೊರೊಟೀನ್‌ಗಳನ್ನು ಬರೆಯಲಾಗಿದೆ ಮತ್ತು ಎಂಟರ್‌ಪ್ರೆಟರ್‌ಗಾಗಿ ಸರಿಸುಮಾರು ಅದೇ API ಅನ್ನು ಅಳವಡಿಸಲಾಗಿದೆ, ನೀವು ಅವುಗಳನ್ನು ಸಂಪರ್ಕಿಸುವ ಅಗತ್ಯವಿದೆ).

ಈ ಸಮಯದಲ್ಲಿ, ನಾನು ಕೋಡ್ ಅನ್ನು WASM ನಲ್ಲಿ ಸಂಕಲಿಸಿದ ಒಂದಕ್ಕೆ ವಿಭಜಿಸಲು ಮತ್ತು ಎಂಟರ್‌ಪ್ರೆಟರ್ ಬಳಸಿ ಅರ್ಥೈಸಲು ಇನ್ನೂ ನಿರ್ವಹಿಸಲಿಲ್ಲ, ಆದ್ದರಿಂದ ಬ್ಲಾಕ್ ಸಾಧನಗಳು ಇನ್ನೂ ಕಾರ್ಯನಿರ್ವಹಿಸುವುದಿಲ್ಲ (ಮುಂದಿನ ಸರಣಿಯಲ್ಲಿ ಅವರು ಹೇಳಿದಂತೆ ನೋಡಿ...). ಅಂದರೆ, ಕೊನೆಯಲ್ಲಿ ನೀವು ಈ ತಮಾಷೆಯ ಲೇಯರ್ಡ್ ವಿಷಯವನ್ನು ಪಡೆಯಬೇಕು:

  • ವ್ಯಾಖ್ಯಾನಿಸಲಾದ ಬ್ಲಾಕ್ I/O. ಸರಿ, ಸ್ಥಳೀಯ ಕಾರ್ಯಕ್ಷಮತೆಯೊಂದಿಗೆ NVMe ಅನ್ನು ಅನುಕರಣೆ ಮಾಡುವುದನ್ನು ನೀವು ನಿಜವಾಗಿಯೂ ನಿರೀಕ್ಷಿಸಿದ್ದೀರಾ? 🙂
  • ಸ್ಥಿರವಾಗಿ ಕಂಪೈಲ್ ಮಾಡಲಾದ ಮುಖ್ಯ QEMU ಕೋಡ್ (ಅನುವಾದಕ, ಇತರ ಎಮ್ಯುಲೇಟೆಡ್ ಸಾಧನಗಳು, ಇತ್ಯಾದಿ)
  • WASM ಗೆ ಕ್ರಿಯಾತ್ಮಕವಾಗಿ ಕಂಪೈಲ್ ಮಾಡಿದ ಅತಿಥಿ ಕೋಡ್

QEMU ಮೂಲಗಳ ವೈಶಿಷ್ಟ್ಯಗಳು

ನೀವು ಬಹುಶಃ ಈಗಾಗಲೇ ಊಹಿಸಿದಂತೆ, ಅತಿಥಿ ಆರ್ಕಿಟೆಕ್ಚರ್‌ಗಳನ್ನು ಅನುಕರಿಸುವ ಕೋಡ್ ಮತ್ತು ಹೋಸ್ಟ್ ಯಂತ್ರ ಸೂಚನೆಗಳನ್ನು ಉತ್ಪಾದಿಸುವ ಕೋಡ್ ಅನ್ನು QEMU ನಲ್ಲಿ ಪ್ರತ್ಯೇಕಿಸಲಾಗಿದೆ. ವಾಸ್ತವವಾಗಿ, ಇದು ಸ್ವಲ್ಪ ತಂತ್ರವಾಗಿದೆ:

  • ಅತಿಥಿ ವಾಸ್ತುಶಿಲ್ಪಗಳಿವೆ
  • ಆಗಿದೆ ವೇಗವರ್ಧಕಗಳು, ಅವುಗಳೆಂದರೆ, ಲಿನಕ್ಸ್‌ನಲ್ಲಿ ಹಾರ್ಡ್‌ವೇರ್ ವರ್ಚುವಲೈಸೇಶನ್‌ಗಾಗಿ KVM (ಅತಿಥಿ ಮತ್ತು ಹೋಸ್ಟ್ ಸಿಸ್ಟಮ್‌ಗಳಿಗೆ ಪರಸ್ಪರ ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತದೆ), ಎಲ್ಲಿಯಾದರೂ JIT ಕೋಡ್ ಉತ್ಪಾದನೆಗೆ TCG. QEMU 2.9 ರಿಂದ ಪ್ರಾರಂಭಿಸಿ, ವಿಂಡೋಸ್‌ನಲ್ಲಿ HAXM ಹಾರ್ಡ್‌ವೇರ್ ವರ್ಚುವಲೈಸೇಶನ್ ಮಾನದಂಡಕ್ಕೆ ಬೆಂಬಲವು ಕಾಣಿಸಿಕೊಂಡಿತು (ವಿವರಗಳು)
  • TCG ಅನ್ನು ಬಳಸಿದರೆ ಮತ್ತು ಹಾರ್ಡ್‌ವೇರ್ ವರ್ಚುವಲೈಸೇಶನ್ ಅಲ್ಲ, ಅದು ಪ್ರತಿ ಹೋಸ್ಟ್ ಆರ್ಕಿಟೆಕ್ಚರ್‌ಗೆ ಪ್ರತ್ಯೇಕ ಕೋಡ್ ಉತ್ಪಾದನೆಯ ಬೆಂಬಲವನ್ನು ಹೊಂದಿದೆ, ಹಾಗೆಯೇ ಸಾರ್ವತ್ರಿಕ ಇಂಟರ್ಪ್ರಿಟರ್‌ಗೆ
  • ... ಮತ್ತು ಈ ಎಲ್ಲದರ ಸುತ್ತಲೂ - ಅನುಕರಿಸಿದ ಪೆರಿಫೆರಲ್ಸ್, ಬಳಕೆದಾರ ಇಂಟರ್ಫೇಸ್, ವಲಸೆ, ರೆಕಾರ್ಡ್-ರೀಪ್ಲೇ, ಇತ್ಯಾದಿ.

ಅಂದಹಾಗೆ, ನಿಮಗೆ ತಿಳಿದಿದೆಯೇ: QEMU ಸಂಪೂರ್ಣ ಕಂಪ್ಯೂಟರ್ ಅನ್ನು ಮಾತ್ರ ಅನುಕರಿಸಬಹುದು, ಆದರೆ ಹೋಸ್ಟ್ ಕರ್ನಲ್‌ನಲ್ಲಿ ಪ್ರತ್ಯೇಕ ಬಳಕೆದಾರ ಪ್ರಕ್ರಿಯೆಗಾಗಿ ಪ್ರೊಸೆಸರ್ ಅನ್ನು ಸಹ ಅನುಕರಿಸಬಹುದು, ಇದನ್ನು ಬೈನರಿ ಇನ್‌ಸ್ಟ್ರುಮೆಂಟೇಶನ್‌ಗಾಗಿ AFL ಫಝರ್‌ನಿಂದ ಬಳಸಲಾಗುತ್ತದೆ. ಬಹುಶಃ ಯಾರಾದರೂ ಈ QEMU ಕಾರ್ಯಾಚರಣೆಯ ವಿಧಾನವನ್ನು JS ಗೆ ಪೋರ್ಟ್ ಮಾಡಲು ಬಯಸುತ್ತಾರೆಯೇ? 😉

ಬಹುಕಾಲದ ಉಚಿತ ಸಾಫ್ಟ್‌ವೇರ್‌ನಂತೆ, QEMU ಅನ್ನು ಕರೆಯ ಮೂಲಕ ನಿರ್ಮಿಸಲಾಗಿದೆ configure и make. ನೀವು ಏನನ್ನಾದರೂ ಸೇರಿಸಲು ನಿರ್ಧರಿಸಿದ್ದೀರಿ ಎಂದು ಹೇಳೋಣ: TCG ಬ್ಯಾಕೆಂಡ್, ಥ್ರೆಡ್ ಅಳವಡಿಕೆ, ಇನ್ನೇನಾದರೂ. ಆಟೋಕಾನ್ಫ್‌ನೊಂದಿಗೆ ಸಂವಹನ ಮಾಡುವ ನಿರೀಕ್ಷೆಯಲ್ಲಿ ಸಂತೋಷ/ಗಾಬರಿಯಾಗಲು (ಸೂಕ್ತವಾದ ಅಂಡರ್‌ಲೈನ್) ಹೊರದಬ್ಬಬೇಡಿ - ವಾಸ್ತವವಾಗಿ, configure QEMU ಗಳು ಸ್ಪಷ್ಟವಾಗಿ ಸ್ವಯಂ-ಬರೆಯಲ್ಪಟ್ಟಿವೆ ಮತ್ತು ಯಾವುದರಿಂದಲೂ ಉತ್ಪತ್ತಿಯಾಗುವುದಿಲ್ಲ.

ವೆಬ್ಅಸೆಬಲ್

ಹಾಗಾದರೆ ವೆಬ್‌ಅಸೆಂಬ್ಲಿ (ಅಕಾ WASM) ಎಂದು ಕರೆಯಲ್ಪಡುವ ಈ ವಿಷಯ ಯಾವುದು? ಇದು Asm.js ಗೆ ಬದಲಿಯಾಗಿದೆ, ಇನ್ನು ಮುಂದೆ ಮಾನ್ಯವಾದ JavaScript ಕೋಡ್‌ನಂತೆ ನಟಿಸುವುದಿಲ್ಲ. ಇದಕ್ಕೆ ತದ್ವಿರುದ್ಧವಾಗಿ, ಇದು ಸಂಪೂರ್ಣವಾಗಿ ಬೈನರಿ ಮತ್ತು ಆಪ್ಟಿಮೈಸ್ಡ್ ಆಗಿದೆ, ಮತ್ತು ಅದರಲ್ಲಿ ಪೂರ್ಣಾಂಕವನ್ನು ಬರೆಯುವುದು ತುಂಬಾ ಸರಳವಲ್ಲ: ಸಾಂದ್ರತೆಗಾಗಿ, ಅದನ್ನು ಸ್ವರೂಪದಲ್ಲಿ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ LEB128.

Asm.js ಗಾಗಿ ರಿಲೂಪಿಂಗ್ ಅಲ್ಗಾರಿದಮ್ ಬಗ್ಗೆ ನೀವು ಕೇಳಿರಬಹುದು - ಇದು "ಉನ್ನತ-ಮಟ್ಟದ" ಹರಿವಿನ ನಿಯಂತ್ರಣ ಸೂಚನೆಗಳ ಮರುಸ್ಥಾಪನೆಯಾಗಿದೆ (ಅಂದರೆ, ಇಲ್ಲದಿದ್ದರೆ, ಲೂಪ್‌ಗಳು, ಇತ್ಯಾದಿ), ಇದಕ್ಕಾಗಿ JS ಎಂಜಿನ್‌ಗಳನ್ನು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ಕಡಿಮೆ ಮಟ್ಟದ LLVM IR, ಪ್ರೊಸೆಸರ್‌ನಿಂದ ಕಾರ್ಯಗತಗೊಳಿಸಿದ ಯಂತ್ರದ ಕೋಡ್‌ಗೆ ಹತ್ತಿರದಲ್ಲಿದೆ. ಸ್ವಾಭಾವಿಕವಾಗಿ, QEMU ನ ಮಧ್ಯಂತರ ಪ್ರಾತಿನಿಧ್ಯವು ಎರಡನೆಯದಕ್ಕೆ ಹತ್ತಿರದಲ್ಲಿದೆ. ಇಲ್ಲಿ ಅದು, ಬೈಟ್‌ಕೋಡ್, ಹಿಂಸೆಯ ಅಂತ್ಯ ಎಂದು ತೋರುತ್ತದೆ ... ಮತ್ತು ನಂತರ ಬ್ಲಾಕ್‌ಗಳು, ವೇಳೆ-ನಂತರ-ಇಲ್ಲ ಮತ್ತು ಲೂಪ್‌ಗಳಿವೆ!..

ಮತ್ತು ಇದು Binaryen ಏಕೆ ಉಪಯುಕ್ತವಾಗಿದೆ ಎಂಬುದಕ್ಕೆ ಮತ್ತೊಂದು ಕಾರಣವಾಗಿದೆ: ಇದು ಸ್ವಾಭಾವಿಕವಾಗಿ WASM ನಲ್ಲಿ ಶೇಖರಿಸಲ್ಪಟ್ಟಿರುವ ಉನ್ನತ ಮಟ್ಟದ ಬ್ಲಾಕ್ಗಳನ್ನು ಸ್ವೀಕರಿಸಬಹುದು. ಆದರೆ ಇದು ಮೂಲಭೂತ ಬ್ಲಾಕ್‌ಗಳು ಮತ್ತು ಅವುಗಳ ನಡುವಿನ ಪರಿವರ್ತನೆಗಳ ಗ್ರಾಫ್‌ನಿಂದ ಕೋಡ್ ಅನ್ನು ಸಹ ಉತ್ಪಾದಿಸಬಹುದು. ಸರಿ, ಇದು ಅನುಕೂಲಕರ C/C++ API ಹಿಂದೆ WebAssembly ಶೇಖರಣಾ ಸ್ವರೂಪವನ್ನು ಮರೆಮಾಡುತ್ತದೆ ಎಂದು ನಾನು ಈಗಾಗಲೇ ಹೇಳಿದ್ದೇನೆ.

TCG (ಸಣ್ಣ ಕೋಡ್ ಜನರೇಟರ್)

ಟಿಸಿಜಿ ಮೂಲತಃ ಆಗಿತ್ತು C ಕಂಪೈಲರ್‌ಗಾಗಿ ಬ್ಯಾಕೆಂಡ್ ನಂತರ, ಸ್ಪಷ್ಟವಾಗಿ, ಇದು GCC ಯೊಂದಿಗಿನ ಸ್ಪರ್ಧೆಯನ್ನು ತಡೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ, ಆದರೆ ಕೊನೆಯಲ್ಲಿ ಅದು ಹೋಸ್ಟ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್‌ಗಾಗಿ ಕೋಡ್ ಉತ್ಪಾದನಾ ಕಾರ್ಯವಿಧಾನವಾಗಿ QEMU ನಲ್ಲಿ ತನ್ನ ಸ್ಥಾನವನ್ನು ಕಂಡುಕೊಂಡಿತು. ಕೆಲವು ಅಮೂರ್ತ ಬೈಟ್‌ಕೋಡ್ ಅನ್ನು ಉತ್ಪಾದಿಸುವ TCG ಬ್ಯಾಕೆಂಡ್ ಸಹ ಇದೆ, ಅದನ್ನು ಇಂಟರ್‌ಪ್ರಿಟರ್‌ನಿಂದ ತಕ್ಷಣವೇ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುತ್ತದೆ, ಆದರೆ ಈ ಸಮಯದಲ್ಲಿ ಅದನ್ನು ಬಳಸುವುದನ್ನು ತಪ್ಪಿಸಲು ನಾನು ನಿರ್ಧರಿಸಿದೆ. ಆದಾಗ್ಯೂ, QEMU ನಲ್ಲಿ ಕಾರ್ಯದ ಮೂಲಕ ರಚಿತವಾದ TB ಗೆ ಪರಿವರ್ತನೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಈಗಾಗಲೇ ಸಾಧ್ಯವಿದೆ. tcg_qemu_tb_exec, ಇದು ನನಗೆ ತುಂಬಾ ಉಪಯುಕ್ತವಾಗಿದೆ.

QEMU ಗೆ ಹೊಸ TCG ಬ್ಯಾಕೆಂಡ್ ಅನ್ನು ಸೇರಿಸಲು, ನೀವು ಉಪ ಡೈರೆಕ್ಟರಿಯನ್ನು ರಚಿಸಬೇಕಾಗಿದೆ tcg/<имя архитектуры> (ಈ ವಿಷಯದಲ್ಲಿ, tcg/binaryen), ಮತ್ತು ಇದು ಎರಡು ಫೈಲ್‌ಗಳನ್ನು ಒಳಗೊಂಡಿದೆ: tcg-target.h и tcg-target.inc.c и ಸೂಚಿಸಿ ಇದು ಎಲ್ಲಾ ಬಗ್ಗೆ configure. ನೀವು ಇತರ ಫೈಲ್‌ಗಳನ್ನು ಅಲ್ಲಿ ಇರಿಸಬಹುದು, ಆದರೆ, ಈ ಎರಡರ ಹೆಸರುಗಳಿಂದ ನೀವು ಊಹಿಸಬಹುದಾದಂತೆ, ಅವೆರಡನ್ನೂ ಎಲ್ಲೋ ಸೇರಿಸಲಾಗುತ್ತದೆ: ಒಂದು ಸಾಮಾನ್ಯ ಹೆಡರ್ ಫೈಲ್‌ನಂತೆ (ಇದನ್ನು ಸೇರಿಸಲಾಗಿದೆ tcg/tcg.h, ಮತ್ತು ಅದು ಈಗಾಗಲೇ ಡೈರೆಕ್ಟರಿಗಳಲ್ಲಿನ ಇತರ ಫೈಲ್‌ಗಳಲ್ಲಿದೆ tcg, accel ಮತ್ತು ಮಾತ್ರವಲ್ಲ), ಇನ್ನೊಂದು - ಕೋಡ್ ತುಣುಕಾಗಿ ಮಾತ್ರ tcg/tcg.c, ಆದರೆ ಇದು ಅದರ ಸ್ಥಿರ ಕಾರ್ಯಗಳಿಗೆ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿದೆ.

ಇದು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ವಿವರವಾದ ತನಿಖೆಗಳಲ್ಲಿ ನಾನು ಹೆಚ್ಚು ಸಮಯವನ್ನು ಕಳೆಯುತ್ತೇನೆ ಎಂದು ನಿರ್ಧರಿಸಿ, ನಾನು ಈ ಎರಡು ಫೈಲ್‌ಗಳ "ಅಸ್ಥಿಪಂಜರಗಳನ್ನು" ಮತ್ತೊಂದು ಬ್ಯಾಕೆಂಡ್ ಅನುಷ್ಠಾನದಿಂದ ಸರಳವಾಗಿ ನಕಲಿಸಿದ್ದೇನೆ, ಇದನ್ನು ಪರವಾನಗಿ ಹೆಡರ್‌ನಲ್ಲಿ ಪ್ರಾಮಾಣಿಕವಾಗಿ ಸೂಚಿಸುತ್ತದೆ.

ಕಡತ tcg-target.h ರೂಪದಲ್ಲಿ ಮುಖ್ಯವಾಗಿ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಒಳಗೊಂಡಿದೆ #define-ಗಳು:

  • ಟಾರ್ಗೆಟ್ ಆರ್ಕಿಟೆಕ್ಚರ್‌ನಲ್ಲಿ ಎಷ್ಟು ರೆಜಿಸ್ಟರ್‌ಗಳು ಮತ್ತು ಎಷ್ಟು ಅಗಲವಿದೆ (ನಮಗೆ ಬೇಕಾದಷ್ಟು, ನಮಗೆ ಬೇಕಾದಷ್ಟು ಇವೆ - "ಸಂಪೂರ್ಣವಾಗಿ ಗುರಿಪಡಿಸಿದ" ಆರ್ಕಿಟೆಕ್ಚರ್‌ನಲ್ಲಿ ಬ್ರೌಸರ್‌ನಿಂದ ಹೆಚ್ಚು ಪರಿಣಾಮಕಾರಿ ಕೋಡ್‌ಗೆ ಏನನ್ನು ರಚಿಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ಪ್ರಶ್ನೆ ಹೆಚ್ಚು ...)
  • ಹೋಸ್ಟ್ ಸೂಚನೆಗಳ ಜೋಡಣೆ: x86 ನಲ್ಲಿ, ಮತ್ತು TCI ಯಲ್ಲಿಯೂ ಸಹ, ಸೂಚನೆಗಳನ್ನು ಜೋಡಿಸಲಾಗಿಲ್ಲ, ಆದರೆ ನಾನು ಕೋಡ್ ಬಫರ್‌ನಲ್ಲಿ ಸೂಚನೆಗಳನ್ನು ಹಾಕಲು ಹೋಗುತ್ತೇನೆ, ಆದರೆ ಬೈನಾರೆನ್ ಲೈಬ್ರರಿ ರಚನೆಗಳಿಗೆ ಪಾಯಿಂಟರ್‌ಗಳನ್ನು ಹಾಕುತ್ತೇನೆ, ಆದ್ದರಿಂದ ನಾನು ಹೇಳುತ್ತೇನೆ: 4 ಬೈಟ್‌ಗಳು
  • ಬ್ಯಾಕೆಂಡ್ ಯಾವ ಐಚ್ಛಿಕ ಸೂಚನೆಗಳನ್ನು ರಚಿಸಬಹುದು - ನಾವು ಬೈನಾರಿನ್‌ನಲ್ಲಿ ಕಾಣುವ ಎಲ್ಲವನ್ನೂ ಸೇರಿಸುತ್ತೇವೆ, ವೇಗವರ್ಧಕವು ಉಳಿದವುಗಳನ್ನು ಸರಳವಾದವುಗಳಾಗಿ ಒಡೆಯುತ್ತದೆ
  • ಬ್ಯಾಕೆಂಡ್‌ನಿಂದ ವಿನಂತಿಸಲಾದ TLB ಸಂಗ್ರಹದ ಅಂದಾಜು ಗಾತ್ರ ಎಷ್ಟು. ಸತ್ಯವೆಂದರೆ QEMU ನಲ್ಲಿ ಎಲ್ಲವೂ ಗಂಭೀರವಾಗಿದೆ: ಅತಿಥಿ MMU ಅನ್ನು ಗಣನೆಗೆ ತೆಗೆದುಕೊಂಡು ಲೋಡ್/ಸ್ಟೋರ್ ಅನ್ನು ನಿರ್ವಹಿಸುವ ಸಹಾಯಕ ಕಾರ್ಯಗಳಿದ್ದರೂ (ನಾವು ಈಗ ಅದು ಇಲ್ಲದೆ ಎಲ್ಲಿದ್ದೇವೆ?), ಅವರು ತಮ್ಮ ಅನುವಾದ ಸಂಗ್ರಹವನ್ನು ರಚನೆಯ ರೂಪದಲ್ಲಿ ಉಳಿಸುತ್ತಾರೆ, ಇದರ ಸಂಸ್ಕರಣೆಯು ನೇರವಾಗಿ ಪ್ರಸಾರ ಬ್ಲಾಕ್‌ಗಳಲ್ಲಿ ಎಂಬೆಡ್ ಮಾಡಲು ಅನುಕೂಲಕರವಾಗಿದೆ. ಪ್ರಶ್ನೆಯೆಂದರೆ, ಈ ರಚನೆಯಲ್ಲಿ ಯಾವ ಆಫ್‌ಸೆಟ್ ಅನ್ನು ಸಣ್ಣ ಮತ್ತು ವೇಗದ ಆಜ್ಞೆಗಳ ಅನುಕ್ರಮದಿಂದ ಹೆಚ್ಚು ಪರಿಣಾಮಕಾರಿಯಾಗಿ ಸಂಸ್ಕರಿಸಲಾಗುತ್ತದೆ?
  • ಇಲ್ಲಿ ನೀವು ಒಂದು ಅಥವಾ ಎರಡು ಕಾಯ್ದಿರಿಸಿದ ರೆಜಿಸ್ಟರ್‌ಗಳ ಉದ್ದೇಶವನ್ನು ತಿರುಚಬಹುದು, ಒಂದು ಫಂಕ್ಷನ್ ಮೂಲಕ TB ಗೆ ಕರೆ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು ಮತ್ತು ಐಚ್ಛಿಕವಾಗಿ ಒಂದೆರಡು ಚಿಕ್ಕದನ್ನು ವಿವರಿಸಬಹುದು inline- ಮುಂತಾದ ಕಾರ್ಯಗಳು flush_icache_range (ಆದರೆ ಇದು ನಮ್ಮ ಪ್ರಕರಣವಲ್ಲ)

ಕಡತ tcg-target.inc.c, ಸಹಜವಾಗಿ, ಸಾಮಾನ್ಯವಾಗಿ ಗಾತ್ರದಲ್ಲಿ ಹೆಚ್ಚು ದೊಡ್ಡದಾಗಿದೆ ಮತ್ತು ಹಲವಾರು ಕಡ್ಡಾಯ ಕಾರ್ಯಗಳನ್ನು ಒಳಗೊಂಡಿದೆ:

  • ಪ್ರಾರಂಭಿಕತೆ, ಯಾವ ಸೂಚನೆಗಳು ಯಾವ ಆಪರೇಂಡ್‌ಗಳಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸಬಹುದು ಎಂಬ ನಿರ್ಬಂಧಗಳನ್ನು ಒಳಗೊಂಡಂತೆ. ಬೇರೊಂದು ಬ್ಯಾಕೆಂಡ್‌ನಿಂದ ನನ್ನಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ನಕಲಿಸಲಾಗಿದೆ
  • ಒಂದು ಆಂತರಿಕ ಬೈಟ್‌ಕೋಡ್ ಸೂಚನೆಯನ್ನು ತೆಗೆದುಕೊಳ್ಳುವ ಕಾರ್ಯ
  • ನೀವು ಇಲ್ಲಿ ಸಹಾಯಕ ಕಾರ್ಯಗಳನ್ನು ಸಹ ಹಾಕಬಹುದು ಮತ್ತು ನೀವು ಸ್ಥಿರ ಕಾರ್ಯಗಳನ್ನು ಸಹ ಬಳಸಬಹುದು tcg/tcg.c

ನನಗಾಗಿ, ನಾನು ಈ ಕೆಳಗಿನ ತಂತ್ರವನ್ನು ಆರಿಸಿಕೊಂಡಿದ್ದೇನೆ: ಮುಂದಿನ ಅನುವಾದ ಬ್ಲಾಕ್ನ ಮೊದಲ ಪದಗಳಲ್ಲಿ, ನಾನು ನಾಲ್ಕು ಪಾಯಿಂಟರ್ಗಳನ್ನು ಬರೆದಿದ್ದೇನೆ: ಪ್ರಾರಂಭದ ಗುರುತು (ಸಮೀಪದಲ್ಲಿ ಒಂದು ನಿರ್ದಿಷ್ಟ ಮೌಲ್ಯ 0xFFFFFFFF, ಇದು TB ಯ ಪ್ರಸ್ತುತ ಸ್ಥಿತಿಯನ್ನು ನಿರ್ಧರಿಸುತ್ತದೆ), ಸಂದರ್ಭ, ರಚಿಸಲಾದ ಮಾಡ್ಯೂಲ್ ಮತ್ತು ಡೀಬಗ್ ಮಾಡಲು ಮ್ಯಾಜಿಕ್ ಸಂಖ್ಯೆ. ಮೊದಲಿಗೆ ಗುರುತು ಹಾಕಲಾಯಿತು 0xFFFFFFFF - nಅಲ್ಲಿ n - ಒಂದು ಸಣ್ಣ ಧನಾತ್ಮಕ ಸಂಖ್ಯೆ, ಮತ್ತು ಪ್ರತಿ ಬಾರಿ ಅದನ್ನು ಇಂಟರ್ಪ್ರಿಟರ್ ಮೂಲಕ ಕಾರ್ಯಗತಗೊಳಿಸಿದಾಗ ಅದು 1 ರಿಂದ ಹೆಚ್ಚಾಗುತ್ತದೆ. ಅದು ತಲುಪಿದಾಗ 0xFFFFFFFE, ಸಂಕಲನ ನಡೆಯಿತು, ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಫಂಕ್ಷನ್ ಟೇಬಲ್‌ನಲ್ಲಿ ಉಳಿಸಲಾಗಿದೆ, ಸಣ್ಣ "ಲಾಂಚರ್" ಗೆ ಆಮದು ಮಾಡಿಕೊಳ್ಳಲಾಗಿದೆ, ಅದರೊಳಗೆ ಮರಣದಂಡನೆ ಹೋಯಿತು tcg_qemu_tb_exec, ಮತ್ತು ಮಾಡ್ಯೂಲ್ ಅನ್ನು QEMU ಮೆಮೊರಿಯಿಂದ ತೆಗೆದುಹಾಕಲಾಗಿದೆ.

ಕ್ಲಾಸಿಕ್ಸ್ ಅನ್ನು ಪ್ಯಾರಾಫ್ರೇಸ್ ಮಾಡಲು, "ಊರುಗೋಲು, ಪ್ರೊಗರ್ನ ಹೃದಯಕ್ಕೆ ಈ ಧ್ವನಿಯಲ್ಲಿ ಎಷ್ಟು ಹೆಣೆದುಕೊಂಡಿದೆ ...". ಆದರೆ, ನೆನಪು ಎಲ್ಲೋ ಸೋರುತ್ತಿತ್ತು. ಇದಲ್ಲದೆ, ಇದು QEMU ನಿಂದ ನಿರ್ವಹಿಸಲ್ಪಟ್ಟ ಮೆಮೊರಿಯಾಗಿದೆ! ನಾನು ಕೋಡ್ ಅನ್ನು ಹೊಂದಿದ್ದೇನೆ, ಮುಂದಿನ ಸೂಚನೆಯನ್ನು ಬರೆಯುವಾಗ (ಅಂದರೆ, ಅಂದರೆ, ಪಾಯಿಂಟರ್), ಈ ಹಿಂದೆ ಈ ಸ್ಥಳದಲ್ಲಿ ಲಿಂಕ್ ಇರುವದನ್ನು ಅಳಿಸಿದೆ, ಆದರೆ ಇದು ಸಹಾಯ ಮಾಡಲಿಲ್ಲ. ವಾಸ್ತವವಾಗಿ, ಸರಳವಾದ ಸಂದರ್ಭದಲ್ಲಿ, QEMU ಪ್ರಾರಂಭದಲ್ಲಿ ಮೆಮೊರಿಯನ್ನು ನಿಯೋಜಿಸುತ್ತದೆ ಮತ್ತು ಅಲ್ಲಿ ರಚಿಸಿದ ಕೋಡ್ ಅನ್ನು ಬರೆಯುತ್ತದೆ. ಬಫರ್ ಖಾಲಿಯಾದಾಗ, ಕೋಡ್ ಅನ್ನು ಹೊರಹಾಕಲಾಗುತ್ತದೆ ಮತ್ತು ಮುಂದಿನದನ್ನು ಅದರ ಸ್ಥಳದಲ್ಲಿ ಬರೆಯಲು ಪ್ರಾರಂಭಿಸುತ್ತದೆ.

ಕೋಡ್ ಅನ್ನು ಅಧ್ಯಯನ ಮಾಡಿದ ನಂತರ, ಮ್ಯಾಜಿಕ್ ನಂಬರ್‌ನೊಂದಿಗಿನ ಟ್ರಿಕ್ ಮೊದಲ ಪಾಸ್‌ನಲ್ಲಿ ಏನಾದರೂ ತಪ್ಪಾದ ಬಫರ್ ಅನ್ನು ಮುಕ್ತಗೊಳಿಸುವ ಮೂಲಕ ರಾಶಿ ವಿನಾಶದಲ್ಲಿ ವಿಫಲವಾಗದಿರಲು ನನಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಟ್ಟಿತು ಎಂದು ನಾನು ಅರಿತುಕೊಂಡೆ. ಆದರೆ ನಂತರ ನನ್ನ ಕಾರ್ಯವನ್ನು ಬೈಪಾಸ್ ಮಾಡಲು ಬಫರ್ ಅನ್ನು ಯಾರು ಪುನಃ ಬರೆಯುತ್ತಾರೆ? ಎಂಸ್ಕ್ರಿಪ್ಟನ್ ಡೆವಲಪರ್‌ಗಳು ಸಲಹೆ ನೀಡಿದಂತೆ, ನಾನು ಸಮಸ್ಯೆಗೆ ಸಿಲುಕಿದಾಗ, ನಾನು ಫಲಿತಾಂಶದ ಕೋಡ್ ಅನ್ನು ಸ್ಥಳೀಯ ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಹಿಂತಿರುಗಿಸಿದೆ, ಅದರ ಮೇಲೆ ಮೊಜಿಲ್ಲಾ ರೆಕಾರ್ಡ್-ರಿಪ್ಲೇ ಅನ್ನು ಹೊಂದಿಸಿ... ಸಾಮಾನ್ಯವಾಗಿ, ಕೊನೆಯಲ್ಲಿ ನಾನು ಸರಳವಾದ ವಿಷಯವನ್ನು ಅರಿತುಕೊಂಡೆ: ಪ್ರತಿ ಬ್ಲಾಕ್‌ಗೆ, ಎ struct TranslationBlock ಅದರ ವಿವರಣೆಯೊಂದಿಗೆ. ಎಲ್ಲಿ ಊಹಿಸಿ... ಅದು ಸರಿ, ಬಫರ್‌ನಲ್ಲಿನ ಬ್ಲಾಕ್‌ಗೆ ಸ್ವಲ್ಪ ಮೊದಲು. ಇದನ್ನು ಅರಿತುಕೊಂಡು, ನಾನು ಊರುಗೋಲನ್ನು (ಕನಿಷ್ಠ ಕೆಲವು) ಬಳಸುವುದನ್ನು ಬಿಡಲು ನಿರ್ಧರಿಸಿದೆ ಮತ್ತು ಮ್ಯಾಜಿಕ್ ಸಂಖ್ಯೆಯನ್ನು ಸರಳವಾಗಿ ಎಸೆದಿದ್ದೇನೆ ಮತ್ತು ಉಳಿದ ಪದಗಳನ್ನು ವರ್ಗಾಯಿಸಿದೆ struct TranslationBlock, ಅನುವಾದ ಸಂಗ್ರಹವನ್ನು ಮರುಹೊಂದಿಸಿದಾಗ ತ್ವರಿತವಾಗಿ ಚಲಿಸಬಹುದಾದ ಏಕ ಲಿಂಕ್ ಪಟ್ಟಿಯನ್ನು ರಚಿಸುವುದು ಮತ್ತು ಮೆಮೊರಿಯನ್ನು ಮುಕ್ತಗೊಳಿಸುವುದು.

ಕೆಲವು ಊರುಗೋಲುಗಳು ಉಳಿದಿವೆ: ಉದಾಹರಣೆಗೆ, ಕೋಡ್ ಬಫರ್‌ನಲ್ಲಿ ಗುರುತಿಸಲಾದ ಪಾಯಿಂಟರ್‌ಗಳು - ಅವುಗಳಲ್ಲಿ ಕೆಲವು ಸರಳವಾಗಿರುತ್ತವೆ BinaryenExpressionRef, ಅಂದರೆ, ಅವರು ರಚಿಸಲಾದ ಮೂಲ ಬ್ಲಾಕ್‌ಗೆ ರೇಖೀಯವಾಗಿ ಇರಿಸಬೇಕಾದ ಅಭಿವ್ಯಕ್ತಿಗಳನ್ನು ನೋಡುತ್ತಾರೆ, ಭಾಗವು BB ಗಳ ನಡುವಿನ ಪರಿವರ್ತನೆಯ ಸ್ಥಿತಿಯಾಗಿದೆ, ಭಾಗವು ಎಲ್ಲಿಗೆ ಹೋಗಬೇಕು. ಸರಿ, ರಿಲೂಪರ್‌ಗಾಗಿ ಈಗಾಗಲೇ ಸಿದ್ಧಪಡಿಸಲಾದ ಬ್ಲಾಕ್‌ಗಳು ಇವೆ, ಅದು ಷರತ್ತುಗಳ ಪ್ರಕಾರ ಸಂಪರ್ಕಿಸಬೇಕಾಗಿದೆ. ಅವುಗಳನ್ನು ಪ್ರತ್ಯೇಕಿಸಲು, ಅವೆಲ್ಲವನ್ನೂ ಕನಿಷ್ಠ ನಾಲ್ಕು ಬೈಟ್‌ಗಳಿಂದ ಜೋಡಿಸಲಾಗಿದೆ ಎಂಬ ಊಹೆಯನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಆದ್ದರಿಂದ ನೀವು ಲೇಬಲ್‌ಗಾಗಿ ಕನಿಷ್ಠ ಎರಡು ಬಿಟ್‌ಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಬಳಸಬಹುದು, ಅಗತ್ಯವಿದ್ದರೆ ಅದನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ನೆನಪಿಟ್ಟುಕೊಳ್ಳಬೇಕು. ಮೂಲಕ, TCG ಲೂಪ್‌ನಿಂದ ನಿರ್ಗಮಿಸುವ ಕಾರಣವನ್ನು ಸೂಚಿಸಲು ಅಂತಹ ಲೇಬಲ್‌ಗಳನ್ನು ಈಗಾಗಲೇ QEMU ನಲ್ಲಿ ಬಳಸಲಾಗುತ್ತದೆ.

ಬೈನಾರೆನ್ ಅನ್ನು ಬಳಸುವುದು

WebAssembly ನಲ್ಲಿರುವ ಮಾಡ್ಯೂಲ್‌ಗಳು ಕಾರ್ಯಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತವೆ, ಪ್ರತಿಯೊಂದೂ ಒಂದು ದೇಹವನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ, ಅದು ಅಭಿವ್ಯಕ್ತಿಯಾಗಿದೆ. ಅಭಿವ್ಯಕ್ತಿಗಳು ಯುನರಿ ಮತ್ತು ಬೈನರಿ ಕಾರ್ಯಾಚರಣೆಗಳು, ಇತರ ಅಭಿವ್ಯಕ್ತಿಗಳ ಪಟ್ಟಿಗಳನ್ನು ಒಳಗೊಂಡಿರುವ ಬ್ಲಾಕ್ಗಳು, ನಿಯಂತ್ರಣ ಹರಿವು, ಇತ್ಯಾದಿ. ನಾನು ಈಗಾಗಲೇ ಹೇಳಿದಂತೆ, ಇಲ್ಲಿ ನಿಯಂತ್ರಣ ಹರಿವು ಉನ್ನತ ಮಟ್ಟದ ಶಾಖೆಗಳು, ಕುಣಿಕೆಗಳು, ಕಾರ್ಯ ಕರೆಗಳು, ಇತ್ಯಾದಿಯಾಗಿ ನಿಖರವಾಗಿ ಆಯೋಜಿಸಲಾಗಿದೆ. ಕಾರ್ಯಗಳಿಗೆ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳನ್ನು ಸ್ಟಾಕ್‌ನಲ್ಲಿ ರವಾನಿಸಲಾಗುವುದಿಲ್ಲ, ಆದರೆ JS ನಲ್ಲಿರುವಂತೆ ಸ್ಪಷ್ಟವಾಗಿ. ಜಾಗತಿಕ ಅಸ್ಥಿರಗಳು ಸಹ ಇವೆ, ಆದರೆ ನಾನು ಅವುಗಳನ್ನು ಬಳಸಿಲ್ಲ, ಆದ್ದರಿಂದ ನಾನು ಅವುಗಳ ಬಗ್ಗೆ ನಿಮಗೆ ಹೇಳುವುದಿಲ್ಲ.

ಕಾರ್ಯಗಳು ಸ್ಥಳೀಯ ವೇರಿಯಬಲ್‌ಗಳನ್ನು ಹೊಂದಿವೆ, ಸೊನ್ನೆಯಿಂದ ಸಂಖ್ಯೆ, ಪ್ರಕಾರದ: int32 / int64 / float / double. ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಮೊದಲ n ಸ್ಥಳೀಯ ವೇರಿಯಬಲ್‌ಗಳು ಕಾರ್ಯಕ್ಕೆ ರವಾನಿಸಲಾದ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳಾಗಿವೆ. ನಿಯಂತ್ರಣ ಹರಿವಿನ ವಿಷಯದಲ್ಲಿ ಇಲ್ಲಿರುವ ಎಲ್ಲವೂ ಸಂಪೂರ್ಣವಾಗಿ ಕೆಳಮಟ್ಟದಲ್ಲಿಲ್ಲದಿದ್ದರೂ, ಪೂರ್ಣಾಂಕಗಳು ಇನ್ನೂ "ಸಹಿ/ಸಹಿ ಮಾಡದ" ಗುಣಲಕ್ಷಣವನ್ನು ಹೊಂದಿರುವುದಿಲ್ಲ: ಸಂಖ್ಯೆಯು ಹೇಗೆ ವರ್ತಿಸುತ್ತದೆ ಎಂಬುದು ಕಾರ್ಯಾಚರಣೆಯ ಕೋಡ್ ಅನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ.

ಸಾಮಾನ್ಯವಾಗಿ ಹೇಳುವುದಾದರೆ, Binaryen ಒದಗಿಸುತ್ತದೆ ಸರಳ C-API: ನೀವು ಮಾಡ್ಯೂಲ್ ಅನ್ನು ರಚಿಸುತ್ತೀರಿ, ಅವನಲ್ಲಿ ಅಭಿವ್ಯಕ್ತಿಗಳನ್ನು ರಚಿಸಿ - ಯುನರಿ, ಬೈನರಿ, ಇತರ ಅಭಿವ್ಯಕ್ತಿಗಳಿಂದ ಬ್ಲಾಕ್ಗಳು, ನಿಯಂತ್ರಣ ಹರಿವು, ಇತ್ಯಾದಿ. ನಂತರ ನೀವು ಅದರ ದೇಹವಾಗಿ ಅಭಿವ್ಯಕ್ತಿಯೊಂದಿಗೆ ಕಾರ್ಯವನ್ನು ರಚಿಸುತ್ತೀರಿ. ನೀವು, ನನ್ನಂತೆ, ಕಡಿಮೆ ಮಟ್ಟದ ಪರಿವರ್ತನೆಯ ಗ್ರಾಫ್ ಹೊಂದಿದ್ದರೆ, ರಿಲೂಪರ್ ಘಟಕವು ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ. ನಾನು ಅರ್ಥಮಾಡಿಕೊಂಡಂತೆ, ಒಂದು ಬ್ಲಾಕ್‌ನಲ್ಲಿನ ಮರಣದಂಡನೆಯ ಹರಿವಿನ ಉನ್ನತ ಮಟ್ಟದ ನಿಯಂತ್ರಣವನ್ನು ಬಳಸಲು ಸಾಧ್ಯವಿದೆ, ಅದು ಬ್ಲಾಕ್‌ನ ಗಡಿಗಳನ್ನು ಮೀರಿ ಹೋಗುವುದಿಲ್ಲ - ಅಂದರೆ, ಆಂತರಿಕ ವೇಗದ ಮಾರ್ಗವನ್ನು / ನಿಧಾನಗೊಳಿಸಲು ಸಾಧ್ಯವಿದೆ ಅಂತರ್ನಿರ್ಮಿತ TLB ಸಂಗ್ರಹ ಸಂಸ್ಕರಣಾ ಕೋಡ್ ಒಳಗೆ ಕವಲೊಡೆಯುವ ಮಾರ್ಗ, ಆದರೆ "ಬಾಹ್ಯ" ನಿಯಂತ್ರಣ ಹರಿವಿನೊಂದಿಗೆ ಮಧ್ಯಪ್ರವೇಶಿಸುವುದಿಲ್ಲ . ನೀವು ರಿಲೂಪರ್ ಅನ್ನು ಮುಕ್ತಗೊಳಿಸಿದಾಗ, ಅದರ ಬ್ಲಾಕ್ಗಳನ್ನು ಮುಕ್ತಗೊಳಿಸಲಾಗುತ್ತದೆ; ನೀವು ಮಾಡ್ಯೂಲ್ ಅನ್ನು ಮುಕ್ತಗೊಳಿಸಿದಾಗ, ಅದಕ್ಕೆ ನಿಯೋಜಿಸಲಾದ ಅಭಿವ್ಯಕ್ತಿಗಳು, ಕಾರ್ಯಗಳು, ಇತ್ಯಾದಿಗಳು ಕಣ್ಮರೆಯಾಗುತ್ತವೆ. ರಂಗ.

ಆದಾಗ್ಯೂ, ನೀವು ಹಾರಾಟದಲ್ಲಿ ಕೋಡ್ ಅನ್ನು ಅನಗತ್ಯವಾಗಿ ರಚಿಸದೆ ಮತ್ತು ಇಂಟರ್ಪ್ರಿಟರ್ ನಿದರ್ಶನವನ್ನು ಅಳಿಸಲು ಬಯಸಿದರೆ, ಈ ತರ್ಕವನ್ನು C++ ಫೈಲ್‌ಗೆ ಹಾಕಲು ಇದು ಅರ್ಥಪೂರ್ಣವಾಗಬಹುದು ಮತ್ತು ಅಲ್ಲಿಂದ ನೇರವಾಗಿ ಲೈಬ್ರರಿಯ ಸಂಪೂರ್ಣ C++ API ಅನ್ನು ನಿರ್ವಹಿಸಿ, ಸಿದ್ಧ- ಹೊದಿಕೆಗಳನ್ನು ಮಾಡಿದರು.

ಆದ್ದರಿಂದ ನಿಮಗೆ ಅಗತ್ಯವಿರುವ ಕೋಡ್ ಅನ್ನು ರಚಿಸಲು

// настроить глобальные параметры (можно поменять потом)
BinaryenSetAPITracing(0);

BinaryenSetOptimizeLevel(3);
BinaryenSetShrinkLevel(2);

// создать модуль
BinaryenModuleRef MODULE = BinaryenModuleCreate();

// описать типы функций (как создаваемых, так и вызываемых)
helper_type  BinaryenAddFunctionType(MODULE, "helper-func", BinaryenTypeInt32(), int32_helper_args, ARRAY_SIZE(int32_helper_args));
// (int23_helper_args приоб^Wсоздаются отдельно)

// сконструировать супер-мега выражение
// ... ну тут уж вы как-нибудь сами :)

// потом создать функцию
BinaryenAddFunction(MODULE, "tb_fun", tb_func_type, func_locals, FUNC_LOCALS_COUNT, expr);
BinaryenAddFunctionExport(MODULE, "tb_fun", "tb_fun");
...
BinaryenSetMemory(MODULE, (1 << 15) - 1, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
BinaryenAddMemoryImport(MODULE, NULL, "env", "memory", 0);
BinaryenAddTableImport(MODULE, NULL, "env", "tb_funcs");

// запросить валидацию и оптимизацию при желании
assert (BinaryenModuleValidate(MODULE));
BinaryenModuleOptimize(MODULE);

... ನಾನು ಏನನ್ನಾದರೂ ಮರೆತಿದ್ದರೆ, ಕ್ಷಮಿಸಿ, ಇದು ಪ್ರಮಾಣವನ್ನು ಪ್ರತಿನಿಧಿಸಲು ಮತ್ತು ವಿವರಗಳು ದಾಖಲಾತಿಯಲ್ಲಿವೆ.

ಮತ್ತು ಈಗ ಕ್ರ್ಯಾಕ್-ಫೆಕ್ಸ್-ಪೆಕ್ಸ್ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ, ಈ ರೀತಿ:

static char buf[1 << 20];
BinaryenModuleOptimize(MODULE);
BinaryenSetMemory(MODULE, 0, -1, NULL, NULL, NULL, NULL, NULL, 0, 0);
int sz = BinaryenModuleWrite(MODULE, buf, sizeof(buf));
BinaryenModuleDispose(MODULE);
EM_ASM({
  var module = new WebAssembly.Module(new Uint8Array(wasmMemory.buffer, $0, $1));
  var fptr = $2;
  var instance = new WebAssembly.Instance(module, {
      'env': {
          'memory': wasmMemory,
          // ...
      }
  );
  // и вот уже у вас есть instance!
}, buf, sz);

QEMU ಮತ್ತು JS ನ ಪ್ರಪಂಚಗಳನ್ನು ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಮತ್ತು ಅದೇ ಸಮಯದಲ್ಲಿ ಕಂಪೈಲ್ ಮಾಡಿದ ಕಾರ್ಯಗಳನ್ನು ತ್ವರಿತವಾಗಿ ಪ್ರವೇಶಿಸಲು, ಒಂದು ಶ್ರೇಣಿಯನ್ನು ರಚಿಸಲಾಗಿದೆ (ಲಾಂಚರ್‌ಗೆ ಆಮದು ಮಾಡಲು ಕಾರ್ಯಗಳ ಕೋಷ್ಟಕ), ಮತ್ತು ರಚಿಸಿದ ಕಾರ್ಯಗಳನ್ನು ಅಲ್ಲಿ ಇರಿಸಲಾಗಿದೆ. ಸೂಚ್ಯಂಕವನ್ನು ತ್ವರಿತವಾಗಿ ಲೆಕ್ಕಾಚಾರ ಮಾಡಲು, ಶೂನ್ಯ ಪದ ಅನುವಾದ ಬ್ಲಾಕ್‌ನ ಸೂಚ್ಯಂಕವನ್ನು ಆರಂಭದಲ್ಲಿ ಬಳಸಲಾಗುತ್ತಿತ್ತು, ಆದರೆ ನಂತರ ಈ ಸೂತ್ರವನ್ನು ಬಳಸಿಕೊಂಡು ಲೆಕ್ಕಾಚಾರ ಮಾಡಿದ ಸೂಚ್ಯಂಕವು ಕ್ಷೇತ್ರಕ್ಕೆ ಸರಳವಾಗಿ ಹೊಂದಿಕೊಳ್ಳಲು ಪ್ರಾರಂಭಿಸಿತು. struct TranslationBlock.

ಮೂಲಕ, ಡೆಮೊ (ಪ್ರಸ್ತುತ ಮರ್ಕಿ ಪರವಾನಗಿಯೊಂದಿಗೆ) Firefox ನಲ್ಲಿ ಮಾತ್ರ ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಕ್ರೋಮ್ ಡೆವಲಪರ್‌ಗಳಾಗಿದ್ದರು ಹೇಗಾದರೂ ಸಿದ್ಧವಾಗಿಲ್ಲ ಯಾರಾದರೂ WebAssembly ಮಾಡ್ಯೂಲ್‌ಗಳ ಸಾವಿರಕ್ಕೂ ಹೆಚ್ಚು ನಿದರ್ಶನಗಳನ್ನು ರಚಿಸಲು ಬಯಸುತ್ತಾರೆ ಎಂಬ ಅಂಶಕ್ಕೆ, ಆದ್ದರಿಂದ ಅವರು ಪ್ರತಿಯೊಂದಕ್ಕೂ ಒಂದು ಗಿಗಾಬೈಟ್ ವರ್ಚುವಲ್ ವಿಳಾಸ ಜಾಗವನ್ನು ನಿಗದಿಪಡಿಸಿದ್ದಾರೆ...

ಈಗ ಅಷ್ಟೆ. ಯಾರಾದರೂ ಆಸಕ್ತಿ ಹೊಂದಿದ್ದರೆ ಬಹುಶಃ ಇನ್ನೊಂದು ಲೇಖನ ಇರುತ್ತದೆ. ಅವುಗಳೆಂದರೆ, ಕನಿಷ್ಠ ಉಳಿದಿದೆ ಕೇವಲ ಬ್ಲಾಕ್ ಸಾಧನಗಳು ಕಾರ್ಯನಿರ್ವಹಿಸುವಂತೆ ಮಾಡಿ. JS ಪ್ರಪಂಚದಲ್ಲಿ ರೂಢಿಯಲ್ಲಿರುವಂತೆ WebAssembly ಮಾಡ್ಯೂಲ್‌ಗಳ ಸಂಕಲನವನ್ನು ಅಸಮಕಾಲಿಕವಾಗಿಸಲು ಇದು ಅರ್ಥಪೂರ್ಣವಾಗಿರಬಹುದು, ಏಕೆಂದರೆ ಸ್ಥಳೀಯ ಮಾಡ್ಯೂಲ್ ಸಿದ್ಧವಾಗುವವರೆಗೆ ಇದನ್ನೆಲ್ಲ ಮಾಡಬಹುದಾದ ಇಂಟರ್ಪ್ರಿಟರ್ ಇನ್ನೂ ಇದೆ.

ಅಂತಿಮವಾಗಿ ಒಂದು ಒಗಟು: ನೀವು 32-ಬಿಟ್ ಆರ್ಕಿಟೆಕ್ಚರ್‌ನಲ್ಲಿ ಬೈನರಿಯನ್ನು ಸಂಕಲಿಸಿದ್ದೀರಿ, ಆದರೆ ಕೋಡ್, ಮೆಮೊರಿ ಕಾರ್ಯಾಚರಣೆಗಳ ಮೂಲಕ, ಬೈನರಿನ್‌ನಿಂದ, ಎಲ್ಲೋ ಸ್ಟಾಕ್‌ನಲ್ಲಿ ಅಥವಾ 2-ಬಿಟ್ ವಿಳಾಸದ ಜಾಗದ ಮೇಲಿನ 32 GB ಯಲ್ಲಿ ಬೇರೆಡೆ ಏರುತ್ತದೆ. ಸಮಸ್ಯೆಯೆಂದರೆ ಬೈನಾರೆನ್ ಅವರ ದೃಷ್ಟಿಕೋನದಿಂದ ಇದು ತುಂಬಾ ದೊಡ್ಡ ಫಲಿತಾಂಶದ ವಿಳಾಸವನ್ನು ಪ್ರವೇಶಿಸುತ್ತಿದೆ. ಇದನ್ನು ಹೇಗೆ ಸುತ್ತುವುದು?

ನಿರ್ವಾಹಕರ ರೀತಿಯಲ್ಲಿ

ನಾನು ಇದನ್ನು ಪರೀಕ್ಷಿಸುವುದನ್ನು ಕೊನೆಗೊಳಿಸಲಿಲ್ಲ, ಆದರೆ ನನ್ನ ಮೊದಲ ಆಲೋಚನೆಯು "ನಾನು 32-ಬಿಟ್ ಲಿನಕ್ಸ್ ಅನ್ನು ಸ್ಥಾಪಿಸಿದರೆ ಏನು?" ನಂತರ ವಿಳಾಸದ ಜಾಗದ ಮೇಲಿನ ಭಾಗವನ್ನು ಕರ್ನಲ್ ಆಕ್ರಮಿಸುತ್ತದೆ. ಎಷ್ಟು ಆಕ್ರಮಿಸಲಾಗುವುದು ಎಂಬುದು ಒಂದೇ ಪ್ರಶ್ನೆ: 1 ಅಥವಾ 2 ಜಿಬಿ.

ಪ್ರೋಗ್ರಾಮರ್ ರೀತಿಯಲ್ಲಿ (ಅಭ್ಯಾಸ ಮಾಡುವವರಿಗೆ ಆಯ್ಕೆ)

ವಿಳಾಸದ ಜಾಗದ ಮೇಲ್ಭಾಗದಲ್ಲಿ ಒಂದು ಗುಳ್ಳೆಯನ್ನು ಸ್ಫೋಟಿಸೋಣ. ಅದು ಏಕೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ ಎಂದು ನನಗೆ ಅರ್ಥವಾಗುತ್ತಿಲ್ಲ - ಅಲ್ಲಿ ಈಗಾಗಲೇ ಒಂದು ಸ್ಟಾಕ್ ಇರಬೇಕು. ಆದರೆ "ನಾವು ಅಭ್ಯಾಸಕಾರರು: ಎಲ್ಲವೂ ನಮಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ, ಆದರೆ ಏಕೆ ಎಂದು ಯಾರಿಗೂ ತಿಳಿದಿಲ್ಲ ..."

// 2gbubble.c
// Usage: LD_PRELOAD=2gbubble.so <program>

#include <sys/mman.h>
#include <assert.h>

void __attribute__((constructor)) constr(void)
{
  assert(MAP_FAILED != mmap(1u >> 31, (1u >> 31) - (1u >> 20), PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
}

... ಇದು Valgrind ಗೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ ಎಂಬುದು ನಿಜ, ಆದರೆ, ಅದೃಷ್ಟವಶಾತ್, Valgrind ಸ್ವತಃ ಎಲ್ಲರನ್ನು ಅಲ್ಲಿಂದ ಹೊರಗೆ ತಳ್ಳುತ್ತದೆ :)

ಬಹುಶಃ ನನ್ನ ಈ ಕೋಡ್ ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ಯಾರಾದರೂ ಉತ್ತಮ ವಿವರಣೆಯನ್ನು ನೀಡುತ್ತಾರೆ ...

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ