コード例 #1
0
    BreakpointProbe* DebugDocument::SetBreakPoint(StatementLocation statement, BREAKPOINT_STATE bps)
    {
        ScriptContext* scriptContext = this->utf8SourceInfo->GetScriptContext();

        if (scriptContext == nullptr || scriptContext->IsClosed())
        {
            return nullptr;
        }

        switch (bps)
        {
            default:
                AssertMsg(FALSE, "Bad breakpoint state");
                // Fall thru
            case BREAKPOINT_DISABLED:
            case BREAKPOINT_DELETED:
            {
                BreakpointProbeList* pBreakpointList = this->GetBreakpointList();
                if (pBreakpointList)
                {
                    ArenaAllocator arena(_u("TemporaryBreakpointList"), scriptContext->GetThreadContext()->GetDebugManager()->GetDiagnosticPageAllocator(), Throw::OutOfMemory);
                    BreakpointProbeList* pDeleteList = this->NewBreakpointList(&arena);

                    pBreakpointList->Map([&statement, scriptContext, pDeleteList](int index, BreakpointProbe * breakpointProbe)
                    {
                        if (breakpointProbe->Matches(statement.function, statement.statement.begin))
                        {
                            scriptContext->GetDebugContext()->GetProbeContainer()->RemoveProbe(breakpointProbe);
                            pDeleteList->Add(breakpointProbe);
                        }
                    });

                    pDeleteList->Map([pBreakpointList](int index, BreakpointProbe * breakpointProbe)
                    {
                        pBreakpointList->Remove(breakpointProbe);
                    });
                    pDeleteList->Clear();
                }

                break;
            }
            case BREAKPOINT_ENABLED:
            {
                BreakpointProbe* pProbe = Anew(scriptContext->AllocatorForDiagnostics(), BreakpointProbe, this, statement,
                    scriptContext->GetThreadContext()->GetDebugManager()->GetNextBreakpointId());

                scriptContext->GetDebugContext()->GetProbeContainer()->AddProbe(pProbe);
                BreakpointProbeList* pBreakpointList = this->GetBreakpointList();
                pBreakpointList->Add(pProbe);
                return pProbe;
                break;
            }
        }
        return nullptr;
    }
コード例 #2
0
    void __cdecl JavascriptExternalFunction::DeferredInitializer(DynamicObject* instance, DeferredTypeHandlerBase* typeHandler, DeferredInitializeMode mode)
    {
        JavascriptExternalFunction* object = static_cast<JavascriptExternalFunction*>(instance);
        HRESULT hr = E_FAIL;

        ScriptContext* scriptContext = object->GetScriptContext();
        AnalysisAssert(scriptContext);
        // Don't call the implicit call if disable implicit call
        if (scriptContext->GetThreadContext()->IsDisableImplicitCall())
        {
            scriptContext->GetThreadContext()->AddImplicitCallFlags(ImplicitCall_External);
            //we will return if we get call further into implicitcalls.
            return;
        }

        if (scriptContext->IsClosed() || scriptContext->IsInvalidatedForHostObjects())
        {
            Js::JavascriptError::MapAndThrowError(scriptContext, E_ACCESSDENIED);
        }
        ThreadContext* threadContext = scriptContext->GetThreadContext();

        typeHandler->Convert(instance, mode, object->typeSlots, object->hasAccessors);

        BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext)
        {
            ASYNC_HOST_OPERATION_START(threadContext);

            hr = object->initMethod(instance);

            ASYNC_HOST_OPERATION_END(threadContext);
        }
        END_LEAVE_SCRIPT_INTERNAL(scriptContext);

        if (FAILED(hr))
        {
            Js::JavascriptError::MapAndThrowError(scriptContext, hr);
        }

        JavascriptString * functionName = nullptr;
        if (scriptContext->GetConfig()->IsES6FunctionNameEnabled() &&
            object->GetFunctionName(&functionName))
        {
            object->SetPropertyWithAttributes(PropertyIds::name, functionName, PropertyConfigurable, nullptr);
        }

    }
コード例 #3
0
    HRESULT DebugDocument::SetBreakPoint(int32 ibos, BREAKPOINT_STATE breakpointState)
    {
        ScriptContext* scriptContext = this->utf8SourceInfo->GetScriptContext();

        if (scriptContext == nullptr || scriptContext->IsClosed())
        {
            return E_UNEXPECTED;
        }

        StatementLocation statement;
        if (!this->GetStatementLocation(ibos, &statement))
        {
            return E_FAIL;
        }

        this->SetBreakPoint(statement, breakpointState);

        return S_OK;
    }
コード例 #4
0
    BreakpointProbeList* DebugDocument::GetBreakpointList()
    {
        if (m_breakpointList != nullptr)
        {
            return m_breakpointList;
        }

        ScriptContext * scriptContext = this->utf8SourceInfo->GetScriptContext();
        if (scriptContext == nullptr || scriptContext->IsClosed())
        {
            return nullptr;
        }

        ArenaAllocator* diagnosticArena = scriptContext->AllocatorForDiagnostics();
        AssertMem(diagnosticArena);

        m_breakpointList = this->NewBreakpointList(diagnosticArena);
        return m_breakpointList;
    }
コード例 #5
0
 JavascriptString* CharStringCache::GetStringForCharW(char16 c)
 {
     Assert(!JavascriptString::IsASCII7BitChar(c));
     JavascriptString* str;
     ScriptContext * scriptContext = JavascriptLibrary::FromCharStringCache(this)->GetScriptContext();
     if (!scriptContext->IsClosed())
     {
         if (charStringCache == nullptr)
         {
             Recycler * recycler = scriptContext->GetRecycler();
             charStringCache = RecyclerNew(recycler, CharStringCacheMap, recycler, 17);
         }
         if (!charStringCache->TryGetValue(c, &str))
         {
             str = SingleCharString::New(c, scriptContext);
             charStringCache->Add(c, str);
         }
     }
     else
     {
         str = SingleCharString::New(c, scriptContext);
     }
     return str;
 }
コード例 #6
0
ファイル: EtwTrace.cpp プロジェクト: Rastaban/ChakraCore
//
// 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());
    }
}
コード例 #7
0
    BOOL DebugDocument::GetStatementLocation(int32 ibos, StatementLocation* plocation)
    {
        if (ibos < 0)
        {
            return FALSE;
        }

        ScriptContext* scriptContext = this->utf8SourceInfo->GetScriptContext();
        if (scriptContext == nullptr || scriptContext->IsClosed())
        {
            return FALSE;
        }

        uint32 ubos = static_cast<uint32>(ibos);

        // Getting the appropriate statement on the asked position works on the heuristic which requires two
        // probable candidates. These candidates will be closest to the ibos where first.range.start < ibos and
        // second.range.start >= ibos. They will be fetched out by going into each FunctionBody.

        StatementLocation candidateMatch1 = {};
        StatementLocation candidateMatch2 = {};

        this->utf8SourceInfo->MapFunction([&](FunctionBody* pFuncBody)
        {
            uint32 functionStart = pFuncBody->StartInDocument();
            uint32 functionEnd = functionStart + pFuncBody->LengthInBytes();

            // For the first candidate, we should allow the current function to participate if its range
            // (instead of just start offset) is closer to the ubos compared to already found candidate1.

            if (candidateMatch1.function == nullptr ||
                ((candidateMatch1.statement.begin <= static_cast<int>(functionStart) ||
                candidateMatch1.statement.end <= static_cast<int>(functionEnd)) &&
                ubos > functionStart) ||
                candidateMatch2.function == nullptr ||
                (candidateMatch2.statement.begin > static_cast<int>(functionStart) &&
                ubos <= functionStart) ||
                (functionStart <= ubos &&
                ubos < functionEnd))
            {
                // We need to find out two possible candidate from the current FunctionBody.
                pFuncBody->FindClosestStatements(ibos, &candidateMatch1, &candidateMatch2);
            }
        });

        if (candidateMatch1.function == nullptr && candidateMatch2.function == nullptr)
        {
            return FALSE; // No Match found
        }

        if (candidateMatch1.function == nullptr || candidateMatch2.function == nullptr)
        {
            *plocation = (candidateMatch1.function == nullptr) ? candidateMatch2 : candidateMatch1;

            return TRUE;
        }

        // If one of the func is inner to another one, and ibos is in the inner one, disregard the outer one/let the inner one win.
        // See WinBlue 575634. Scenario is like this: var foo = function () {this;} -- and BP is set to 'this;' 'function'.
        if (candidateMatch1.function != candidateMatch2.function)
        {
            Assert(candidateMatch1.function && candidateMatch2.function);

            regex::Interval func1Range(candidateMatch1.function->StartInDocument());
            func1Range.End(func1Range.Begin() + candidateMatch1.function->LengthInBytes());
            regex::Interval func2Range(candidateMatch2.function->StartInDocument());
            func2Range.End(func2Range.Begin() + candidateMatch2.function->LengthInBytes());

            // If cursor (ibos) is just after the closing braces of the inner function then we can't
            // directly choose inner function and have to make line break check, so fallback
            // function foo(){function bar(){var y=1;}#var x=1;bar();}foo(); - ibos is #
            if (func1Range.Includes(func2Range) && func2Range.Includes(ibos) && func2Range.End() != ibos)
            {
                *plocation = candidateMatch2;
                return TRUE;
            }
            else if (func2Range.Includes(func1Range) && func1Range.Includes(ibos) && func1Range.End() != ibos)
            {
                *plocation = candidateMatch1;
                return TRUE;
            }
        }

        // At this point we have both candidate to consider.

        Assert(candidateMatch1.statement.begin < candidateMatch2.statement.begin);
        Assert(candidateMatch1.statement.begin < ibos);
        Assert(candidateMatch2.statement.begin >= ibos);

        // Default selection
        *plocation = candidateMatch1;

        // If the second candidate start at ibos or
        // if the first candidate has line break between ibos and the second candidate is on the same line as ibos
        // then consider the second one.

        BOOL fNextHasLineBreak = this->HasLineBreak(ibos, candidateMatch2.statement.begin);

        if ((candidateMatch2.statement.begin == ibos)
            || (this->HasLineBreak(candidateMatch1.statement.begin, ibos) && !fNextHasLineBreak))
        {
            *plocation = candidateMatch2;
        }
        // If ibos is out of the range of first candidate, choose second candidate if  ibos is on the same line as second candidate
        // or ibos is not on the same line of the end of the first candidate.
        else if (candidateMatch1.statement.end < ibos && (!fNextHasLineBreak || this->HasLineBreak(candidateMatch1.statement.end, ibos)))
        {
            *plocation = candidateMatch2;
        }

        return TRUE;
    }
コード例 #8
0
ファイル: PerfTrace.cpp プロジェクト: litian2025/ChakraCore
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;
}
コード例 #9
0
ファイル: CrossSite.cpp プロジェクト: raghujayan/ChakraCore
    Var CrossSite::CommonThunk(RecyclableObject* recyclableObject, JavascriptMethod entryPoint, Arguments args)
    {
        DynamicObject* function = DynamicObject::FromVar(recyclableObject);

        FunctionInfo * functionInfo = (JavascriptFunction::Is(function) ? JavascriptFunction::FromVar(function)->GetFunctionInfo() : nullptr);
        AutoDisableRedeferral autoDisableRedeferral(functionInfo);

        ScriptContext* targetScriptContext = function->GetScriptContext();
        Assert(!targetScriptContext->IsClosed());
        Assert(function->IsExternal() || function->IsCrossSiteObject());
        Assert(targetScriptContext->GetThreadContext()->IsScriptActive());

        HostScriptContext* calleeHostScriptContext = targetScriptContext->GetHostScriptContext();
        HostScriptContext* callerHostScriptContext = targetScriptContext->GetThreadContext()->GetPreviousHostScriptContext();

        if (callerHostScriptContext == calleeHostScriptContext || (callerHostScriptContext == nullptr && !calleeHostScriptContext->HasCaller()))
        {
            return JavascriptFunction::CallFunction<true>(function, entryPoint, args, true /*useLargeArgCount*/);
        }

#if DBG_DUMP || defined(PROFILE_EXEC) || defined(PROFILE_MEM)
        calleeHostScriptContext->EnsureParentInfo(callerHostScriptContext->GetScriptContext());
#endif

        TTD_XSITE_LOG(recyclableObject->GetScriptContext(), "CommonThunk -- Pass Through", recyclableObject);

        uint i = 0;
        if (args.Values[0] == nullptr)
        {
            i = 1;
            Assert(args.IsNewCall());
            Assert(JavascriptProxy::Is(function) || (JavascriptFunction::Is(function) && JavascriptFunction::FromVar(function)->GetFunctionInfo()->GetAttributes() & FunctionInfo::SkipDefaultNewObject));
        }
        uint count = args.Info.Count;
        for (; i < count; i++)
        {
            args.Values[i] = CrossSite::MarshalVar(targetScriptContext, args.Values[i]);
        }
        if (args.HasExtraArg())
        {
            // The final eval arg is a frame display that needs to be marshaled specially.
            args.Values[count] = CrossSite::MarshalFrameDisplay(targetScriptContext, args.GetFrameDisplay());
        }
        

#if ENABLE_NATIVE_CODEGEN
        CheckCodeGenFunction checkCodeGenFunction = GetCheckCodeGenFunction(entryPoint);
        if (checkCodeGenFunction != nullptr)
        {
            ScriptFunction* callFunc = ScriptFunction::FromVar(function);
            entryPoint = checkCodeGenFunction(callFunc);
            Assert(CrossSite::IsThunk(function->GetEntryPoint()));
        }
#endif

        // We need to setup the caller chain when we go across script site boundary. Property access
        // is OK, and we need to let host know who the caller is when a call is from another script site.
        // CrossSiteObject is the natural place but it is in the target site. We build up the site
        // chain through PushDispatchExCaller/PopDispatchExCaller, and we call SetCaller in the target site
        // to indicate who the caller is. We first need to get the site from the previously pushed site
        // and set that as the caller for current call, and push a new DispatchExCaller for future calls
        // off this site. GetDispatchExCaller and ReleaseDispatchExCaller is used to get the current caller.
        // currentDispatchExCaller is cached to avoid multiple allocations.
        IUnknown* sourceCaller = nullptr, *previousSourceCaller = nullptr;
        HRESULT hr = NOERROR;
        Var result = nullptr;
        BOOL wasDispatchExCallerPushed = FALSE, wasCallerSet = FALSE;

        TryFinally([&]()
        {
            hr = callerHostScriptContext->GetDispatchExCaller((void**)&sourceCaller);

            if (SUCCEEDED(hr))
            {
                hr = calleeHostScriptContext->SetCaller((IUnknown*)sourceCaller, (IUnknown**)&previousSourceCaller);
            }

            if (SUCCEEDED(hr))
            {
                wasCallerSet = TRUE;
                hr = calleeHostScriptContext->PushHostScriptContext();
            }
            if (FAILED(hr))
            {
                // CONSIDER: Should this be callerScriptContext if we failed?
                JavascriptError::MapAndThrowError(targetScriptContext, hr);
            }
            wasDispatchExCallerPushed = TRUE;

            result = JavascriptFunction::CallFunction<true>(function, entryPoint, args, true /*useLargeArgCount*/);
            ScriptContext* callerScriptContext = callerHostScriptContext->GetScriptContext();
            result = CrossSite::MarshalVar(callerScriptContext, result);
        },
        [&](bool hasException)
        {
            if (sourceCaller != nullptr)
            {
                callerHostScriptContext->ReleaseDispatchExCaller(sourceCaller);
            }
            IUnknown* originalCaller = nullptr;
            if (wasDispatchExCallerPushed)
            {
                calleeHostScriptContext->PopHostScriptContext();
            }
            if (wasCallerSet)
            {
                calleeHostScriptContext->SetCaller(previousSourceCaller, &originalCaller);
                if (previousSourceCaller)
                {
                    previousSourceCaller->Release();
                }
                if (originalCaller)
                {
                    originalCaller->Release();
                }
            }
        });
        Assert(result != nullptr);
        return result;
    }