Changeset 249661 in webkit


Ignore:
Timestamp:
Sep 9, 2019 1:32:56 PM (5 years ago)
Author:
keith_miller@apple.com
Message:

OSR entry into wasm misses some contexts
https://bugs.webkit.org/show_bug.cgi?id=201569

Reviewed by Yusuke Suzuki.

JSTests:

Add a new harness and wast and the generated wasm file for
testing. The idea long term is to make it easy to test by creating
a C file and converting it to a wast then modify that to produce a
test.

  • wasm.yaml:
  • wasm/wast-tests/harness.js: Added.

(async.runWasmFile):

  • wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm: Added.
  • wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast: Added.
  • wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm: Added.
  • wasm/wast-tests/osr-entry-inner-loop-branch-above.wast: Added.
  • wasm/wast-tests/osr-entry-inner-loop.wasm: Added.
  • wasm/wast-tests/osr-entry-inner-loop.wast: Added.
  • wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm: Added.
  • wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast: Added.

Source/JavaScriptCore:

This patch fixes an issue where we could fail to capture some of
our contexts when OSR entering into wasm code. Before we would
only capture the state of the block immediately surrounding the
entrance loop block header. We actually need to capture all
enclosed stacks.

Additionally, we don't need to use variables for all the captured
values. We can use a Phi and insert an upsilon just below the
captured value.

  • interpreter/CallFrame.h:
  • jsc.cpp:

(GlobalObject::finishCreation):
(functionCallerIsOMGCompiled):

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::AirIRGenerator):
(JSC::Wasm::AirIRGenerator::emitEntryTierUpCheck):
(JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck):
(JSC::Wasm::AirIRGenerator::addLoop):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::createStack):
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::addConstant):
(JSC::Wasm::B3IRGenerator::emitEntryTierUpCheck):
(JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck):
(JSC::Wasm::B3IRGenerator::addLoop):
(JSC::Wasm::B3IRGenerator::addEndToUnreachable):
(JSC::Wasm::dumpExpressionStack):
(JSC::Wasm::B3IRGenerator::dump):
(JSC::Wasm::B3IRGenerator::Stack::Stack): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::append): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::takeLast): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::last): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::size const): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::isEmpty const): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::convertToExpressionList): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::at const): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::variableAt const): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::shrink): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::swap): Deleted.
(JSC::Wasm::B3IRGenerator::Stack::dump const): Deleted.

  • wasm/WasmFunctionParser.h:

(JSC::Wasm::FunctionParser::controlStack):

Tools:

Add new test harness mode for tests created from wast files.

  • Scripts/run-jsc-stress-tests:
Location:
trunk
Files:
10 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r249650 r249661  
     12019-09-07  Keith Miller  <keith_miller@apple.com>
     2
     3        OSR entry into wasm misses some contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=201569
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Add a new harness and wast and the generated wasm file for
     9        testing. The idea long term is to make it easy to test by creating
     10        a C file and converting it to a wast then modify that to produce a
     11        test.
     12
     13        * wasm.yaml:
     14        * wasm/wast-tests/harness.js: Added.
     15        (async.runWasmFile):
     16        * wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wasm: Added.
     17        * wasm/wast-tests/osr-entry-inner-loop-branch-above-no-consts.wast: Added.
     18        * wasm/wast-tests/osr-entry-inner-loop-branch-above.wasm: Added.
     19        * wasm/wast-tests/osr-entry-inner-loop-branch-above.wast: Added.
     20        * wasm/wast-tests/osr-entry-inner-loop.wasm: Added.
     21        * wasm/wast-tests/osr-entry-inner-loop.wast: Added.
     22        * wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wasm: Added.
     23        * wasm/wast-tests/osr-entry-multiple-enclosed-contexts.wast: Added.
     24
    1252019-09-09  Yusuke Suzuki  <ysuzuki@apple.com>
    226
  • trunk/JSTests/wasm.yaml

    r246645 r249661  
    2222# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2323
    24 - path: wasm/self-test/
    25   cmd: runWebAssemblySuite unless parseRunCommands
     24- path: wasm/wast-tests/
     25  cmd: runWebAssemblyWithHarness
    2626- path: wasm/js-api/
    2727  cmd: runWebAssemblySuite unless parseRunCommands
     
    4444- path: wasm/modules/
    4545  cmd: runWebAssembly unless parseRunCommands
     46- path: wasm/self-test/
     47  cmd: runWebAssemblySuite unless parseRunCommands
    4648
    4749- path: wasm/spec-tests/address.wast.js
     
    186188- path: wasm/modules/run-from-wasm.wasm
    187189  cmd: runWebAssembly
     190
  • trunk/Source/JavaScriptCore/ChangeLog

    r249650 r249661  
     12019-09-07  Keith Miller  <keith_miller@apple.com>
     2
     3        OSR entry into wasm misses some contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=201569
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        This patch fixes an issue where we could fail to capture some of
     9        our contexts when OSR entering into wasm code. Before we would
     10        only capture the state of the block immediately surrounding the
     11        entrance loop block header. We actually need to capture all
     12        enclosed stacks.
     13
     14        Additionally, we don't need to use variables for all the captured
     15        values. We can use a Phi and insert an upsilon just below the
     16        captured value.
     17
     18        * interpreter/CallFrame.h:
     19        * jsc.cpp:
     20        (GlobalObject::finishCreation):
     21        (functionCallerIsOMGCompiled):
     22        * wasm/WasmAirIRGenerator.cpp:
     23        (JSC::Wasm::AirIRGenerator::AirIRGenerator):
     24        (JSC::Wasm::AirIRGenerator::emitEntryTierUpCheck):
     25        (JSC::Wasm::AirIRGenerator::emitLoopTierUpCheck):
     26        (JSC::Wasm::AirIRGenerator::addLoop):
     27        * wasm/WasmB3IRGenerator.cpp:
     28        (JSC::Wasm::B3IRGenerator::createStack):
     29        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
     30        (JSC::Wasm::B3IRGenerator::addConstant):
     31        (JSC::Wasm::B3IRGenerator::emitEntryTierUpCheck):
     32        (JSC::Wasm::B3IRGenerator::emitLoopTierUpCheck):
     33        (JSC::Wasm::B3IRGenerator::addLoop):
     34        (JSC::Wasm::B3IRGenerator::addEndToUnreachable):
     35        (JSC::Wasm::dumpExpressionStack):
     36        (JSC::Wasm::B3IRGenerator::dump):
     37        (JSC::Wasm::B3IRGenerator::Stack::Stack): Deleted.
     38        (JSC::Wasm::B3IRGenerator::Stack::append): Deleted.
     39        (JSC::Wasm::B3IRGenerator::Stack::takeLast): Deleted.
     40        (JSC::Wasm::B3IRGenerator::Stack::last): Deleted.
     41        (JSC::Wasm::B3IRGenerator::Stack::size const): Deleted.
     42        (JSC::Wasm::B3IRGenerator::Stack::isEmpty const): Deleted.
     43        (JSC::Wasm::B3IRGenerator::Stack::convertToExpressionList): Deleted.
     44        (JSC::Wasm::B3IRGenerator::Stack::at const): Deleted.
     45        (JSC::Wasm::B3IRGenerator::Stack::variableAt const): Deleted.
     46        (JSC::Wasm::B3IRGenerator::Stack::shrink): Deleted.
     47        (JSC::Wasm::B3IRGenerator::Stack::swap): Deleted.
     48        (JSC::Wasm::B3IRGenerator::Stack::dump const): Deleted.
     49        * wasm/WasmFunctionParser.h:
     50        (JSC::Wasm::FunctionParser::controlStack):
     51
    1522019-09-09  Yusuke Suzuki  <ysuzuki@apple.com>
    253
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.h

    r246505 r249661  
    133133        JSGlobalObject* wasmAwareLexicalGlobalObject(VM&);
    134134
    135         bool isAnyWasmCallee();
     135        JS_EXPORT_PRIVATE bool isAnyWasmCallee();
    136136
    137137        // Global object in which the currently executing code was defined.
  • trunk/Source/JavaScriptCore/jsc.cpp

    r249612 r249661  
    2828#include "ButterflyInlines.h"
    2929#include "BytecodeCacheError.h"
     30#include "CallFrameInlines.h"
    3031#include "CatchScope.h"
    3132#include "CodeBlock.h"
     
    321322static EncodedJSValue JSC_HOST_CALL functionOptimizeNextInvocation(ExecState*);
    322323static EncodedJSValue JSC_HOST_CALL functionNumberOfDFGCompiles(ExecState*);
     324static EncodedJSValue JSC_HOST_CALL functionCallerIsOMGCompiled(ExecState*);
    323325static EncodedJSValue JSC_HOST_CALL functionJSCOptions(ExecState*);
    324326static EncodedJSValue JSC_HOST_CALL functionReoptimizationRetryCount(ExecState*);
     
    542544        addFunction(vm, "noOSRExitFuzzing", functionNoOSRExitFuzzing, 1);
    543545        addFunction(vm, "numberOfDFGCompiles", functionNumberOfDFGCompiles, 1);
     546        addFunction(vm, "callerIsOMGCompiled", functionCallerIsOMGCompiled, 0);
    544547        addFunction(vm, "jscOptions", functionJSCOptions, 0);
    545548        addFunction(vm, "optimizeNextInvocation", functionOptimizeNextInvocation, 1);
     
    17281731}
    17291732
     1733EncodedJSValue JSC_HOST_CALL functionCallerIsOMGCompiled(ExecState* exec)
     1734{
     1735    VM& vm = exec->vm();
     1736    auto scope = DECLARE_THROW_SCOPE(vm);
     1737
     1738    if (!Options::useBBQTierUpChecks())
     1739        return JSValue::encode(jsBoolean(true));
     1740
     1741    CallerFunctor wasmToJSFrame;
     1742    StackVisitor::visit(exec, &vm, wasmToJSFrame);
     1743    if (!wasmToJSFrame.callerFrame()->isAnyWasmCallee())
     1744        return throwVMError(exec, scope, "caller is not a wasm->js import function");
     1745
     1746    // We have a wrapper frame that we generate for imports. If we ever can direct call from wasm we would need to change this.
     1747    ASSERT(!wasmToJSFrame.callerFrame()->callee().isWasm());
     1748    CallerFunctor wasmFrame;
     1749    StackVisitor::visit(wasmToJSFrame.callerFrame(), &vm, wasmFrame);
     1750    ASSERT(wasmFrame.callerFrame()->callee().isWasm());
     1751#if ENABLE(WEBASSEMBLY)
     1752    auto mode = wasmFrame.callerFrame()->callee().asWasmCallee()->compilationMode();
     1753    return JSValue::encode(jsBoolean(mode == Wasm::CompilationMode::OMGMode || mode == Wasm::CompilationMode::OMGForOSREntryMode));
     1754#endif
     1755    RELEASE_ASSERT_NOT_REACHED();
     1756}
     1757
    17301758Message::Message(ArrayBufferContents&& contents, int32_t index)
    17311759    : m_contents(WTFMove(contents))
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r249221 r249661  
    592592    void emitThrowException(CCallHelpers&, ExceptionType);
    593593
    594     void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin);
    595     void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin);
     594    void emitEntryTierUpCheck();
     595    void emitLoopTierUpCheck(uint32_t loopIndex);
    596596
    597597    void emitWriteBarrierForJSWrapper();
     
    853853    });
    854854
    855     emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), B3::Origin());
     855    emitEntryTierUpCheck();
    856856}
    857857
     
    16041604}
    16051605
    1606 void AirIRGenerator::emitEntryTierUpCheck(int32_t incrementCount, B3::Origin origin)
    1607 {
    1608     UNUSED_PARAM(origin);
    1609 
     1606void AirIRGenerator::emitEntryTierUpCheck()
     1607{
    16101608    if (!m_tierUp)
    16111609        return;
     
    16251623        AllowMacroScratchRegisterUsage allowScratch(jit);
    16261624
    1627         CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
     1625        CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::functionEntryIncrement()), CCallHelpers::Address(params[0].gpr()));
    16281626        CCallHelpers::Label tierUpResume = jit.label();
    16291627
     
    16511649}
    16521650
    1653 void AirIRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin)
    1654 {
    1655     UNUSED_PARAM(origin);
     1651void AirIRGenerator::emitLoopTierUpCheck(uint32_t loopIndex)
     1652{
     1653    uint32_t outerLoopIndex = this->outerLoopIndex();
     1654    m_outerLoops.append(loopIndex);
    16561655
    16571656    if (!m_tierUp)
     
    16811680    patchArgs.append(countdownPtr);
    16821681
    1683     Vector<B3::Type> types;
    1684     for (auto& local : m_locals) {
     1682    for (auto& local : m_locals)
    16851683        patchArgs.append(ConstrainedTmp(local, B3::ValueRep::ColdAny));
    1686         types.append(toB3Type(local.type()));
    1687     }
    1688     for (auto& expression : expressionStack) {
    1689         patchArgs.append(ConstrainedTmp(expression, B3::ValueRep::ColdAny));
    1690         types.append(toB3Type(expression.type()));
     1684    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     1685        ExpressionList& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     1686        for (auto& value : expressionStack)
     1687            patchArgs.append(ConstrainedTmp(value, B3::ValueRep::ColdAny));
     1688
     1689        const auto& results = m_parser->controlStack()[controlIndex].controlData.result;
     1690        for (auto& value : results)
     1691            patchArgs.append(ConstrainedTmp(value, B3::ValueRep::ColdAny));
    16911692    }
    16921693
     
    16971698        AllowMacroScratchRegisterUsage allowScratch(jit);
    16981699        CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger));
    1699         CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
     1700        CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::loopIncrement()), CCallHelpers::Address(params[0].gpr()));
    17001701        MacroAssembler::Label tierUpResume = jit.label();
    17011702
    17021703        OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex);
    1703         for (unsigned index = 0; index < types.size(); ++index)
    1704             osrEntryData.values().constructAndAppend(params[index + 1], types[index]);
     1704        // First argument is the countdown location.
     1705        for (unsigned index = 1; index < params.value()->numChildren(); ++index)
     1706            osrEntryData.values().constructAndAppend(params[index], params.value()->child(index)->type());
    17051707        OSREntryData* osrEntryDataPtr = &osrEntryData;
    17061708
     
    17191721}
    17201722
    1721 AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature, const Stack& expressionStack, uint32_t loopIndex)
     1723AirIRGenerator::ControlData AirIRGenerator::addLoop(Type signature, const Stack&, uint32_t loopIndex)
    17221724{
    17231725    BasicBlock* body = m_code.addBlock();
     
    17271729    m_currentBlock->setSuccessors(body);
    17281730
    1729     uint32_t outerLoopIndex = this->outerLoopIndex();
    1730     m_outerLoops.append(loopIndex);
    17311731    m_currentBlock = body;
    1732     emitLoopTierUpCheck(TierUpCount::loopIncrement(), expressionStack, loopIndex, outerLoopIndex, origin());
     1732    emitLoopTierUpCheck(loopIndex);
    17331733
    17341734    return ControlData(origin(), signature, tmpForType(signature), BlockType::Loop, continuation, body);
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r249221 r249661  
    162162    typedef Vector<ExpressionType, 1> ExpressionList;
    163163
    164     friend class Stack;
    165     class Stack {
    166     public:
    167         Stack(B3IRGenerator* generator)
    168             : m_generator(generator)
    169         {
    170         }
    171 
    172         void append(ExpressionType expression)
    173         {
    174             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
    175                 Variable* variable = m_generator->m_proc.addVariable(expression->type());
    176                 m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, Set, m_generator->origin(), variable, expression);
    177                 m_stack.append(variable);
    178                 return;
    179             }
    180             m_data.append(expression);
    181         }
    182 
    183         ExpressionType takeLast()
    184         {
    185             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
    186                 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.takeLast());
    187             return m_data.takeLast();
    188         }
    189 
    190         ExpressionType last()
    191         {
    192             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
    193                 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.last());
    194             return m_data.last();
    195         }
    196 
    197         unsigned size() const
    198         {
    199             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
    200                 return m_stack.size();
    201             return m_data.size();
    202         }
    203         bool isEmpty() const { return size() == 0; }
    204 
    205         ExpressionList convertToExpressionList()
    206         {
    207             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
    208                 ExpressionList results;
    209                 for (unsigned i = 0; i < m_stack.size(); ++i)
    210                     results.append(at(i));
    211                 return results;
    212             }
    213             return m_data;
    214         }
    215 
    216         ExpressionType at(unsigned i) const
    217         {
    218             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
    219                 return m_generator->m_currentBlock->appendNew<VariableValue>(m_generator->m_proc, B3::Get, m_generator->origin(), m_stack.at(i));
    220             return m_data.at(i);
    221         }
    222 
    223         Variable* variableAt(unsigned i) const
    224         {
    225             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode)
    226                 return m_stack.at(i);
    227             return nullptr;
    228         }
    229 
    230         void shrink(unsigned i)
    231         {
    232             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
    233                 m_stack.shrink(i);
    234                 return;
    235             }
    236             m_data.shrink(i);
    237         }
    238 
    239         void swap(Stack& stack)
    240         {
    241             std::swap(m_generator, stack.m_generator);
    242             m_data.swap(stack.m_data);
    243             m_stack.swap(stack.m_stack);
    244         }
    245 
    246         void dump() const
    247         {
    248             CommaPrinter comma(", ", "");
    249             dataLog(comma, "ExpressionStack:");
    250             if (m_generator->m_compilationMode == CompilationMode::OMGForOSREntryMode) {
    251                 for (const auto& variable : m_stack)
    252                     dataLog(comma, *variable);
    253                 return;
    254             }
    255             for (const auto& expression : m_data)
    256                 dataLog(comma, *expression);
    257         }
    258 
    259     private:
    260         B3IRGenerator* m_generator { nullptr };
    261         ExpressionList m_data;
    262         Vector<Variable*> m_stack;
    263     };
    264     Stack createStack() { return Stack(this); }
     164    using Stack = ExpressionList;
     165    Stack createStack() { return { }; }
    265166
    266167    using ControlType = ControlData;
     
    352253    void emitExceptionCheck(CCallHelpers&, ExceptionType);
    353254
    354     void emitEntryTierUpCheck(int32_t incrementCount, B3::Origin);
    355     void emitLoopTierUpCheck(int32_t incrementCount, const Stack&, uint32_t, uint32_t, B3::Origin);
     255    void emitEntryTierUpCheck();
     256    void emitLoopTierUpCheck(uint32_t loopIndex);
    356257
    357258    void emitWriteBarrierForJSWrapper();
     
    585486    }
    586487
    587     emitEntryTierUpCheck(TierUpCount::functionEntryIncrement(), Origin());
     488    emitEntryTierUpCheck();
    588489
    589490    if (m_compilationMode == CompilationMode::OMGForOSREntryMode)
     
    11881089B3IRGenerator::ExpressionType B3IRGenerator::addConstant(Type type, uint64_t value)
    11891090{
     1091
    11901092    return constant(toB3Type(type), value);
    11911093}
    11921094
    1193 void B3IRGenerator::emitEntryTierUpCheck(int32_t incrementCount, Origin origin)
     1095void B3IRGenerator::emitEntryTierUpCheck()
    11941096{
    11951097    if (!m_tierUp)
     
    11971099
    11981100    ASSERT(m_tierUp);
    1199     Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), origin);
    1200 
    1201     PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, origin);
     1101    Value* countDownLocation = constant(pointerType(), reinterpret_cast<uint64_t>(&m_tierUp->m_counter), Origin());
     1102
     1103    PatchpointValue* patch = m_currentBlock->appendNew<PatchpointValue>(m_proc, B3::Void, Origin());
    12021104    Effects effects = Effects::none();
    12031105    // FIXME: we should have a more precise heap range for the tier up count.
     
    12101112    patch->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
    12111113        AllowMacroScratchRegisterUsage allowScratch(jit);
    1212         CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
     1114        CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::functionEntryIncrement()), CCallHelpers::Address(params[0].gpr()));
    12131115        CCallHelpers::Label tierUpResume = jit.label();
    12141116
     
    12341136}
    12351137
    1236 void B3IRGenerator::emitLoopTierUpCheck(int32_t incrementCount, const Stack& expressionStack, uint32_t loopIndex, uint32_t outerLoopIndex, B3::Origin origin)
    1237 {
     1138void B3IRGenerator::emitLoopTierUpCheck(uint32_t loopIndex)
     1139{
     1140    uint32_t outerLoopIndex = this->outerLoopIndex();
     1141    m_outerLoops.append(loopIndex);
     1142
    12381143    if (!m_tierUp)
    12391144        return;
    12401145
    1241     ASSERT(m_tierUp);
    1242 
     1146    Origin origin = this->origin();
    12431147    ASSERT(m_tierUp->osrEntryTriggers().size() == loopIndex);
    12441148    m_tierUp->osrEntryTriggers().append(TierUpCount::TriggerReason::DontTrigger);
     
    12481152
    12491153    Vector<ExpressionType> stackmap;
    1250     Vector<B3::Type> types;
    12511154    for (auto& local : m_locals) {
    12521155        ExpressionType result = m_currentBlock->appendNew<VariableValue>(m_proc, B3::Get, origin, local);
    12531156        stackmap.append(result);
    1254         types.append(result->type());
    1255     }
    1256     for (unsigned i = 0; i < expressionStack.size(); ++i) {
    1257         ExpressionType result = expressionStack.at(i);
    1258         stackmap.append(result);
    1259         types.append(result->type());
     1157    }
     1158    for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     1159        auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     1160        for (Value* value : expressionStack)
     1161            stackmap.append(value);
    12601162    }
    12611163
     
    12821184        AllowMacroScratchRegisterUsage allowScratch(jit);
    12831185        CCallHelpers::Jump forceOSREntry = jit.branchTest8(CCallHelpers::NonZero, CCallHelpers::AbsoluteAddress(forceEntryTrigger));
    1284         CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(incrementCount), CCallHelpers::Address(params[0].gpr()));
     1186        CCallHelpers::Jump tierUp = jit.branchAdd32(CCallHelpers::PositiveOrZero, CCallHelpers::TrustedImm32(TierUpCount::loopIncrement()), CCallHelpers::Address(params[0].gpr()));
    12851187        MacroAssembler::Label tierUpResume = jit.label();
    12861188
    12871189        OSREntryData& osrEntryData = m_tierUp->addOSREntryData(m_functionIndex, loopIndex);
    1288         for (unsigned index = 0; index < types.size(); ++index)
    1289             osrEntryData.values().constructAndAppend(params[index + 1], types[index]);
     1190        // First argument is the countdown location.
     1191        for (unsigned i = 1; i < params.value()->numChildren(); ++i)
     1192            osrEntryData.values().constructAndAppend(params[i], params.value()->child(i)->type());
    12901193        OSREntryData* osrEntryDataPtr = &osrEntryData;
    12911194
     
    13021205}
    13031206
    1304 B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature, const Stack& stack, uint32_t loopIndex)
     1207B3IRGenerator::ControlData B3IRGenerator::addLoop(Type signature, const Stack&, uint32_t loopIndex)
    13051208{
    13061209    BasicBlock* body = m_proc.addBlock();
     
    13091212    m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
    13101213    if (loopIndex == m_loopIndexForOSREntry) {
     1214        dataLogLnIf(WasmB3IRGeneratorInternal::verbose, "Setting up for OSR entry");
    13111215        m_currentBlock = m_rootBlock;
    1312         m_osrEntryScratchBufferSize = m_locals.size() + stack.size();
    13131216        Value* pointer = m_rootBlock->appendNew<ArgumentRegValue>(m_proc, Origin(), GPRInfo::argumentGPR0);
    13141217
    1315         auto loadFromScratchBuffer = [&] (B3::Type type, unsigned index) {
    1316             size_t offset = sizeof(uint64_t) * index;
    1317             switch (type.kind()) {
    1318             case B3::Int32:
    1319                 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(), pointer, offset);
    1320             case B3::Int64:
    1321                 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Int64, origin(), pointer, offset);
    1322             case B3::Float:
    1323                 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Float, origin(), pointer, offset);
    1324             case B3::Double:
    1325                 return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, B3::Double, origin(), pointer, offset);
    1326             default:
    1327                 RELEASE_ASSERT_NOT_REACHED();
    1328                 break;
     1218        unsigned indexInBuffer = 0;
     1219        auto loadFromScratchBuffer = [&] (B3::Type type) {
     1220            size_t offset = sizeof(uint64_t) * indexInBuffer++;
     1221            RELEASE_ASSERT(type.isNumeric());
     1222            return m_currentBlock->appendNew<MemoryValue>(m_proc, Load, type, origin(), pointer, offset);
     1223        };
     1224
     1225        for (auto& local : m_locals)
     1226            m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type()));
     1227
     1228        for (unsigned controlIndex = 0; controlIndex < m_parser->controlStack().size(); ++controlIndex) {
     1229            const auto& data = m_parser->controlStack()[controlIndex].controlData;
     1230            auto& expressionStack = m_parser->controlStack()[controlIndex].enclosedExpressionStack;
     1231
     1232            // For each stack entry enclosed by this loop we need to replace the value with a phi so we can fill it on OSR entry.
     1233            BasicBlock* sourceBlock = nullptr;
     1234            unsigned blockIndex = 0;
     1235            B3::InsertionSet insertionSet(m_proc);
     1236            for (unsigned i = 0; i < expressionStack.size(); i++) {
     1237                auto* value = expressionStack[i];
     1238                if (value->isConstant())
     1239                    continue;
     1240
     1241                if (value->owner != sourceBlock) {
     1242                    insertionSet.execute(sourceBlock);
     1243                    ASSERT(insertionSet.isEmpty());
     1244                    dataLogLnIf(WasmB3IRGeneratorInternal::verbose && sourceBlock, "Executed insertion set into: ", *sourceBlock);
     1245                    blockIndex = 0;
     1246                    sourceBlock = value->owner;
     1247                }
     1248
     1249                while (sourceBlock->at(blockIndex++) != value)
     1250                    ASSERT(blockIndex < sourceBlock->size());
     1251                ASSERT(sourceBlock->at(blockIndex - 1) == value);
     1252
     1253                auto* phi = data.continuation->appendNew<Value>(m_proc, Phi,  value->type(), value->origin());
     1254                expressionStack[i] = phi;
     1255                m_currentBlock->appendNew<UpsilonValue>(m_proc, value->origin(), loadFromScratchBuffer(value->type()), phi);
     1256
     1257                auto* sourceUpsilon = m_proc.add<UpsilonValue>(value->origin(), value, phi);
     1258                insertionSet.insertValue(blockIndex, sourceUpsilon);
    13291259            }
    1330         };
    1331 
    1332         unsigned indexInBuffer = 0;
    1333         for (auto& local : m_locals)
    1334             m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), local, loadFromScratchBuffer(local->type(), indexInBuffer++));
    1335         for (unsigned i = 0; i < stack.size(); ++i) {
    1336             auto* variable = stack.variableAt(i);
    1337             m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), variable, loadFromScratchBuffer(variable->type(), indexInBuffer++));
     1260            insertionSet.execute(sourceBlock);
    13381261        }
     1262
     1263        m_osrEntryScratchBufferSize = indexInBuffer;
    13391264        m_currentBlock->appendNewControlValue(m_proc, Jump, origin(), body);
    13401265        body->addPredecessor(m_currentBlock);
    13411266    }
    13421267
    1343     uint32_t outerLoopIndex = this->outerLoopIndex();
    1344     m_outerLoops.append(loopIndex);
    13451268    m_currentBlock = body;
    1346     emitLoopTierUpCheck(TierUpCount::loopIncrement(), stack, loopIndex, outerLoopIndex, origin());
     1269    emitLoopTierUpCheck(loopIndex);
    13471270
    13481271    return ControlData(m_proc, origin(), signature, BlockType::Loop, continuation, body);
     
    14681391    // TopLevel does not have any code after this so we need to make sure we emit a return here.
    14691392    if (data.type() == BlockType::TopLevel)
    1470         return addReturn(entry.controlData, entry.enclosedExpressionStack.convertToExpressionList());
     1393        return addReturn(entry.controlData, entry.enclosedExpressionStack);
    14711394
    14721395    return { };
     
    17401663}
    17411664
     1665static void dumpExpressionStack(const CommaPrinter& comma, const B3IRGenerator::ExpressionList& expressionStack)
     1666{
     1667    dataLog(comma, "ExpressionStack:");
     1668    for (const auto& expression : expressionStack)
     1669        dataLog(comma, *expression);
     1670}
     1671
    17421672void B3IRGenerator::dump(const Vector<ControlEntry>& controlStack, const Stack* expressionStack)
    17431673{
     
    17531683    for (size_t i = controlStack.size(); i--;) {
    17541684        dataLog("  ", controlStack[i].controlData, ": ");
    1755         expressionStack->dump();
     1685        CommaPrinter comma(", ", "");
     1686        dumpExpressionStack(comma, *expressionStack);
    17561687        expressionStack = &controlStack[i].enclosedExpressionStack;
    17571688        dataLogLn();
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r248989 r249661  
    6161    size_t currentOpcodeStartingOffset() const { return m_currentOpcodeStartingOffset; }
    6262
     63    Vector<ControlEntry>& controlStack() { return m_controlStack; }
     64
    6365private:
    6466    static const bool verbose = false;
  • trunk/Source/JavaScriptCore/wasm/WasmOpcodeOrigin.cpp

    r214544 r249661  
    3333void OpcodeOrigin::dump(PrintStream& out) const
    3434{
    35     out.print("{opcode: ", makeString(opcode()), ", location: ", location(), "}");
     35    out.print("{opcode: ", makeString(opcode()), ", location: ", RawPointer(reinterpret_cast<void*>(location())), "}");
    3636}
    3737
  • trunk/Tools/ChangeLog

    r249653 r249661  
     12019-09-07  Keith Miller  <keith_miller@apple.com>
     2
     3        OSR entry into wasm misses some contexts
     4        https://bugs.webkit.org/show_bug.cgi?id=201569
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        Add new test harness mode for tests created from wast files.
     9
     10        * Scripts/run-jsc-stress-tests:
     11
    1122019-09-09  Daniel Bates  <dabates@apple.com>
    213
  • trunk/Tools/Scripts/run-jsc-stress-tests

    r249116 r249661  
    11151115end
    11161116
     1117def runHarnessTest(kind, *options)
     1118    wasmFiles = allWasmFiles($collection)
     1119    wasmFiles.each {
     1120        | file |
     1121        basename = file.basename.to_s
     1122        addRunCommand("(" + basename + ")-" + kind, [pathToVM.to_s] + $testSpecificRequiredOptions + options + [$benchmark.to_s, "--", basename], silentOutputHandler, simpleErrorHandler)
     1123    }
     1124end
     1125
     1126def runWebAssemblyWithHarness(*optionalTestSpecificOptions)
     1127    raise unless $benchmark.to_s =~ /harness\.m?js/
     1128    return if !$jitTests
     1129    return if !$isFTLPlatform
     1130
     1131    wasmFiles = allWasmFiles($collection)
     1132    prepareExtraRelativeFiles(wasmFiles.map { |f| f.basename }, $collection)
     1133
     1134    runHarnessTest("default-wasm", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1135    if $mode != "quick"
     1136        runHarnessTest("wasm-no-cjit-yes-tls-context", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS + optionalTestSpecificOptions))
     1137        runHarnessTest("wasm-eager", *(FTL_OPTIONS + EAGER_OPTIONS + optionalTestSpecificOptions))
     1138        runHarnessTest("wasm-eager-jettison", "--forceCodeBlockToJettisonDueToOldAge=true", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1139        runHarnessTest("wasm-no-call-ic", "--useCallICsForWebAssemblyToJSCalls=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1140        runHarnessTest("wasm-no-tls-context", "--useFastTLSForWasmContext=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1141        runHarnessTest("wasm-slow-memory", "--useWebAssemblyFastMemory=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1142        runHarnessTest("wasm-no-air", "--wasmBBQUsesAir=false", *(FTL_OPTIONS + optionalTestSpecificOptions))
     1143        runHarnessTest("wasm-collect-continuously", "--collectContinuously=true", *(FTL_OPTIONS + optionalTestSpecificOptions)) if shouldCollectContinuously?
     1144    end
     1145end
     1146
    11171147def runWebAssemblyEmscripten(mode)
    11181148    case mode
     
    14821512    $skipped = true
    14831513    puts "Skipping #{$collectionName}/#{$benchmark}"
     1514end
     1515
     1516def allWasmFiles(path)
     1517    if path.file?
     1518        [path]
     1519    else
     1520        result = []
     1521        Dir.foreach(path) {
     1522            | filename |
     1523            next unless filename =~ /\.m?wasm$/
     1524            next unless (path + filename).file?
     1525            result << path + filename
     1526        }
     1527        result
     1528    end
    14841529end
    14851530
Note: See TracChangeset for help on using the changeset viewer.