Ignore:
Timestamp:
May 12, 2009, 1:58:56 AM (16 years ago)
Author:
[email protected]
Message:

Improve function call forwarding performance

Reviewed by Gavin Barraclough

Make creation of the Arguments object occur lazily, so it
is not necessarily created for every function that references
it. Then add logic to Function.apply to allow it to avoid
allocating the Arguments object at all. Helps a lot with
the function forwarding/binding logic in jQuery, Prototype,
and numerous other JS libraries.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r43471 r43559  
    333333        emitOpcode(op_enter);
    334334
    335     if (usesArguments)
    336         emitOpcode(op_create_arguments);
     335     if (usesArguments)
     336        emitOpcode(op_init_arguments);
    337337
    338338    const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     
    429429        return 0;
    430430
     431    if (ident == propertyNames().arguments)
     432        createArgumentsIfNecessary();
     433
     434    return &registerFor(entry.getIndex());
     435}
     436
     437bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
     438{
     439    if (ident != propertyNames().arguments)
     440        return false;
     441   
     442    if (!shouldOptimizeLocals())
     443        return false;
     444   
     445    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
     446    if (entry.isNull())
     447        return false;
     448   
     449    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
     450        return true;
     451   
     452    return false;
     453}
     454
     455RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
     456{
     457    ASSERT(willResolveToArguments(propertyNames().arguments));
     458
     459    SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep());
     460    ASSERT(!entry.isNull());
    431461    return &registerFor(entry.getIndex());
    432462}
     
    13471377}
    13481378
     1379void BytecodeGenerator::createArgumentsIfNecessary()
     1380{
     1381    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
     1382        emitOpcode(op_create_arguments);
     1383}
     1384
    13491385RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
    13501386{
     1387    createArgumentsIfNecessary();
    13511388    return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
    13521389}
     
    15731610    m_scopeContextStack.append(context);
    15741611    m_dynamicScopeDepth++;
     1612    createArgumentsIfNecessary();
    15751613
    15761614    return emitUnaryNoDstOp(op_push_scope, scope);
Note: See TracChangeset for help on using the changeset viewer.