// WARNING: the implementation of this method must be kept compatible with unsynchronizedEvaluate
  private final synchronized RTValue synchronizedEvaluate(RTExecutionContext ec)
      throws CALExecutorException {
    if (!LECCMachineConfiguration.nonInterruptibleRuntime() && ec.isQuitRequested()) {
      throw RTValue.INTERRUPT_EXCEPTION;
    }

    RTValue newResult = result == null ? this : result;
    RTValue lastResult;

    // do not repeatedly poll the SourceGenerationConfiguration settings in the most performance
    // important common case
    // where we are not generating any runtime statistics

    if (RTResultFunction.HAS_RUNTIME_STATS) {

      // Attempt to reduce this result
      do {
        if (LECCMachineConfiguration.generateStatistics()) {
          ec.incrementNReductions();
        }

        lastResult = newResult;
        newResult = newResult.synchronizedReduce(ec);

      } while (lastResult != newResult);

    } else {

      // Attempt to reduce this result
      do {
        lastResult = newResult;
        newResult = newResult.synchronizedReduce(ec);
      } while (lastResult != newResult);
    }

    if (newResult != this) {
      setResult(newResult);
    }

    return newResult;
  }