Ignore:
Timestamp:
Dec 11, 2016, 7:11:18 PM (9 years ago)
Author:
[email protected]
Message:

We should be able to throw exceptions from Wasm code and when Wasm frames are on the stack
https://bugs.webkit.org/show_bug.cgi?id=165429

Reviewed by Keith Miller.

JSTests:

  • wasm/function-tests/trap-load.js: Added.

(assert):
(wasmFrameCountFromError):
(i.catch):
(assert.continuation):

  • wasm/function-tests/trap-store.js: Added.

(import.Builder.from.string_appeared_here.assert):
(i.catch):
(assert.continuation):
(assert):

  • wasm/js-api/test_memory_constructor.js:

(assert):

Source/JavaScriptCore:

This patch teaches the stack walking runtime about wasm.
To do this, I taught StackVisitor that a callee is not
always an object.

To be able to unwind callee save registers properly, I've given
JSWebAssemblyCallee a list of RegisterAtOffsetList for the callee
saves that B3 saved in the prologue. Also, because we have two
B3Compilations per wasm function, one for wasm entrypoint, and
one for the JS entrypoint, I needed to create a callee for each
because they each might spill callee save registers.

I also fixed a bug inside the Wasm::Memory constructor where we
were trying to mmap the same number of bytes even after the first
mmap failed. We should start by trying to mmap the maximum bytes,
and if that fails, fall back to the specified initial bytes. However,
the code was just mmapping the maximum twice. I've fixed that and
also added a RELEASE_ASSERT_NOT_REACHED() for when the second mmap
fails along with a FIXME to throw an OOM error.

There was a second bug I fixed where JSModuleRecord was calling
visitWeak on its CallLinkInfos inside ::visitChldren(). It needs
to do this after marking. I changed JSModuleRecord to do what
CodeBlock does and call visitWeak on its CallLinkInfos inside
an UnconditionalFinalizer.

  • API/JSContextRef.cpp:

(BacktraceFunctor::operator()):

  • inspector/ScriptCallStackFactory.cpp:

(Inspector::createScriptCallStackFromException):

  • interpreter/CallFrame.cpp:

(JSC::CallFrame::vmEntryGlobalObject):

  • interpreter/CallFrame.h:

(JSC::ExecState::callee):

  • interpreter/Interpreter.cpp:

(JSC::GetStackTraceFunctor::operator()):
(JSC::UnwindFunctor::operator()):
(JSC::UnwindFunctor::copyCalleeSavesToVMEntryFrameCalleeSavesBuffer):

  • interpreter/Interpreter.h:
  • interpreter/ShadowChicken.cpp:

(JSC::ShadowChicken::update):

  • interpreter/StackVisitor.cpp:

(JSC::StackVisitor::StackVisitor):
(JSC::StackVisitor::readFrame):
(JSC::StackVisitor::readNonInlinedFrame):
(JSC::StackVisitor::readInlinedFrame):
(JSC::StackVisitor::Frame::isWasmFrame):
(JSC::StackVisitor::Frame::codeType):
(JSC::StackVisitor::Frame::calleeSaveRegisters):
(JSC::StackVisitor::Frame::functionName):
(JSC::StackVisitor::Frame::sourceURL):
(JSC::StackVisitor::Frame::toString):
(JSC::StackVisitor::Frame::hasLineAndColumnInfo):
(JSC::StackVisitor::Frame::setToEnd):

  • interpreter/StackVisitor.h:

(JSC::StackVisitor::Frame::callee):
(JSC::StackVisitor::Frame::isNativeFrame):
(JSC::StackVisitor::Frame::isJSFrame): Deleted.

  • jsc.cpp:

(callWasmFunction):
(functionTestWasmModuleFunctions):

  • runtime/Error.cpp:

(JSC::addErrorInfoAndGetBytecodeOffset):

  • runtime/JSCell.cpp:

(JSC::JSCell::isAnyWasmCallee):

  • runtime/JSCell.h:
  • runtime/JSFunction.cpp:

(JSC::RetrieveArgumentsFunctor::operator()):
(JSC::RetrieveCallerFunctionFunctor::operator()):

  • runtime/StackFrame.cpp:

(JSC::StackFrame::sourceID):
(JSC::StackFrame::sourceURL):
(JSC::StackFrame::functionName):
(JSC::StackFrame::computeLineAndColumn):
(JSC::StackFrame::toString):

  • runtime/StackFrame.h:

(JSC::StackFrame::StackFrame):
(JSC::StackFrame::hasLineAndColumnInfo):
(JSC::StackFrame::hasBytecodeOffset):
(JSC::StackFrame::bytecodeOffset):
(JSC::StackFrame::isNative): Deleted.

  • runtime/VM.h:
  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):

  • wasm/WasmCallingConvention.h:

(JSC::Wasm::CallingConvention::setupFrameInPrologue):

  • wasm/WasmFormat.h:
  • wasm/WasmMemory.cpp:

(JSC::Wasm::Memory::Memory):

  • wasm/WasmMemory.h:

(JSC::Wasm::Memory::isValid):

  • wasm/WasmPlan.cpp:

(JSC::Wasm::Plan::run):
(JSC::Wasm::Plan::initializeCallees):

  • wasm/WasmPlan.h:

(JSC::Wasm::Plan::jsToWasmEntryPointForFunction): Deleted.

  • wasm/js/JSWebAssemblyCallee.cpp:

(JSC::JSWebAssemblyCallee::finishCreation):

  • wasm/js/JSWebAssemblyCallee.h:

(JSC::JSWebAssemblyCallee::create):
(JSC::JSWebAssemblyCallee::entrypoint):
(JSC::JSWebAssemblyCallee::calleeSaveRegisters):
(JSC::JSWebAssemblyCallee::jsToWasmEntryPoint): Deleted.

  • wasm/js/JSWebAssemblyModule.cpp:

(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::visitChildren):
(JSC::JSWebAssemblyModule::UnconditionalFinalizer::finalizeUnconditionally):

  • wasm/js/JSWebAssemblyModule.h:

(JSC::JSWebAssemblyModule::jsEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::wasmEntrypointCalleeFromFunctionIndexSpace):
(JSC::JSWebAssemblyModule::setJSEntrypointCallee):
(JSC::JSWebAssemblyModule::setWasmEntrypointCallee):
(JSC::JSWebAssemblyModule::allocationSize):
(JSC::JSWebAssemblyModule::calleeFromFunctionIndexSpace): Deleted.

  • wasm/js/JSWebAssemblyRuntimeError.h:
  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::call):

  • wasm/js/WebAssemblyInstanceConstructor.cpp:

(JSC::constructJSWebAssemblyInstance):

  • wasm/js/WebAssemblyMemoryConstructor.cpp:

(JSC::constructJSWebAssemblyMemory):

  • wasm/js/WebAssemblyModuleConstructor.cpp:

(JSC::constructJSWebAssemblyModule):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::link):

Source/WebCore:

  • bindings/js/JSDOMBinding.cpp:

(WebCore::GetCallerGlobalObjectFunctor::operator()):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r209433 r209696  
    6464#include "ScopedArguments.h"
    6565#include "StackAlignment.h"
     66#include "StackFrame.h"
    6667#include "StackVisitor.h"
    6768#include "StrictEvalActivation.h"
     
    467468
    468469        if (m_remainingCapacityForFrameCapture) {
    469             if (visitor->isJSFrame()
     470            if (!visitor->isWasmFrame()
     471                && !!visitor->codeBlock()
    470472                && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) {
    471                 StackFrame s = {
    472                     Strong<JSObject>(m_vm, visitor->callee()),
    473                     Strong<CodeBlock>(m_vm, visitor->codeBlock()),
    474                     visitor->bytecodeOffset()
    475                 };
    476                 m_results.append(s);
     473                m_results.append(
     474                    StackFrame(m_vm, visitor->callee(), visitor->codeBlock(), visitor->bytecodeOffset()));
    477475            } else {
    478                 StackFrame s = {
    479                     Strong<JSObject>(m_vm, visitor->callee()),
    480                     Strong<CodeBlock>(),
    481                     0 // unused value because codeBlock is null.
    482                 };
    483                 m_results.append(s);
     476                m_results.append(
     477                    StackFrame(m_vm,  visitor->callee()));
    484478            }
    485479   
     
    609603        m_handler = nullptr;
    610604        if (!m_isTermination) {
    611             if (m_codeBlock)
     605            if (m_codeBlock) {
    612606                m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
    613         }
    614 
    615         if (m_handler)
     607                if (m_handler)
     608                    return StackVisitor::Done;
     609            }
     610        }
     611
     612        notifyDebuggerOfUnwinding(m_callFrame);
     613
     614        copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
     615
     616        bool shouldStopUnwinding = visitor->callerIsVMEntryFrame();
     617        if (shouldStopUnwinding)
    616618            return StackVisitor::Done;
    617 
    618         notifyDebuggerOfUnwinding(m_callFrame);
    619 
    620         bool shouldStopUnwinding = visitor->callerIsVMEntryFrame();
    621         if (shouldStopUnwinding) {
    622             copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
    623 
    624             return StackVisitor::Done;
    625         }
    626 
    627         copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(visitor);
    628619
    629620        return StackVisitor::Continue;
     
    634625    {
    635626#if ENABLE(JIT) && NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    636 
    637         if (!visitor->isJSFrame())
    638             return;
    639 
    640 #if ENABLE(DFG_JIT)
    641         if (visitor->inlineCallFrame())
    642             return;
    643 #endif
    644         RegisterAtOffsetList* currentCalleeSaves = m_codeBlock ? m_codeBlock->calleeSaveRegisters() : nullptr;
     627        RegisterAtOffsetList* currentCalleeSaves = visitor->calleeSaveRegisters();
    645628
    646629        if (!currentCalleeSaves)
Note: See TracChangeset for help on using the changeset viewer.