Ignore:
Timestamp:
Nov 30, 2015, 12:36:54 PM (10 years ago)
Author:
[email protected]
Message:

implement op_get_rest_length so that we can allocate the rest array with the right size from the start
https://bugs.webkit.org/show_bug.cgi?id=151467

Reviewed by Geoffrey Garen and Mark Lam.

This patch implements op_get_rest_length which returns the length
that the rest parameter array will be. We're implementing this because
it might be a constant value in the presence of inlining in the DFG.
We will take advantage of this optimization opportunity in a future patch:
https://bugs.webkit.org/show_bug.cgi?id=151454
to emit better code for op_copy_rest.

op_get_rest_length has two operands:
1) a destination
2) A constant indicating the number of parameters to skip when copying the rest array.

op_get_rest_length lowers to a JSConstant node when we're inlined
and not a varargs call (in this case, we statically know the arguments
length). When that condition isn't met, we lower op_get_rest_length to
GetRestArray. GetRestArray produces its result as an int32.

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitNewArray):
(JSC::BytecodeGenerator::emitNewArrayWithSize):
(JSC::BytecodeGenerator::emitNewFunction):
(JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
(JSC::BytecodeGenerator::emitRestParameter):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::RestParameterNode::emit):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGMayExit.cpp:

(JSC::DFG::mayExit):

  • dfg/DFGNode.h:

(JSC::DFG::Node::numberOfArgumentsToSkip):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCopyRest):
(JSC::DFG::SpeculativeJIT::compileGetRestLength):
(JSC::DFG::SpeculativeJIT::compileNotifyWrite):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest):
(JSC::FTL::DFG::LowerDFGToLLVM::compileGetRestLength):
(JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_copy_rest):
(JSC::JIT::emit_op_get_rest_length):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r192671 r192814  
    33323332        }
    33333333
     3334        case op_get_rest_length: {
     3335            InlineCallFrame* inlineCallFrame = this->inlineCallFrame();
     3336            Node* length;
     3337            if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
     3338                unsigned argumentsLength = inlineCallFrame->arguments.size() - 1;
     3339                unsigned numParamsToSkip = currentInstruction[2].u.unsignedValue;
     3340                JSValue restLength;
     3341                if (argumentsLength <= numParamsToSkip)
     3342                    restLength = jsNumber(0);
     3343                else
     3344                    restLength = jsNumber(argumentsLength - numParamsToSkip);
     3345
     3346                length = jsConstant(restLength);
     3347            } else
     3348                length = addToGraph(GetRestLength, OpInfo(currentInstruction[2].u.unsignedValue));
     3349            set(VirtualRegister(currentInstruction[1].u.operand), length);
     3350            NEXT_OPCODE(op_get_rest_length);
     3351        }
     3352
    33343353        case op_copy_rest: {
    33353354            noticeArgumentsUse();
    3336             addToGraph(CopyRest,
    3337                 OpInfo(currentInstruction[2].u.unsignedValue), get(VirtualRegister(currentInstruction[1].u.operand)));
     3355            Node* array = get(VirtualRegister(currentInstruction[1].u.operand));
     3356            Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand));
     3357            addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue),
     3358                array, arrayLength);
    33383359            NEXT_OPCODE(op_copy_rest);
    33393360        }
Note: See TracChangeset for help on using the changeset viewer.