Changeset 31119 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Mar 17, 2008, 10:36:26 PM (17 years ago)
Author:
[email protected]
Message:

Optimise multi-scope function call resolution

Reviewed by Geoff

Refactor multiscope variable resolution and use to add
optimised FunctionCallResolveNode subclasses.

2.6% gain in sunspider performance, *25%* gain in controlflow-recursive

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r31114 r31119  
    594594}
    595595
    596 void ResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
    597 {
    598     size_t index = symbolTable.get(m_ident.ustring().rep());
     596static size_t getSymbolTableEntry(ExecState* exec, const Identifier& ident, const SymbolTable& symbolTable, size_t& stackDepth)
     597{
     598    size_t index = symbolTable.get(ident.ustring().rep());
    599599    if (index != missingSymbolMarker()) {
    600         new (this) LocalVarAccessNode(index);
    601         return;
     600        stackDepth = 0;
     601        return index;
    602602    }
    603603   
    604     if (m_ident == exec->propertyNames().arguments)
    605         return;
     604    if (ident == exec->propertyNames().arguments) {
     605        stackDepth = 0;
     606        return missingSymbolMarker();
     607    }
     608   
    606609    const ScopeChain& chain = exec->scopeChain();
    607610    ScopeChainIterator iter = chain.begin();
     
    613616            break;
    614617        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
    615         index = currentVariableObject->symbolTable().get(m_ident.ustring().rep());
     618        index = currentVariableObject->symbolTable().get(ident.ustring().rep());
    616619        if (index != missingSymbolMarker()) {
    617             new (this) ScopedVarAccessNode(index, depth);
    618             return;
     620            stackDepth = depth;
     621            return index;
    619622        }
    620623        if (currentVariableObject->isDynamicScope())
    621624            break;
    622625    }
    623     if (depth > 0)
    624         new (this) NonLocalVarAccessNode(depth);
     626    stackDepth = depth;
     627    return missingSymbolMarker();
     628}
     629
     630void ResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack&)
     631{
     632    size_t depth = 0;
     633    size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
     634    if (index != missingSymbolMarker()) {
     635        if (!depth)
     636            new (this) LocalVarAccessNode(index);
     637        else
     638            new (this) ScopedVarAccessNode(index, depth);
     639        return;
     640    }
     641
     642    if (!depth)
     643        return;
     644
     645    new (this) NonLocalVarAccessNode(depth);
    625646}
    626647
     
    656677}
    657678
    658 JSValue* ScopedVarAccessNode::inlineEvaluate(ExecState* exec)
     679static inline JSValue* getNonLocalSymbol(ExecState* exec, size_t index, size_t scopeDepth)
    659680{
    660681    const ScopeChain& chain = exec->scopeChain();
    661682    ScopeChainIterator iter = chain.begin();
    662     for (size_t i = 0; i < m_scopeDepth; ++iter, ++i)
     683    for (size_t i = 0; i < scopeDepth; ++iter, ++i)
    663684        ASSERT(iter != chain.end());
    664685    JSObject* scope = *iter;
    665     ASSERT(scope->isActivationObject() || scope->isGlobalObject());
     686    ASSERT(scope->isVariableObject());
    666687    JSVariableObject* variableObject = static_cast<JSVariableObject*>(scope);
    667     return variableObject->localStorage()[m_index].value;
     688    return variableObject->localStorage()[index].value;
     689}
     690
     691JSValue* ScopedVarAccessNode::inlineEvaluate(ExecState* exec)
     692{
     693    return getNonLocalSymbol(exec, m_index, m_scopeDepth);
    668694}
    669695
     
    10621088}
    10631089
    1064 template <ExpressionNode::CallerType callerType>
    1065 inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args)
     1090template <ExpressionNode::CallerType callerType, bool scopeDepthIsZero>
     1091inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args, size_t scopeDepth)
    10661092{
    10671093    const ScopeChain& chain = exec->scopeChain();
     
    10691095    ScopeChainIterator end = chain.end();
    10701096
     1097    if (!scopeDepthIsZero) {
     1098        for (size_t i = 0; i < scopeDepth; ++iter, ++i)
     1099            ASSERT(iter != chain.end());
     1100    }
     1101   
    10711102    // we must always have something in the scope chain
    10721103    ASSERT(iter != end);
     
    11231154JSValue* EvalFunctionCallNode::evaluate(ExecState* exec)
    11241155{
    1125     return resolveAndCall<EvalOperator>(exec, exec->propertyNames().eval, m_args.get());
     1156    return resolveAndCall<EvalOperator, true>(exec, exec->propertyNames().eval, m_args.get());
    11261157}
    11271158
     
    11571188}
    11581189
    1159 void FunctionCallResolveNode::optimizeVariableAccess(ExecState*, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
     1190void FunctionCallResolveNode::optimizeVariableAccess(ExecState* exec, const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
    11601191{
    11611192    nodeStack.append(m_args.get());
    11621193
    1163     size_t index = symbolTable.get(m_ident.ustring().rep());
    1164     if (index != missingSymbolMarker())
    1165         new (this) LocalVarFunctionCallNode(index);
     1194    size_t depth = 0;
     1195    size_t index = getSymbolTableEntry(exec, m_ident, symbolTable, depth);
     1196    if (index != missingSymbolMarker()) {
     1197        if (!depth)
     1198            new (this) LocalVarFunctionCallNode(index);
     1199        else
     1200            new (this) ScopedVarFunctionCallNode(index, depth);
     1201        return;
     1202    }
     1203   
     1204    if (!depth)
     1205        return;
     1206   
     1207    new (this) NonLocalVarFunctionCallNode(depth);
    11661208}
    11671209
     
    11721214    ASSERT(!canSkipLookup(exec, m_ident));
    11731215
    1174     return resolveAndCall<FunctionCall>(exec, m_ident, m_args.get());
     1216    return resolveAndCall<FunctionCall, true>(exec, m_ident, m_args.get());
    11751217}
    11761218
     
    12551297
    12561298uint32_t LocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
     1299{
     1300    JSValue* v = inlineEvaluate(exec);
     1301    KJS_CHECKEXCEPTIONNUMBER
     1302    return v->toUInt32(exec);
     1303}
     1304
     1305JSValue* ScopedVarFunctionCallNode::inlineEvaluate(ExecState* exec)
     1306{
     1307    ASSERT(exec->variableObject() == exec->scopeChain().top());
     1308   
     1309    JSValue* v = getNonLocalSymbol(exec, m_index, m_scopeDepth);
     1310   
     1311    if (!v->isObject())
     1312        return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
     1313   
     1314    JSObject* func = static_cast<JSObject*>(v);
     1315    if (!func->implementsCall())
     1316        return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
     1317   
     1318    List argList;
     1319    m_args->evaluateList(exec, argList);
     1320    KJS_CHECKEXCEPTIONVALUE
     1321   
     1322    return func->call(exec, exec->dynamicGlobalObject(), argList);
     1323}
     1324
     1325JSValue* ScopedVarFunctionCallNode::evaluate(ExecState* exec)
     1326{
     1327    return inlineEvaluate(exec);
     1328}
     1329
     1330double ScopedVarFunctionCallNode::evaluateToNumber(ExecState* exec)
     1331{
     1332    JSValue* v = inlineEvaluate(exec);
     1333    KJS_CHECKEXCEPTIONNUMBER
     1334    return v->toNumber(exec);
     1335}
     1336
     1337bool ScopedVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
     1338{
     1339    JSValue* v = inlineEvaluate(exec);
     1340    KJS_CHECKEXCEPTIONBOOLEAN
     1341    return v->toBoolean(exec);
     1342}
     1343
     1344int32_t ScopedVarFunctionCallNode::evaluateToInt32(ExecState* exec)
     1345{
     1346    JSValue* v = inlineEvaluate(exec);
     1347    KJS_CHECKEXCEPTIONNUMBER
     1348    return v->toInt32(exec);
     1349}
     1350
     1351uint32_t ScopedVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
     1352{
     1353    JSValue* v = inlineEvaluate(exec);
     1354    KJS_CHECKEXCEPTIONNUMBER
     1355    return v->toUInt32(exec);
     1356}
     1357
     1358JSValue* NonLocalVarFunctionCallNode::inlineEvaluate(ExecState* exec)
     1359{
     1360    // Check for missed optimization opportunity.
     1361    ASSERT(!canSkipLookup(exec, m_ident));
     1362   
     1363    return resolveAndCall<FunctionCall, false>(exec, m_ident, m_args.get(), m_scopeDepth);
     1364}
     1365
     1366JSValue* NonLocalVarFunctionCallNode::evaluate(ExecState* exec)
     1367{
     1368    return inlineEvaluate(exec);
     1369}
     1370
     1371double NonLocalVarFunctionCallNode::evaluateToNumber(ExecState* exec)
     1372{
     1373    JSValue* v = inlineEvaluate(exec);
     1374    KJS_CHECKEXCEPTIONNUMBER
     1375    return v->toNumber(exec);
     1376}
     1377
     1378bool NonLocalVarFunctionCallNode::evaluateToBoolean(ExecState* exec)
     1379{
     1380    JSValue* v = inlineEvaluate(exec);
     1381    KJS_CHECKEXCEPTIONBOOLEAN
     1382    return v->toBoolean(exec);
     1383}
     1384
     1385int32_t NonLocalVarFunctionCallNode::evaluateToInt32(ExecState* exec)
     1386{
     1387    JSValue* v = inlineEvaluate(exec);
     1388    KJS_CHECKEXCEPTIONNUMBER
     1389    return v->toInt32(exec);
     1390}
     1391
     1392uint32_t NonLocalVarFunctionCallNode::evaluateToUInt32(ExecState* exec)
    12571393{
    12581394    JSValue* v = inlineEvaluate(exec);
Note: See TracChangeset for help on using the changeset viewer.