Ignore:
Timestamp:
Jan 19, 2015, 8:47:55 PM (10 years ago)
Author:
[email protected]
Message:

Basic block start offsets should never be larger than end offsets in the control flow profiler
https://bugs.webkit.org/show_bug.cgi?id=140377

Reviewed by Filip Pizlo.

The bytecode generator will emit code more than once for some AST nodes. For instance,
the finally block of TryNode will emit two code paths for its finally block: one for
the normal path, and another for the path where an exception is thrown in the catch block.

This repeated code emission of the same AST node previously broke how the control
flow profiler computed text ranges of basic blocks because when the same AST node
is emitted multiple times, there is a good chance that there are ranges that span
from the end offset of one of these duplicated nodes back to the start offset of
the same duplicated node. This caused a basic block range to report a larger start
offset than end offset. This was incorrect. Now, when this situation is encountered
while linking a CodeBlock, the faulty range in question is ignored.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::insertBasicBlockBoundariesForControlFlowProfiler):

  • bytecode/CodeBlock.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ForInNode::emitMultiLoopBytecode):
(JSC::ForOfNode::emitBytecode):
(JSC::TryNode::emitBytecode):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseConditionalExpression):

  • runtime/ControlFlowProfiler.cpp:

(JSC::ControlFlowProfiler::ControlFlowProfiler):

  • runtime/ControlFlowProfiler.h:

(JSC::ControlFlowProfiler::dummyBasicBlock):

File:
1 edited

Legend:

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

    r178591 r178692  
    21112111        this->emitLoopHeader(generator, propertyName.get());
    21122112
     2113        generator.emitProfileControlFlow(m_statement->startOffset());
     2114
    21132115        generator.pushIndexedForInScope(local.get(), i.get());
    21142116        generator.emitNode(dst, m_statement);
    21152117        generator.popIndexedForInScope(local.get());
     2118
     2119        generator.emitProfileControlFlow(m_statement->endOffset());
    21162120
    21172121        generator.emitLabel(scope->continueTarget());
     
    21452149        this->emitLoopHeader(generator, propertyName.get());
    21462150
     2151        generator.emitProfileControlFlow(m_statement->startOffset());
     2152
    21472153        generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
    21482154        generator.emitNode(dst, m_statement);
    21492155        generator.popStructureForInScope(local.get());
     2156
     2157        generator.emitProfileControlFlow(m_statement->endOffset());
    21502158
    21512159        generator.emitLabel(scope->continueTarget());
     
    21782186        this->emitLoopHeader(generator, propertyName.get());
    21792187
     2188        generator.emitProfileControlFlow(m_statement->startOffset());
     2189
    21802190        generator.emitNode(dst, m_statement);
    21812191
     
    21972207    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
    21982208    generator.emitLabel(end.get());
     2209    generator.emitProfileControlFlow(m_statement->endOffset());
    21992210}
    22002211
     
    22482259            assignNode->bindings()->bindValue(generator, value);
    22492260        }
     2261        generator.emitProfileControlFlow(m_statement->startOffset());
    22502262        generator.emitNode(dst, m_statement);
    22512263    };
    22522264    generator.emitEnumeration(this, m_expr, extractor);
     2265    generator.emitProfileControlFlow(m_statement->endOffset());
    22532266}
    22542267
     
    26092622        RefPtr<Label> finallyEndLabel = generator.newLabel();
    26102623
    2611         // FIXME: To the JS programmer, running the normal path is the same basic block as running the uncaught exception path.
    2612         // But, we generate two different code paths for this, but we shouldn't generate two op_profile_control_flows for these because they
    2613         // logically represent the same basic block.
    2614         // https://bugs.webkit.org/show_bug.cgi?id=139287
    2615         if (m_catchBlock)
    2616             generator.emitProfileControlFlow(m_catchBlock->endOffset());
    2617         else
    2618             generator.emitProfileControlFlow(m_tryBlock->endOffset());
     2624        int finallyStartOffset = m_catchBlock ? m_catchBlock->endOffset() : m_tryBlock->endOffset();
    26192625
    26202626        // Normal path: run the finally code, and jump to the end.
     2627        generator.emitProfileControlFlow(finallyStartOffset);
    26212628        generator.emitNode(dst, m_finallyBlock);
     2629        generator.emitProfileControlFlow(m_finallyBlock->endOffset());
    26222630        generator.emitJump(finallyEndLabel.get());
    26232631
    26242632        // Uncaught exception path: invoke the finally block, then re-throw the exception.
    26252633        RefPtr<RegisterID> tempExceptionRegister = generator.popTryAndEmitCatch(tryData, generator.newTemporary(), preFinallyLabel.get());
     2634        generator.emitProfileControlFlow(finallyStartOffset);
    26262635        generator.emitNode(dst, m_finallyBlock);
    26272636        generator.emitThrow(tempExceptionRegister.get());
    26282637
    26292638        generator.emitLabel(finallyEndLabel.get());
    2630     } else
     2639        generator.emitProfileControlFlow(m_finallyBlock->endOffset());
     2640    } else
    26312641        generator.emitProfileControlFlow(m_catchBlock->endOffset());
    26322642
Note: See TracChangeset for help on using the changeset viewer.