[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/WhyNot135/daScript/master/src/runtime/context.cpp [Back]  [Original]

#include "daScript/simulate/simulate.h"
#include "daScript/ast/ast.h"
#include "daScript/misc/fpe.h"

#include 

namespace das
{
    // Context
    std::recursive_mutex g_DebugAgentMutex;
    das_safe_map   g_DebugAgents;
    static DAS_THREAD_LOCAL(bool) g_isInDebugAgentCreation;
    extern atomic g_envTotal;

    template 
    void on_debug_agent_mutex ( const TT & lmbd ) {
        std::lock_guard guard(g_DebugAgentMutex);
        lmbd ();
    }

    template 
    void for_each_debug_agent ( const TT & lmbd ) {
        if ( g_envTotal > 0 && *daScriptEnvironment::g_threadLocalDebugAgent && (*daScriptEnvironment::g_threadLocalDebugAgent)->debugAgent ) {
            lmbd ( (*daScriptEnvironment::g_threadLocalDebugAgent)->debugAgent );
        }
        std::lock_guard guard(g_DebugAgentMutex);
        for ( auto & it : g_DebugAgents ) {
            if ( !it.second.debugAgent ) continue;
            lmbd ( it.second.debugAgent );
        }
    }

    void dapiReportContextState ( Context & ctx, const char * category, const char * name, const TypeInfo * info, void * data ) {
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onVariable(&ctx,category,name,(TypeInfo*)info,data);
        });
    }

    void dapiSimulateContext ( Context & ctx ) {
        for_each_debug_agent([&]( const DebugAgentPtr & pAgent ){
            pAgent->onSimulateContext(&ctx);
        });
    }

    void dapiUserCommand ( const char * command ) {
        if ( !command ) command = "";
        bool any = false;
        for_each_debug_agent([&]( const DebugAgentPtr & pAgent ){
            if ( !any ) any = pAgent->onUserCommand(command);
        });
    }

    void dapiOnBeforeGC ( Context & ctx ) {
        for_each_debug_agent([&]( const DebugAgentPtr & pAgent ){
            pAgent->onBeforeGC(&ctx);
        });
    }

    void dapiOnAfterGC ( Context & ctx ) {
        for_each_debug_agent([&]( const DebugAgentPtr & pAgent ){
            pAgent->onAfterGC(&ctx);
        });
    }

    Context::Context(uint32_t stackSize, bool ph) : stack(stackSize) {
        ref_count_magic = TRACK_PTR_CONTEXT;
        code = make_shared();
        constStringHeap = make_shared();
        debugInfo = make_shared();
        ownStack = (stackSize != 0);
        persistent = ph;
    }

    void Context::setup(int totalVars, uint32_t globalStringHeapSize, CodeOfPolicies policies, AnnotationArgumentList options) {
        verySafeContext = options.getBoolOption("very_safe_context",policies.very_safe_context);
        breakOnException |= policies.debugger;
        gcEnabled = options.getBoolOption("gc", false);
        gcLogTime = options.getBoolOption("log_gc_time", policies.log_gc_time);
        persistent = options.getBoolOption("persistent_heap", policies.persistent_heap);
        if ( persistent ) {
            heap = make_unique();
            stringHeap = make_unique();
        } else {
            heap = make_unique();
            stringHeap = make_unique();
        }
        heap->setInitialSize ( options.getIntOption("heap_size_hint", policies.heap_size_hint) );
        heap->setLimit ( options.getUInt64OptionEx("heap_size_limit", "max_heap_allocated", policies.max_heap_allocated) );
        stringHeap->setInitialSize ( options.getIntOption("string_heap_size_hint", policies.string_heap_size_hint) );
        stringHeap->setLimit ( options.getUInt64OptionEx("string_heap_size_limit", "max_string_heap_allocated", policies.max_string_heap_allocated) );
        bool track = options.getBoolOption("track_allocations", policies.track_allocations);
        heap->setTrackAllocations(track);
        stringHeap->setTrackAllocations(track);
        constStringHeap = make_shared();
        totalVariables = totalVars;
        if ( globalStringHeapSize ) {
            constStringHeap->setInitialSize(globalStringHeapSize);
        }
        globalVariables = (GlobalVariable *) code->allocate( uint32_t(totalVars*sizeof(GlobalVariable)) );
        globalsSize = 0;
        sharedSize = 0;
    }

    void Context::strip() {
        stringHeap.reset();
        heap.reset();
        stack.strip();
        if ( globals && globalsOwner ) {
            das_aligned_free16(globals);
            globals = nullptr;
        }
        if ( shared && sharedOwner ) {
            das_aligned_free16(shared);
            shared = nullptr;
        }
    }

    void Context::logMemInfo(TextWriter & tw) {
        uint64_t bytesTotal = 0, bytesUsed = 0;
    // context
        tw eval(*this);
#if DAS_ENABLE_STACK_WALK
                        pp->info = nullptr;
#endif
                    }
                }
            }
        }
        abiArg = nullptr;
        stack.pop(EP,SP);
        // run init functions
        for ( int j=0, js=totalInitFunctions; j!=js && !stopFlags; ++j ) {
            auto & pf = initFunctions[j];
            callOrFastcall(pf, nullptr, 0);
        }
        // now, share the data
        if ( sharedOwner && shared ) {
            SharedDataWalker sdw;
            for ( int i=0, is=totalVariables; i!=is; ++i ) {
                auto & pv = globalVariables[i];
                if ( pv.init && pv.shared ) {
                    sdw.walk(shared + pv.offset, pv.debugInfo);
                }
            }
        }
    }

    bool Context::runShutdownScript ( ) {
        DAS_ASSERTF(insideContext==0,"can't run init script on the locked context");
        if ( shutdown ) return false;
        shutdown = true;
        auto ssz = 16384 + globalInitStackSize;
        StackAllocator init_stack(ssz);
        SharedStackGuard guard(*this, init_stack);
        return runWithCatch([&](){
            vector lateShutdown;
            for ( int j=0, js=totalFunctions; j!=js && !stopFlags; ++j ) {
                auto & pf = functions[j];
                DAS_ASSERTF(pf.debugInfo, "Missing debug info for %s", pf.name);
                if ( pf.debugInfo->flags & FuncInfo::flag_shutdown ) {
                    if ( pf.debugInfo->flags & FuncInfo::flag_late_shutdown ) {
                        lateShutdown.push_back(&pf);
                    } else {
                        callOrFastcall(&pf, nullptr, 0);
                    }
                }
            }
            if ( !stopFlags && !lateShutdown.empty() ) {
                for ( auto pf : lateShutdown ) {
                    callOrFastcall(pf, nullptr, 0);
                    if ( stopFlags ) break;
                }
            }
        });
    }

    vector Context::findFunctions ( const char * fnname ) const {
        vector res;
        for ( auto & kv : *tabMnLookup ) {
            auto fn = kv.second;
            if ( fn!=nullptr && strcmp(fn->name, fnname)==0 ) {
                res.push_back(fn);
            }
        }
        return res;
    }

    SimFunction * Context::findFunction ( const char * fnname ) const {
        for ( auto & kv : *tabMnLookup ) {
            auto fn = kv.second;
            if ( fn!=nullptr && strcmp(fn->name, fnname)==0 ) {
                return fn;
            }
        }
        return nullptr;
    }

    SimFunction * Context::findFunction ( const char * fnname, bool & isUnique ) const {
        int candidates = 0;
        SimFunction * found = nullptr;
        for ( auto & kv : *tabMnLookup ) {
            auto fn = kv.second;
            if ( fn!=nullptr && strcmp(fn->name, fnname)==0 ) {
                found = fn;
                candidates++;
            }
        }
        isUnique = candidates == 1;
        return found;
    }

    int Context::findVariable ( const char * fnname ) const {
        for ( int vni=0, vnis=totalVariables; vni!=vnis; ++vni ) {
            if ( strcmp(globalVariables[vni].name, fnname)==0 ) {
                return vni;
            }
        }
        return -1;
    }

    void Context::stackWalk( const LineInfo * at, bool showArguments, bool showLocalVariables ) {
        auto str = getStackWalk(at, showArguments, showLocalVariables);
        to_out(at, str.c_str());
    }

    class StackWalkerTextWriter : public StackWalker {
    public:
        StackWalkerTextWriter ( TextWriter & tw, Context * ctx ) : ssw(tw), context(ctx) {}
        virtual bool canWalkArguments () override {
            return showArguments;
        }
        virtual bool canWalkVariables () override {
            return showLocalVariables;
        }
        virtual bool canWalkOutOfScopeVariables() override {
            return showOutOfScope;
        }
        virtual void onCallAOT ( Prologue *, const char * fileName ) override {
            ssw   " : "\n    ");
                }
            } else {
                if ( row>=ROW-3 && rowdebugAgent ) {
            (*daScriptEnvironment::g_threadLocalDebugAgent)->debugAgent->onInstrumentFunction(this, sim, entering, userData);
        }
    }

    void Context::instrumentFunctionCallback ( SimFunction * sim, bool entering, uint64_t userData ) {
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onInstrumentFunction(this, sim, entering, userData);
        });
    }

    void Context::bpcallback( const LineInfo & at ) {
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onSingleStep(this, at);
        });
    }

    void Context::runVisitor ( SimVisitor * vis ) const {
        for ( int gvi=0, gvis=totalVariables; gvi!=gvis; ++gvi ) {
            const auto & gv = globalVariables[gvi];
            if ( gv.init ) gv.init->visit(*vis);
        }
        for ( int fni=0, fnis=totalFunctions; fni!=fnis; ++fni ) {
            const auto & fn = functions[fni];
            if ( fn.code ) fn.code->visit(*vis);
        }
    }

    void Context::onAllocateString ( void * ptr, uint64_t size, bool tempString, const LineInfo & at ) {
        if ( g_envTotal == 0 ) return;
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onAllocateString(this, ptr, size, tempString, at);
        });
    }

    void Context::onFreeString ( void * ptr, bool tempString, const LineInfo & at ) {
        if ( g_envTotal == 0 ) return;
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onFreeString(this, ptr, tempString, at);
        });
    }

    void Context::onAllocate ( void * ptr, uint64_t size, const LineInfo & at ) {
        if ( g_envTotal == 0 ) return;
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onAllocate(this, ptr, size, at);
        });
    }

    void Context::onReallocate ( void * ptr, uint64_t size, void * newPtr, uint64_t newSize, const LineInfo & at ) {
        if ( g_envTotal == 0 ) return;
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onReallocate(this, ptr, size, newPtr, newSize, at);
        });
    }

    void Context::onFree ( void * ptr, const LineInfo & at ) {
        if ( g_envTotal == 0 ) return;
        for_each_debug_agent([&](const DebugAgentPtr & pAgent){
            pAgent->onFree(this, ptr, at);
        });
    }

}

Web Proxy Viewer  |  New URL  |  Original Page