Skip to content

Commit

Permalink
Merge pull request #1658 from clasp-developers/snapshot-cleanup
Browse files Browse the repository at this point in the history
Snapshot cleanup
  • Loading branch information
Bike authored Jan 14, 2025
2 parents 976dbc4 + 1c66161 commit 117ff63
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 1,312 deletions.
14 changes: 0 additions & 14 deletions include/clasp/core/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,20 +209,6 @@ class ExitProgramException : public std::exception {
int getExitResult() { return this->_ExitResult; };
};

typedef enum { undef, stomp, noStomp, testStomp } ForwardingEnum;


struct SaveLispAndDie {
string _FileName;
bool _Executable;
string _LibDir;
bool _Exit; // Set to true unless debugging
ForwardingEnum _ForwardingKind;
bool _TestMemory;
SaveLispAndDie(const std::string& filename, bool executable, const std::string& libDir, bool ep=true, ForwardingEnum fk=noStomp, bool tm=true)
: _FileName(filename), _Executable(executable), _LibDir(libDir), _Exit(ep), _ForwardingKind(fk), _TestMemory(tm) {};
};

/*! To exit the program throw this exception
*/
class TerminateProgramIfBatch {
Expand Down
104 changes: 40 additions & 64 deletions include/clasp/gctools/gcalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,33 @@ template <class Stage, class Cons> struct ConsAllocator {
}; // namespace gctools

namespace gctools {
template <class OT>
static smart_ptr<OT> initialize_snapshot_object(Header_s* base, snapshotSaveLoad::snapshot_save_load_init_s* init) {
// transfer the badge
base->_badge_stamp_wtag_mtag._header_badge.store(init->_headStart->_badge_stamp_wtag_mtag._header_badge.load());
#ifdef DEBUG_GUARD
// Copy the source from the image save/load memory.
base->_source = snapshot_save_load_init->_headStart->_source;
#endif
OT* ptr = HeaderPtrToGeneralPtr<OT>(base);
#ifdef DEBUG_GUARD
uintptr_t guardBefore0 = *(uintptr_t*)((uintptr_t*)ptr - 1);
uintptr_t guardAfter0 = *(uintptr_t*)((uintptr_t*)((char*)ptr + sizeWithHeader - sizeof(Header_s)) + 1);
#endif
init->fill(ptr);
#ifdef DEBUG_GUARD
uintptr_t guardBefore1 = *(uintptr_t*)((uintptr_t*)ptr - 1);
uintptr_t guardAfter1 = *(uintptr_t*)((uintptr_t*)((char*)ptr + sizeWithHeader - sizeof(Header_s)) + 1);
if (guardBefore0 != guardBefore1) {
printf("%s:%d:%s We stomped on the memory before the object\n", __FILE__, __LINE__, __FUNCTION__);
}
if (guardAfter0 != guardAfter1) {
printf("%s:%d:%s We stomped on the memory after the object\n", __FILE__, __LINE__, __FUNCTION__);
}
#endif
return smart_ptr<OT>(ptr);
}

template <class OT, GCInfo_policy Policy = normal> struct GCObjectAppropriatePoolAllocator {
typedef OT value_type;
typedef OT* pointer_type;
Expand All @@ -176,31 +203,7 @@ template <class OT, GCInfo_policy Policy = normal> struct GCObjectAppropriatePoo
size_t sizeWithHeader = sizeof(Header_s) + (snapshot_save_load_init->_clientEnd - snapshot_save_load_init->_clientStart);
DO_DRAG_GENERAL_ALLOCATION();
Header_s* base = do_general_allocation(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, sizeWithHeader);
// transfer the badge
base->_badge_stamp_wtag_mtag._header_badge.store(
snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag._header_badge.load());
#ifdef DEBUG_GUARD
// Copy the source from the image save/load memory.
base->_source = snapshot_save_load_init->_headStart->_source;
#endif
pointer_type ptr = HeaderPtrToGeneralPtr<OT>(base);
#ifdef DEBUG_GUARD
uintptr_t guardBefore0 = *(uintptr_t*)((uintptr_t*)ptr - 1);
uintptr_t guardAfter0 = *(uintptr_t*)((uintptr_t*)((char*)ptr + sizeWithHeader - sizeof(Header_s)) + 1);
#endif
snapshot_save_load_init->fill(ptr);
#ifdef DEBUG_GUARD
uintptr_t guardBefore1 = *(uintptr_t*)((uintptr_t*)ptr - 1);
uintptr_t guardAfter1 = *(uintptr_t*)((uintptr_t*)((char*)ptr + sizeWithHeader - sizeof(Header_s)) + 1);
if (guardBefore0 != guardBefore1) {
printf("%s:%d:%s We stomped on the memory before the object\n", __FILE__, __LINE__, __FUNCTION__);
}
if (guardAfter0 != guardAfter1) {
printf("%s:%d:%s We stomped on the memory after the object\n", __FILE__, __LINE__, __FUNCTION__);
}
#endif
smart_pointer_type sp = smart_ptr<value_type>(ptr);
return sp;
return initialize_snapshot_object<OT>(base, snapshot_save_load_init);
};

static void deallocate(OT* memory){
Expand Down Expand Up @@ -228,20 +231,11 @@ template <class OT> struct GCObjectAppropriatePoolAllocator<OT, /* Policy= */ at
// so that the static analyzer has something to call
};

static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init,
size_t size) {
static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init) {
size_t sizeWithHeader = sizeof(Header_s) + (snapshot_save_load_init->_clientEnd - snapshot_save_load_init->_clientStart);
Header_s* base =
do_atomic_allocation<SnapshotLoadStage>(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, size);
#ifdef DEBUG_GUARD
// Copy the source from the image save/load memory.
base->_source = snapshot_save_load_init->_headStart->_source;
#endif
pointer_type ptr = HeaderPtrToGeneralPtr<OT>(base);
new (ptr) OT(snapshot_save_load_init);
printf("%s:%d:%s This is where we should copy in the stuff from the snapshot_save_load_init object\n", __FILE__, __LINE__,
__FUNCTION__);
smart_pointer_type sp = smart_ptr<value_type>(ptr);
return sp;
do_atomic_allocation<SnapshotLoadStage>(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, sizeWithHeader);
return initialize_snapshot_object<OT>(base, snapshot_save_load_init);
};
};

Expand All @@ -267,20 +261,11 @@ template <class OT> struct GCObjectAppropriatePoolAllocator<OT, /* Policy= */ co
// so that the static analyzer has something to call
};

static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init,
size_t size) {
static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init) {
size_t sizeWithHeader = sizeof(Header_s) + (snapshot_save_load_init->_clientEnd - snapshot_save_load_init->_clientStart);
DO_DRAG_GENERAL_ALLOCATION();
Header_s* base = do_general_allocation(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, size);
#ifdef DEBUG_GUARD
// Copy the source from the image save/load memory.
base->_source = snapshot_save_load_init->_headStart->_source;
#endif
pointer_type ptr = HeaderPtrToGeneralPtr<OT>(base);
new (ptr) OT(snapshot_save_load_init);
printf("%s:%d:%s This is where we should copy in the stuff from the snapshot_save_load_init object\n", __FILE__, __LINE__,
__FUNCTION__);
smart_pointer_type sp = smart_ptr<value_type>(ptr);
return sp;
Header_s* base = do_general_allocation(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, sizeWithHeader);
return initialize_snapshot_object<OT>(base, snapshot_save_load_init);
};
};

Expand All @@ -300,19 +285,10 @@ template <class OT> struct GCObjectAppropriatePoolAllocator<OT, unmanaged> {
return sp;
}

static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init,
size_t size) {
Header_s* base = do_uncollectable_allocation(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, size);
#ifdef DEBUG_GUARD
// Copy the source from the image save/load memory.
base->_source = snapshot_save_load_init->_headStart->_source;
#endif
pointer_type ptr = HeaderPtrToGeneralPtr<OT>(base);
new (ptr) OT(snapshot_save_load_init);
printf("%s:%d:%s This is where we should copy in the stuff from the snapshot_save_load_init object\n", __FILE__, __LINE__,
__FUNCTION__);
smart_pointer_type sp = smart_ptr<value_type>(ptr);
return sp;
static smart_pointer_type snapshot_save_load_allocate(snapshotSaveLoad::snapshot_save_load_init_s* snapshot_save_load_init) {
size_t sizeWithHeader = sizeof(Header_s) + (snapshot_save_load_init->_clientEnd - snapshot_save_load_init->_clientStart);
Header_s* base = do_uncollectable_allocation(snapshot_save_load_init->_headStart->_badge_stamp_wtag_mtag, sizeWithHeader);
return initialize_snapshot_object<OT>(base, snapshot_save_load_init);
};

static void deallocate(OT* memory) {
Expand Down
22 changes: 22 additions & 0 deletions include/clasp/gctools/snapshotSaveLoad.fwd.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <string>

/*
File: snapshotSaveLoad.h
*/
Expand All @@ -12,6 +14,26 @@ struct Fixup;

FixupOperation_ operation(Fixup* fixup);

// noStomp - forwarding uses a separate map of pointer -> forwarded-pointer.
// This is slow and is meant for snapshot_save and to facilitate debugging.
// stomp - The forwarding pointer is written into the pointer address.
// This is fast and is meant for snapshot_load
// testStomp - maintain a map of pointer -> forwarded-pointer AND write the forwarding
// pointer into the pointer address and compare the two on every operation.
// This is to test stomp.
enum class ForwardingEnum { stomp, noStomp, testStomp };

struct SaveLispAndDie {
std::string _FileName;
bool _Executable;
std::string _LibDir;
bool _Exit; // Set to true unless debugging
ForwardingEnum _ForwardingKind;
bool _TestMemory;
SaveLispAndDie(const std::string& filename, bool executable, const std::string& libDir, bool ep=true, ForwardingEnum fk=ForwardingEnum::noStomp, bool tm=true)
: _FileName(filename), _Executable(executable), _LibDir(libDir), _Exit(ep), _ForwardingKind(fk), _TestMemory(tm) {};
};

struct snapshot_save_load_init_s {
gctools::Header_s* _headStart;
gctools::clasp_ptr_t _clientStart; // include vtable
Expand Down
2 changes: 1 addition & 1 deletion include/clasp/gctools/snapshotSaveLoad.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ struct Fixup {
Fixup(const Fixup& fixup, uintptr_t memoryStart) : _memoryStart(memoryStart), _trackAddressName(true){};
};

void snapshot_save(core::SaveLispAndDie& data);
void snapshot_save(SaveLispAndDie& data);
void snapshot_load(void* maybeStartOfSnapshot, void* maybeEndOfSnapshot, const std::string& filename);

void clearLibraries();
Expand Down
4 changes: 0 additions & 4 deletions include/clasp/gctools/threadlocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ struct VirtualMachine {
#define IHS_BACKTRACE_SIZE 16
struct ThreadLocalState {

core::T_sp _ObjectFiles;
mp::Process_sp _Process;
DynamicBindingStack _Bindings;
std::atomic<core::Cons_sp> _PendingInterruptsHead;
Expand Down Expand Up @@ -328,9 +327,6 @@ struct ThreadLocalState {

uint32_t random();

llvmo::ObjectFile_sp topObjectFile();
void pushObjectFile(llvmo::ObjectFile_sp of);
void popObjectFile();
inline DynamicBindingStack& bindings() { return this->_Bindings; };

void startUpVM();
Expand Down
7 changes: 4 additions & 3 deletions include/clasp/llvmo/jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,17 @@ class ClaspJIT_O : public core::General_O {
core::T_sp lookup_all_dylibs(const std::string& Name);
JITDylib_sp getMainJITDylib();
JITDylib_sp createAndRegisterJITDylib(const std::string& name);
void registerJITDylibAfterLoad(JITDylib_O* jitDylib);
void registerJITDylibAfterLoad(JITDylib_sp jitDylib);

ObjectFile_sp addIRModule(JITDylib_sp dylib, Module_sp cM, ThreadSafeContext_sp context, size_t startupID);
ObjectFile_sp addObjectFile(JITDylib_sp dylib, std::unique_ptr<llvm::MemoryBuffer> objectFile, bool print, size_t startupId);
/*! Return a pointer to a function WHAT FUNCTION???????
llvm_sys__jitFinalizeReplFunction needs to build a closure over it
*/
void* runStartupCode(JITDylib_sp dylib, const std::string& startupName, core::T_sp initialDataOrUnbound);
ClaspJIT_O(bool loading, JITDylib_O* mainJITDylib);
~ClaspJIT_O();
void installMainJITDylib();
void adjustMainJITDylib(JITDylib_sp dylib);
ClaspJIT_O();

public:
JITDylib_sp _MainJITDylib;
Expand Down
2 changes: 0 additions & 2 deletions src/core/commandLineOptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,6 @@ Environment variables:
Dump info during bundle setup
CLASP_DEBUG_START_CODE
Dump info during startup for every start-code
CLASP_DEBUG_SNAPSHOT
Dump info during snapshot loading
CLASP_EXIT_ON_WAIT_FOR_USER_SIGNAL
Exit if wait-for-user-signal is encountered. Used for debugging under live-record.
CLASP_DEBUG_OBJECT_FILES=save
Expand Down
12 changes: 2 additions & 10 deletions src/core/compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1723,17 +1723,9 @@ void start_code_interpreter(gctools::GCRootsInModule* roots, char* bytecode, siz
#include <virtualMachine.h>
#undef DEFINE_LTV_SWITCH
default: {
std::string fasoFile = "NotFaso";
size_t fasoIndex = 0;
T_sp maybeObjectFile = my_thread->topObjectFile();
if (gc::IsA<llvmo::ObjectFile_sp>(maybeObjectFile)) {
llvmo::ObjectFile_sp objectFile = gc::As_unsafe<llvmo::ObjectFile_sp>(maybeObjectFile);
fasoFile = objectFile->_FasoName->get_std_string();
fasoIndex = objectFile->_FasoIndex;
}
SIMPLE_ERROR("While loading the faso file {} {} an illegal byte-code {} was detected. This usually happens when a faso file "
SIMPLE_ERROR("While loading a faso file an illegal byte-code {} was detected. This usually happens when a faso file "
"is out of date and the byte code has changed in the meantime.",
fasoFile, fasoIndex, (int)c);
(int)c);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/core/lispStream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4943,7 +4943,6 @@ void CFileStream_O::set_buffering_mode(T_sp mode) {
void CFileStream_O::fixupInternalsForSnapshotSaveLoad(snapshotSaveLoad::Fixup* fixup) {
if (snapshotSaveLoad::operation(fixup) == snapshotSaveLoad::LoadOp) {
std::string name = gc::As<String_sp>(_filename)->get_path_string();
T_sp stream = this->asSmartPtr();
if (name == "*STDIN*") {
_file = stdin;
} else if (name == "*STDOUT*") {
Expand Down
12 changes: 6 additions & 6 deletions src/gctools/gcFunctions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -456,10 +456,10 @@ The following &KEY arguments are defined:
Test memory prior to saving snapshot.
If NIL then snapshot saving is faster.)dx")
DOCGROUP(clasp);
CL_DEFUN void gctools__save_lisp_and_die(core::T_sp filename, core::T_sp executable, core::T_sp testMemory) {
CL_DEFUN void gctools__save_lisp_and_die(core::String_sp filename, bool executable, bool testMemory) {
#ifdef USE_PRECISE_GC
throw(core::SaveLispAndDie(gc::As<core::String_sp>(filename)->get_std_string(), executable.notnilp(),
globals_->_Bundle->_Directories->_LibDir, true, core::noStomp, testMemory.notnilp() ));
throw(snapshotSaveLoad::SaveLispAndDie(filename->get_std_string(), executable,
globals_->_Bundle->_Directories->_LibDir, true, snapshotSaveLoad::ForwardingEnum::noStomp, testMemory ));
#else
SIMPLE_ERROR("save-lisp-and-die only works for precise GC");
#endif
Expand All @@ -478,10 +478,10 @@ The following &KEY arguments are defined:
to create a standalone executable. If false (the default), the
snapshot will not be executable on its own.)dx")
DOCGROUP(clasp);
CL_DEFUN void gctools__save_lisp_and_continue(core::T_sp filename, core::T_sp executable) {
CL_DEFUN void gctools__save_lisp_and_continue(core::String_sp filename, bool executable) {
#ifdef USE_PRECISE_GC
core::SaveLispAndDie ee(gc::As<core::String_sp>(filename)->get_std_string(), executable.notnilp(),
globals_->_Bundle->_Directories->_LibDir, false );
snapshotSaveLoad::SaveLispAndDie ee(filename->get_std_string(), executable,
globals_->_Bundle->_Directories->_LibDir, false );
snapshotSaveLoad::snapshot_save(ee);
#else
SIMPLE_ERROR("save-lisp-and-continue only works for precise GC");
Expand Down
Loading

0 comments on commit 117ff63

Please sign in to comment.