Example #1
0
static void* attribute_align_arg worker(void *v)
{
    AVCodecContext *avctx = v;
    ThreadContext *c = avctx->thread_opaque;
    int our_job = c->job_count;
    int thread_count = avctx->thread_count;
    int self_id;

    pthread_mutex_lock(&c->current_job_lock);
    self_id = c->current_job++;
    for (;;){
        while (our_job >= c->job_count) {
            if (c->current_job == thread_count + c->job_count)
                pthread_cond_signal(&c->last_job_cond);

            pthread_cond_wait(&c->current_job_cond, &c->current_job_lock);
            our_job = self_id;

            if (c->done) {
                pthread_mutex_unlock(&c->current_job_lock);
                return NULL;
            }
        }
        pthread_mutex_unlock(&c->current_job_lock);

        c->rets[our_job%c->rets_count] = c->func ? c->func(avctx, (char*)c->args + our_job*c->job_size):
                                                   c->func2(avctx, c->args, our_job, self_id);

        pthread_mutex_lock(&c->current_job_lock);
        our_job = c->current_job++;
    }
}
Example #2
0
    BOOL DynamicObject::CallToPrimitiveFunction(Var toPrimitiveFunction, PropertyId propertyId, Var* result, ScriptContext * requestContext)
    {
        if (JavascriptConversion::IsCallable(toPrimitiveFunction))
        {
            RecyclableObject* toStringFunction = RecyclableObject::FromVar(toPrimitiveFunction);

            ThreadContext * threadContext = requestContext->GetThreadContext();
            Var aResult = threadContext->ExecuteImplicitCall(toStringFunction, ImplicitCall_ToPrimitive, [=]() -> Js::Var
            {
                // Stack object should have a pre-op bail on implicit call.  We shouldn't see them here.
                Assert(!ThreadContext::IsOnStack(this) || threadContext->HasNoSideEffect(toStringFunction));
                return toStringFunction->GetEntryPoint()(toStringFunction, CallInfo(CallFlags_Value, 1), this);
            });
 
            if (!aResult)
            {
                // There was an implicit call and implicit calls are disabled. This would typically cause a bailout.
                Assert(threadContext->IsDisableImplicitCall());
                *result = requestContext->GetLibrary()->GetNull();
                return true;
            }

            if (JavascriptOperators::GetTypeId(aResult) <= TypeIds_LastToPrimitiveType)
            {
                *result = aResult;
                return true;
            }
        }
        return false;
    }
Example #3
0
ThreadContext& DebugThreadManager::StartThread(const Common::StackPreparator& stack, size_t stackSize, const PEF::TransitionVector& entryPoint, bool startNow)
{
	// lldb enforces some alignment constraints on the stack, so align it correctly by allocating some additional memory
	ThreadContext* context = new ThreadContext(allocator, nextId, stackSize + 0x200);
	uint32_t stackAddress = allocator.ToIntPtr(*context->stack);
	stackAddress += 0x200;
	stackAddress &= ~0x1ff;
	auto info = stack.WriteStack(allocator.ToPointer<char>(stackAddress), stackAddress, stackSize);
	context->machineState.r1 = allocator.ToIntPtr(info.sp);
	context->machineState.r2 = entryPoint.TableOfContents;
	context->machineState.r3 = context->machineState.r27 = info.argc;
	context->machineState.r4 = context->machineState.r28 = allocator.ToIntPtr(info.argv);
	context->machineState.r5 = context->machineState.r29 = allocator.ToIntPtr(info.envp);
	context->machineState.lr = allocator.ToIntPtr(context->interpreter.GetEndAddress());
	context->pc = entryPoint.EntryPoint;
	
	context->thread = std::thread(&DebugThreadManager::DebugLoop, this, std::ref(*context), startNow);
	
	// this should stay at the end of the method or be scoped
	std::lock_guard<std::mutex> lock(threadsLock);
	threads[context->GetThreadId()].reset(context);
	nextId += 0x10;
	
	return *context;
}
Example #4
0
ThreadContext* PhysicalOperator::CreateOrReuseContext(context_reuse_mode crm) {
  ThreadContext* target = GetFreeContext(crm);
  if (target != NULL) {
    return target;
  }

  target = CreateContext();
  target->set_locality_(GetCurrentCpuAffinity());
  InitContext(target);
  return target;
}
    SourceDynamicProfileManager *
    SourceDynamicProfileManager::Deserialize(T * reader, Recycler* recycler)
    {
        uint functionCount;
        if (!reader->Peek(&functionCount))
        {
            return nullptr;
        }

        BVFixed * startupFunctions = BVFixed::New(functionCount, recycler);
        if (!reader->ReadArray(((char *)startupFunctions),
            BVFixed::GetAllocSize(functionCount)))
        {
            return nullptr;
        }

        uint profileCount;

        if (!reader->Read(&profileCount))
        {
            return nullptr;
        }

        ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();

        SourceDynamicProfileManager * sourceDynamicProfileManager = RecyclerNew(threadContext->GetRecycler(), SourceDynamicProfileManager, recycler);

        sourceDynamicProfileManager->cachedStartupFunctions = startupFunctions;

#if DBG_DUMP
        if(Configuration::Global.flags.Dump.IsEnabled(DynamicProfilePhase))
        {
            Output::Print(L"Loaded: Startup functions bit vector:");
            startupFunctions->Dump();
        }
#endif

        for (uint i = 0; i < profileCount; i++)
        {
            Js::LocalFunctionId functionId;
            DynamicProfileInfo * dynamicProfileInfo = DynamicProfileInfo::Deserialize(reader, recycler, &functionId);
            if (dynamicProfileInfo == nullptr || functionId >= functionCount)
            {
                return nullptr;
            }
            sourceDynamicProfileManager->dynamicProfileInfoMap.Add(functionId, dynamicProfileInfo);
        }
        return sourceDynamicProfileManager;
    }
Example #6
0
// This is called at process detach.
// threadcontext created from runtime should not be destroyed in ThreadBoundThreadContext
// we should clean them up at process detach only as runtime can be used in other threads
// even after the current physical thread was destroyed.
// This is called after ThreadBoundThreadContext are cleaned up, so the remaining items
// in the globalthreadContext linklist should be for jsrt only.
void JsrtRuntime::Uninitialize()
{
    ThreadContext* currentThreadContext = ThreadContext::GetThreadContextList();
    ThreadContext* tmpThreadContext;
    while (currentThreadContext)
    {
        Assert(!currentThreadContext->IsScriptActive());
        JsrtRuntime* currentRuntime = static_cast<JsrtRuntime*>(currentThreadContext->GetJSRTRuntime());
        tmpThreadContext = currentThreadContext;
        currentThreadContext = currentThreadContext->Next();

        currentRuntime->CloseContexts();
        RentalThreadContextManager::DestroyThreadContext(tmpThreadContext);
        HeapDelete(currentRuntime);
    }
}
Example #7
0
void
LRWMode::EncryptBlock(ThreadContext& context, uint8 *data, size_t length,
	uint64 blockIndex)
{
	uint8 i[8];
	uint8 t[16];
	uint32 b;

	blockIndex = ((blockIndex - fOffset) << 5) + 1;
	*(uint64*)i = B_HOST_TO_BENDIAN_INT64(blockIndex);

	for (b = 0; b < length >> 4; b++) {
		gf128_mul_by_tab64(i, t,
			(galois_field_context*)context.BufferFor(fGaloisField));
		xor128((uint64*)data, (uint64*)t);

		fAlgorithm->Encrypt(context, data, 16);

		xor128((uint64*)data, (uint64*)t);

		data += 16;

		if (i[7] != 0xff)
			i[7]++;
		else {
			*(uint64*)i = B_HOST_TO_BENDIAN_INT64(
				B_BENDIAN_TO_HOST_INT64(*(uint64*)i) + 1);
		}
	}

	memset(t, 0, sizeof (t));
}
Example #8
0
void
AESAlgorithm::Encrypt(ThreadContext& context, uint8 *data, size_t length)
{
//dprintf("  aes-encrypt-pre:  %x\n", *(int*)data);
	aes_encrypt(data, data,
		(const aes_encrypt_ctx*)context.BufferFor(fEncryptScheduler));
//dprintf("  aes-encrypt-post: %x\n", *(int*)data);
}
Example #9
0
status_t
AESAlgorithm::SetKey(ThreadContext& context, const uint8* key,
	size_t keyLength)
{
//dprintf("%s-aes key: %x (%lu)\n", fMode == MODE_LRW ? "lrw" : "xts", *(int*)key, keyLength);
	if (aes_encrypt_key(key, keyLength,
			(aes_encrypt_ctx*)context.BufferFor(fEncryptScheduler))
				!= EXIT_SUCCESS)
		return B_ERROR;

	if (aes_decrypt_key(key, keyLength,
			(aes_decrypt_ctx*)context.BufferFor(fDecryptScheduler))
				!= EXIT_SUCCESS)
		return B_ERROR;

	return B_OK;
}
Example #10
0
status_t
LRWMode::SetKey(ThreadContext& context, const uint8* key, size_t keyLength)
{
//dprintf("lrw key: %x\n", *(int*)key);
	gf128_tab64_init(key,
		(struct galois_field_context*)context.BufferFor(fGaloisField));

	return B_OK;
}
Example #11
0
 // Recover/Release unused memory and give it back to OS.
 // The function doesn't throw if the attempt to recover memory fails, in which case it simply does nothing.
 // Useful when running out of memory e.g. for Arena but there is some recycler memory which has been committed but is unused.
 void Exception::RecoverUnusedMemory()
 {
     ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();
     if (threadContext)
     {
         Recycler* threadRecycler = threadContext->GetRecycler();
         if (threadRecycler)
         {
             try
             {
                 threadRecycler->CollectNow<CollectOnRecoverFromOutOfMemory>();
             }
             catch (...)
             {
                 // Technically, exception is a valid scenario: we asked to recover mem, and it couldn't.
                 // Do not let the exception leak out.
             }
         }
     }
 }
Example #12
0
status_t
AESAlgorithm::Init(ThreadContext& context)
{
	// Make space for our key schedule buffer
	fEncryptScheduler = context.AddBuffer(sizeof(aes_encrypt_ctx));
	fDecryptScheduler = context.AddBuffer(sizeof(aes_decrypt_ctx));
	if (fEncryptScheduler < 0 || fDecryptScheduler < 0)
		return B_NO_MEMORY;

	return B_OK;
}
void ThreadBoundThreadContextManager::DestroyContextAndEntryForCurrentThread()
{
    AutoCriticalSection lock(ThreadContext::GetCriticalSection());

    ThreadContextTLSEntry * entry = ThreadContextTLSEntry::GetEntryForCurrentThread();

    if (entry == NULL)
    {
        return;
    }

    ThreadContext * threadContext = static_cast<ThreadContext *>(entry->GetThreadContext());
    entries.Remove(entry);

    if (threadContext != NULL && threadContext->IsThreadBound())
    {
        ShutdownThreadContext(threadContext);
    }

    ThreadContextTLSEntry::CleanupThread();
}
Example #14
0
    bool Exception::RaiseIfScriptActive(ScriptContext *scriptContext, unsigned kind, PVOID returnAddress)
    {
        ThreadContext *threadContext = ThreadContext::GetContextForCurrentThread();

        if (threadContext != nullptr && threadContext->IsScriptActive())
        {
            switch (kind) {
            case ExceptionKind_OutOfMemory:
                AssertMsg(returnAddress == NULL, "should not have returnAddress passed in");
                JavascriptError::ThrowOutOfMemoryError(scriptContext);

            case ExceptionKind_StackOverflow:
                JavascriptError::ThrowStackOverflowError(scriptContext, returnAddress);

            default:
                AssertMsg(false, "Invalid ExceptionKind");
            }
        }

        return false;
    }
void ThreadBoundThreadContextManager::DestroyAllContextsAndEntries()
{
    AutoCriticalSection lock(ThreadContext::GetCriticalSection());

    while (!entries.Empty())
    {
        ThreadContextTLSEntry * entry = entries.Head();
        ThreadContext * threadContext =  static_cast<ThreadContext *>(entry->GetThreadContext());

        entries.RemoveHead();

        if (threadContext != nullptr)
        {
#if DBG
            PageAllocator* pageAllocator = threadContext->GetPageAllocator();
            if (pageAllocator)
            {
                pageAllocator->SetConcurrentThreadId(::GetCurrentThreadId());
            }
#endif

            threadContext->ShutdownThreads();

            HeapDelete(threadContext);
        }

        ThreadContextTLSEntry::Delete(entry);
    }

#if ENABLE_BACKGROUND_JOB_PROCESSOR
    if (s_sharedJobProcessor != NULL)
    {
        s_sharedJobProcessor->Close();

        HeapDelete(s_sharedJobProcessor);
        s_sharedJobProcessor = NULL;
    }
#endif
}
    void DynamicObjectPropertyEnumerator::Reset()
    {
        if (this->object)
        {
            enumeratedCount = 0;
            initialType = object->GetDynamicType();
            objectIndex = Constants::NoBigSlot;
            initialPropertyCount = GetSnapShotSemantics() ? this->object->GetPropertyCount() : Constants::NoBigSlot;
            // Create the appropriate enumerator object.
            if (GetSnapShotSemantics() && this->initialType->PrepareForTypeSnapshotEnumeration())
            {
                ScriptContext* scriptContext = this->object->GetScriptContext();
                ThreadContext * threadContext = scriptContext->GetThreadContext();
                CachedData * data = (CachedData *)threadContext->GetDynamicObjectEnumeratorCache(this->initialType);

                if (data == nullptr || data->scriptContext != this->requestContext || data->enumNonEnumerable != GetEnumNonEnumerable() || data->enumSymbols != GetEnumSymbols())
                {
                    data = RecyclerNewStructPlus(scriptContext->GetRecycler(),
                        this->initialPropertyCount * sizeof(PropertyString *) + this->initialPropertyCount * sizeof(BigPropertyIndex) + this->initialPropertyCount * sizeof(PropertyAttributes), CachedData);
                    data->scriptContext = requestContext;
                    data->cachedCount = 0;
                    data->strings = (PropertyString **)(data + 1);
                    data->indexes = (BigPropertyIndex *)(data->strings + this->initialPropertyCount);
                    data->attributes = (PropertyAttributes*)(data->indexes + this->initialPropertyCount);
                    data->completed = false;
                    data->enumNonEnumerable = GetEnumNonEnumerable();
                    data->enumSymbols = GetEnumSymbols();
                    threadContext->AddDynamicObjectEnumeratorCache(this->initialType, data);
                }
                this->cachedData = data;
                this->cachedDataType = this->initialType;
            }
            else
            {
                this->cachedData = nullptr;
                this->cachedDataType = nullptr;
            }
        }
    }
Example #17
0
/* static */
bool JsrtContext::TrySetCurrent(JsrtContext * context)
{
    Assert(s_tlsSlot != TLS_OUT_OF_INDEXES);

    ThreadContext * threadContext;

    //We are not pinning the context after SetCurrentContext, so if the context is not pinned
    //it might be reclaimed half way during execution. In jsrtshell the runtime was optimized out
    //at time of JsrtContext::Run by the compiler.
    //The change is to pin the context at setconcurrentcontext, and unpin the previous one. In
    //JsDisposeRuntime we'll reject if current context is active, so that will make sure all
    //contexts are unpinned at time of JsDisposeRuntime.
    if (context != nullptr)
    {
        threadContext = context->GetScriptContext()->GetThreadContext();

        if (!ThreadContextTLSEntry::TrySetThreadContext(threadContext))
        {
            return false;
        }
        threadContext->GetRecycler()->RootAddRef((LPVOID)context);
    }
    else
    {
        if (!ThreadContextTLSEntry::ClearThreadContext(true))
        {
            return false;
        }
    }

    JsrtContext* originalContext = (JsrtContext*) TlsGetValue(s_tlsSlot);
    if (originalContext != nullptr)
    {
        originalContext->GetScriptContext()->GetRecycler()->RootRelease((LPVOID) originalContext);
    }

    TlsSetValue(s_tlsSlot, context);
    return true;
}
Example #18
0
    void Utf8SourceInfo::EnsureInitialized(int initialFunctionCount)
    {
        ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();
        Recycler* recycler = threadContext->GetRecycler();

        if (this->functionBodyDictionary == nullptr)
        {
            // This collection is allocated with leaf allocation policy. The references to the function body
            // here does not keep the function alive. However, the functions remove themselves at finalize
            // so if a function actually is in this map, it means that it is alive.
            this->functionBodyDictionary = RecyclerNew(recycler, FunctionBodyDictionary, recycler,
                initialFunctionCount, threadContext->GetEtwRundownCriticalSection());
        }

        if (CONFIG_FLAG(DeferTopLevelTillFirstCall) && !m_deferredFunctionsInitialized)
        {
            Assert(this->m_deferredFunctionsDictionary == nullptr);
            this->m_deferredFunctionsDictionary = RecyclerNew(recycler, DeferredFunctionsDictionary, recycler,
                initialFunctionCount, threadContext->GetEtwRundownCriticalSection());
            m_deferredFunctionsInitialized = true;
        }
    }
// This is called at process detach.
// threadcontext created from runtime should not be destroyed in ThreadBoundThreadContext
// we should clean them up at process detach only as runtime can be used in other threads
// even after the current physical thread was destroyed.
// This is called after ThreadBoundThreadContext are cleaned up, so the remaining items
// in the globalthreadContext linklist should be for jsrt only.
void JsrtRuntime::Uninitialize()
{
    ThreadContext* currentThreadContext = ThreadContext::GetThreadContextList();
    ThreadContext* tmpThreadContext;
    while (currentThreadContext)
    {
        Assert(!currentThreadContext->IsScriptActive());
        JsrtRuntime* currentRuntime = static_cast<JsrtRuntime*>(currentThreadContext->GetJSRTRuntime());
        tmpThreadContext = currentThreadContext;
        currentThreadContext = currentThreadContext->Next();

#ifdef CHAKRA_STATIC_LIBRARY
        // xplat-todo: Cleanup staticlib shutdown. This only shuts down threads.
        // Other closing contexts / finalizers having trouble with current
        // runtime/context.
        RentalThreadContextManager::DestroyThreadContext(tmpThreadContext);
#else
        currentRuntime->CloseContexts();
        RentalThreadContextManager::DestroyThreadContext(tmpThreadContext);
        HeapDelete(currentRuntime);
#endif
    }
}
Example #20
0
status_t
LRWMode::Init(ThreadContext& context, EncryptionAlgorithm* algorithm)
{
	if (algorithm == NULL)
		return B_BAD_VALUE;

	fGaloisField = context.AddBuffer(sizeof(struct galois_field_context));
	if (fGaloisField < 0)
		return B_NO_MEMORY;

	fAlgorithm = algorithm;
	fAlgorithm->SetMode(this);
	return B_OK;
}
Example #21
0
Js::ScriptContext* JsrtContextCore::EnsureScriptContext()
{
    Assert(this->GetJavascriptLibrary() == nullptr);

    ThreadContext* localThreadContext = this->GetRuntime()->GetThreadContext();

    AutoPtr<Js::ScriptContext> newScriptContext(Js::ScriptContext::New(localThreadContext));

    newScriptContext->Initialize();

    hostContext = HeapNew(ChakraCoreHostScriptContext, newScriptContext);
    newScriptContext->SetHostScriptContext(hostContext);

    this->SetJavascriptLibrary(newScriptContext.Detach()->GetLibrary());

    Js::JavascriptLibrary *library = this->GetScriptContext()->GetLibrary();
    Assert(library != nullptr);
    localThreadContext->GetRecycler()->RootRelease(library->GetGlobalObject());

    library->GetEvalFunctionObject()->SetEntryPoint(&Js::GlobalObject::EntryEval);
    library->GetFunctionConstructor()->SetEntryPoint(&Js::JavascriptFunction::NewInstance);

    return this->GetScriptContext();
}
ThreadContext * ThreadBoundThreadContextManager::EnsureContextForCurrentThread()
{
    AutoCriticalSection lock(ThreadContext::GetCriticalSection());

    ThreadContextTLSEntry * entry = ThreadContextTLSEntry::GetEntryForCurrentThread();

    if (entry == NULL)
    {
        ThreadContextTLSEntry::CreateEntryForCurrentThread();
        entry = ThreadContextTLSEntry::GetEntryForCurrentThread();
        entries.Prepend(entry);
    }

    ThreadContext * threadContext = entry->GetThreadContext();

    // An existing TLS entry may have a null ThreadContext
    // DllCanUnload may have cleaned out all the TLS entry when the module lock count is 0,
    // but the library didn't get unloaded because someone is holding onto ref count via LoadLibrary.
    // Just reinitialize the thread context.
    if (threadContext == nullptr)
    {
        threadContext = HeapNew(ThreadContext);
        threadContext->SetIsThreadBound();
        if (!ThreadContextTLSEntry::TrySetThreadContext(threadContext))
        {
            HeapDelete(threadContext);
            return NULL;
        }
    }

    Assert(threadContext != NULL);

    s_maxNumberActiveThreadContexts = max(s_maxNumberActiveThreadContexts, GetActiveThreadContextCount());

    return threadContext;
}
Example #23
0
void  PerfTrace::WritePerfMap()
{
#if ENABLE_NATIVE_CODEGEN
    // Lock threadContext list during etw rundown
    AutoCriticalSection autoThreadContextCs(ThreadContext::GetCriticalSection());

    ThreadContext * threadContext = ThreadContext::GetThreadContextList();

    FILE * perfMapFile;

    {
        const size_t PERFMAP_FILENAME_MAX_LENGTH = 30;
        char perfMapFilename[PERFMAP_FILENAME_MAX_LENGTH];
        pid_t processId = getpid();
        snprintf(perfMapFilename, PERFMAP_FILENAME_MAX_LENGTH, "/tmp/perf-%d.map", processId);

        perfMapFile = fopen(perfMapFilename, "w");
        if (perfMapFile == NULL) {
            return;
        }
    }

    while(threadContext != nullptr)
    {
        // Take etw rundown lock on this thread context
        AutoCriticalSection autoEtwRundownCs(threadContext->GetFunctionBodyLock());

        ScriptContext* scriptContext = threadContext->GetScriptContextList();
        while(scriptContext != NULL)
        {
            if(scriptContext->IsClosed())
            {
                scriptContext = scriptContext->next;
                continue;
            }

            scriptContext->MapFunction([=] (FunctionBody* body)
            {
#if DYNAMIC_INTERPRETER_THUNK
                if(body->HasInterpreterThunkGenerated())
                {
                    const char16* functionName = body->GetExternalDisplayName();
                    fwprintf(perfMapFile, _u("%llX %llX %s(Interpreted)\n"),
                        body->GetDynamicInterpreterEntryPoint(),
                        body->GetDynamicInterpreterThunkSize(),
                        functionName);
                }
#endif

#if ENABLE_NATIVE_CODEGEN
                body->MapEntryPoints([&](int index, FunctionEntryPointInfo * entryPoint)
                {
                    if(entryPoint->IsCodeGenDone())
                    {
                        const ExecutionMode jitMode = entryPoint->GetJitMode();
                        if (jitMode == ExecutionMode::SimpleJit)
                        {
                            fwprintf(perfMapFile, _u("%llX %llX %s(SimpleJIT)\n"),
                                entryPoint->GetNativeAddress(),
                                entryPoint->GetCodeSize(),
                                body->GetExternalDisplayName());
                        }
                        else
                        {
                            fwprintf(perfMapFile, _u("%llX %llX %s(FullJIT)\n"),
                                entryPoint->GetNativeAddress(),
                                entryPoint->GetCodeSize(),
                                body->GetExternalDisplayName());
                        }
                    }
                });

                body->MapLoopHeadersWithLock([&](uint loopNumber, LoopHeader* header)
                {
                    header->MapEntryPoints([&](int index, LoopEntryPointInfo * entryPoint)
                    {
                        if(entryPoint->IsCodeGenDone())
                        {
                            const uint16 loopNumber = ((uint16)body->GetLoopNumberWithLock(header));
                            fwprintf(perfMapFile, _u("%llX %llX %s(Loop%u)\n"),
                                entryPoint->GetNativeAddress(),
                                entryPoint->GetCodeSize(),
                                body->GetExternalDisplayName(),
                                loopNumber+1);
                        }
                    });
                });
#endif
            });

            scriptContext = scriptContext->next;
        }

        threadContext = threadContext->Next();
    }

    fflush(perfMapFile);
    fclose(perfMapFile);
#endif
    PerfTrace::mapsRequested = 0;
}
Example #24
0
TMMemory::TMMemory()
{
	ThreadContext* tc = ThreadContext::getContext(0);
	virtOffset = tc->getVirt2RealOffset();
	heap = tc->getHeapManager();
}
Example #25
0
//
// Enumerate through all the script contexts in the process and log events
// for each function loaded. Depending on the argument, start or end events are logged.
// In particular, a rundown is needed for the 'Attach' scenario of profiling.
//
void EtwTrace::PerformRundown(bool start)
{
    // Lock threadContext list during etw rundown
    AutoCriticalSection autoThreadContextCs(ThreadContext::GetCriticalSection());

    ThreadContext * threadContext = ThreadContext::GetThreadContextList();
    if(start)
    {
        JS_ETW(EventWriteDCStartInit());
    }
    else
    {
        JS_ETW(EventWriteDCEndInit());
    }

    while(threadContext != nullptr)
    {
        // Take etw rundown lock on this thread context
        AutoCriticalSection autoEtwRundownCs(threadContext->GetEtwRundownCriticalSection());

        ScriptContext* scriptContext = threadContext->GetScriptContextList();
        while(scriptContext != NULL)
        {
            if(scriptContext->IsClosed())
            {
                scriptContext = scriptContext->next;
                continue;
            }
            if(start)
            {
                JS_ETW(EventWriteScriptContextDCStart(scriptContext));

                if(scriptContext->GetSourceContextInfoMap() != nullptr)
                {
                    scriptContext->GetSourceContextInfoMap()->Map( [=] (DWORD_PTR sourceContext, SourceContextInfo * sourceContextInfo)
                    {
                        if (sourceContext != Constants::NoHostSourceContext)
                        {
                            JS_ETW(LogSourceEvent(EventWriteSourceDCStart,
                                sourceContext,
                                scriptContext,
                                /* sourceFlags*/ 0,
                                sourceContextInfo->url));
                        }
                    });
                }
            }
            else
            {
                JS_ETW(EventWriteScriptContextDCEnd(scriptContext));

                if(scriptContext->GetSourceContextInfoMap() != nullptr)
                {
                    scriptContext->GetSourceContextInfoMap()->Map( [=] (DWORD_PTR sourceContext, SourceContextInfo * sourceContextInfo)
                    {
                        if (sourceContext != Constants::NoHostSourceContext)
                        {
                            JS_ETW(LogSourceEvent(EventWriteSourceDCEnd,
                                sourceContext,
                                scriptContext,
                                /* sourceFlags*/ 0,
                                sourceContextInfo->url));
                        }
                    });
                }
            }

            scriptContext->MapFunction([&start] (FunctionBody* body)
            {
#if DYNAMIC_INTERPRETER_THUNK
                if(body->HasInterpreterThunkGenerated())
                {
                    if(start)
                    {
                        LogMethodInterpretedThunkEvent(EventWriteMethodDCStart, body);
                    }
                    else
                    {
                        LogMethodInterpretedThunkEvent(EventWriteMethodDCEnd, body);
                    }
                }
#endif

#if ENABLE_NATIVE_CODEGEN
                body->MapEntryPoints([&](int index, FunctionEntryPointInfo * entryPoint)
                {
                    if(entryPoint->IsCodeGenDone())
                    {
                        if (start)
                        {
                            LogMethodNativeEvent(EventWriteMethodDCStart, body, entryPoint);
                        }
                        else
                        {
                            LogMethodNativeEvent(EventWriteMethodDCEnd, body, entryPoint);
                        }
                    }
                });

                body->MapLoopHeadersWithLock([&](uint loopNumber, LoopHeader* header)
                {
                    header->MapEntryPoints([&](int index, LoopEntryPointInfo * entryPoint)
                    {
                        if(entryPoint->IsCodeGenDone())
                        {
                            if(start)
                            {
                                LogLoopBodyEventBG(EventWriteMethodDCStart, body, header, entryPoint, ((uint16)body->GetLoopNumberWithLock(header)));
                            }
                            else
                            {
                                LogLoopBodyEventBG(EventWriteMethodDCEnd, body, header, entryPoint, ((uint16)body->GetLoopNumberWithLock(header)));
                            }
                        }
                    });
                });
#endif
            });

            scriptContext = scriptContext->next;
        }
#ifdef NTBUILD
        if (EventEnabledJSCRIPT_HOSTING_CEO_START())
        {
            threadContext->EtwLogPropertyIdList();
        }
#endif

        threadContext = threadContext->Next();
    }
    if(start)
    {
        JS_ETW(EventWriteDCStartComplete());
    }
    else
    {
        JS_ETW(EventWriteDCEndComplete());
    }
}
Example #26
0
void DebugThreadManager::DebugLoop(ThreadContext& context, bool autostart)
{
	context.stopReason = StopReason::InterruptTrap;
	context.executionState = ThreadState::Stopped;
	changingContexts.PutOne(ThreadUpdate(context));
	
	if (autostart)
	{
		context.Perform(RunCommand::Continue);
	}
	
	Instruction initialInstruction;
	while (context.executionState != ThreadState::Completed)
	{
		RunCommand action = context.GetNextAction();
		UInt32* location = allocator.ToPointer<UInt32>(context.pc);
		try
		{
			if (action == RunCommand::Kill)
			{
				context.pc = allocator.ToIntPtr(context.interpreter.GetEndAddress());
			}
			else if (action == RunCommand::Continue)
			{
				breakpoints->GetRealInstruction(location, initialInstruction);
				location = context.interpreter.ExecuteOne(location, initialInstruction);
				context.interpreter.Execute(location);
				context.pc = allocator.ToIntPtr(context.interpreter.GetEndAddress());
			}
			else if (action == RunCommand::SingleStep)
			{
				breakpoints->GetRealInstruction(location, initialInstruction);
				location = context.interpreter.ExecuteOne(location, initialInstruction);
				context.pc = allocator.ToIntPtr(location);
			}
			else if (action == RunCommand::StepOver)
			{
				Instruction instruction(location->Get());
				if (instruction.OPCD != 18 || instruction.LK == 0)
				{
					// step over is the same as single step, unless we step over a call instruction...
					location = context.interpreter.ExecuteOne(location);
					context.pc = allocator.ToIntPtr(location);
				}
				else
				{
					// ...then we should set a breakpoint on the next instruction, and execute until we reach it,
					// and make sure the stack is the same size (otherwise we're doing recursion).
					Breakpoint stopAtNext = breakpoints->CreateBreakpoint(&location[1]);
					uint32_t stopPC = allocator.ToIntPtr(stopAtNext.GetLocation());
					uint32_t sp = context.machineState.r1;
					do
					{
						try
						{
							// don't be stuck on the breakpoint if it's the first instruction we execute
							breakpoints->GetRealInstruction(location, initialInstruction);
							location = context.interpreter.ExecuteOne(location, stopAtNext.GetInstruction());
							context.interpreter.Execute(location);
							context.pc = allocator.ToIntPtr(context.interpreter.GetEndAddress());
							break;
						}
						catch (Execution::InterpreterException& ex)
						{
							context.pc = ex.GetPC();
							auto cause = ex.GetReason().get();
							if (dynamic_cast<TrapException*>(cause) == nullptr || context.pc != stopPC)
								throw;
						}
					} while (context.machineState.r1 != sp);
				}
			}
			
			context.executionState = context.pc == allocator.ToIntPtr(context.interpreter.GetEndAddress())
				? ThreadState::Completed
				: ThreadState::Stopped;
		}
		catch (Execution::InterpreterException& ex)
		{
			context.pc = ex.GetPC();
			context.executionState = ThreadState::Stopped;
			auto cause = ex.GetReason().get();
			if (dynamic_cast<Execution::InvalidInstructionException*>(cause))
				context.stopReason = StopReason::InvalidInstruction;
			else if (dynamic_cast<Common::AccessViolationException*>(cause))
				context.stopReason = StopReason::AccessViolation;
			else if (dynamic_cast<TrapException*>(cause))
				context.stopReason = StopReason::InterruptTrap;
		}
		
		changingContexts.PutOne(ThreadUpdate(context));
	}
}
void Js::CharClassifier::initClassifier(ScriptContext * scriptContext, CharClassifierModes identifierSupport,
                                        CharClassifierModes whiteSpaceSupport, CharClassifierModes generalCharClassificationSupport, bool codePointSupport, bool isES6UnicodeVerboseEnabled, CharClassifierModes es6FallbackMode)
{
    bool es6Supported = true;
    bool es6ModeNeeded = identifierSupport == CharClassifierModes::ES6 || whiteSpaceSupport == CharClassifierModes::ES6 || generalCharClassificationSupport == CharClassifierModes::ES6;

#ifdef ENABLE_ES6_CHAR_CLASSIFIER
    ThreadContext* threadContext = scriptContext->GetThreadContext();
    Js::WindowsGlobalizationAdapter* globalizationAdapter = threadContext->GetWindowsGlobalizationAdapter();
    Js::DelayLoadWindowsGlobalization* globLibrary = threadContext->GetWindowsGlobalizationLibrary();
    if (es6ModeNeeded)
    {
        HRESULT hr = globalizationAdapter->EnsureDataTextObjectsInitialized(globLibrary);
        // Failed to load windows.globalization.dll or jsintl.dll. No unicodeStatics support
        // in that case.
        if (FAILED(hr))
        {
            es6Supported = false;
            es6FallbackMode = CharClassifierModes::ES5;
        }
        else
        {
            this->winGlobCharApi = globalizationAdapter->GetUnicodeStatics();
            if (this->winGlobCharApi == nullptr)
            {
                // No fallback mode, then assert
                if (es6FallbackMode == CharClassifierModes::ES6)
                {
                    AssertMsg(false, "Windows::Data::Text::IUnicodeCharactersStatics not initialized");
                    //Fallback to ES5 just in case for fre builds.
                    es6FallbackMode = CharClassifierModes::ES5;
                }
                if (isES6UnicodeVerboseEnabled)
                {
                    Output::Print(L"Windows::Data::Text::IUnicodeCharactersStatics not initialized\r\n");
                }
                //Default to non-es6
                es6Supported = false;
            }
        }
    }
#else
    es6Supported = false;
    es6FallbackMode = CharClassifierModes::ES5;
#endif

    if (es6ModeNeeded && !es6Supported)
    {
        identifierSupport = identifierSupport == CharClassifierModes::ES6 ? es6FallbackMode : identifierSupport;
        whiteSpaceSupport = whiteSpaceSupport == CharClassifierModes::ES6 ? es6FallbackMode : whiteSpaceSupport;
        generalCharClassificationSupport = generalCharClassificationSupport == CharClassifierModes::ES6 ? es6FallbackMode : generalCharClassificationSupport;
    }


    bigCharIsIdStartFunc = identifierSupport == CharClassifierModes::ES6 ? &CharClassifier::BigCharIsIdStartES6 : &CharClassifier::BigCharIsIdStartDefault;
    bigCharIsIdContinueFunc = identifierSupport == CharClassifierModes::ES6 ? &CharClassifier::BigCharIsIdContinueES6 : &CharClassifier::BigCharIsIdContinueDefault;
    bigCharIsWhitespaceFunc = whiteSpaceSupport == CharClassifierModes::ES6 ? &CharClassifier::BigCharIsWhitespaceES6 : &CharClassifier::BigCharIsWhitespaceDefault;

    skipWhiteSpaceFunc = codePointSupport ? &CharClassifier::SkipWhiteSpaceSurrogate : &CharClassifier::SkipWhiteSpaceNonSurrogate;
    skipWhiteSpaceStartEndFunc = codePointSupport ? &CharClassifier::SkipWhiteSpaceSurrogateStartEnd : &CharClassifier::SkipWhiteSpaceNonSurrogateStartEnd;

    skipIdentifierFunc = codePointSupport ? &CharClassifier::SkipIdentifierSurrogate : &CharClassifier::SkipIdentifierNonSurrogate;
    skipIdentifierStartEndFunc = codePointSupport ? &CharClassifier::SkipIdentifierSurrogateStartEnd : &CharClassifier::SkipIdentifierNonSurrogateStartEnd;

    if (generalCharClassificationSupport == CharClassifierModes::ES6)
    {
        getBigCharTypeFunc = &CharClassifier::GetBigCharTypeES6;
        getBigCharFlagsFunc = &CharClassifier::GetBigCharFlagsES6;
    }
    else if (generalCharClassificationSupport == CharClassifierModes::ES5)
    {
        getBigCharTypeFunc = &GetBigCharType;
        getBigCharFlagsFunc = &GetBigCharFlags5;
    }
    else
    {
        getBigCharTypeFunc = &GetBigCharType;
        getBigCharFlagsFunc = &GetBigCharFlags;
    }
}
Example #28
0
CHAKRA_API JsDiagSetStepType(
    _In_ JsDiagStepType stepType)
{
#ifndef ENABLE_SCRIPT_DEBUGGING
    return JsErrorCategoryUsage;
#else
    return ContextAPIWrapper_NoRecord<true>([&](Js::ScriptContext * scriptContext) -> JsErrorCode {

        JsrtContext *currentContext = JsrtContext::GetCurrent();
        JsrtRuntime* runtime = currentContext->GetRuntime();

        VALIDATE_RUNTIME_IS_AT_BREAK(runtime);

        JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();

        VALIDATE_IS_DEBUGGING(jsrtDebugManager);

        if (stepType == JsDiagStepTypeStepIn)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_INTO);
        }
        else if (stepType == JsDiagStepTypeStepOut)
        {
           jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OUT);
        }
        else if (stepType == JsDiagStepTypeStepOver)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OVER);
        }
        else if (stepType == JsDiagStepTypeStepBack)
        {
#if ENABLE_TTD
            ThreadContext* threadContext = runtime->GetThreadContext();
            if(!threadContext->IsRuntimeInTTDMode())
            {
                //Don't want to fail hard when user accidentally clicks this so pring message and step forward 
                fprintf(stderr, "Must be in replay mode to use reverse-step - launch with \"--replay-debug\" flag in Node.");
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_STEP_OVER);
            }
            else
            {
                threadContext->TTDExecutionInfo->SetPendingTTDStepBackMove();

                //don't worry about BP suppression because we are just going to throw after we return
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
#else
            return JsErrorInvalidArgument;
#endif
        }
        else if (stepType == JsDiagStepTypeReverseContinue)
        {
#if ENABLE_TTD
            ThreadContext* threadContext = runtime->GetThreadContext();
            if(!threadContext->IsRuntimeInTTDMode())
            {
                //Don't want to fail hard when user accidentally clicks this so pring message and step forward 
                fprintf(stderr, "Must be in replay mode to use reverse-continue - launch with \"--replay-debug\" flag in Node.");
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
            else
            {
                threadContext->TTDExecutionInfo->SetPendingTTDReverseContinueMove(JsTTDMoveMode::JsTTDMoveScanIntervalForContinue);

                //don't worry about BP suppression because we are just going to throw after we return
                jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
            }
#else
            return JsErrorInvalidArgument;
#endif
        }
        else if (stepType == JsDiagStepTypeContinue)
        {
            jsrtDebugManager->SetResumeType(BREAKRESUMEACTION_CONTINUE);
        }

        return JsNoError;
    });
#endif
}
Example #29
0
CHAKRA_API JsDiagStartDebugging(
    _In_ JsRuntimeHandle runtimeHandle,
    _In_ JsDiagDebugEventCallback debugEventCallback,
    _In_opt_ void* callbackState)
{
#ifndef ENABLE_SCRIPT_DEBUGGING
    return JsErrorCategoryUsage;
#else
    return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {

        VALIDATE_INCOMING_RUNTIME_HANDLE(runtimeHandle);

        PARAM_NOT_NULL(debugEventCallback);

        JsrtRuntime * runtime = JsrtRuntime::FromHandle(runtimeHandle);
        ThreadContext * threadContext = runtime->GetThreadContext();

        VALIDATE_RUNTIME_STATE_FOR_START_STOP_DEBUGGING(threadContext);

        if (runtime->GetJsrtDebugManager() != nullptr && runtime->GetJsrtDebugManager()->IsDebugEventCallbackSet())
        {
            return JsErrorDiagAlreadyInDebugMode;
        }

        // Create the debug object to save callback function and data
        runtime->EnsureJsrtDebugManager();

        JsrtDebugManager* jsrtDebugManager = runtime->GetJsrtDebugManager();

        jsrtDebugManager->SetDebugEventCallback(debugEventCallback, callbackState);

        if (threadContext->GetDebugManager() != nullptr)
        {
            threadContext->GetDebugManager()->SetLocalsDisplayFlags(Js::DebugManager::LocalsDisplayFlags::LocalsDisplayFlags_NoGroupMethods);
        }

        for (Js::ScriptContext *scriptContext = runtime->GetThreadContext()->GetScriptContextList();
        scriptContext != nullptr && !scriptContext->IsClosed();
            scriptContext = scriptContext->next)
        {
            Assert(!scriptContext->IsScriptContextInDebugMode());

            Js::DebugContext* debugContext = scriptContext->GetDebugContext();

            if (debugContext->GetHostDebugContext() == nullptr)
            {
                debugContext->SetHostDebugContext(jsrtDebugManager);
            }

            HRESULT hr;
            if (FAILED(hr = scriptContext->OnDebuggerAttached()))
            {
                Debugger_AttachDetach_fatal_error(hr); // Inconsistent state, we can't continue from here
                return JsErrorFatal;
            }

            // ScriptContext might get closed in OnDebuggerAttached
            if (!scriptContext->IsClosed())
            {
                Js::ProbeContainer* probeContainer = debugContext->GetProbeContainer();
                probeContainer->InitializeInlineBreakEngine(jsrtDebugManager);
                probeContainer->InitializeDebuggerScriptOptionCallback(jsrtDebugManager);
            }
        }

        return JsNoError;
    });
#endif
}
void ThreadBoundThreadContextManager::DestroyAllContexts()
{
#if ENABLE_BACKGROUND_JOB_PROCESSOR
    JsUtil::BackgroundJobProcessor * jobProcessor = NULL;
#endif
    
    {
        AutoCriticalSection lock(ThreadContext::GetCriticalSection());

        ThreadContextTLSEntry * currentEntry = ThreadContextTLSEntry::GetEntryForCurrentThread();

        if (currentEntry == NULL)
        {
            // We need a current thread entry so that we can use it to release any thread contexts
            // we find below.
            try
            {
                AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_OutOfMemory);
                currentEntry = ThreadContextTLSEntry::CreateEntryForCurrentThread();
                entries.Prepend(currentEntry);
            }
            catch (Js::OutOfMemoryException)
            {
                return;
            }
        }
        else
        {
            // We need to clear out the current thread entry so that we can use it to release any
            // thread contexts we find below.
            ThreadContext * threadContext = static_cast<ThreadContext *>(currentEntry->GetThreadContext());

            if (threadContext != NULL)
            {
                if (threadContext->IsThreadBound())
                {
                    ShutdownThreadContext(threadContext);
                    ThreadContextTLSEntry::ClearThreadContext(currentEntry, false);
                }
                else
                {
                    ThreadContextTLSEntry::ClearThreadContext(currentEntry, true);
                }
            }
        }

        EntryList::Iterator iter(&entries);

        while (iter.Next())
        {
            ThreadContextTLSEntry * entry = iter.Data();
            ThreadContext * threadContext =  static_cast<ThreadContext *>(entry->GetThreadContext());

            if (threadContext != nullptr)
            {
                // Found a thread context. Remove it from the containing entry.
                ThreadContextTLSEntry::ClearThreadContext(entry, true);
                // Now set it to our thread's entry.
                ThreadContextTLSEntry::SetThreadContext(currentEntry, threadContext);
                // Clear it out.
                ShutdownThreadContext(threadContext);
                // Now clear it out of our entry.
                ThreadContextTLSEntry::ClearThreadContext(currentEntry, false);
            }
        }

        // We can only clean up our own TLS entry, so we're going to go ahead and do that here.
        entries.Remove(currentEntry);
        ThreadContextTLSEntry::CleanupThread();

#if ENABLE_BACKGROUND_JOB_PROCESSOR
        if (s_sharedJobProcessor != NULL)
        {
            jobProcessor = s_sharedJobProcessor;
            s_sharedJobProcessor = NULL;

            jobProcessor->Close();
        }
#endif
    }

#if ENABLE_BACKGROUND_JOB_PROCESSOR
    if (jobProcessor != NULL)
    {
        HeapDelete(jobProcessor);
    }
#endif
}