コード例 #1
0
    void HandleHelperOrLibraryMethodWrapperException(ScriptContext * scriptContext, JavascriptExceptionObject * exceptionObject)
    {
        Assert(scriptContext);
        Assert(exceptionObject);

        // Note: there also could be plain OutOfMemoryException and StackOverflowException, no special handling for these.
        if (!exceptionObject->IsDebuggerSkip() ||
            exceptionObject == scriptContext->GetThreadContext()->GetPendingOOMErrorObject() ||
            exceptionObject == scriptContext->GetThreadContext()->GetPendingSOErrorObject())
        {
            JavascriptExceptionOperators::DoThrowCheckClone(exceptionObject, scriptContext);
        }

        if (doCheckParentInterpreterFrame)
        {
            // Note: JavascriptStackWalker is slow, but this is not hot path at all.
            // Note: we treat internal script code (such as Intl) as library code, thus
            //       ignore isLibraryCode=true callers.
            bool isTopUserFrameNative;
            bool isTopUserFrameJavaScript = Js::JavascriptStackWalker::TryIsTopJavaScriptFrameNative(
                scriptContext, &isTopUserFrameNative, /* ignoreLibraryCode = */ true);
            AssertMsg(isTopUserFrameJavaScript, "How could we get non-javascript frame on exception?");

            if (isTopUserFrameJavaScript && !isTopUserFrameNative)
            {
                // If parent frame is interpreter frame, it already has try-catch around all calls,
                // so that we don't need any special handling here.
                JavascriptExceptionOperators::DoThrowCheckClone(exceptionObject, scriptContext);
            }
        }

        Assert(exceptionObject->IsDebuggerSkip());
        int nextStatementOffset;
        int offsetFromDebugger = exceptionObject->GetByteCodeOffsetAfterDebuggerSkip();
        if (offsetFromDebugger != DebuggingFlags::InvalidByteCodeOffset)
        {
            // The offset is already set for us by debugger (such as by set next statement).
            nextStatementOffset = offsetFromDebugger;
        }
        else
        {
            ByteCodeReader reader;
            reader.Create(exceptionObject->GetFunctionBody(), exceptionObject->GetByteCodeOffset());
            // Determine offset for next statement here.
            if (!scriptContext->GetDebugContext()->GetProbeContainer()->GetNextUserStatementOffsetForAdvance(
                exceptionObject->GetFunctionBody(), &reader, exceptionObject->GetByteCodeOffset(), &nextStatementOffset))
            {
                // Can't advance.
                JavascriptExceptionOperators::DoThrowCheckClone(exceptionObject, scriptContext);
            }
        }

        // Continue after exception.
        // Note: for this scenario InterpreterStackFrame::DebugProcess resets its state,
        // looks like we don't need to that because we start with brand new interpreter frame.

        // Indicate to bailout check that we should bail out for/into debugger and set the byte code offset to one of next statement.
        scriptContext->GetThreadContext()->GetDebugManager()->GetDebuggingFlags()->SetByteCodeOffsetAndFuncAfterIgnoreException(
            nextStatementOffset, exceptionObject->GetFunctionBody()->GetFunctionNumber());
    }
コード例 #2
0
    void AsmJsByteCodeDumper::Dump(AsmJsFunc* func, FunctionBody* body)
    {
        ByteCodeReader reader;
        reader.Create(body);
        StatementReader statementReader;
        statementReader.Create(body);
        body->DumpFullFunctionName();
        Output::Print(L" Asm.js (");
        const ArgSlot argCount = func->GetArgCount();
        for (ArgSlot i = 0; i < argCount; i++)
        {
            AsmJsType var = func->GetArgType(i);
            if (i > 0)
            {
                Output::Print(L", ");
            }
            if (var.isDouble())
            {
                Output::Print(L"+In%hu", i);
            }
            else if (var.isFloat())
            {
                Output::Print(L"flt(In%hu)", i);
            }
            else if (var.isInt())
            {
                Output::Print(L"In%hu|0", i);
            }
            else if (var.isSIMDType())
            {
                switch (var.GetWhich())
                {
                case AsmJsType::Int32x4:
                    Output::Print(L"I4(In%hu)", i);
                    break;
                case AsmJsType::Float32x4:
                    Output::Print(L"F4(In%hu)", i);
                    break;
                case AsmJsType::Float64x2:
                    Output::Print(L"D2(In%hu)", i);
                    break;
                }
            }
            else
            {
                Assert(UNREACHED);
            }
        }

        Output::Print(L") ");
        Output::Print(L"(size: %d [%d])\n", body->GetByteCodeCount(), body->GetByteCodeWithoutLDACount());
        const auto& intRegisters = func->GetRegisterSpace<int>();
        const auto& doubleRegisters = func->GetRegisterSpace<double>();
        const auto& floatRegisters = func->GetRegisterSpace<float>();
        Output::Print(
            L"      Integer : %u locals (%u temps from I%u)\n",
            intRegisters.GetVarCount(),
            intRegisters.GetTmpCount(),
            intRegisters.GetFirstTmpRegister());
        Output::Print(
            L"      Doubles : %u locals (%u temps from D%u)\n",
            doubleRegisters.GetVarCount(),
            doubleRegisters.GetTmpCount(),
            doubleRegisters.GetFirstTmpRegister());

        Output::Print(
            L"      Floats : %u locals (%u temps from F%u)\n",
            floatRegisters.GetVarCount(),
            floatRegisters.GetTmpCount(),
            floatRegisters.GetFirstTmpRegister());

        const auto& simdRegisters = func->GetRegisterSpace<AsmJsSIMDValue>();
        Output::Print(
            L"      SIMDs : %u locals (%u temps from SIMD%u)\n",
            simdRegisters.GetVarCount(),
            simdRegisters.GetTmpCount(),
            simdRegisters.GetFirstTmpRegister());

        uint32 statementIndex = 0;
        DumpConstants(func, body);

        Output::Print(L"    Implicit Arg Ins:\n    ======== =====\n    ");
        int iArg = intRegisters.GetConstCount(), dArg = doubleRegisters.GetConstCount(), fArg = floatRegisters.GetConstCount();
        int simdArg = simdRegisters.GetConstCount();
        for (ArgSlot i = 0; i < argCount; i++)
        {
            const AsmJsType& var = func->GetArgType(i);
            if (var.isDouble())
            {
                Output::Print(L" D%d  In%d", dArg++, i);
            }
            else if (var.isFloat())
            {
                Output::Print(L" F%d  In%d", fArg++, i);
            }
            else if (var.isInt())
            {
                Output::Print(L" I%d  In%d", iArg++, i);
            }
            else if (var.isSIMDType())
            {
                Output::Print(L" SIMD%d  In%d", simdArg++, i);
            }
            else
            {
                Assert(UNREACHED);
            }
            Output::Print(L"\n    ");
        }
        Output::Print(L"\n");

        if (func->GetReturnType() == AsmJsRetType::Void)
        {
            Output::Print(L"    0000   %-20s R0\n", OpCodeUtilAsmJs::GetOpCodeName(OpCodeAsmJs::LdUndef));
        }

        while (true)
        {
            while (statementReader.AtStatementBoundary(&reader))
            {
                body->PrintStatementSourceLine(statementIndex);
                statementIndex = statementReader.MoveNextStatementBoundary();
            }
            int byteOffset = reader.GetCurrentOffset();
            LayoutSize layoutSize;
            OpCodeAsmJs op = (OpCodeAsmJs)reader.ReadOp(layoutSize);
            if (op == OpCodeAsmJs::EndOfBlock)
            {
                Assert(reader.GetCurrentOffset() == body->GetByteCode()->GetLength());
                break;
            }
            Output::Print(L"    %04x %2s", byteOffset, layoutSize == LargeLayout ? L"L-" : layoutSize == MediumLayout ? L"M-" : L"");
            DumpOp(op, layoutSize, reader, body);
            if (Js::Configuration::Global.flags.Verbose)
            {
                int layoutStart = byteOffset + 2; // Account for the prefix op
                int endByteOffset = reader.GetCurrentOffset();
                Output::SkipToColumn(70);
                if (layoutSize == LargeLayout)
                {
                    Output::Print(L"%02X ",
                        op > Js::OpCodeAsmJs::MaxByteSizedOpcodes ?
                        Js::OpCodeAsmJs::ExtendedLargeLayoutPrefix : Js::OpCodeAsmJs::LargeLayoutPrefix);
                }
                else if (layoutSize == MediumLayout)
                {
                    Output::Print(L"%02X ",
                        op > Js::OpCodeAsmJs::MaxByteSizedOpcodes ?
                        Js::OpCodeAsmJs::ExtendedMediumLayoutPrefix : Js::OpCodeAsmJs::MediumLayoutPrefix);
                }
                else
                {
                    Assert(layoutSize == SmallLayout);
                    if (op > Js::OpCodeAsmJs::MaxByteSizedOpcodes)
                    {
                        Output::Print(L"%02X ", Js::OpCodeAsmJs::ExtendedOpcodePrefix);
                    }
                    else
                    {
                        Output::Print(L"   ");
                        layoutStart--; // don't have a prefix
                    }
                }

                Output::Print(L"%02x", (byte)op);
                for (int i = layoutStart; i < endByteOffset; i++)
                {
                    Output::Print(L" %02x", reader.GetRawByte(i));
                }
            }
            Output::Print(L"\n");
        }
        if (statementReader.AtStatementBoundary(&reader))
        {
            body->PrintStatementSourceLine(statementIndex);
            statementIndex = statementReader.MoveNextStatementBoundary();
        }
        Output::Print(L"\n");
        Output::Flush();
    }