Reduced the size of instruction names array by 2kB by merging shorter names into longer names.

This commit is contained in:
kobalicek
2015-06-20 20:50:55 +02:00
parent 7259dc3f45
commit 4dbaf70c31
2 changed files with 1267 additions and 1463 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,10 @@
// by a linker to make all pointers the binary application/library uses valid. // by a linker to make all pointers the binary application/library uses valid.
// This approach decreases the final size of AsmJit binary and relocation data. // This approach decreases the final size of AsmJit binary and relocation data.
"use strict";
var fs = require("fs"); var fs = require("fs");
var hasOwn = Object.prototype.hasOwnProperty;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// [Utilities] // [Utilities]
@@ -42,73 +45,182 @@ function inject(s, start, end, code) {
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// [Database] // [IndexedString]
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
var Database = (function() { var IndexedString = function() {
// `IndexedString` class.
var IndexedString = function() {
this.array = [];
this.index = 0;
this.map = {}; this.map = {};
}; this.size = -1;
this.array = [];
};
IndexedString.prototype.add = function(s) { IndexedString.prototype.add = function(s) {
var index = this.map[s]; this.map[s] = -1;
};
if (typeof index === "number") IndexedString.prototype.index = function() {
return index; var map = this.map;
var array = this.array;
index = this.index; var partialMap = {};
this.array.push(s); var k, kp;
this.index += s.length + 1; var i, len;
this.map[s] = index;
return index;
};
IndexedString.prototype.get = function(s) { // Create a map that will contain all keys and partial keys.
return this.map[s]; for (k in map) {
}; if (!k) {
partialMap[k] = k;
}
else {
for (i = 0, len = k.length; i < len; i++) {
var kp = k.substr(i);
if (!hasOwn.call(partialMap, kp) || partialMap[kp].length < len)
partialMap[kp] = k;
}
}
}
// Create an array that will only contain keys that are needed.
for (k in map) {
if (partialMap[k] === k)
array.push(k);
}
array.sort();
// Create valid offsets to the `array`.
var offMap = {};
var offset = 0;
for (i = 0, len = array.length; i < len; i++) {
k = array[i];
offMap[k] = offset;
offset += k.length + 1;
}
this.size = offset;
// Assign valid offsets to `map`.
for (kp in map) {
k = partialMap[kp];
map[kp] = offMap[k] + k.length - kp.length;
}
/*
(function() {
// Testing code to experiment with eliminating suffixes from instruction names.
var suffixList = [
"ss", "ps", "sd", "pd",
"bw", "bd", "bq",
"ww", "wd", "wq",
"dq", "b", "w", "d", "q"
];
var reducedMap = {};
var reducedSize = 0;
var xMap = {};
var xArr = [];
for (i = 0, len = array.length; i < len; i++) {
k = array[i];
var suffix = null;
var after = k;
for (var j = 0; j < suffixList.length; j++) {
suffix = suffixList[j];
if (k.lastIndexOf(suffix) === k.length - suffix.length) {
after = k.substr(0, k.length - suffix.length);
break;
}
}
reducedMap[after] = true;
}
// Testing code to get which suffixes are the most used.
for (k in map) {
for (i = 1; i < k.length; i++) {
var xKey = k.substr(i);
if (hasOwn.call(xMap, xKey)) {
xMap[xKey]++;
}
else {
xMap[xKey] = 1;
xArr.push(xKey);
}
}
}
xArr.sort(function(a, b) {
return xMap[a] - xMap[b];
});
for (i = 0; i < xArr.length; i++) {
console.log(xArr[i] + " " + xMap[xArr[i]]);
}
for (k in reducedMap)
reducedSize += k.length + 1;
console.log("ReducedSize=" + reducedSize);
})();
*/
};
IndexedString.prototype.format = function(indent) {
if (this.size === -1)
throw new Error("IndexedString not indexed yet, call index()");
IndexedString.prototype.format = function(indent) {
var s = ""; var s = "";
var array = this.array; var array = this.array;
for (var i = 0; i < array.length; i++) { for (var i = 0; i < array.length; i++) {
s += indent + "\"" + array[i] + "\\0\""; s += indent + "\"" + array[i];
if (i === array.length - 1) s += (i !== array.length - 1) ? "\\0\"" : "\";";
s += ";";
s += "\n"; s += "\n";
} }
return s; return s;
}; };
IndexedString.prototype.getSize = function() { IndexedString.prototype.getSize = function() {
return this.index; if (this.size === -1)
}; throw new Error("IndexedString not indexed yet, call index()");
return this.size;
};
// `Database` class. IndexedString.prototype.getIndex = function(k) {
var Database = function() { if (this.size === -1)
throw new Error("IndexedString not indexed yet, call index()");
if (!hasOwn.call(this.map, k))
throw new Error("Key '" + k + "' not found in IndexedString.");
return this.map[k];
};
// ----------------------------------------------------------------------------
// [Database]
// ----------------------------------------------------------------------------
var Database = function() {
this.instMap = {}; this.instMap = {};
this.instNames = new IndexedString(); this.instNames = new IndexedString();
this.instAlpha = new Array(26); this.instAlpha = new Array(26);
this.extendedData = []; this.extendedData = [];
this.extendedMap = {}; this.extendedMap = {};
}; };
Database.prototype.add = function(name, id, extendedData) { Database.prototype.add = function(name, id, extendedData) {
this.instMap[name] = { this.instMap[name] = {
id : id, // Instruction ID. id : id, // Instruction ID.
nameIndex : 0, // Instruction name-index, used directly by AsmJit. nameIndex : -1, // Instruction name-index.
vPrefix : 0, // Instruction starts with 'v', not used at this point.
extendedData : extendedData, extendedData : extendedData,
extendedIndex : "" extendedIndex : ""
}; };
}; this.instNames.add(name);
};
Database.prototype.index = function() { Database.prototype.index = function() {
var instMap = this.instMap; var instMap = this.instMap;
var instNames = this.instNames; var instNames = this.instNames;
var instAlpha = this.instAlpha; var instAlpha = this.instAlpha;
@@ -116,10 +228,12 @@ var Database = (function() {
var extendedData = this.extendedData; var extendedData = this.extendedData;
var extendedMap = this.extendedMap; var extendedMap = this.extendedMap;
instNames.index();
for (var name in instMap) { for (var name in instMap) {
var inst = instMap[name]; var inst = instMap[name];
var nameIndex = instNames.add(name); var nameIndex = instNames.getIndex(name);
var extendedIndex = extendedMap[inst.extendedData]; var extendedIndex = extendedMap[inst.extendedData];
if (typeof extendedIndex !== "number") { if (typeof extendedIndex !== "number") {
@@ -137,15 +251,8 @@ var Database = (function() {
if (instAlpha[aIndex] === undefined) if (instAlpha[aIndex] === undefined)
instAlpha[aIndex] = inst.id; instAlpha[aIndex] = inst.id;
if (name.indexOf("v") === 0) {
inst.vPrefix = 1;
} }
} };
};
return Database;
})();
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// [Generate] // [Generate]
@@ -271,15 +378,11 @@ var generate = function(fileName, arch) {
code += disclaimer; code += disclaimer;
code += "#if !defined(ASMJIT_DISABLE_NAMES)\n"; code += "#if !defined(ASMJIT_DISABLE_NAMES)\n";
code += "const char _" + arch + "InstName[] =\n"; code += "const char _" + arch + "InstName[] =\n";
for (k in db.instMap) { code += db.instNames.format(" ") + "\n";
var inst = db.instMap[k];
code += " \"" + k + "\\0\"\n";
}
code = code.substr(code, code.length - 1) + ";\n\n";
// Generate AlphaIndex. // Generate AlphaIndex.
code += disclaimer; code += disclaimer;
code += "enum k" + Arch + "InstAlphaIndex {\n"; code += "enum " + Arch + "InstAlphaIndex {\n";
code += " k" + Arch + "InstAlphaIndexFirst = 'a',\n"; code += " k" + Arch + "InstAlphaIndexFirst = 'a',\n";
code += " k" + Arch + "InstAlphaIndexLast = 'z',\n"; code += " k" + Arch + "InstAlphaIndexLast = 'z',\n";
code += " k" + Arch + "InstAlphaIndexInvalid = 0xFFFF\n"; code += " k" + Arch + "InstAlphaIndexInvalid = 0xFFFF\n";
@@ -299,7 +402,7 @@ var generate = function(fileName, arch) {
// Generate NameIndex. // Generate NameIndex.
code += disclaimer; code += disclaimer;
code += "enum k" + Arch + "InstData_NameIndex {\n"; code += "enum " + Arch + "InstData_NameIndex {\n";
for (k in db.instMap) { for (k in db.instMap) {
var inst = db.instMap[k]; var inst = db.instMap[k];
code += " " + inst.id + "_NameIndex = " + inst.nameIndex + ",\n"; code += " " + inst.id + "_NameIndex = " + inst.nameIndex + ",\n";
@@ -321,7 +424,7 @@ var generate = function(fileName, arch) {
code += "\n"; code += "\n";
code += disclaimer; code += disclaimer;
code += "enum k" + Arch + "InstData_ExtendedIndex {\n"; code += "enum " + Arch + "InstData_ExtendedIndex {\n";
for (k in db.instMap) { for (k in db.instMap) {
var inst = db.instMap[k]; var inst = db.instMap[k];
code += " " + inst.id + "_ExtendedIndex = " + inst.extendedIndex + ",\n"; code += " " + inst.id + "_ExtendedIndex = " + inst.extendedIndex + ",\n";