Ignore:
Timestamp:
Feb 26, 2014, 12:40:46 PM (12 years ago)
Author:
[email protected]
Message:

Function.prototype.apply has a bad time with the spread operator
https://bugs.webkit.org/show_bug.cgi?id=129381

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore:

Make sure our apply logic handle the spread operator correctly.
To do this we simply emit the enumeration logic that we'd normally
use for other enumerations, but only store the first two results
to registers. Then perform a varargs call.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ApplyFunctionCallDotNode::emitBytecode):

LayoutTests:

Add tests

  • js/regress/call-spread-apply-expected.txt: Added.
  • js/regress/call-spread-apply.html: Added.
  • js/regress/script-tests/call-spread-apply.js: Added.

(testFunction):
(test2):
(test3):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r164630 r164738  
    627627        if (m_args->m_listNode && m_args->m_listNode->m_expr) {
    628628            ArgumentListNode* oldList = m_args->m_listNode;
    629             if (m_args->m_listNode->m_next) {
     629            if (m_args->m_listNode->m_expr->isSpreadExpression()) {
     630                SpreadExpressionNode* spread = static_cast<SpreadExpressionNode*>(m_args->m_listNode->m_expr);
     631                RefPtr<RegisterID> profileHookRegister;
     632                if (generator.shouldEmitProfileHooks())
     633                    profileHookRegister = generator.newTemporary();
     634                RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get());
     635                RefPtr<RegisterID> index = generator.emitLoad(generator.newTemporary(), jsNumber(0));
     636                RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
     637                RefPtr<RegisterID> argumentsRegister = generator.emitLoad(generator.newTemporary(), jsUndefined());
     638               
     639                auto extractor = [&thisRegister, &argumentsRegister, &index](BytecodeGenerator& generator, RegisterID* value)
     640                {
     641                    RefPtr<Label> haveThis = generator.newLabel();
     642                    RefPtr<Label> end = generator.newLabel();
     643                    RefPtr<RegisterID> compareResult = generator.newTemporary();
     644                    RefPtr<RegisterID> indexZeroCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(0)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
     645                    generator.emitJumpIfFalse(indexZeroCompareResult.get(), haveThis.get());
     646                    generator.emitMove(thisRegister.get(), value);
     647                    generator.emitLoad(index.get(), jsNumber(1));
     648                    generator.emitJump(end.get());
     649                    generator.emitLabel(haveThis.get());
     650                    RefPtr<RegisterID> indexOneCompareResult = generator.emitBinaryOp(op_eq, compareResult.get(), index.get(), generator.emitLoad(0, jsNumber(1)), OperandTypes(ResultType::numberTypeIsInt32(), ResultType::numberTypeIsInt32()));
     651                    generator.emitJumpIfFalse(indexOneCompareResult.get(), end.get());
     652                    generator.emitMove(argumentsRegister.get(), value);
     653                    generator.emitLoad(index.get(), jsNumber(2));
     654                    generator.emitLabel(end.get());
     655                };
     656                generator.emitEnumeration(this, spread->expression(), extractor);
     657                generator.emitCallVarargs(returnValue.get(), realFunction.get(), thisRegister.get(), argumentsRegister.get(), generator.newTemporary(), 0, profileHookRegister.get(), divot(), divotStart(), divotEnd());
     658            } else if (m_args->m_listNode->m_next) {
    630659                ASSERT(m_args->m_listNode->m_next->m_expr->isSimpleArray());
    631660                ASSERT(!m_args->m_listNode->m_next->m_next);
Note: See TracChangeset for help on using the changeset viewer.