Ignore:
Timestamp:
Apr 8, 2009, 4:08:28 PM (16 years ago)
Author:
[email protected]
Message:

Improve function.apply performance

Reviewed by Geoff Garen.

Jump through a few hoops to improve performance of function.apply in the general case.

In the case of zero or one arguments, or if there are only two arguments and the
second is an array literal we treat function.apply as function.call.

Otherwise we use the new opcodes op_load_varargs and op_call_varargs to do the .apply call
without re-entering the virtual machine.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r41904 r42337  
    13751375    return result;
    13761376}
     1377   
     1378int JITStubs::cti_op_load_varargs(STUB_ARGS)
     1379{
     1380    BEGIN_STUB_FUNCTION();
     1381    CallFrame* callFrame = ARG_callFrame;
     1382    RegisterFile* registerFile = ARG_registerFile;
     1383    int argsOffset = ARG_int1;
     1384    JSValuePtr arguments = callFrame[argsOffset].jsValue(callFrame);
     1385    uint32_t argCount = 0;
     1386    if (!arguments.isUndefinedOrNull()) {
     1387        if (!arguments.isObject()) {
     1388            CodeBlock* codeBlock = callFrame->codeBlock();
     1389            unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
     1390            ARG_globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
     1391            VM_THROW_EXCEPTION();
     1392        }
     1393        if (asObject(arguments)->classInfo() == &Arguments::info) {
     1394            Arguments* argsObject = asArguments(arguments);
     1395            argCount = argsObject->numProvidedArguments(callFrame);
     1396            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
     1397            Register* newEnd = callFrame->registers() + sizeDelta;
     1398            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
     1399                ARG_globalData->exception = createStackOverflowError(callFrame);
     1400                VM_THROW_EXCEPTION();
     1401            }
     1402            argsObject->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
     1403        } else if (isJSArray(&callFrame->globalData(), arguments)) {
     1404            JSArray* array = asArray(arguments);
     1405            argCount = array->length();
     1406            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
     1407            Register* newEnd = callFrame->registers() + sizeDelta;
     1408            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
     1409                ARG_globalData->exception = createStackOverflowError(callFrame);
     1410                VM_THROW_EXCEPTION();
     1411            }
     1412            array->copyToRegisters(callFrame, callFrame->registers() + argsOffset, argCount);
     1413        } else if (asObject(arguments)->inherits(&JSArray::info)) {
     1414            JSObject* argObject = asObject(arguments);
     1415            argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
     1416            int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
     1417            Register* newEnd = callFrame->registers() + sizeDelta;
     1418            if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
     1419                ARG_globalData->exception = createStackOverflowError(callFrame);
     1420                VM_THROW_EXCEPTION();
     1421            }
     1422            Register* argsBuffer = callFrame->registers() + argsOffset;
     1423            for (unsigned i = 0; i < argCount; ++i) {
     1424                argsBuffer[i] = asObject(arguments)->get(callFrame, i);
     1425                CHECK_FOR_EXCEPTION();
     1426            }
     1427        } else {
     1428            CodeBlock* codeBlock = callFrame->codeBlock();
     1429            unsigned vPCIndex = codeBlock->getBytecodeIndex(callFrame, STUB_RETURN_ADDRESS);
     1430            ARG_globalData->exception = createInvalidParamError(callFrame, "Function.prototype.apply", arguments, vPCIndex, codeBlock);
     1431            VM_THROW_EXCEPTION();
     1432        }
     1433    }
     1434    CHECK_FOR_EXCEPTION_AT_END();
     1435    return argCount + 1;
     1436}
    13771437
    13781438JSValueEncodedAsPointer* JITStubs::cti_op_negate(STUB_ARGS)
Note: See TracChangeset for help on using the changeset viewer.