Compatibility with save/restore in previous releases

Unfortunately, it has not been possible to retain the semantics of save/[1,2] available in previous releases of Quintus Prolog. This is regrettable because it means that programs that incorporate code for building saved-states will need to be changed. This section explains why it was necessary to remove these predicates. Note, however, that save_program/1 is available and has the same semantics as previous releases (except for foreign code), although it is based on a new implementation using QOF files. A new predicate save_program/2, described in ref-sls-sst, has been provided, which supports the most common usage of save/[1,2], which was to specify an initial goal for a saved-state to call when run.

The difference between save_program/1 and save/[1,2] in previous releases of Quintus Prolog was that save_program/1 saved only the Prolog database, whereas save/[1,2] saved both the Prolog database and the Prolog execution stacks. It has not been possible to retain the saving of the Prolog execution stacks in a way consistent with the release 3 support of embeddability and the general portability of QOF files. This is why save/[1,2] have been removed. The reasoning goes as follows:

  1. QOF files are a completely portable machine-independent representation of Prolog data.
  2. It is difficult, if not impossible, to make the Prolog execution state portable in the same way as facts and rules in QOF files (see further points).
  3. QOF files can also be combined and loaded in flexible ways, and it is unclear what this would mean for execution states.
  4. The QOF file saved-states do not save any C (or other foreign language) state. This is a change from the previous Quintus Prolog saved-states, and is further discussed below.
  5. In the general case, Prolog execution can now be arbitrarily interleaved with C (or other) function calls since Prolog and C are completely intercallable and can call each other recursively.
  6. Since the C state is not saved, it is not possible to meaningfully save the Prolog execution state in the general case where it depends on interleaved C execution state.
  7. In addition, Prolog code embedded in a C (or other) application is highly likely to be manipulating C data, such as pointers and other process-specific information. This data would be meaningless if restored into another process, and indeed would be likely to cause faults.

The model that an arbitrary Prolog execution state can be saved thus only works well within a Prolog-only situation. In the complex embedded environments supported by Quintus Prolog release 3 this model cannot work properly. Hence the removal of the facility.

As mentioned in points 4-7 above, an additional important aspect here is that Prolog no longer makes any attempt to save the state of C (or other foreign language) code. This was a feature of saved-states in previous releases where both the C code and its data structures were saved (as a memory image) into saved-states. This was a feature that caused many problems. A primary problem was that the saved C state was initialized (variables retained their values when restored) and yet the initialized C state could contain many items that were no longer valid in the new process, such as addresses and file descriptors. Such code would often fail when restored. In addition, Prolog was unable to guarantee that it had saved all the necessary foreign code state. With the advent of shared libraries and other complex memory management facilities in the operating system, it became impossible for Prolog to control and manage the states of other tools in the address space.

When one takes a step back and looks at Prolog in the light of the goals of release 3 (see int-hig) -- where Prolog code is a component that can be embedded in complex applications written in many languages -- it is clearly unreasonable for Prolog to try and control, let alone save, arbitrary non-Prolog state. The Prolog operations for saving and loading QOF files now operate solely on the Prolog database and these operations do not involve making any assumptions about non-Prolog state. This is a much cleaner and more robust approach, and is the most appropriate when Prolog applications become embedded software components.