Changeset 184747 in webkit


Ignore:
Timestamp:
May 21, 2015 7:39:25 PM (9 years ago)
Author:
saambarati1@gmail.com
Message:

Object allocation sinking phase should explicitly create bottom values for CreateActivation sink candidates and CreateActivation should have SymbolTable as a child node
https://bugs.webkit.org/show_bug.cgi?id=145192

Reviewed by Filip Pizlo.

When we sink CreateActivation and generate MaterializeCreateActivation
in the object allocation sinking phase, we now explictly add PutHints for
all variables on the activation setting those variables to their default value
(undefined for Function activations and soon to be JS Empty Value for block scope activations).
This allows us to remove code that fills FTL fast activation allocations with Undefined.

This patch also adds the constant SymbolTable as an OpInfo of CreateActivation and MaterializeCreateActivation
nodes. This is in preparation for ES6 block scoping which will introduce a new
op code that gets lowered to CreateActivation.

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::cellOperand):

  • dfg/DFGObjectAllocationSinkingPhase.cpp:

(JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
(JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
(JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
(JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):

  • dfg/DFGPromotedHeapLocation.cpp:

(WTF::printInternal):

  • dfg/DFGPromotedHeapLocation.h:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCreateActivation):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
(JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):

  • ftl/FTLOperations.cpp:

(JSC::FTL::operationMaterializeObjectInOSR):

  • tests/stress/activation-sink-default-value.js: Added.

(bar):

  • tests/stress/activation-sink-osrexit-default-value.js: Added.

(foo.set result):

Location:
trunk/Source/JavaScriptCore
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r184717 r184747  
     12015-05-21  Saam Barati  <saambarati1@gmail.com>
     2
     3        Object allocation sinking phase should explicitly create bottom values for CreateActivation sink candidates and CreateActivation should have SymbolTable as a child node
     4        https://bugs.webkit.org/show_bug.cgi?id=145192
     5
     6        Reviewed by Filip Pizlo.
     7
     8        When we sink CreateActivation and generate MaterializeCreateActivation
     9        in the object allocation sinking phase, we now explictly add PutHints for
     10        all variables on the activation setting those variables to their default value
     11        (undefined for Function activations and soon to be JS Empty Value for block scope activations).
     12        This allows us to remove code that fills FTL fast activation allocations with Undefined.
     13
     14        This patch also adds the constant SymbolTable as an OpInfo of CreateActivation and MaterializeCreateActivation
     15        nodes. This is in preparation for ES6 block scoping which will introduce a new
     16        op code that gets lowered to CreateActivation.
     17
     18        * dfg/DFGByteCodeParser.cpp:
     19        (JSC::DFG::ByteCodeParser::parseBlock):
     20        * dfg/DFGClobberize.h:
     21        (JSC::DFG::clobberize):
     22        * dfg/DFGNode.h:
     23        (JSC::DFG::Node::hasCellOperand):
     24        (JSC::DFG::Node::cellOperand):
     25        * dfg/DFGObjectAllocationSinkingPhase.cpp:
     26        (JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
     27        (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
     28        (JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
     29        (JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):
     30        * dfg/DFGPromotedHeapLocation.cpp:
     31        (WTF::printInternal):
     32        * dfg/DFGPromotedHeapLocation.h:
     33        * dfg/DFGSpeculativeJIT.cpp:
     34        (JSC::DFG::SpeculativeJIT::compileCreateActivation):
     35        * ftl/FTLLowerDFGToLLVM.cpp:
     36        (JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
     37        (JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):
     38        * ftl/FTLOperations.cpp:
     39        (JSC::FTL::operationMaterializeObjectInOSR):
     40        * tests/stress/activation-sink-default-value.js: Added.
     41        (bar):
     42        * tests/stress/activation-sink-osrexit-default-value.js: Added.
     43        (foo.set result):
     44
    1452015-05-21  Per Arne Vollan  <peavo@outlook.com>
    246
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r184646 r184747  
    37343734           
    37353735        case op_create_lexical_environment: {
    3736             Node* lexicalEnvironment = addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[2].u.operand)));
     3736            FrozenValue* symbolTable = m_graph.freezeStrong(m_graph.symbolTableFor(currentNodeOrigin().semantic));
     3737            Node* lexicalEnvironment = addToGraph(CreateActivation, OpInfo(symbolTable), get(VirtualRegister(currentInstruction[2].u.operand)));
    37373738            set(VirtualRegister(currentInstruction[1].u.operand), lexicalEnvironment);
    37383739            set(VirtualRegister(currentInstruction[2].u.operand), lexicalEnvironment);
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r184541 r184747  
    318318
    319319    case CreateActivation: {
    320         SymbolTable* table = graph.symbolTableFor(node->origin.semantic);
     320        SymbolTable* table = node->castOperand<SymbolTable*>();
    321321        if (table->singletonScope()->isStillValid())
    322322            write(Watchpoint_fire);
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r184368 r184747  
    12831283        case NativeCall:
    12841284        case NewFunction:
     1285        case CreateActivation:
     1286        case MaterializeCreateActivation:
    12851287            return true;
    12861288        default:
     
    12921294    {
    12931295        ASSERT(hasCellOperand());
    1294         return reinterpret_cast<FrozenValue*>(m_opInfo);
     1296        switch (op()) {
     1297        case MaterializeCreateActivation:
     1298            return reinterpret_cast<FrozenValue*>(m_opInfo2);
     1299        default:
     1300            return reinterpret_cast<FrozenValue*>(m_opInfo);
     1301        }
     1302        RELEASE_ASSERT_NOT_REACHED();
    12951303    }
    12961304   
  • trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp

    r184445 r184747  
    587587                            PromotedHeapLocation(ActivationScopePLoc, node).createHint(
    588588                                m_graph, node->origin, node->child1().node()));
     589                        Node* symbolTableNode = m_insertionSet.insertConstant(
     590                            nodeIndex + 1, node->origin, node->cellOperand());
     591                        m_insertionSet.insert(
     592                            nodeIndex + 1,
     593                            PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
     594                                m_graph, node->origin, symbolTableNode));
     595
     596                        {
     597                            SymbolTable* symbolTable = node->castOperand<SymbolTable*>();
     598                            Node* undefined = m_insertionSet.insertConstant(
     599                                nodeIndex + 1, node->origin, jsUndefined());
     600                            ConcurrentJITLocker locker(symbolTable->m_lock);
     601                            for (auto iter = symbolTable->begin(locker), end = symbolTable->end(locker); iter != end; ++iter) {
     602                                m_insertionSet.insert(
     603                                    nodeIndex + 1,
     604                                    PromotedHeapLocation(
     605                                        ClosureVarPLoc, node, iter->value.scopeOffset().offset()).createHint(
     606                                        m_graph, node->origin, undefined));
     607                            }
     608                        }
     609
    589610                        node->convertToPhantomCreateActivation();
    590611                    }
     
    598619                            PromotedHeapLocation(ActivationScopePLoc, node).createHint(
    599620                                m_graph, node->origin, m_graph.varArgChild(node, 0).node()));
     621                        Node* symbolTableNode = m_insertionSet.insertConstant(
     622                            nodeIndex + 1, node->origin, node->cellOperand());
     623                        m_insertionSet.insert(
     624                            nodeIndex + 1,
     625                            PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
     626                                m_graph, node->origin, symbolTableNode));
    600627                        ObjectMaterializationData& data = node->objectMaterializationData();
    601628                        for (unsigned i = 0; i < data.m_properties.size(); ++i) {
     
    830857
    831858        case CreateActivation:
    832             if (!m_graph.symbolTableFor(node->origin.semantic)->singletonScope()->isStillValid())
     859            if (!node->castOperand<SymbolTable*>()->singletonScope()->isStillValid())
    833860                sinkCandidate();
    834861            escape(node->child1().node());
     
    933960        case MaterializeCreateActivation: {
    934961            ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
    935 
     962            FrozenValue* symbolTable = escapee->cellOperand();
    936963            result = m_graph.addNode(
    937964                escapee->prediction(), Node::VarArg, MaterializeCreateActivation,
     
    939966                    escapee->origin.semantic,
    940967                    where->origin.forExit),
    941                 OpInfo(data), OpInfo(), 0, 0);
     968                OpInfo(data), OpInfo(symbolTable), 0, 0);
    942969            break;
    943970        }
     
    10101037
    10111038            PromotedHeapLocation scope(ActivationScopePLoc, escapee);
     1039            PromotedHeapLocation symbolTable(ActivationSymbolTablePLoc, escapee);
    10121040            ASSERT(locations.contains(scope));
    10131041
     
    10181046                case ActivationScopePLoc: {
    10191047                    ASSERT(locations[i] == scope);
     1048                    break;
     1049                }
     1050
     1051                case ActivationSymbolTablePLoc: {
     1052                    ASSERT(locations[i] == symbolTable);
    10201053                    break;
    10211054                }
  • trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp

    r183812 r184747  
    6767        out.print("StructurePLoc");
    6868        return;
     69
     70    case ActivationSymbolTablePLoc:
     71        out.print("ActivationSymbolTablePLoc");
     72        return;
    6973       
    7074    case NamedPropertyPLoc:
  • trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h

    r183812 r184747  
    3838   
    3939    StructurePLoc,
     40    ActivationSymbolTablePLoc,
    4041    NamedPropertyPLoc,
    4142    ArgumentPLoc,
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r184397 r184747  
    45224522void SpeculativeJIT::compileCreateActivation(Node* node)
    45234523{
    4524     SymbolTable* table = m_jit.graph().symbolTableFor(node->origin.semantic);
     4524    SymbolTable* table = node->castOperand<SymbolTable*>();
    45254525    Structure* structure = m_jit.graph().globalObjectFor(
    45264526        node->origin.semantic)->activationStructure();
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r184542 r184747  
    29482948    {
    29492949        LValue scope = lowCell(m_node->child1());
    2950         SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic);
     2950        SymbolTable* table = m_node->castOperand<SymbolTable*>();
    29512951        Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
    29522952       
     
    52655265
    52665266        LValue scope = lowCell(m_graph.varArgChild(m_node, 0));
    5267         SymbolTable* table = m_graph.symbolTableFor(m_node->origin.semantic);
     5267        SymbolTable* table = m_node->castOperand<SymbolTable*>();
    52685268        Structure* structure = m_graph.globalObjectFor(m_node->origin.semantic)->activationStructure();
    52695269
     
    52795279        m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
    52805280
    5281         for (unsigned i = 0; i < table->scopeSize(); ++i) {
    5282             m_out.store64(
    5283                 m_out.constInt64(JSValue::encode(jsUndefined())),
    5284                 fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
    5285         }
    52865281
    52875282        ValueFromBlock fastResult = m_out.anchor(fastObject);
     
    52975292        m_out.appendTo(continuation, lastNext);
    52985293        LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
     5294        RELEASE_ASSERT(data.m_properties.size() == table->scopeSize());
    52995295        for (unsigned i = 0; i < data.m_properties.size(); ++i) {
    53005296            m_out.store64(values[i],
     
    53025298                m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]);
    53035299        }
     5300
     5301        if (validationEnabled()) {
     5302            // Validate to make sure every slot in the scope has one value.
     5303            ConcurrentJITLocker locker(table->m_lock);
     5304            for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
     5305                bool found = false;
     5306                for (unsigned i = 0; i < data.m_properties.size(); ++i) {
     5307                    if (iter->value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) {
     5308                        found = true;
     5309                        break;
     5310                    }
     5311                }
     5312                ASSERT(found);
     5313            }
     5314        }
     5315
    53045316        setJSValue(activation);
    53055317    }
  • trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp

    r184445 r184747  
    116116        // Figure out where the scope is
    117117        JSScope* scope = nullptr;
    118         for (unsigned i = materialization->properties().size(); i--;) {
    119             const ExitPropertyValue& property = materialization->properties()[i];
    120             if (property.location() != PromotedLocationDescriptor(ActivationScopePLoc))
    121                 continue;
    122             scope = jsCast<JSScope*>(JSValue::decode(values[i]));
     118        SymbolTable* table = nullptr;
     119        for (unsigned i = materialization->properties().size(); i--;) {
     120            const ExitPropertyValue& property = materialization->properties()[i];
     121            if (property.location() == PromotedLocationDescriptor(ActivationScopePLoc))
     122                scope = jsCast<JSScope*>(JSValue::decode(values[i]));
     123            else if (property.location() == PromotedLocationDescriptor(ActivationSymbolTablePLoc))
     124                table = jsCast<SymbolTable*>(JSValue::decode(values[i]));
    123125        }
    124126        RELEASE_ASSERT(scope);
     127        RELEASE_ASSERT(table);
    125128
    126129        CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
    127130            materialization->origin(), exec->codeBlock());
    128         SymbolTable* table = codeBlock->symbolTable();
    129131        Structure* structure = codeBlock->globalObject()->activationStructure();
    130132
    131133        JSLexicalEnvironment* result = JSLexicalEnvironment::create(vm, structure, scope, table);
    132134
     135        RELEASE_ASSERT(materialization->properties().size() - 2 == table->scopeSize());
    133136        // Figure out what to populate the activation with
    134137        for (unsigned i = materialization->properties().size(); i--;) {
     
    138141
    139142            result->variableAt(ScopeOffset(property.location().info())).set(exec->vm(), result, JSValue::decode(values[i]));
     143        }
     144
     145        if (validationEnabled()) {
     146            // Validate to make sure every slot in the scope has one value.
     147            ConcurrentJITLocker locker(table->m_lock);
     148            for (auto iter = table->begin(locker), end = table->end(locker); iter != end; ++iter) {
     149                bool found = false;
     150                for (unsigned i = materialization->properties().size(); i--;) {
     151                    const ExitPropertyValue& property = materialization->properties()[i];
     152                    if (property.location().kind() != ClosureVarPLoc)
     153                        continue;
     154                    if (ScopeOffset(property.location().info()) == iter->value.scopeOffset()) {
     155                        found = true;
     156                        break;
     157                    }
     158                }
     159                ASSERT(found);
     160            }
     161            unsigned numberOfClosureVarPloc = 0;
     162            for (unsigned i = materialization->properties().size(); i--;) {
     163                const ExitPropertyValue& property = materialization->properties()[i];
     164                if (property.location().kind() == ClosureVarPLoc)
     165                    numberOfClosureVarPloc++;
     166            }
     167            ASSERT(numberOfClosureVarPloc == table->scopeSize());
    140168        }
    141169
Note: See TracChangeset for help on using the changeset viewer.