function thrower1(x) {
    throw x + 2;

    // Dead code, should be ignored.
    throw ++x;
    return x;
}
function test1() {
    // If we ever inline functions containing JSOP_THROW,
    // this shouldn't assert.
    function f(x) {
        thrower1(x + 1);
    }
    for (var i=0; i<11000; i++) {
        try {
            f(i);
            assertEq(0, 1);
        } catch(e) {
            assertEq(e, i + 3);
        }
    }
}
test1();

// Test throwing from an uncompilable (interpreted) function.
function getException(f) {
    try {
        f();
        assertEq(0, 1);
    } catch(e) {
        return e;
    }
    assertEq(0, 1);
}

function thrower2(x) {
    if (x > 90)
        throw x;
    with ({}) {}; // Abort compilation...(?)
}
function test2() {
    for (var i = 0; i < 100; i++) {
        thrower2(i);
    }
}
assertEq(getException(test2), 91);

// Throwing |this| from a constructor.
function thrower3(x) {
    this.x = x;
    if (x > 90)
        throw this;
}
function test3() {
    for (var i=0; i < 100; i++) {
        new thrower3(i);
    }
}
assertEq(getException(test3).x, 91);

// Throwing an exception in various loop blocks.
var count = 0;
function thrower4(x) {
    throw count++;
    count += 12345; // Shouldn't be executed.
}
function test4_1() {
    var i = 0;
    for (new thrower4(i); i < 100; i++) {
        count += 2000; // Shouldn't be executed.
    }
}
function test4_2() {
    for (var i = 0; thrower4(i); i++) {
	count += 3000; // Shouldn't be executed.
    }
}
function test4_3() {
    for (var i = 0; i < 100; thrower4(i)) {
	count += 5;
    }
}
function test4_4() {
    for (var i = 0; i < 10; i++) {
        if (i > 8)
            thrower4();
        count += i;
    }
}
for (var i = 0; i < 100; i++) {
    assertEq(getException(test4_1), count-1);
    assertEq(getException(test4_2), count-1);
    assertEq(getException(test4_3), count-1);
    assertEq(getException(test4_4), count-1);
}
assertEq(count, 4500);

function test5() {
    var res = 0;
    for (var i=0; i<40; i++) {
	try {
	    throw i;
	} catch (e if e % 2) {
	    res += e;
	} catch (e) {
	    res += e * 3;
	}
    }
    return res;
}
assertEq(test5(), 1540);
