ContextFactory.observeInstructionCount() not always called consistently in interpreted mode



10 years ago
9 years ago


(Reporter: David Parks, Assigned: Norris Boyd)





10 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/2008092417 Firefox/3.0.3
Build Identifier: 1.7R2-RC1

It is possible for scripts to execute indefinitely while never calling the observeInstructionCount method when running in interpreted mode.

This script is one such case:

var i = 0; function x(){ while (true) i++; } x();

Reproducible: Always

Steps to Reproduce:
I made a simple update to ObserveInstructionCountTest to demonstrate the issue.

Replace line 74 with the following line:
var i = 0; function x(){ while (true) i++; } x();

Copy and paste source code is also included below, simply run this TestCase. The only change from the included ObserveInstructionCount class is the input script (line 74) in which I wrapped a function around the while(true) i++; statement.


package org.mozilla.javascript.tests;

import junit.framework.TestCase;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.ContextFactory;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Callable;

 * @author Norris Boyd
public class ObserveInstructionCountTest_Fail extends TestCase {
    // Custom Context to store execution time.
    static class MyContext extends Context {
        MyContext(ContextFactory factory) {
        int quota;

    static class QuotaExceeded extends RuntimeException {

    static {
        ContextFactory.initGlobal(new MyFactory());

    static class MyFactory extends ContextFactory {

        protected Context makeContext()
            MyContext cx = new MyContext(this);
            // Make Rhino runtime call observeInstructionCount
            // each 500 bytecode instructions (if we're really enforcing
            // a quota of 2000, we could set this closer to 2000)
            return cx;

        protected void observeInstructionCount(Context cx, int instructionCount)
            MyContext mcx = (MyContext)cx;
            mcx.quota -= instructionCount;
            if (mcx.quota <= 0) {
                throw new QuotaExceeded();

        protected Object doTopCall(Callable callable,
                                   Context cx, Scriptable scope,
                                   Scriptable thisObj, Object[] args)
            MyContext mcx = (MyContext)cx;
            mcx.quota = 2000;
            return super.doTopCall(callable, cx, scope, thisObj, args);

    private void baseCase(int optimizationLevel) {
        ContextFactory factory = new MyFactory();
        Context cx = factory.enterContext();
        assertTrue(cx instanceof MyContext);
        try {
            Scriptable globalScope = cx.initStandardObjects();
                    "var i = 0; function x(){ while (true) i++; } x();",        //This line is the only update to the original test case
//                    "var i = 0; while (true) i++;",                           //Original test case code
                    "test source", 1, null);
        } catch (QuotaExceeded e) {
            // expected
        } catch (RuntimeException e) {
        } finally {

    public void testInterpreted() {
        baseCase(-1); // interpreted mode

    public void testCompiled() {
        baseCase(1); // compiled mode
Actual Results:  
Script will execute indefinitely even though the test case is set up to exit after a certain # of instructions.

Expected Results:  
The only difference in this test case is the input script. This test case should function just like ObserveInstructionCountTest and exit the script after counting ~2000 instructions.

Note: compiled mode works as expected, only when the optimization level is set to -1 does it fail.

Perhaps I don't understand the limitations of this function, however based on the javadocs example (essentially the same as the test case), I don't believe an end user would be able to know that this function has limitations in interpreted mode.

If these limitations are part of the design then they should be documented.


9 years ago
Assignee: nobody → norrisboyd

Comment 1

9 years ago
I can't reproduce this problem. When I change the test case as this bug describes, the test still executes successfully. This is using the latest CVS source. 

I'll check in a new version of the unit test that tests both the current and new cases.

Comment 2

9 years ago
Last Resolved: 9 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.