コード例 #1
0
    Var SIMDBool8x16Lib::EntryAnyTrue(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 2 && JavascriptSIMDBool8x16::Is(args[1]))
        {
            JavascriptSIMDBool8x16 *a = JavascriptSIMDBool8x16::FromVar(args[1]);
            Assert(a);

            bool result = SIMDBool32x4Operation::OpAnyTrue(a->GetValue());

            return JavascriptBoolean::ToVar(result, scriptContext);
        }

        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdBool8x16TypeMismatch, _u("AnyTrue"));
    }
コード例 #2
0
ファイル: Jobs.cpp プロジェクト: ianwjhalliday/ChakraCore
void BackgroundJobProcessor::Run(ParallelThreadData* threadData)
{
    JS_ETW(EventWriteJSCRIPT_NATIVECODEGEN_START(this, 0));

    ArenaAllocator threadArena(_u("ThreadArena"), threadData->GetPageAllocator(), Js::Throw::OutOfMemory);
    threadData->threadArena = &threadArena;

    {
        // Make sure we take decommit action before the threadArena is torn down, in case the
        // thread context goes away and the loop exits.
        struct AutoDecommit
        {
            AutoDecommit(JobProcessor *proc, ParallelThreadData *data) : processor(proc), threadData(data) {}
            ~AutoDecommit()
            {
                processor->ForEachManager([this](JobManager *manager) {
                    manager->OnDecommit(this->threadData);
                });
            }
            ParallelThreadData *threadData;
            JobProcessor *processor;
        } autoDecommit(this, threadData);

        criticalSection.Enter();
        while (!IsClosed() || (jobs.Head() && jobs.Head()->IsCritical()))
        {
            Job *job = jobs.UnlinkFromBeginning();

            if(!job)
            {
                // No jobs in queue, wait for one

                Assert(!IsClosed());
                Assert(!threadData->isWaitingForJobs);
                threadData->isWaitingForJobs = true;
                criticalSection.Leave();
                JS_ETW(EventWriteJSCRIPT_NATIVECODEGEN_STOP(this, 0));

                if (threadService->HasCallback())
                {
                    // We have a thread service, so simply return the thread back now.
                    // When new jobs are submitted, we will be called to process again.
                    return;
                }

                WaitForJobReadyOrShutdown(threadData);

                JS_ETW(EventWriteJSCRIPT_NATIVECODEGEN_START(this, 0));
                criticalSection.Enter();
                threadData->isWaitingForJobs = false;
                continue;
            }

            Assert(numJobs != 0);
            --numJobs;
            threadData->currentJob = job;
            criticalSection.Leave();

            const bool succeeded = Process(job, threadData);

            criticalSection.Enter();
            threadData->currentJob = 0;
            JobManager *const manager = job->Manager();
            JobProcessed(manager, job, succeeded); // the job may be deleted during this and should not be used afterwards
            Assert(manager->numJobsAddedToProcessor != 0);
            --manager->numJobsAddedToProcessor;
            if(manager->isWaitable)
            {
                WaitableJobManager *const waitableManager = static_cast<WaitableJobManager *>(manager);
                Assert(!(waitableManager->jobBeingWaitedUpon && waitableManager->isWaitingForQueuedJobs));
                if(waitableManager->jobBeingWaitedUpon == job)
                {
                    waitableManager->jobBeingWaitedUpon = 0;
                    waitableManager->jobBeingWaitedUponProcessed.Set();
                }
                else if(waitableManager->isWaitingForQueuedJobs && manager->numJobsAddedToProcessor == 0)
                {
                    waitableManager->isWaitingForQueuedJobs = false;
                    waitableManager->queuedJobsProcessed.Set();
                }
            }
            if(manager->numJobsAddedToProcessor == 0)
                LastJobProcessed(manager); // the manager may be deleted during this and should not be used afterwards
        }
        criticalSection.Leave();

        JS_ETW(EventWriteJSCRIPT_NATIVECODEGEN_STOP(this, 0));
    }
}
コード例 #3
0
ファイル: ScopeInfo.cpp プロジェクト: EdMaurer/ChakraCore
    //
    // Load persisted scope info.
    //
    void ScopeInfo::GetScopeInfo(Parser *parser, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo, Scope* scope)
    {
        ScriptContext* scriptContext;
        ArenaAllocator* alloc;

        // Load scope attributes and push onto scope stack.
        scope->SetIsDynamic(this->isDynamic);
        if (this->isObject)
        {
            scope->SetIsObject();
        }
        scope->SetMustInstantiate(this->mustInstantiate);
        if (!this->GetCanMergeWithBodyScope())
        {
            scope->SetCannotMergeWithBodyScope();
        }
        scope->SetHasOwnLocalInClosure(this->hasLocalInClosure);
        if (parser)
        {
            scriptContext = parser->GetScriptContext();
            alloc = parser->GetAllocator();
        }
        else
        {
            TRACE_BYTECODE(_u("\nRestore ScopeInfo: %s #symbols: %d %s\n"),
                funcInfo->name, symbolCount, isObject ? _u("isObject") : _u(""));

            Assert(!this->isCached || scope == funcInfo->GetBodyScope());
            funcInfo->SetHasCachedScope(this->isCached);
            byteCodeGenerator->PushScope(scope);

            // The scope is already populated, so we're done.
            return;
        }

        // Load scope symbols
        // On first access to the scopeinfo, replace the ID's with PropertyRecord*'s to save the dictionary lookup
        // on later accesses. Replace them all before allocating Symbol's to prevent inconsistency on OOM.
        if (!this->areNamesCached && !PHASE_OFF1(Js::CacheScopeInfoNamesPhase))
        {
            for (int i = 0; i < symbolCount; i++)
            {
                PropertyId propertyId = GetSymbolId(i);
                if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot
                {
                    PropertyRecord const* name = scriptContext->GetPropertyName(propertyId);
                    this->SetPropertyName(i, name);
                }
            }
            this->areNamesCached = true;
        }

        for (int i = 0; i < symbolCount; i++)
        {
            PropertyRecord const* name = nullptr;
            if (this->areNamesCached)
            {
                name = this->GetPropertyName(i);
            }
            else
            {
                PropertyId propertyId = GetSymbolId(i);
                if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot
                {
                    name = scriptContext->GetPropertyName(propertyId);
                }
            }

            if (name != nullptr)
            {
                SymbolType symbolType = GetSymbolType(i);
                SymbolName symName(name->GetBuffer(), name->GetLength());
                Symbol *sym = Anew(alloc, Symbol, symName, nullptr, symbolType);

                sym->SetScopeSlot(static_cast<PropertyId>(i));
                sym->SetIsBlockVar(GetIsBlockVariable(i));
                if (GetHasFuncAssignment(i))
                {
                    sym->RestoreHasFuncAssignment();
                }
                scope->AddNewSymbol(sym);
                if (parser)
                {
                    parser->RestorePidRefForSym(sym);
                }

                TRACE_BYTECODE(_u("%12s %d\n"), sym->GetName().GetBuffer(), sym->GetScopeSlot());
            }
        }
        this->scope = scope;
        DebugOnly(scope->isRestored = true);
    }
コード例 #4
0
Js::FunctionInfo *InliningDecider::Inline(Js::FunctionBody *const inliner, Js::FunctionInfo* functionInfo,
    bool isConstructorCall, bool isPolymorphicCall, uint16 constantArgInfo, Js::ProfileId callSiteId, uint recursiveInlineDepth, bool allowRecursiveInlining)
{
#if defined(DBG_DUMP) || defined(ENABLE_DEBUG_CONFIG_OPTIONS)
    char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
    char16 debugStringBuffer2[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
#endif
    Js::FunctionProxy * proxy = functionInfo->GetFunctionProxy();
    if (proxy && proxy->IsFunctionBody())
    {
        if (isLoopBody && PHASE_OFF(Js::InlineInJitLoopBodyPhase, this->topFunc))
        {
            INLINE_TESTTRACE_VERBOSE(_u("INLINING: Skip Inline: Jit loop body: %s (%s)\n"), this->topFunc->GetDisplayName(),
                this->topFunc->GetDebugNumberSet(debugStringBuffer));
            return nullptr;
        }

        // Note: disable inline for debugger, as we can't bailout at return from function.
        // Alternative can be generate this bailout as part of inline, which can be done later as perf improvement.
        const auto inlinee = proxy->GetFunctionBody();
        Assert(this->jitMode == ExecutionMode::FullJit);
        if (PHASE_OFF(Js::InlinePhase, inlinee) ||
            PHASE_OFF(Js::GlobOptPhase, inlinee) ||
            !ContinueInliningUserDefinedFunctions(this->bytecodeInlinedCount) ||
            this->isInDebugMode)
        {
            return nullptr;
        }

        if (functionInfo->IsDeferred() || inlinee->GetByteCode() == nullptr)
        {
            // DeferredParse...
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: No bytecode\tInlinee: %s (%s)\tCaller: %s (%s)\n"),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inliner->GetDisplayName(),
                inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }

#ifdef _M_IX86
        if (inlinee->GetHasTry())
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Has try\tInlinee: %s (%s)\tCaller: %s (%s)\n"),
            inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inliner->GetDisplayName(),
            inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }
#endif

        // This is a hard limit as the argOuts array is statically sized.
        if (inlinee->GetInParamsCount() > Js::InlineeCallInfo::MaxInlineeArgoutCount)
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Params count greater then MaxInlineeArgoutCount\tInlinee: %s (%s)\tParamcount: %d\tMaxInlineeArgoutCount: %d\tCaller: %s (%s)\n"),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inlinee->GetInParamsCount(), Js::InlineeCallInfo::MaxInlineeArgoutCount,
                inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }

        // Wasm functions can have no params
        if (inlinee->GetInParamsCount() == 0 && !inlinee->GetIsAsmjsMode())
        {
            // Inline candidate has no params, not even a this pointer.  This can only be the global function,
            // which we shouldn't inline.
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Params count is zero!\tInlinee: %s (%s)\tParamcount: %d\tCaller: %s (%s)\n"),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inlinee->GetInParamsCount(),
                inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }

        if (inlinee->GetDontInline())
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Do not inline\tInlinee: %s (%s)\tCaller: %s (%s)\n"),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inliner->GetDisplayName(),
                inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }

        // Do not inline a call to a class constructor if it isn't part of a new expression since the call will throw a TypeError anyway.
        if (inlinee->IsClassConstructor() && !isConstructorCall)
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Class constructor without new keyword\tInlinee: %s (%s)\tCaller: %s (%s)\n"),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inliner->GetDisplayName(),
                inliner->GetDebugNumberSet(debugStringBuffer2));
            return nullptr;
        }

        if (!DeciderInlineIntoInliner(inlinee, inliner, isConstructorCall, isPolymorphicCall, constantArgInfo, recursiveInlineDepth, allowRecursiveInlining))
        {
            return nullptr;
        }

#if defined(ENABLE_DEBUG_CONFIG_OPTIONS)
        TraceInlining(inliner, inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer), inlinee->GetByteCodeCount(), this->topFunc, this->bytecodeInlinedCount, inlinee, callSiteId, this->isLoopBody);
#endif

        this->bytecodeInlinedCount += inlinee->GetByteCodeCount();
        return inlinee->GetFunctionInfo();
    }

    Js::OpCode builtInInlineCandidateOpCode;
    ValueType builtInReturnType;
    GetBuiltInInfo(functionInfo, &builtInInlineCandidateOpCode, &builtInReturnType);

    if(builtInInlineCandidateOpCode == 0 && builtInReturnType.IsUninitialized())
    {
        return nullptr;
    }

    Assert(this->jitMode == ExecutionMode::FullJit);
    if (builtInInlineCandidateOpCode != 0 &&
        (
            PHASE_OFF(Js::InlinePhase, inliner) ||
            PHASE_OFF(Js::GlobOptPhase, inliner) ||
            isConstructorCall
        ))
    {
        return nullptr;
    }

    // Note: for built-ins at this time we don't have enough data (the instr) to decide whether it's going to be inlined.
    return functionInfo;
}
コード例 #5
0
 const char16* JavascriptSIMDInt8x16::GetFullBuiltinName(char16** aBuffer, const char16* name)
 {
     Assert(aBuffer && *aBuffer);
     swprintf_s(*aBuffer, SIMD_STRING_BUFFER_MAX, _u("SIMD.Int8x16.%s"), name);
     return *aBuffer;
 }
コード例 #6
0
ファイル: AsmJsTypes.cpp プロジェクト: dilijev/ChakraCore
 template<> void PrintTmpRegisterDeAllocation<AsmJsSIMDValue>(RegSlot loc)
 {
     if (PHASE_ON1(AsmjsTmpRegisterAllocationPhase))
         Output::Print(_u("-SIMD%d\n"), loc);
 }
コード例 #7
0
ファイル: DateUtilities.cpp プロジェクト: Rastaban/ChakraCore
namespace Js
{
    const INT64 DateUtilities::ticksPerMillisecond = 10000;
    const double DateUtilities::ticksPerMillisecondDouble = 10000.0;
    const INT64 DateUtilities::ticksPerSecond = ticksPerMillisecond * 1000;
    const INT64 DateUtilities::ticksPerMinute = ticksPerSecond * 60;
    const INT64 DateUtilities::ticksPerHour = ticksPerMinute * 60;
    const INT64 DateUtilities::ticksPerDay = ticksPerHour * 24;
    const INT64 DateUtilities::jsEpochMilliseconds = 11644473600000;
    const INT64 DateUtilities::jsEpochTicks = jsEpochMilliseconds * ticksPerMillisecond;

    // The day numbers for the months of a leap year.
    static const int g_rgday[12] =
    {
          0,  31,  60,  91, 121, 152,
        182, 213, 244, 274, 305, 335,
    };

    const double g_kdblJanuary1st1970 = 25569.0;

    const char16 g_rgpszDay[7][4] =
    {
        _u("Sun"),
        _u("Mon"),
        _u("Tue"),
        _u("Wed"),
        _u("Thu"),
        _u("Fri"),
        _u("Sat")
    };

    const char16 g_rgpszMonth[12][4] =
    {
        _u("Jan"),
        _u("Feb"),
        _u("Mar"),
        _u("Apr"),
        _u("May"),
        _u("Jun"),
        _u("Jul"),
        _u("Aug"),
        _u("Sep"),
        _u("Oct"),
        _u("Nov"),
        _u("Dec")
    };

    const char16 g_rgpszZone[8][4] =
    {
        _u("EST"),
        _u("EDT"),
        _u("CST"),
        _u("CDT"),
        _u("MST"),
        _u("MDT"),
        _u("PST"),
        _u("PDT")
    };


    //
    // Convert an ES5 date based on double to a WinRT DateTime
    // DateTime is the number of ticks that have elapsed since 1/1/1601 00:00:00 in 100ns precision
    // If we return a failure HRESULT other than E_INVALIDARG, the es5 date can't be expressed
    // in the WinRT scheme
    //
    HRESULT DateUtilities::ES5DateToWinRTDate(double es5Date, __out INT64* pRet)
    {
        Assert(pRet != NULL);

        if (pRet == NULL)
        {
            return E_INVALIDARG;
        }

        INT64 es5DateAsInt64 = NumberUtilities::TryToInt64(es5Date);

        if (!NumberUtilities::IsValidTryToInt64(es5DateAsInt64)) return INTSAFE_E_ARITHMETIC_OVERFLOW;

        // First, we rebase it to the WinRT epoch, then we convert the time in milliseconds to ticks
        INT64 numTicks;
        if (!Int64Math::Add(es5DateAsInt64, jsEpochMilliseconds, &numTicks))
        {
            INT64 adjustedTicks = 0;
            if (!Int64Math::Mul(numTicks, ticksPerMillisecond, &adjustedTicks))
            {
                (*pRet) = adjustedTicks;
                return S_OK;
            }
        }

         return INTSAFE_E_ARITHMETIC_OVERFLOW;
    }

    ///------------------------------------------------------------------------------
    /// Get a time value from SYSTEMTIME structure.
    ///
    /// Returns number of milliseconds since Jan 1, 1970
    ///------------------------------------------------------------------------------
    double
    DateUtilities::TimeFromSt(SYSTEMTIME *pst)
    {
        return TvFromDate(pst->wYear,pst->wMonth-1,pst->wDay-1, DayTimeFromSt(pst));
    }

    ///------------------------------------------------------------------------------
    /// Get a time value from SYSTEMTIME structure within a day
    ///
    /// Returns number of milliseconds since 12:00 AM
    ///------------------------------------------------------------------------------
    double
    DateUtilities::DayTimeFromSt(SYSTEMTIME *pst)
    {
        return (pst->wHour * 3600000.0) + (pst->wMinute * 60000.0) + (pst->wSecond * 1000.0) + pst->wMilliseconds;
    }

    ///------------------------------------------------------------------------------
    /// Get a time value from (year, mon, day, time) values.
    ///------------------------------------------------------------------------------
    double
    DateUtilities::TvFromDate(double year, double mon, double day, double time)
    {
        // For positive month, use fast path: '/' and '%' rather than 'floor()' and 'fmod()'.
        // But make sure there is no overflow when casting double -> int -- WOOB 1142298.
        if (mon >= 0 && mon <= INT_MAX)
        {
            year +=  ((int)mon) / 12;
            mon = ((int)mon) % 12;
        }
        else
        {
            year += floor(mon/12);
            mon = DblModPos(mon,12);
        }

        day += DayFromYear(year);

        AssertMsg(mon >= 0 && mon <= 11, "'mon' must be in the range of [0..11].");
        day += g_rgday[(int)mon];

        if (mon >= 2 && !FLeap((int)year))
        {
            day -= 1;
        }

        return day * 86400000 + time;
    }

    ///------------------------------------------------------------------------------
    /// Get the non-negative remainder.
    ///------------------------------------------------------------------------------
    double
    DateUtilities::DblModPos(double dbl, double dblDen)
    {
        AssertMsg(dblDen > 0, "value not positive");
        dbl = fmod(dbl, dblDen);
        if (dbl < 0)
        {
            dbl += dblDen;
        }
        AssertMsg(dbl >= 0 && dbl < dblDen, "");
        return dbl;
    }

    ///------------------------------------------------------------------------------
    /// DayFromYear is:
    ///    365 * y + floor((y+1)/4) - floor((y+69)/100) + floor((y+369)/400).
    /// where y is the calendar year minus 1970.
    ///------------------------------------------------------------------------------
    double
    DateUtilities::DayFromYear(double year)
    {
        double day = 365 * (year -= 1970);

        if (day > 0)
        {
            day += ((int)((year + 1) / 4)) - ((int)((year + 69) / 100)) +
                ((int)((year + 369) / 400));
        }
        else
        {
            day += floor((year + 1) / 4) - floor((year + 69) / 100) +
                floor((year + 369) / 400);
        }
        return day;
    }

    ///------------------------------------------------------------------------------
    /// Return whether the given year is a leap year.
    ///------------------------------------------------------------------------------
    bool
    DateUtilities::FLeap(int year)
    {
        return (0 == (year & 3)) && (0 != (year % 100) || 0 == (year % 400));
    }

    ///------------------------------------------------------------------------------
    /// Get the first day of the year, and if the first day is bigger than the passed day, then get the first day of the previous year.
    ///------------------------------------------------------------------------------
    /*static*/
    int DateUtilities::GetDayMinAndUpdateYear(int day, int &year)
    {
        int dayMin = (int)DayFromYear(year);
        if (day < dayMin)
        {
            year--;
            dayMin = (int)DayFromYear(year);
        }
        return dayMin;
    }

    ///------------------------------------------------------------------------------
    /// Converts the time value relative to Jan 1, 1970 into a YMD.
    ///
    /// The year number y and day number d relative to Jan 1, 1970 satisfy the
    /// inequalities:
    ///    floor((400*d-82)/146097) <= y <= floor((400*d+398)/146097)
    /// These inequalities get us within one of the correct answer for the year.
    /// We then use DayFromYear to adjust if necessary.
    ///------------------------------------------------------------------------------
    void
    DateUtilities::GetYmdFromTv(double tv, DateTime::YMD *pymd)
    {
//      AssertMem(pymd);

        int day;
        int dayMin;
        int yday;

        if (tv > 0)
        {
            day = (int)(tv / 86400000);
            pymd->time = (int)DblModPos(tv, 86400000);
            pymd->wday = (day + 4) % 7;

            pymd->year = 1970 + (int)((400 * (double)day + 398) / 146097);
            dayMin = GetDayMinAndUpdateYear(day, pymd->year);
            pymd->yt = (int)((dayMin + 4) % 7);

        }
        else
        {
            day = (int)floor(tv / 86400000);
            pymd->time = (int)DblModPos(tv, 86400000);
            pymd->wday = (int)DblModPos(day + 4, 7);

            pymd->year = 1970 + (int)floor(((400 * (double)day + 398) / 146097));
            dayMin = GetDayMinAndUpdateYear(day, pymd->year);
            pymd->yt = (int)DblModPos(dayMin + 4, 7);
        }
        yday = (int)(day - dayMin);
//      Assert(yday >= 0 && (yday < 365 || yday == 365 && FLeap(pymd->year)));
        pymd->yday = yday;

        if (FLeap(pymd->year))
        {
            pymd->yt += 7;
        }
        else if (yday >= 59)
        {
            yday++;
        }

        // Get the month.
        if (yday < 182)
        {
            if (yday < 60)
            {
                pymd->mon = 0 + ((yday >= 31) ? 1 : 0);
            }
            else if (yday < 121)
            {
                pymd->mon = 2 + ((yday >= 91) ? 1 : 0);
            }
            else
            {
                pymd->mon = 4 + ((yday >= 152) ? 1 : 0);
            }
        }
        else
        {
            if (yday < 244)
            {
                pymd->mon = 6 + ((yday >= 213) ? 1 : 0);
            }
            else if (yday < 305)
            {
                pymd->mon = 8 + ((yday >= 274) ? 1 : 0);
            }
            else
            {
                pymd->mon = 10 + ((yday >= 335) ? 1 : 0);
            }
        }
//      Assert(pymd->mon >= 0 && pymd->mon < 12);

        pymd->mday = yday - g_rgday[pymd->mon];
    }

    void DateUtilities::GetYearFromTv(double tv, int &year, int &yearType)
    {
        //      AssertMem(pymd);

        int day;
        int dayMin;

        if (tv > 0)
        {
            day = (int)(tv / 86400000);
            year = 1970 + (int)((400 * (double)day + 398) / 146097);
            dayMin = GetDayMinAndUpdateYear(day, year);
            yearType = (int)((dayMin + 4) % 7);

        }
        else
        {
            day = (int)floor(tv / 86400000);
            year = 1970 + (int)floor(((400 * (double)day + 398) / 146097));
            dayMin = GetDayMinAndUpdateYear(day, year);
            yearType = (int)DblModPos(dayMin + 4, 7);
        }

        if (FLeap(year))
        {
            yearType += 7;
        }
    }

    double DateUtilities::JsLocalTimeFromVarDate(double dbl)
    {
        // So that the arithmetic works even for negative dates, convert the
        // date to the _actual number of days_ since 0000h 12/30/1899.
        if (dbl < 0.0)
            dbl = 2.0 * ceil(dbl) - dbl;

        // Get the local time value.
        dbl = (dbl - g_kdblJanuary1st1970) * 86400000;
        if (NumberUtilities::IsNan(dbl))
        {
            return dbl;
        }
        return NumberUtilities::IsFinite(dbl) ? floor( dbl + 0.5) : dbl;
    }
}
コード例 #8
0
    Var SIMDUint8x16Lib::EntrySubSaturate(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        // If any of the args are missing, then it is Undefined type which causes TypeError exception.
        // strict type on both operands
        if (args.Info.Count >= 3 && JavascriptSIMDUint8x16::Is(args[1]) && JavascriptSIMDUint8x16::Is(args[2]))
        {
            JavascriptSIMDUint8x16 *a = JavascriptSIMDUint8x16::FromVar(args[1]);
            JavascriptSIMDUint8x16 *b = JavascriptSIMDUint8x16::FromVar(args[2]);
            Assert(a && b);

            SIMDValue result, aValue, bValue;

            aValue = a->GetValue();
            bValue = b->GetValue();

            result = SIMDUint8x16Operation::OpSubSaturate(aValue, bValue);

            return JavascriptSIMDUint8x16::New(&result, scriptContext);
        }

        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("subSaturate"));
    }
コード例 #9
0
    Var SIMDUint8x16Lib::EntrySelect(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 4 && JavascriptSIMDBool8x16::Is(args[1]) &&
            JavascriptSIMDUint8x16::Is(args[2]) && JavascriptSIMDUint8x16::Is(args[3]))
        {
            JavascriptSIMDBool8x16 *m = JavascriptSIMDBool8x16::FromVar(args[1]);
            JavascriptSIMDUint8x16 *t = JavascriptSIMDUint8x16::FromVar(args[2]);
            JavascriptSIMDUint8x16 *f = JavascriptSIMDUint8x16::FromVar(args[3]);
            Assert(m && t && f);

            SIMDValue result, maskValue, trueValue, falseValue;

            maskValue = m->GetValue();
            trueValue = t->GetValue();
            falseValue = f->GetValue();

            result = SIMDInt32x4Operation::OpSelect(maskValue, trueValue, falseValue);

            return JavascriptSIMDUint8x16::New(&result, scriptContext);
        }

        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("select"));
    }
コード例 #10
0
    Var SIMDUint8x16Lib::EntryShiftRightByScalar(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 3 && JavascriptSIMDUint8x16::Is(args[1]))
        {
            JavascriptSIMDUint8x16 *a = JavascriptSIMDUint8x16::FromVar(args[1]);
            Assert(a);

            SIMDValue result, aValue;

            aValue = a->GetValue();
            Var countVar = args[2]; // {int} bits Bit count
            int8 count = JavascriptConversion::ToInt8(countVar, scriptContext);

            result = SIMDUint8x16Operation::OpShiftRightByScalar(aValue, count);

            return JavascriptSIMDUint8x16::New(&result, scriptContext);
        }

        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("shiftRightByScalar"));
    }
コード例 #11
0
    Var SIMDUint8x16Lib::EntryReplaceLane(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        // first arg has to be of type Uint8x16, so cannot be missing.
        if (args.Info.Count >= 4 && JavascriptSIMDUint8x16::Is(args[1]))
        {
            // if value arg is missing, then it is undefined.
            Var laneVar = args.Info.Count >= 4 ? args[2] : scriptContext->GetLibrary()->GetUndefined();
            Var argVal = args.Info.Count >= 4 ? args[3] : scriptContext->GetLibrary()->GetUndefined();
            uint8 value = JavascriptConversion::ToInt8(argVal, scriptContext);

            SIMDValue result = SIMD128ReplaceLane<JavascriptSIMDUint8x16, 16, uint8>(args[1], laneVar, value, scriptContext);

            return JavascriptSIMDUint8x16::New(&result, scriptContext);
        }

        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("ReplaceLane"));
    }
コード例 #12
0
    Var SIMDUint8x16Lib::EntryCheck(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();
        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));
        if (args.Info.Count >= 2 && JavascriptSIMDUint8x16::Is(args[1]))
        {
            return args[1];
        }
        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("Uint8x16"));
    }
コード例 #13
0
    Var SIMDUint8x16Lib::EntryNot(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 2 && JavascriptSIMDUint8x16::Is(args[1]))
        {
            JavascriptSIMDUint8x16 *a = JavascriptSIMDUint8x16::FromVar(args[1]);
            Assert(a);

            SIMDValue value, result;

            value = a->GetValue();
            result = SIMDInt32x4Operation::OpNot(value);

            return JavascriptSIMDUint8x16::New(&result, scriptContext);
        }
        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("not"));
    }
コード例 #14
0
    //Lane Access
    Var SIMDBool8x16Lib::EntryExtractLane(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);

        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 3 && JavascriptSIMDBool8x16::Is(args[1]))
        {
            // if value arg is missing, then it is undefined.
            Var laneVar = args.Info.Count >= 3 ? args[2] : scriptContext->GetLibrary()->GetUndefined();
            bool result = (SIMDUtils::SIMD128ExtractLane<JavascriptSIMDBool8x16, 16, int8>(args[1], laneVar, scriptContext)) ? true : false;
            return JavascriptBoolean::ToVar(result, scriptContext);
        }
        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdBool8x16TypeMismatch, _u("ExtractLane"));
    }
コード例 #15
0
    void
    ConfigFlagsTable::PrintUsageString()
    {
        Output::Print(_u("List of Phases:\n"));
        for(int i = 0; i < PhaseCount; i++)
        {
            if (i % 4 == 0)
            {
                Output::Print(_u("\n  "));
            }
            Output::Print(_u("%-40ls "), PhaseNames[i]);
        }

        Output::Print(_u("\n\nList of flags:\n\n"));
        for(int i = 0; i < FlagCount; i++)
        {
            Output::Print(_u("%60ls "), FlagNames[i]);
            switch(GetFlagType(Flag(i)))
            {
            case InvalidFlagType:
                break;
            case FlagString:
                Output::Print(_u("[:String]        "));
                break;
            case FlagPhases:
                Output::Print(_u("[:Phase]         "));
                break;
            case FlagNumber:
                Output::Print(_u("[:Number]        "));
                break;
            case FlagBoolean:
                Output::Print(_u("                 "));
                break;
            case FlagNumberSet:
                Output::Print(_u("[:NumberSet]     "));
                break;
            case FlagNumberPairSet:
                Output::Print(_u("[:NumberPairSet] "));
                break;
            case FlagNumberTrioSet:
                Output::Print(_u("[:NumberTrioSet] "));
                break;
            case FlagNumberRange:
                Output::Print(_u("[:NumberRange]   "));
                break;
            default:
                Assert(false);
                __assume(false);
            }
            Output::Print(_u("%ls\n"), FlagDescriptions[i]);
        }
    }
コード例 #16
0
    Var SIMDUint8x16Lib::EntryFromInt32x4Bits(RecyclableObject* function, CallInfo callInfo, ...)
    {
        PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
        ARGUMENTS(args, callInfo);
        ScriptContext* scriptContext = function->GetScriptContext();

        AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
        Assert(!(callInfo.Flags & CallFlags_New));

        if (args.Info.Count >= 2 && JavascriptSIMDInt32x4::Is(args[1]))
        {
            JavascriptSIMDInt32x4 *instance = JavascriptSIMDInt32x4::FromVar(args[1]);
            Assert(instance);
            return  SIMDConvertTypeFromBits<JavascriptSIMDInt32x4, JavascriptSIMDUint8x16>(instance, scriptContext);
        }
        JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("fromInt32x4Bits"));
    }
コード例 #17
0
ファイル: AsmJsTypes.cpp プロジェクト: dilijev/ChakraCore
 template<> void PrintTmpRegisterAllocation<int>(RegSlot loc)
 {
     if (PHASE_ON1(AsmjsTmpRegisterAllocationPhase))
         Output::Print(_u("+I%d\n"), loc);
 }
コード例 #18
0
LPVOID PreReservedVirtualAllocWrapper::Alloc(LPVOID lpAddress, size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
{
    Assert(this);
    AssertMsg(isCustomHeapAllocation, "PreReservation used for allocations other than CustomHeap?");
    AssertMsg(AutoSystemInfo::Data.IsCFGEnabled() || PHASE_FORCE1(Js::PreReservedHeapAllocPhase), "PreReservation without CFG ?");
    Assert(dwSize != 0);

    {
        AutoCriticalSection autocs(&this->cs);
        //Return nullptr, if no space to Reserve
        if (EnsurePreReservedRegionInternal() == nullptr)
        {
            PreReservedHeapTrace(_u("No space to pre-reserve memory with %d pages. Returning NULL\n"), PreReservedAllocationSegmentCount * AutoSystemInfo::Data.GetAllocationGranularityPageCount());
            return nullptr;
        }

        char * addressToReserve = nullptr;

        uint freeSegmentsBVIndex = BVInvalidIndex;
        size_t requestedNumOfSegments = dwSize / (AutoSystemInfo::Data.GetAllocationGranularityPageSize());
        Assert(requestedNumOfSegments <= MAXUINT32);

        if (lpAddress == nullptr)
        {
            Assert(requestedNumOfSegments != 0);
            AssertMsg(dwSize % AutoSystemInfo::Data.GetAllocationGranularityPageSize() == 0, "dwSize should be aligned with Allocation Granularity");

            do
            {
                freeSegmentsBVIndex = freeSegments.GetNextBit(freeSegmentsBVIndex + 1);
                //Return nullptr, if we don't have free/decommit pages to allocate
                if ((freeSegments.Length() - freeSegmentsBVIndex < requestedNumOfSegments) ||
                    freeSegmentsBVIndex == BVInvalidIndex)
                {
                    PreReservedHeapTrace(_u("No more space to commit in PreReserved Memory region.\n"));
                    return nullptr;
                }
            } while (!freeSegments.TestRange(freeSegmentsBVIndex, static_cast<uint>(requestedNumOfSegments)));

            uint offset = freeSegmentsBVIndex * AutoSystemInfo::Data.GetAllocationGranularityPageSize();
            addressToReserve = (char*) preReservedStartAddress + offset;

            //Check if the region is not already in MEM_COMMIT state.
            MEMORY_BASIC_INFORMATION memBasicInfo;
            size_t bytes = VirtualQuery(addressToReserve, &memBasicInfo, sizeof(memBasicInfo));
            if (bytes == 0
                || memBasicInfo.RegionSize < requestedNumOfSegments * AutoSystemInfo::Data.GetAllocationGranularityPageSize()
                || memBasicInfo.State == MEM_COMMIT
                )
            {
                CustomHeap_BadPageState_fatal_error((ULONG_PTR)this);
                return nullptr;
            }
        }
        else
        {
            //Check If the lpAddress is within the range of the preReserved Memory Region
            Assert(((char*) lpAddress) >= (char*) preReservedStartAddress || ((char*) lpAddress + dwSize) < GetPreReservedEndAddress());

            addressToReserve = (char*) lpAddress;
            freeSegmentsBVIndex = (uint) ((addressToReserve - (char*) preReservedStartAddress) / AutoSystemInfo::Data.GetAllocationGranularityPageSize());
#if DBG
            uint numOfSegments = (uint)ceil((double)dwSize / (double)AutoSystemInfo::Data.GetAllocationGranularityPageSize());
            Assert(numOfSegments != 0);
            Assert(freeSegmentsBVIndex + numOfSegments - 1 < freeSegments.Length());
            Assert(!freeSegments.TestRange(freeSegmentsBVIndex, numOfSegments));
#endif
        }

        AssertMsg(freeSegmentsBVIndex < PreReservedAllocationSegmentCount, "Invalid BitVector index calculation?");
        AssertMsg(dwSize % AutoSystemInfo::PageSize == 0, "COMMIT is managed at AutoSystemInfo::PageSize granularity");

        char * allocatedAddress = nullptr;

        if ((allocationType & MEM_COMMIT) != 0)
        {
#if defined(ENABLE_JIT_CLAMP)
            AutoEnableDynamicCodeGen enableCodeGen;
#endif

#if defined(_CONTROL_FLOW_GUARD)
            if (AutoSystemInfo::Data.IsCFGEnabled())
            {
                DWORD oldProtect = 0;
                DWORD allocProtectFlags = 0;

                if (AutoSystemInfo::Data.IsCFGEnabled())
                {
                    allocProtectFlags = PAGE_EXECUTE_RW_TARGETS_INVALID;
                }
                else
                {
                    allocProtectFlags = PAGE_EXECUTE_READWRITE;
                }

                allocatedAddress = (char *)VirtualAlloc(addressToReserve, dwSize, MEM_COMMIT, allocProtectFlags);

                if (allocatedAddress != nullptr)
                {
                    VirtualProtect(allocatedAddress, dwSize, protectFlags, &oldProtect);
                    AssertMsg(oldProtect == (PAGE_EXECUTE_READWRITE), "CFG Bitmap gets allocated and bits will be set to invalid only upon passing these flags.");
                }
            }
            else
#endif
            {
                allocatedAddress = (char *)VirtualAlloc(addressToReserve, dwSize, MEM_COMMIT, protectFlags);
            }
        }
        else
        {
            // Just return the uncommitted address if we didn't ask to commit it.
            allocatedAddress = addressToReserve;
        }

        // Keep track of the committed pages within the preReserved Memory Region
        if (lpAddress == nullptr && allocatedAddress != nullptr)
        {
            Assert(allocatedAddress == addressToReserve);
            Assert(requestedNumOfSegments != 0);
            freeSegments.ClearRange(freeSegmentsBVIndex, static_cast<uint>(requestedNumOfSegments));
        }

        PreReservedHeapTrace(_u("MEM_COMMIT: StartAddress: 0x%p of size: 0x%x * 0x%x bytes \n"), allocatedAddress, requestedNumOfSegments, AutoSystemInfo::Data.GetAllocationGranularityPageSize());
        return allocatedAddress;
    }
}
コード例 #19
0
ファイル: AsmJsTypes.cpp プロジェクト: dilijev/ChakraCore
 const char16 * AsmJsType::toChars() const
 {
     switch (which_)
     {
     case Double:      return _u("double");
     case MaybeDouble: return _u("double?");
     case DoubleLit:   return _u("doublelit");
     case Float:       return _u("float");
     case Floatish:    return _u("floatish");
     case FloatishDoubleLit: return _u("FloatishDoubleLit");
     case MaybeFloat:  return _u("float?");
     case Fixnum:      return _u("fixnum");
     case Int:         return _u("int");
     case Signed:      return _u("signed");
     case Unsigned:    return _u("unsigned");
     case Intish:      return _u("intish");
     case Void:        return _u("void");
     case Int32x4:     return _u("SIMD.Int32x4");
     case Bool32x4:    return _u("SIMD.Bool32x4");
     case Bool16x8:    return _u("SIMD.Bool16x8");
     case Bool8x16:    return _u("SIMD.Bool8x16");
     case Float32x4:   return _u("SIMD.Float32x4");
     case Float64x2:   return _u("SIMD.Float64x2");
     case Int16x8:     return _u("SIMD.Int16x8");
     case Int8x16:     return _u("SIMD.Int8x16");
     case Uint32x4:    return _u("SIMD.Uint32x4");
     case Uint16x8:    return _u("SIMD.Uint16x8");
     case Uint8x16:    return _u("SIMD.Uint8x16");
     }
     Assert(false);
     return _u("none");
 }
コード例 #20
0
AutoEnableDynamicCodeGen::AutoEnableDynamicCodeGen(bool enable) : enabled(false)
{
    if (enable == false)
    {
        return;
    }

    //
    // Snap the dynamic code generation policy for this process so that we
    // don't need to resolve APIs and query it each time. We expect the policy
    // to have been established upfront.
    //

    if (processPolicyObtained == false)
    {
        AutoCriticalSection autocs(&processPolicyCS);

        if (processPolicyObtained == false)
        {
            PGET_PROCESS_MITIGATION_POLICY_PROC GetProcessMitigationPolicyProc = nullptr;

            HMODULE module = GetModuleHandleW(_u("api-ms-win-core-processthreads-l1-1-3.dll"));

            if (module != nullptr)
            {
                GetProcessMitigationPolicyProc = (PGET_PROCESS_MITIGATION_POLICY_PROC) GetProcAddress(module, "GetProcessMitigationPolicy");
                SetThreadInformationProc = (PSET_THREAD_INFORMATION_PROC) GetProcAddress(module, "SetThreadInformation");
                GetThreadInformationProc = (PGET_THREAD_INFORMATION_PROC) GetProcAddress(module, "GetThreadInformation");
            }

            if ((GetProcessMitigationPolicyProc == nullptr) ||
                (!GetProcessMitigationPolicyProc(GetCurrentProcess(), ProcessDynamicCodePolicy, (PPROCESS_MITIGATION_DYNAMIC_CODE_POLICY) &processPolicy, sizeof(processPolicy))))
            {
                processPolicy.ProhibitDynamicCode = 0;
            }

            processPolicyObtained = true;
        }
    }

    //
    // The process is not prohibiting dynamic code or does not allow threads
    // to opt out.  In either case, return to the caller.
    //
    // N.B. It is OK that this policy is mutable at runtime. If a process
    //      really does not allow thread opt-out, then the call below will fail
    //      benignly.
    //
    
    if ((processPolicy.ProhibitDynamicCode == 0) || (processPolicy.AllowThreadOptOut == 0))
    {
        return;
    }

    if (SetThreadInformationProc == nullptr || GetThreadInformationProc == nullptr)
    {
        return;
    }

    // 
    // If dynamic code is already allowed for this thread, then don't attempt to allow it again.
    //

    DWORD threadPolicy;

    if ((GetThreadInformationProc(GetCurrentThread(), ThreadDynamicCodePolicy, &threadPolicy, sizeof(DWORD))) &&
        (threadPolicy == THREAD_DYNAMIC_CODE_ALLOW))
    {
        return;
    }

    threadPolicy = THREAD_DYNAMIC_CODE_ALLOW;

    BOOL result = SetThreadInformationProc(GetCurrentThread(), ThreadDynamicCodePolicy, &threadPolicy, sizeof(DWORD));
    Assert(result);

    enabled = true;
}
コード例 #21
0
const char16 *GetVtableName(VTableValue value)
{
    switch (value)
    {
#if !defined(_M_X64)
    case VtableJavascriptNumber:
        return _u("vtable JavascriptNumber");
        break;
#endif
    case VtableDynamicObject:
        return _u("vtable DynamicObject");
        break;
    case VtableInvalid:
        return _u("vtable Invalid");
        break;
    case VtablePropertyString:
        return _u("vtable PropertyString");
        break;
    case VtableJavascriptBoolean:
        return _u("vtable JavascriptBoolean");
        break;
    case VtableJavascriptArray:
        return _u("vtable JavascriptArray");
        break;
    case VtableInt8Array:
        return _u("vtable Int8Array");
        break;
    case VtableUint8Array:
        return _u("vtable Uint8Array");
        break;
    case VtableUint8ClampedArray:
        return _u("vtable Uint8ClampedArray");
        break;
    case VtableInt16Array:
        return _u("vtable Int16Array");
        break;
    case VtableUint16Array:
        return _u("vtable Uint16Array");
        break;
    case VtableInt32Array:
        return _u("vtable Int32Array");
        break;
    case VtableUint32Array:
        return _u("vtable Uint32Array");
        break;
    case VtableFloat32Array:
        return _u("vtable Float32Array");
        break;
    case VtableFloat64Array:
        return _u("vtable Float64Array");
        break;
    case VtableJavascriptPixelArray:
        return _u("vtable JavascriptPixelArray");
        break;
    case VtableInt64Array:
        return _u("vtable Int64Array");
        break;
    case VtableUint64Array:
        return _u("vtable Uint64Array");
        break;
    case VtableInt8VirtualArray:
        return _u("vtable Int8VirtualArray");
        break;
    case VtableUint8VirtualArray:
        return _u("vtable Uint8VirtualArray");
        break;
    case VtableUint8ClampedVirtualArray:
        return _u("vtable Uint8ClampedVirtualArray");
        break;
    case VtableInt16VirtualArray:
        return _u("vtable Int16VirtualArray");
        break;
    case VtableUint16VirtualArray:
        return _u("vtable Uint16VirtualArray");
        break;
    case VtableInt32VirtualArray:
        return _u("vtable Int32VirtualArray");
        break;
    case VtableUint32VirtualArray:
        return _u("vtable Uint32VirtualArray");
        break;
    case VtableFloat32VirtualArray:
        return _u("vtable Float32VirtualArray");
        break;
    case VtableFloat64VirtualArray:
        return _u("vtable Float64VirtualArray");
        break;
    case VtableBoolArray:
        return _u("vtable BoolArray");
        break;
    case VtableCharArray:
        return _u("vtable CharArray");
        break;
    case VtableNativeIntArray:
        return _u("vtable NativeIntArray");
        break;
    case VtableNativeFloatArray:
        return _u("vtable NativeFloatArray");
        break;
    case VtableJavascriptNativeIntArray:
        return _u("vtable JavascriptNativeIntArray");
        break;
    case VtableJavascriptRegExp:
        return _u("vtable JavascriptRegExp");
        break;
    case VtableStackScriptFunction:
        return _u("vtable StackScriptFunction");
        break;
    case VtableConcatStringMulti:
        return _u("vtable ConcatStringMulti");
        break;
    case VtableCompoundString:
        return _u("vtable CompoundString");
        break;
    default:
        Assert(false);
        break;
    }

    return _u("vtable unknown");
}
コード例 #22
0
ファイル: AsmJsUtils.cpp プロジェクト: muh00mad/ChakraCore
    void * UnboxAsmJsArguments(ScriptFunction* func, Var * origArgs, char * argDst, CallInfo callInfo)
    {
        void * address = reinterpret_cast<void*>(func->GetEntryPointInfo()->jsMethod);
        Assert(address);
        AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo();
        ScriptContext* scriptContext = func->GetScriptContext();

#if ENABLE_DEBUG_CONFIG_OPTIONS
        bool allowTestInputs = CONFIG_FLAG(WasmI64);
#endif
        ArgumentReader reader(&callInfo, origArgs);
        uint actualArgCount = reader.Info.Count - 1; // -1 for ScriptFunction
        argDst = argDst + MachPtr; // add one first so as to skip the ScriptFunction argument
        for (ArgSlot i = 0; i < info->GetArgCount(); i++)
        {

            if (info->GetArgType(i).isInt())
            {
                int32 intVal;
                if (i < actualArgCount)
                {
#if ENABLE_DEBUG_CONFIG_OPTIONS
                    if (allowTestInputs && JavascriptString::Is(*origArgs))
                    {
                        intVal = (int32)ConvertStringToInt64(*origArgs, scriptContext);
                    }
                    else
#endif
                        intVal = JavascriptMath::ToInt32(*origArgs, scriptContext);
                }
                else
                {
                    intVal = 0;
                }

#if TARGET_64
                *(int64*)(argDst) = 0;
#endif
                *(int32*)argDst = intVal;
                argDst = argDst + MachPtr;
            }
            else if (info->GetArgType(i).isInt64())
            {
#if ENABLE_DEBUG_CONFIG_OPTIONS
                if (!allowTestInputs)
#endif
                {
                    JavascriptError::ThrowTypeError(scriptContext, WASMERR_InvalidTypeConversion);
                }

#if ENABLE_DEBUG_CONFIG_OPTIONS
                int64 val;
                if (i < actualArgCount)
                {
                    if (JavascriptString::Is(*origArgs))
                    {
                        val = ConvertStringToInt64(*origArgs, scriptContext);
                    }
                    else if (JavascriptObject::Is(*origArgs))
                    {
                        RecyclableObject* object = RecyclableObject::FromVar(*origArgs);
                        PropertyRecord const * lowPropRecord = nullptr;
                        PropertyRecord const * highPropRecord = nullptr;
                        scriptContext->GetOrAddPropertyRecord(_u("low"), (int)wcslen(_u("low")), &lowPropRecord);
                        scriptContext->GetOrAddPropertyRecord(_u("high"), (int)wcslen(_u("high")), &highPropRecord);
                        Var low = JavascriptOperators::OP_GetProperty(object, lowPropRecord->GetPropertyId(), scriptContext);
                        Var high = JavascriptOperators::OP_GetProperty(object, highPropRecord->GetPropertyId(), scriptContext);

                        uint64 lowVal = JavascriptMath::ToInt32(low, scriptContext);
                        uint64 highVal = JavascriptMath::ToInt32(high, scriptContext);
                        val = (highVal << 32) | (lowVal & 0xFFFFFFFF);
                    }
                    else
                    {
                        int32 intVal = JavascriptMath::ToInt32(*origArgs, scriptContext);
                        val = (int64)intVal;
                    }
                }
                else
                {
                    val = 0;
                }

                *(int64*)(argDst) = val;
                argDst += sizeof(int64);
#endif
            }
            else if (info->GetArgType(i).isFloat())
            {
                float floatVal;
                if (i < actualArgCount)
                {
#if ENABLE_DEBUG_CONFIG_OPTIONS
                    if (allowTestInputs && JavascriptString::Is(*origArgs))
                    {
                        int32 val = (int32)ConvertStringToInt64(*origArgs, scriptContext);
                        floatVal = *(float*)&val;
                    }
                    else
#endif
                        floatVal = (float)(JavascriptConversion::ToNumber(*origArgs, scriptContext));
                }
                else
                {
                    floatVal = (float)(JavascriptNumber::NaN);
                }
#if TARGET_64
                *(int64*)(argDst) = 0;
#endif
                *(float*)argDst = floatVal;
                argDst = argDst + MachPtr;
            }
            else if (info->GetArgType(i).isDouble())
            {
                double doubleVal;
                if (i < actualArgCount)
                {
#if ENABLE_DEBUG_CONFIG_OPTIONS
                    if (allowTestInputs && JavascriptString::Is(*origArgs))
                    {
                        int64 val = ConvertStringToInt64(*origArgs, scriptContext);
                        doubleVal = *(double*)&val;
                    }
                    else
#endif
                        doubleVal = JavascriptConversion::ToNumber(*origArgs, scriptContext);
                }
                else
                {
                    doubleVal = JavascriptNumber::NaN;
                }

                *(double*)argDst = doubleVal;
                argDst = argDst + sizeof(double);
            }
            else if (info->GetArgType(i).isSIMD())
            {
                // Todo:: support test input for wasm.simd
                JavascriptError::ThrowTypeError(scriptContext, WASMERR_InvalidTypeConversion);
            }
            else
            {
                Assert(UNREACHED);
                JavascriptError::ThrowTypeError(scriptContext, WASMERR_InvalidTypeConversion);
            }
            ++origArgs;
        }

        AsmJsModuleInfo::EnsureHeapAttached(func);

        // for convenience, lets take the opportunity to return the asm.js entrypoint address
        return address;
    }
コード例 #23
0
// This only enables collection of the inlinee data, we are much more aggressive here.
// Actual decision of whether something is inlined or not is taken in CommitInlineIntoInliner
bool InliningDecider::DeciderInlineIntoInliner(Js::FunctionBody * inlinee, Js::FunctionBody * inliner, bool isConstructorCall, bool isPolymorphicCall, uint16 constantArgInfo, uint recursiveInlineDepth, bool allowRecursiveInlining)
{

    if (!CanRecursivelyInline(inlinee, inliner, allowRecursiveInlining, recursiveInlineDepth))
    {
        return false;
    }

    if (inliner->GetIsAsmjsMode() != inlinee->GetIsAsmjsMode())
    {
        return false;
    }
// Force inline all Js Builtins functions
// The existing JsBuiltInForceInline flag can work only when we explictly create scriptFunction
// We can also have methods that we define on the prototype like next of ArrayIterator for which we don't explictly create a script function
// TODO (megupta) : use forceInline for methods defined on the prototype using ObjectDefineProperty
    if (inlinee->GetSourceContextId() == Js::Constants::JsBuiltInSourceContextId ||
        PHASE_FORCE(Js::InlinePhase, this->topFunc) ||
        PHASE_FORCE(Js::InlinePhase, inliner) ||
        PHASE_FORCE(Js::InlinePhase, inlinee))
    {
        return true;
    }

    if (PHASE_OFF(Js::InlinePhase, this->topFunc) ||
        PHASE_OFF(Js::InlinePhase, inliner) ||
        PHASE_OFF(Js::InlinePhase, inlinee))
    {
        return false;
    }

    if (PHASE_FORCE(Js::InlineTreePhase, this->topFunc) ||
        PHASE_FORCE(Js::InlineTreePhase, inliner))
    {
        return true;
    }

    if (PHASE_FORCE(Js::InlineAtEveryCallerPhase, inlinee))
    {
        return true;
    }

    uint inlineeByteCodeCount = inlinee->GetByteCodeWithoutLDACount();

    // Heuristics are hit in the following order (Note *order* is important)
    // 1. Leaf function:  If the inlinee is a leaf (but not a constructor or a polymorphic call) inline threshold is LeafInlineThreshold (60). Also it can have max 1 loop
    // 2. Constant Function Argument: If the inlinee candidate has a constant argument and that argument is used for branching, then the inline threshold is ConstantArgumentInlineThreshold (157)
    // 3. InlineThreshold: If an inlinee candidate exceeds InlineThreshold just don't inline no matter what.

    // Following are additional constraint for an inlinee which meets InlineThreshold (Rule no 3)
    // 4. Rule for inlinee with loops:
    //      4a. Only single loop in inlinee is permitted.
    //      4b. Should not have polymorphic field access.
    //      4c. Should not be a constructor.
    //      4d. Should meet LoopInlineThreshold (25)
    // 5. Rule for polymorphic inlinee:
    //      4a. Should meet PolymorphicInlineThreshold (32)
    // 6. Rule for constructors:
    //       5a. Always inline if inlinee has polymorphic field access (as we have cloned runtime data).
    //       5b. If inlinee is monomorphic, inline only small constructors. They are governed by ConstructorInlineThreshold (21)
    // 7. Rule for inlinee which is not interpreted enough (as we might not have all the profile data):
    //       7a. As of now it is still governed by the InlineThreshold. Plan to play with this in future.
    // 8. Rest should be inlined.

    uint16 mask = constantArgInfo &  inlinee->m_argUsedForBranch;
    if (mask && inlineeByteCodeCount <  (uint)CONFIG_FLAG(ConstantArgumentInlineThreshold))
    {
        return true;
    }

    int inlineThreshold = threshold.inlineThreshold;
    if (!isPolymorphicCall && !isConstructorCall && IsInlineeLeaf(inlinee) && (inlinee->GetLoopCount() <= 2))
    {
        // Inlinee is a leaf function
        if (inlinee->GetLoopCount() == 0 || GetNumberOfInlineesWithLoop() <= (uint)threshold.maxNumberOfInlineesWithLoop) // Don't inlinee too many inlinees with loops.
        {
            // Negative LeafInlineThreshold disable the threshold
            if (threshold.leafInlineThreshold >= 0)
            {
                inlineThreshold += threshold.leafInlineThreshold - threshold.inlineThreshold;
            }
        }
    }

#if ENABLE_DEBUG_CONFIG_OPTIONS
    char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
    char16 debugStringBuffer2[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
    char16 debugStringBuffer3[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE];
#endif

    if (inlinee->GetHasLoops())
    {
        if (threshold.loopInlineThreshold < 0 ||                                     // Negative LoopInlineThreshold disable inlining with loop
            GetNumberOfInlineesWithLoop()  >(uint)threshold.maxNumberOfInlineesWithLoop || // See if we are inlining too many inlinees with loops.
            (inlinee->GetLoopCount() > 2) ||                                         // Allow at most 2 loops.
            inlinee->GetHasNestedLoop() ||                                           // Nested loops are not a good inlinee candidate
            isConstructorCall ||                                                     // If the function is constructor with loops, don't inline.
            PHASE_OFF(Js::InlineFunctionsWithLoopsPhase, this->topFunc))
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Has loops \tBytecode size: %d \tgetNumberOfInlineesWithLoop: %d\tloopCount: %d\thasNestedLoop: %d\tisConstructorCall:%d\tInlinee: %s (%s)\tCaller: %s (%s) \tRoot: %s (%s)\n"),
                inlinee->GetByteCodeCount(),
                GetNumberOfInlineesWithLoop(),
                inlinee->GetLoopCount(),
                inlinee->GetHasNestedLoop(),
                isConstructorCall,
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer),
                inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2),
                topFunc->GetDisplayName(), topFunc->GetDebugNumberSet(debugStringBuffer3));
            // Don't inline function with loops
            return false;
        }
        else
        {
            inlineThreshold -= (threshold.inlineThreshold > threshold.loopInlineThreshold) ? threshold.inlineThreshold - threshold.loopInlineThreshold : 0;
        }
    }

    if (isPolymorphicCall)
    {
        if (threshold.polymorphicInlineThreshold < 0 ||                              // Negative PolymorphicInlineThreshold disable inlining
            isConstructorCall)
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Polymorphic call under PolymorphicInlineThreshold: %d \tBytecode size: %d\tInlinee: %s (%s)\tCaller: %s (%s) \tRoot: %s (%s)\n"),
                threshold.polymorphicInlineThreshold,
                inlinee->GetByteCodeCount(),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer),
                inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2),
                topFunc->GetDisplayName(), topFunc->GetDebugNumberSet(debugStringBuffer3));
            return false;
        }
        else
        {
            inlineThreshold -= (threshold.inlineThreshold > threshold.polymorphicInlineThreshold) ? threshold.inlineThreshold - threshold.polymorphicInlineThreshold : 0;
        }
    }

    if (isConstructorCall)
    {
#pragma prefast(suppress: 6285, "logical-or of constants is by design")
        if (PHASE_OFF(Js::InlineConstructorsPhase, this->topFunc) ||
            PHASE_OFF(Js::InlineConstructorsPhase, inliner) ||
            PHASE_OFF(Js::InlineConstructorsPhase, inlinee) ||
            !CONFIG_FLAG(CloneInlinedPolymorphicCaches))
        {
            return false;
        }

        if (PHASE_FORCE(Js::InlineConstructorsPhase, this->topFunc) ||
            PHASE_FORCE(Js::InlineConstructorsPhase, inliner) ||
            PHASE_FORCE(Js::InlineConstructorsPhase, inlinee))
        {
            return true;
        }

        if (inlinee->HasDynamicProfileInfo() && inlinee->GetAnyDynamicProfileInfo()->HasPolymorphicFldAccess())
        {
            // As of now this is not dependent on bytecodeInlinedThreshold.
            return true;
        }

        // Negative ConstructorInlineThreshold always disable constructor inlining
        if (threshold.constructorInlineThreshold < 0)
        {
            INLINE_TESTTRACE(_u("INLINING: Skip Inline: Constructor with no polymorphic field access \tBytecode size: %d\tInlinee: %s (%s)\tCaller: %s (%s) \tRoot: %s (%s)\n"),
                inlinee->GetByteCodeCount(),
                inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer),
                inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2),
                topFunc->GetDisplayName(), topFunc->GetDebugNumberSet(debugStringBuffer3));
            // Don't inline constructor that does not have a polymorphic field access, or if cloning polymorphic inline
            // caches is disabled
            return false;
        }
        else
        {
            inlineThreshold -= (threshold.inlineThreshold > threshold.constructorInlineThreshold) ? threshold.inlineThreshold - threshold.constructorInlineThreshold : 0;
        }
    }

    if (threshold.forLoopBody)
    {
        inlineThreshold /= CONFIG_FLAG(InlineInLoopBodyScaleDownFactor);
    }

    if (inlineThreshold > 0 && inlineeByteCodeCount <= (uint)inlineThreshold)
    {
        if (inlinee->GetLoopCount())
        {
            IncrementNumberOfInlineesWithLoop();
        }
        return true;
    }
    else
    {
        INLINE_TESTTRACE(_u("INLINING: Skip Inline: Too long \tBytecode size: %d\tThreshold: %d\tInlinee: %s (%s)\tCaller: %s (%s) \tRoot: %s (%s)\n"),
            inlinee->GetByteCodeCount(),
            inlineThreshold,
            inlinee->GetDisplayName(), inlinee->GetDebugNumberSet(debugStringBuffer),
            inliner->GetDisplayName(), inliner->GetDebugNumberSet(debugStringBuffer2),
            topFunc->GetDisplayName(), topFunc->GetDebugNumberSet(debugStringBuffer3));
        return false;
    }
}
コード例 #24
0
ファイル: JSONParser.cpp プロジェクト: 280185386/ChakraCore
 Js::Var JSONParser::Parse(LPCWSTR str, int length)
 {
     if (length > MIN_CACHE_LENGTH)
     {
         if (!this->arenaAllocatorObject)
         {
             this->arenaAllocatorObject = scriptContext->GetTemporaryGuestAllocator(_u("JSONParse"));
             this->arenaAllocator = arenaAllocatorObject->GetAllocator();
         }
     }
     m_scanner.Init(str, length, &m_token, scriptContext, str, this->arenaAllocator);
     Scan();
     Js::Var ret = ParseObject();
     if (m_token.tk != tkEOF)
     {
         m_scanner.ThrowSyntaxError(JSERR_JsonSyntax);
     }
     return ret;
 }
コード例 #25
0
ファイル: Type.cpp プロジェクト: AlexElting/ChakraCore
namespace Js
{
    DEFINE_RECYCLER_TRACKER_WEAKREF_PERF_COUNTER(Type);

    InternalString Type::ObjectTypeNameString    = InternalString(_u("object"), 6);
    InternalString Type::UndefinedTypeNameString = InternalString(_u("undefined"), 9);
    InternalString Type::BooleanTypeNameString   = InternalString(_u("boolean"), 7);
    InternalString Type::StringTypeNameString    = InternalString(_u("string"), 6);
    InternalString Type::NumberTypeNameString    = InternalString(_u("number"), 6);
    InternalString Type::FunctionTypeNameString  = InternalString(_u("function"), 8);

    Type::Type(ScriptContext* scriptContext, TypeId typeId, RecyclableObject* prototype, JavascriptMethod entryPoint) :
        javascriptLibrary(scriptContext->GetLibrary()),
        typeId(typeId),
        prototype(prototype),
        propertyCache(nullptr),
        flags(TypeFlagMask_None)
    {
#ifdef PROFILE_TYPES
        if (typeId < sizeof(scriptContext->typeCount)/sizeof(int))
        {
            scriptContext->typeCount[typeId]++;
        }
#endif
        this->entryPoint = entryPoint != nullptr ? entryPoint : RecyclableObject::DefaultEntryPoint;
        if (prototype)
        {
            Assert(! CrossSite::NeedMarshalVar(prototype,scriptContext));
            prototype->SetIsPrototype();
        }
    }

    Type::Type(Type * type) :
        typeId(type->typeId),
        javascriptLibrary(type->javascriptLibrary),
        prototype(type->prototype),
        entryPoint(type->entryPoint),
        flags(type->flags),
        propertyCache(nullptr)
    {
#ifdef PROFILE_TYPES
        if (typeId < sizeof(javascriptLibrary->GetScriptContext()->typeCount)/sizeof(int))
        {
            javascriptLibrary->GetScriptContext()->typeCount[typeId]++;
        }
#endif
        Assert(! (prototype && CrossSite::NeedMarshalVar(prototype, javascriptLibrary->GetScriptContext())));

        // If the type property cache is copied over to this new type, then if a property ID caused the type to be changed for
        // the purpose of invalidating caches due to the property being deleted or its attributes being changed, then the cache
        // for that property ID must be cleared on this new type after the type property cache is copied. Also, types are not
        // changed consistently to use this copy constructor, so those would need to be fixed as well.

        if(type->AreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties())
        {
            SetAreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties(true);
        }
        if(type->IsFalsy())
        {
            SetIsFalsy(true);
        }
    }

    ScriptContext *
    Type::GetScriptContext() const
    {
        return GetLibrary()->GetScriptContext();
    }

    Recycler *
    Type::GetRecycler() const
    {
        return GetLibrary()->GetRecycler();
    }

    TypePropertyCache *Type::GetPropertyCache()
    {
        return propertyCache;
    }

    TypePropertyCache *Type::CreatePropertyCache()
    {
        Assert(!propertyCache);

        propertyCache = RecyclerNew(GetRecycler(), TypePropertyCache);
        return propertyCache;
    }

    void Type::SetAreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties(const bool truth)
    {
        if (truth)
        {
            if (GetScriptContext()->IsClosed())
            {
                // The cache is disabled after the script context is closed, to avoid issues between being closed and being deleted,
                // where the cache of these types in JavascriptLibrary may be reclaimed at any point
                return;
            }

            flags |= TypeFlagMask_AreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties;
            javascriptLibrary->TypeAndPrototypesAreEnsuredToHaveOnlyWritableDataProperties(this);
        }
        else
        {
            flags &= ~TypeFlagMask_AreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties;
        }
    }

    BOOL Type::AreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties() const
    {
        return flags & TypeFlagMask_AreThisAndPrototypesEnsuredToHaveOnlyWritableDataProperties;
    }

    BOOL Type::IsFalsy() const
    {
        return flags & TypeFlagMask_IsFalsy;
    }

    void Type::SetIsFalsy(const bool truth)
    {
        if (truth)
        {
            Assert(this->GetScriptContext()->GetThreadContext()->CanBeFalsy(this->GetTypeId()));
            flags |= TypeFlagMask_IsFalsy;
        }
        else
        {
            flags &= ~TypeFlagMask_IsFalsy;
        }
    }

    void Type::SetHasSpecialPrototype(const bool truth)
    {
        if (truth)
        {
            flags |= TypeFlagMask_HasSpecialPrototype;
        }
        else
        {
            flags &= ~TypeFlagMask_HasSpecialPrototype;
        }
    }

    uint32 Type::GetOffsetOfTypeId()
    {
        return offsetof(Type, typeId);
    }

    uint32 Type::GetOffsetOfFlags()
    {
        return offsetof(Type, flags);
    }

    uint32 Type::GetOffsetOfEntryPoint()
    {
        return offsetof(Type, entryPoint);
    }

    uint32 Type::GetOffsetOfPrototype()
    {
        return offsetof(Type, prototype);
    }

#if defined(PROFILE_RECYCLER_ALLOC) && defined(RECYCLER_DUMP_OBJECT_GRAPH)
    bool Type::DumpObjectFunction(type_info const * typeinfo, bool isArray, void * objectAddress)
    {
        if (isArray)
        {
            // Don't deal with array
            return false;
        }

        Output::Print(_u("%S{%x} %p"), typeinfo->name(), ((Type *)objectAddress)->GetTypeId(), objectAddress);
        return true;
    }
#endif
}
コード例 #26
0
    ///----------------------------------------------------------------------------
    ///
    /// ConfigFlagsTable::SetAsBoolean
    ///
    /// Set the value of a boolean flag. If the flag is a parent flag, all children flag
    //  will be set accordingly.
    ///
    ///----------------------------------------------------------------------------
    void
    ConfigFlagsTable::SetAsBoolean(Flag flag, Boolean value)
    {
        AssertMsg(this->GetFlagType(flag) == FlagBoolean, "flag not a boolean type");

        Boolean* settingAsBoolean = this->GetAsBoolean(flag);
        Assert(settingAsBoolean != nullptr);

        Output::VerboseNote(_u("FLAG %s = %d\n"), FlagNames[(int) flag], value);
        *settingAsBoolean = value;

        // check if parent flag
        if (this->IsParentFlag(flag))
        {
            // parent flag, will iterate through all child flags
            Flag childFlag = GetNextChildFlag(flag, /* no currentChildFlag */ InvalidFlag);
            while (childFlag != InvalidFlag)
            {
                Boolean childDefaultValue = GetDefaultValueAsBoolean(childFlag);

                // if the parent flag is TRUE, the children flag values are based on their default values
                // if the parent flag is FALSE, the children flag values are FALSE (always - as disabled)
                Boolean childValue = value == TRUE ? childDefaultValue : FALSE;

                Output::VerboseNote(_u("FLAG %s = %d - setting child flag %s = %d\n"), FlagNames[(int) flag], value, FlagNames[(int) childFlag], childValue);
                this->SetAsBoolean(childFlag, childValue);

                // get next child flag
                childFlag = GetNextChildFlag(flag, /* currentChildFlag */ childFlag);
            }
        }

#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
        // in case the flag is marked as 'callback' - to call the method
#define FLAG(type, name, description, defaultValue, parentName, hasCallback) FLAGCALLBACK##hasCallback(type, name)
#define FLAGCALLBACKFALSE(type, name)
#define FLAGCALLBACKTRUE(type, name)    FLAGDOCALLBACK##type(name)

        // define an overload for each FlagTypes - type
            //   * all defaults we don't care about - should assert
#define FLAGDOCALLBACKNumberRange(name)        Assert(false);
#define FLAGDOCALLBACKPhases(name)        Assert(false);
#define FLAGDOCALLBACKString(name)        Assert(false);
#define FLAGDOCALLBACKNumber(name)        Assert(false);
#define FLAGDOCALLBACKNumberSet(name)     Assert(false);
#define FLAGDOCALLBACKNumberPairSet(name) Assert(false);
#define FLAGDOCALLBACKNumberTrioSet(name) Assert(false);
            //   * and those we do care about
#define FLAGDOCALLBACKBoolean(name)       if( flag == name##Flag ) this->FlagSetCallback_##name(value);

#include "ConfigFlagsList.h"

#undef FLAGDOCALLBACKBoolean
#undef FLAGDOCALLBACKNumberRange
#undef FLAGDOCALLBACKNumberPairSet
#undef FLAGDOCALLBACKNumberTrioSet
#undef FLAGDOCALLBACKNumberSet
#undef FLAGDOCALLBACKNumber
#undef FLAGDOCALLBACKString
#undef FLAGDOCALLBACKPhases
#undef FLAGCALLBACKTRUE
#undef FLAGCALLBACKFALSE
#undef FLAG
#endif
    }
コード例 #27
0
ファイル: Jobs.cpp プロジェクト: ianwjhalliday/ChakraCore
void BackgroundJobProcessor::InitializeParallelThreadData(AllocationPolicyManager* policyManager, bool disableParallelThreads)
{
    if (!disableParallelThreads)
    {
        InitializeThreadCount();
    }
    else
    {
        this->maxThreadCount = 1;
    }

    Assert(this->maxThreadCount >= 1);
    this->parallelThreadData = HeapNewArrayZ(ParallelThreadData*, this->maxThreadCount);

    for (uint i = 0; i < this->maxThreadCount; i++)
    {
        this->parallelThreadData[i] = HeapNewNoThrow(ParallelThreadData, policyManager);

        if (this->parallelThreadData[i] == nullptr)
        {
            if (i == 0)
            {
                HeapDeleteArray(this->maxThreadCount, this->parallelThreadData);
                Js::Throw::OutOfMemory();
            }
            // At least one thread is created, continue
            break;
        }

        this->parallelThreadData[i]->processor = this;
        // Make sure to create the thread suspended so the thread handle can be assigned before the thread starts running
        this->parallelThreadData[i]->threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, &StaticThreadProc, this->parallelThreadData[i], CREATE_SUSPENDED, 0));
        if (!this->parallelThreadData[i]->threadHandle)
        {
            HeapDelete(parallelThreadData[i]);
            parallelThreadData[i] = nullptr;
            if (i == 0)
            {
                Js::Throw::OutOfMemory();
            }
            // At least one thread is created, continue
            break;
        }

        if (ResumeThread(this->parallelThreadData[i]->threadHandle) == static_cast<DWORD>(-1))
        {
            CloseHandle(this->parallelThreadData[i]->threadHandle);
            HeapDelete(parallelThreadData[i]);
            this->parallelThreadData[i] = nullptr;

            if (i == 0)
            {
                Js::Throw::OutOfMemory();
            }
            // At least one thread is created, continue
            break;
        }

        this->threadCount++;

        // Wait for the thread to fully start. This is necessary because Close may be called before the thread starts and if
        // Close is called while holding the loader lock during DLL_THREAD_DETACH, the thread may be stuck waiting for the
        // loader lock for DLL_THREAD_ATTACH to start up, and Close would then end up waiting forever, causing a deadlock.
        WaitWithThreadForThreadStartedOrClosingEvent(this->parallelThreadData[i]);
        this->parallelThreadData[i]->threadStartedOrClosing.Reset(); // after this, the event will be used to wait for the thread to close

#if DBG_DUMP
        if (i < (sizeof(DebugThreadNames) / sizeof(DebugThreadNames[i])))
        {
            this->parallelThreadData[i]->backgroundPageAllocator.debugName = DebugThreadNames[i];
        }
        else
        {
            this->parallelThreadData[i]->backgroundPageAllocator.debugName = _u("BackgroundJobProcessor thread");
        }
#endif
    }

    Assert(this->threadCount >= 1);
}
コード例 #28
0
    void ConfigFlagsTable::TranslateFlagConfiguration()
    {
        const auto VerifyExecutionModeLimits = [this]()
        {
            const Number zero = static_cast<Number>(0);
            const Number maxUint8 = static_cast<Number>(static_cast<uint8>(-1)); // entry point call count is uint8
            const Number maxUint16 = static_cast<Number>(static_cast<uint16>(-1));

        #if ENABLE_DEBUG_CONFIG_OPTIONS
            Assert(MinInterpretCount >= zero);
            Assert(MinInterpretCount <= maxUint16);
            Assert(MaxInterpretCount >= zero);
            Assert(MaxInterpretCount <= maxUint16);
            Assert(MinSimpleJitRunCount >= zero);
            Assert(MinSimpleJitRunCount <= maxUint8);
            Assert(MaxSimpleJitRunCount >= zero);
            Assert(MaxSimpleJitRunCount <= maxUint8);

            Assert(SimpleJitAfter >= zero);
            Assert(SimpleJitAfter <= maxUint8);
            Assert(FullJitAfter >= zero);
            Assert(FullJitAfter <= maxUint16);
        #endif

            Assert(AutoProfilingInterpreter0Limit >= zero);
            Assert(AutoProfilingInterpreter0Limit <= maxUint16);
            Assert(ProfilingInterpreter0Limit >= zero);
            Assert(ProfilingInterpreter0Limit <= maxUint16);
            Assert(AutoProfilingInterpreter1Limit >= zero);
            Assert(AutoProfilingInterpreter1Limit <= maxUint16);
            Assert(SimpleJitLimit >= zero);
            Assert(SimpleJitLimit <= maxUint8);
            Assert(ProfilingInterpreter1Limit >= zero);
            Assert(ProfilingInterpreter1Limit <= maxUint16);
            Assert(
                (
                    AutoProfilingInterpreter0Limit +
                    ProfilingInterpreter0Limit +
                    AutoProfilingInterpreter1Limit +
                    SimpleJitLimit +
                    ProfilingInterpreter1Limit
                ) <= maxUint16);
        };
        VerifyExecutionModeLimits();

    #if ENABLE_DEBUG_CONFIG_OPTIONS
    #if !DISABLE_JIT
        if(ForceDynamicProfile)
        {
            Force.Enable(DynamicProfilePhase);
        }
        if(ForceJITLoopBody)
        {
            Force.Enable(JITLoopBodyPhase);
        }
    #endif
        if(NoDeferParse)
        {
            Off.Enable(DeferParsePhase);
        }
    #endif

    #if ENABLE_DEBUG_CONFIG_OPTIONS && !DISABLE_JIT
        bool dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = false;
        if((IsEnabled(MinInterpretCountFlag) || IsEnabled(MaxInterpretCountFlag)) &&
            !(IsEnabled(SimpleJitAfterFlag) || IsEnabled(FullJitAfterFlag)))
        {
            if(Off.IsEnabled(SimpleJitPhase))
            {
                Enable(FullJitAfterFlag);
                if(IsEnabled(MaxInterpretCountFlag))
                {
                    FullJitAfter = MaxInterpretCount;
                }
                else
                {
                    FullJitAfter = MinInterpretCount;
                    dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = true;
                }
            }
            else
            {
                Enable(SimpleJitAfterFlag);
                if(IsEnabled(MaxInterpretCountFlag))
                {
                    SimpleJitAfter = MaxInterpretCount;
                }
                else
                {
                    SimpleJitAfter = MinInterpretCount;
                    dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = true;
                }
                if((IsEnabled(MinInterpretCountFlag) && IsEnabled(MinSimpleJitRunCountFlag)) ||
                    IsEnabled(MaxSimpleJitRunCountFlag))
                {
                    Enable(FullJitAfterFlag);
                    FullJitAfter = SimpleJitAfter;
                    if(IsEnabled(MaxSimpleJitRunCountFlag))
                    {
                        FullJitAfter += MaxSimpleJitRunCount;
                    }
                    else
                    {
                        FullJitAfter += MinSimpleJitRunCount;
                        Assert(dontEnforceLimitsForSimpleJitAfterOrFullJitAfter);
                    }
                }
            }
        }

        // Configure execution mode limits
        do
        {
            if(IsEnabled(AutoProfilingInterpreter0LimitFlag) ||
                IsEnabled(ProfilingInterpreter0LimitFlag) ||
                IsEnabled(AutoProfilingInterpreter1LimitFlag) ||
                IsEnabled(SimpleJitLimitFlag) ||
                IsEnabled(ProfilingInterpreter1LimitFlag))
            {
                break;
            }

            if(IsEnabled(ExecutionModeLimitsFlag))
            {
                uint autoProfilingInterpreter0Limit;
                uint profilingInterpreter0Limit;
                uint autoProfilingInterpreter1Limit;
                uint simpleJitLimit;
                uint profilingInterpreter1Limit;
                const int scannedCount =
                    swscanf_s(
                        static_cast<LPCWSTR>(ExecutionModeLimits),
                        _u("%u.%u.%u.%u.%u"),
                        &autoProfilingInterpreter0Limit,
                        &profilingInterpreter0Limit,
                        &autoProfilingInterpreter1Limit,
                        &simpleJitLimit,
                        &profilingInterpreter1Limit);
                Assert(scannedCount == 5);

                Enable(AutoProfilingInterpreter0LimitFlag);
                Enable(ProfilingInterpreter0LimitFlag);
                Enable(AutoProfilingInterpreter1LimitFlag);
                Enable(SimpleJitLimitFlag);
                Enable(ProfilingInterpreter1LimitFlag);

                AutoProfilingInterpreter0Limit = autoProfilingInterpreter0Limit;
                ProfilingInterpreter0Limit = profilingInterpreter0Limit;
                AutoProfilingInterpreter1Limit = autoProfilingInterpreter1Limit;
                SimpleJitLimit = simpleJitLimit;
                ProfilingInterpreter1Limit = profilingInterpreter1Limit;
                break;
            }

            if(!NewSimpleJit)
            {
                // Use the defaults for old simple JIT. The flags are not enabled here because the values can be changed later
                // based on other flags, only the defaults values are adjusted here.
                AutoProfilingInterpreter0Limit = DEFAULT_CONFIG_AutoProfilingInterpreter0Limit;
                ProfilingInterpreter0Limit = DEFAULT_CONFIG_ProfilingInterpreter0Limit;
                CompileAssert(
                    DEFAULT_CONFIG_AutoProfilingInterpreter0Limit <= DEFAULT_CONFIG_AutoProfilingInterpreterLimit_OldSimpleJit);
                AutoProfilingInterpreter1Limit =
                    DEFAULT_CONFIG_AutoProfilingInterpreterLimit_OldSimpleJit - DEFAULT_CONFIG_AutoProfilingInterpreter0Limit;
                CompileAssert(DEFAULT_CONFIG_ProfilingInterpreter0Limit <= DEFAULT_CONFIG_SimpleJitLimit_OldSimpleJit);
                SimpleJitLimit = DEFAULT_CONFIG_SimpleJitLimit_OldSimpleJit - DEFAULT_CONFIG_ProfilingInterpreter0Limit;
                ProfilingInterpreter1Limit = 0;
                VerifyExecutionModeLimits();
            }

            if (IsEnabled(SimpleJitAfterFlag))
            {
                Enable(AutoProfilingInterpreter0LimitFlag);
                Enable(ProfilingInterpreter0LimitFlag);
                Enable(AutoProfilingInterpreter1LimitFlag);
                Enable(EnforceExecutionModeLimitsFlag);

                {
                    Js::Number iterationsNeeded = SimpleJitAfter;
                    ProfilingInterpreter0Limit = min(ProfilingInterpreter0Limit, iterationsNeeded);
                    iterationsNeeded -= ProfilingInterpreter0Limit;
                    AutoProfilingInterpreter0Limit = iterationsNeeded;
                    AutoProfilingInterpreter1Limit = 0;
                }

                if(IsEnabled(FullJitAfterFlag))
                {
                    Enable(SimpleJitLimitFlag);
                    Enable(ProfilingInterpreter1LimitFlag);

                    Assert(SimpleJitAfter <= FullJitAfter);
                    Js::Number iterationsNeeded = FullJitAfter - SimpleJitAfter;
                    Js::Number profilingIterationsNeeded =
                        min(NewSimpleJit
                                ? DEFAULT_CONFIG_MinProfileIterations
                                : DEFAULT_CONFIG_MinProfileIterations_OldSimpleJit,
                            FullJitAfter) -
                        ProfilingInterpreter0Limit;
                    if(NewSimpleJit)
                    {
                        ProfilingInterpreter1Limit = min(ProfilingInterpreter1Limit, iterationsNeeded);
                        iterationsNeeded -= ProfilingInterpreter1Limit;
                        profilingIterationsNeeded -= ProfilingInterpreter1Limit;
                        SimpleJitLimit = iterationsNeeded;
                    }
                    else
                    {
                        SimpleJitLimit = iterationsNeeded;
                        profilingIterationsNeeded -= min(SimpleJitLimit, profilingIterationsNeeded);
                        ProfilingInterpreter1Limit = 0;
                    }

                    if(profilingIterationsNeeded != 0)
                    {
                        Js::Number iterationsToMove = min(AutoProfilingInterpreter1Limit, profilingIterationsNeeded);
                        AutoProfilingInterpreter1Limit -= iterationsToMove;
                        ProfilingInterpreter0Limit += iterationsToMove;
                        profilingIterationsNeeded -= iterationsToMove;

                        iterationsToMove = min(AutoProfilingInterpreter0Limit, profilingIterationsNeeded);
                        AutoProfilingInterpreter0Limit -= iterationsToMove;
                        ProfilingInterpreter0Limit += iterationsToMove;
                        profilingIterationsNeeded -= iterationsToMove;

                        Assert(profilingIterationsNeeded == 0);
                    }

                    Assert(
                        (
                            AutoProfilingInterpreter0Limit +
                            ProfilingInterpreter0Limit +
                            AutoProfilingInterpreter1Limit +
                            SimpleJitLimit +
                            ProfilingInterpreter1Limit
                        ) == FullJitAfter);
                }

                Assert(
                    (
                        AutoProfilingInterpreter0Limit +
                        ProfilingInterpreter0Limit +
                        AutoProfilingInterpreter1Limit
                    ) == SimpleJitAfter);
                EnforceExecutionModeLimits = true;
                break;
            }

            if(IsEnabled(FullJitAfterFlag))
            {
                Enable(AutoProfilingInterpreter0LimitFlag);
                Enable(ProfilingInterpreter0LimitFlag);
                Enable(AutoProfilingInterpreter1LimitFlag);
                Enable(SimpleJitLimitFlag);
                Enable(ProfilingInterpreter1LimitFlag);
                Enable(EnforceExecutionModeLimitsFlag);

                Js::Number iterationsNeeded = FullJitAfter;
                if(NewSimpleJit)
                {
                    ProfilingInterpreter1Limit = min(ProfilingInterpreter1Limit, iterationsNeeded);
                    iterationsNeeded -= ProfilingInterpreter1Limit;
                }
                else
                {
                    ProfilingInterpreter1Limit = 0;
                    SimpleJitLimit = min(SimpleJitLimit, iterationsNeeded);
                    iterationsNeeded -= SimpleJitLimit;
                }
                ProfilingInterpreter0Limit = min(ProfilingInterpreter0Limit, iterationsNeeded);
                iterationsNeeded -= ProfilingInterpreter0Limit;
                if(NewSimpleJit)
                {
                    SimpleJitLimit = min(SimpleJitLimit, iterationsNeeded);
                    iterationsNeeded -= SimpleJitLimit;
                }
                AutoProfilingInterpreter0Limit = min(AutoProfilingInterpreter0Limit, iterationsNeeded);
                iterationsNeeded -= AutoProfilingInterpreter0Limit;
                AutoProfilingInterpreter1Limit = iterationsNeeded;

                Assert(
                    (
                        AutoProfilingInterpreter0Limit +
                        ProfilingInterpreter0Limit +
                        AutoProfilingInterpreter1Limit +
                        SimpleJitLimit +
                        ProfilingInterpreter1Limit
                    ) == FullJitAfter);
                EnforceExecutionModeLimits = true;
                break;
            }
            if (IsEnabled(MaxTemplatizedJitRunCountFlag))
            {
                if (MaxTemplatizedJitRunCount >= 0)
                {
                    MinTemplatizedJitRunCount = MaxTemplatizedJitRunCount;
                }
            }
            if (IsEnabled(MaxAsmJsInterpreterRunCountFlag))
            {
                if (MaxAsmJsInterpreterRunCount >= 0)
                {
                    MinAsmJsInterpreterRunCount = MaxAsmJsInterpreterRunCount;
                }
            }

        } while(false);
    #endif

        if( (
            #ifdef ENABLE_PREJIT
                Prejit ||
            #endif
                ForceNative
            ) &&
            !NoNative)
        {
            Enable(AutoProfilingInterpreter0LimitFlag);
            Enable(ProfilingInterpreter0LimitFlag);
            Enable(AutoProfilingInterpreter1LimitFlag);
            Enable(EnforceExecutionModeLimitsFlag);

            // Override any relevant automatic configuration above
            AutoProfilingInterpreter0Limit = 0;
            ProfilingInterpreter0Limit = 0;
            AutoProfilingInterpreter1Limit = 0;
        #if ENABLE_DEBUG_CONFIG_OPTIONS
            if(Off.IsEnabled(SimpleJitPhase))
            {
                Enable(SimpleJitLimitFlag);
                Enable(ProfilingInterpreter1LimitFlag);

                SimpleJitLimit = 0;
                ProfilingInterpreter1Limit = 0;
            }
        #endif

            EnforceExecutionModeLimits = true;
        }

        VerifyExecutionModeLimits();
    }
コード例 #29
0
ファイル: Debugger.cpp プロジェクト: Rastaban/ChakraCore
bool Debugger::CompareOrWriteBaselineFile(LPCSTR fileName)
{
    AutoRestoreContext autoRestoreContext(this->m_context);

    // Pass in undefined for 'this'
    JsValueRef undefinedRef;
    IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsGetUndefinedValue(&undefinedRef));

    JsValueRef result = JS_INVALID_REFERENCE;

    bool testPassed = false;

    if (HostConfigFlags::flags.dbgbaselineIsEnabled)
    {
        this->CallFunction("Verify", &result);
        JsValueRef numberVal;
        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsConvertValueToNumber(result, &numberVal));
        int val;
        IfJsrtErrorFailLogAndRetFalse(ChakraRTInterface::JsNumberToInt(numberVal, &val));
        testPassed = (val == 0);
    }

    if (!testPassed)
    {
        this->CallFunction("GetOutputJson", &result);

        AutoString baselineData;
        IfJsrtErrorFailLogAndRetFalse(baselineData.Initialize(result));

        char16 baselineFilename[256];
        swprintf_s(baselineFilename, HostConfigFlags::flags.dbgbaselineIsEnabled ? _u("%S.dbg.baseline.rebase") : _u("%S.dbg.baseline"), fileName);

        FILE *file = nullptr;
        if (_wfopen_s(&file, baselineFilename, _u("wt")) != 0)
        {
            return false;
        }

        if (file != nullptr)
        {
            int countWritten = static_cast<int>(fwrite(baselineData.GetString(), sizeof(char), baselineData.GetLength(), file));
            Assert(baselineData.GetLength() <= INT_MAX);
            if (countWritten != (int)baselineData.GetLength())
            {
                Assert(false);
                return false;
            }

            fclose(file);
        }

        if (!HostConfigFlags::flags.dbgbaselineIsEnabled)
        {
            wprintf(_u("No baseline file specified, baseline created at '%s'\n"), baselineFilename);
        }
        else
        {
            Helpers::LogError(_u("Rebase file created at '%s'\n"), baselineFilename);
        }
    }

    return true;
}
コード例 #30
0
Js::Var WabtInterface::EntryConvertWast2Wasm(RecyclableObject* function, CallInfo callInfo, ...)
{
    ScriptContext* scriptContext = function->GetScriptContext();
    PROBE_STACK(function->GetScriptContext(), Constants::MinStackDefault);

    ARGUMENTS(args, callInfo);
    AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");

    Assert(!(callInfo.Flags & CallFlags_New));

    if (args.Info.Count < 2 || !JavascriptString::Is(args[1]))
    {
        JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedBufferSource);
    }
    bool isSpecText = false;
    if (args.Info.Count > 2)
    {
        // optional config object
        if (!JavascriptOperators::IsObject(args[2]))
        {
            JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject, _u("config"));
        }
        DynamicObject * configObject = JavascriptObject::FromVar(args[2]);

        Js::Var isSpecVar = JavascriptOperators::OP_GetProperty(configObject, PropertyIds::spec, scriptContext);
        isSpecText = JavascriptConversion::ToBool(isSpecVar, scriptContext);
    }

    ArenaAllocator arena(_u("Wast2Wasm"), scriptContext->GetThreadContext()->GetPageAllocator(), Throw::OutOfMemory);
    Context context;
    size_t wastSize;
    char* wastBuffer = nullptr;

    ENTER_PINNED_SCOPE(JavascriptString, string);
    string = (JavascriptString*)args[1];
    const char16* str = string->GetString();
    context.allocator = &arena;
    context.scriptContext = scriptContext;

    size_t origSize = string->GetLength();
    auto allocator = [&arena](size_t size) {return (utf8char_t*)AnewArray(&arena, byte, size);};
    utf8::WideStringToNarrow(allocator, str, origSize, &wastBuffer, &wastSize);
    LEAVE_PINNED_SCOPE();   //  string

    try
    {
        ChakraWabt::SpecContext spec;
        ChakraWabt::ChakraContext wabtCtx;
        wabtCtx.user_data = &context;
        wabtCtx.createBuffer = CreateBuffer;
        wabtCtx.features.sign_extends = CONFIG_FLAG(WasmSignExtends);
        if (isSpecText)
        {
            wabtCtx.spec = &spec;
            spec.setProperty = SetProperty;
            spec.int32ToVar = Int32ToVar;
            spec.int64ToVar = Int64ToVar;
            spec.stringToVar = StringToVar;
            spec.createObject = CreateObject;
            spec.createArray = CreateArray;
            spec.push = Push;
        }
        void* result = ChakraWabt::ConvertWast2Wasm(wabtCtx, wastBuffer, (uint)wastSize, isSpecText);
        if (result == nullptr)
        {
            return scriptContext->GetLibrary()->GetUndefined();
        }
        return result;
    }
    catch (ChakraWabt::Error& e)
    {
        JavascriptError::ThrowTypeErrorVar(scriptContext, WABTERR_WabtError, NarrowStringToWide(&context, e.message));
    }
}