Ignore:
Timestamp:
Nov 22, 2019, 11:55:27 AM (6 years ago)
Author:
[email protected]
Message:

[JSC] DFG terminal's liveness should respect caller's opcodeID
https://bugs.webkit.org/show_bug.cgi?id=204317

Reviewed by Saam Barati.

JSTests:

  • stress/call-var-args-phantom-arguments-handler-strict.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/call-var-args-phantom-arguments-handler.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/call-var-args-phantom-arguments-strict.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/call-var-args-phantom-arguments.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/derived-class-construct-varargs.js: Added.

(shouldThrow):
(B):

  • stress/tail-call-var-args-phantom-arguments-handler-strict.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/tail-call-var-args-phantom-arguments-handler.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/tail-call-var-args-phantom-arguments-strict.js: Added.

(shouldBe):
(inlined):
(test):

  • stress/tail-call-var-args-phantom-arguments.js: Added.

(shouldBe):
(inlined):
(test):

Source/JavaScriptCore:

Let's consider the following example, which is freqneutly seen in Speedometer2/EmberJS-Debug.

"use strict";

function assertImpl(cond)
{

if (!cond)

throw new Error();

}

function assert()
{

assertImpl.apply(undefined, arguments);

}
noInline(assert);

When compiling throw, we emit a terminal node and put Phantom/PhantomLocal based on the bytecode liveness.
When collecting liveness for each frame, we use the liveness information of the bytecode op_call_varargs in assert function.
This means that op_call_varargs's uses are considered as live (like, arguments in this example).
But it is not necessary to mark it "live": if we are in assertImpl, arguments is already loaded into the stack, and we no longer
use arguments when exiting, and the execution after the exit. Marking this arguments live makes this arguments allocated
in DFG, but this is wasteful.

In this patch, we introduce BeforeUse and AfterUse concept into bytecode liveness information. And use AfterUse information when
collecting liveness in the caller's frame in DFG. We only enable this for varargs for now since (1) applying this to the other ones
is not profitable, and (2) we need to be careful to make stack arguments live to allow materialization of arguments objects.
In op_call_varargs / op_tail_call_varargs / op_construct_varargs cases, uses are happen only for |callee|, |this|, and |arguments|.
And these are no longer necessary after calling.

We don't use liveness information in the next bytecode since it misses uses marked by exception handlers.

  • bytecode/BytecodeLivenessAnalysis.cpp:

(JSC::BytecodeLivenessAnalysis::computeFullLiveness):

  • bytecode/BytecodeLivenessAnalysis.h:

(JSC::BytecodeLivenessAnalysis::graph):

  • bytecode/BytecodeLivenessAnalysisInlines.h:

(JSC::BytecodeLivenessPropagation::stepOverInstructionDef):
(JSC::BytecodeLivenessPropagation::stepOverInstructionUse):
(JSC::BytecodeLivenessPropagation::stepOverInstructionUseInExceptionHandler):
(JSC::BytecodeLivenessPropagation::stepOverInstruction):

  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeIndex):
(JSC::computeDefsForBytecodeIndex):

  • bytecode/FullBytecodeLiveness.h:

(JSC::FullBytecodeLiveness::getLiveness const):
(JSC::FullBytecodeLiveness::operandIsLive const):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::ForInContext::finalize):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::flushForTerminalImpl):

  • dfg/DFGForAllKills.h:

(JSC::DFG::forAllKilledOperands):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::isLiveInBytecode):

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::forAllLocalsLiveInBytecode):
(JSC::DFG::Graph::appropriateLivenessCalculationPoint):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
File:
1 edited

Legend:

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

    r252684 r252789  
    11401140    if (verbose)
    11411141        dataLog("Checking of operand is live: ", operand, "\n");
     1142    bool isCallerOrigin = false;
    11421143    CodeOrigin* codeOriginPtr = &codeOrigin;
    11431144    for (;;) {
     
    11731174            if (verbose)
    11741175                dataLog("Asking the bytecode liveness.\n");
    1175             return livenessFor(inlineCallFrame).operandIsLive(reg.offset(), codeOriginPtr->bytecodeIndex());
     1176            CodeBlock* codeBlock = baselineCodeBlockFor(inlineCallFrame);
     1177            FullBytecodeLiveness& fullLiveness = livenessFor(codeBlock);
     1178            BytecodeIndex bytecodeIndex = codeOriginPtr->bytecodeIndex();
     1179            return fullLiveness.operandIsLive(reg.offset(), bytecodeIndex, appropriateLivenessCalculationPoint(*codeOriginPtr, isCallerOrigin));
    11761180        }
    11771181
     
    11941198        // the return bytecode following the tail call.
    11951199        codeOriginPtr = &inlineCallFrame->directCaller;
     1200        isCallerOrigin = true;
    11961201    }
    11971202   
Note: See TracChangeset for help on using the changeset viewer.