Ignore:
Timestamp:
Apr 15, 2009, 12:13:25 AM (16 years ago)
Author:
[email protected]
Message:

Bug 25202: Improve performance of repeated callbacks into the VM

Reviewed by Cameron Zwarich

Add the concept of a CachedCall to native code for use in Array
prototype and similar functions where a single callback function
is called repeatedly with the same number of arguments.

Used Array.prototype.filter as the test function and got a 50% win
over a naive non-caching specialised version. This makes the native
implementation of Array.prototype.filter faster than the JS one once
more.

File:
1 edited

Legend:

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

    r42337 r42537  
    699699    m_registerFile.shrink(oldEnd);
    700700    return result;
     701}
     702
     703Interpreter::CallFrameClosure Interpreter::prepareForRepeatCall(FunctionBodyNode* functionBodyNode, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValuePtr* exception)
     704{
     705    ASSERT(!scopeChain->globalData->exception);
     706   
     707    if (m_reentryDepth >= MaxReentryDepth) {
     708        *exception = createStackOverflowError(callFrame);
     709        return CallFrameClosure();
     710    }
     711   
     712    Register* oldEnd = m_registerFile.end();
     713    int argc = 1 + argCount; // implicit "this" parameter
     714   
     715    if (!m_registerFile.grow(oldEnd + argc)) {
     716        *exception = createStackOverflowError(callFrame);
     717        return CallFrameClosure();
     718    }
     719
     720    CallFrame* newCallFrame = CallFrame::create(oldEnd);
     721    size_t dst = 0;
     722    for (int i = 0; i < argc; ++i)
     723        newCallFrame[++dst] = jsUndefined();
     724   
     725    CodeBlock* codeBlock = &functionBodyNode->bytecode(scopeChain);
     726    newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
     727    if (UNLIKELY(!newCallFrame)) {
     728        *exception = createStackOverflowError(callFrame);
     729        m_registerFile.shrink(oldEnd);
     730        return CallFrameClosure();
     731    }
     732    // a 0 codeBlock indicates a built-in caller
     733    newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), 0, argc, function);
     734#if ENABLE(JIT)
     735    if (!codeBlock->jitCode())
     736        JIT::compile(scopeChain->globalData, codeBlock);
     737#endif
     738
     739    CallFrameClosure result = { callFrame, newCallFrame, function, codeBlock, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
     740    return result;
     741}
     742
     743JSValuePtr Interpreter::execute(CallFrameClosure& closure, JSValuePtr* exception)
     744{
     745    closure.resetCallFrame();
     746    Profiler** profiler = Profiler::enabledProfilerReference();
     747    if (*profiler)
     748        (*profiler)->willExecute(closure.oldCallFrame, closure.function);
     749   
     750    JSValuePtr result;
     751    {
     752        SamplingTool::CallRecord callRecord(m_sampler);
     753       
     754        m_reentryDepth++;
     755#if ENABLE(JIT)
     756        result = closure.codeBlock->jitCode().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
     757#else
     758        result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
     759#endif
     760        m_reentryDepth--;
     761    }
     762   
     763    if (*profiler)
     764        (*profiler)->didExecute(closure.oldCallFrame, closure.function);
     765    return result;
     766}
     767
     768void Interpreter::endRepeatCall(CallFrameClosure& closure)
     769{
     770    m_registerFile.shrink(closure.oldEnd);
    701771}
    702772
Note: See TracChangeset for help on using the changeset viewer.