private Object resume(Context cx, Scriptable scope, int operation,
                          Object value)
    {
        if (savedState == null) {
            if (operation == GENERATOR_CLOSE)
                return Undefined.instance;
            Object thrown;
            if (operation == GENERATOR_THROW) {
                thrown = value;
            } else {
                thrown = NativeIterator.getStopIterationObject(scope);
            }
            throw new JavaScriptException(thrown, lineSource, lineNumber);
        }
        try {
            synchronized (this) {
              // generator execution is necessarily single-threaded and
              // non-reentrant.
              // See https://bugzilla.mozilla.org/show_bug.cgi?id=349263
              if (locked)
                  throw ScriptRuntime.typeError0("msg.already.exec.gen");
              locked = true;
            }
            return function.resumeGenerator(cx, scope, operation, savedState,
                                            value);
        } catch (GeneratorClosedException e) {
            // On closing a generator in the compile path, the generator
            // throws a special exception. This ensures execution of all pending
            // finalizers and will not get caught by user code.
            return Undefined.instance;
        } catch (RhinoException e) {
            lineNumber = e.lineNumber();
            lineSource = e.lineSource();
            savedState = null;
            throw e;
        } finally {
            synchronized (this) {
              locked = false;
            }
            if (operation == GENERATOR_CLOSE)
                savedState = null;
        }
    }