Ignore:
Timestamp:
Dec 8, 2013, 11:01:17 AM (12 years ago)
Author:
[email protected]
Message:

Fold typedArray.length if typedArray is constant
https://bugs.webkit.org/show_bug.cgi?id=125252

Source/JavaScriptCore:

Reviewed by Sam Weinig.

This was meant to be easy. The problem is that there was no good place for putting
the folding of typedArray.length to a constant. You can't quite do it in the
bytecode parser because at that point you don't yet know if typedArray is really
a typed array. You can't do it as part of constant folding because the folder
assumes that it can opportunistically forward-flow a constant value without changing
the IR; this doesn't work since we need to first change the IR to register a
desired watchpoint and only after that can we introduce that constant. We could have
done it in Fixup but that would have been awkward since Fixup's code for turning a
GetById of "length" into GetArrayLength is already somewhat complex. We could have
done it in CSE but CSE is already fairly gnarly and will probably get rewritten.

So I introduced a new phase, called StrengthReduction. This phase should have any
transformations that don't requite CFA or CSE and that it would be weird to put into
those other phases.

I also took the opportunity to refactor some of the other folding code.

This also adds a test, but the test couldn't quite be a LayoutTests/js/regress so I
introduced the notion of JavaScriptCore/tests/stress.

The goal of this patch isn't really to improve performance or anything like that.
It adds an optimization for completeness, and in doing so it unlocks a bunch of new
possibilities. The one that I'm most excited about is revealing array length checks
in DFG IR, which will allow for array bounds check hoisting and elimination.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::::executeEffects):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::tryGetFoldableView):
(JSC::DFG::Graph::tryGetFoldableViewForChild1):

  • dfg/DFGGraph.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasTypedArray):
(JSC::DFG::Node::typedArray):

  • dfg/DFGNodeType.h:
  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::compileInThreadImpl):

  • dfg/DFGPredictionPropagationPhase.cpp:

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

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
(JSC::DFG::SpeculativeJIT::compileConstantIndexedPropertyStorage):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGStrengthReductionPhase.cpp: Added.

(JSC::DFG::StrengthReductionPhase::StrengthReductionPhase):
(JSC::DFG::StrengthReductionPhase::run):
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::foldTypedArrayPropertyToConstant):
(JSC::DFG::performStrengthReduction):

  • dfg/DFGStrengthReductionPhase.h: Added.
  • dfg/DFGWatchpointCollectionPhase.cpp:

(JSC::DFG::WatchpointCollectionPhase::handle):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::typedArrayLength):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionTransferArrayBuffer):

  • runtime/ArrayBufferView.h:
  • tests/stress: Added.
  • tests/stress/fold-typed-array-properties.js: Added.

(foo):

Tools:

Reviewed by Sam Weinig.

Add Source/JavaScriptCore/tests/stress to the set of JS tests. This is where you
should put tests that run just like JSRegress but don't run as part of LayoutTests.
Currently I'm using it for tests that require some surgical support from jsc.cpp.

  • Scripts/run-javascriptcore-tests:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r160257 r160292  
    267267            compilePhantom();
    268268            break;
     269        case ArithAdd:
     270        case ValueAdd:
     271            compileAddSub();
     272            break;
     273        case ArithSub:
     274            compileAddSub();
     275            break;
     276        case ArithMul:
     277            compileArithMul();
     278            break;
     279        case ArithDiv:
     280            compileArithDivMod();
     281            break;
     282        case ArithMod:
     283            compileArithDivMod();
     284            break;
     285        case ArithMin:
     286        case ArithMax:
     287            compileArithMinOrMax();
     288            break;
     289        case ArithAbs:
     290            compileArithAbs();
     291            break;
     292        case ArithNegate:
     293            compileArithNegate();
     294            break;
     295        case BitAnd:
     296            compileBitAnd();
     297            break;
     298        case BitOr:
     299            compileBitOr();
     300            break;
     301        case BitXor:
     302            compileBitXor();
     303            break;
     304        case BitRShift:
     305            compileBitRShift();
     306            break;
     307        case BitLShift:
     308            compileBitLShift();
     309            break;
     310        case BitURShift:
     311            compileBitURShift();
     312            break;
     313        case UInt32ToNumber:
     314            compileUInt32ToNumber();
     315            break;
     316        case Int32ToDouble:
     317            compileInt32ToDouble();
     318            break;
     319        case CheckStructure:
     320            compileCheckStructure();
     321            break;
     322        case StructureTransitionWatchpoint:
     323            compileStructureTransitionWatchpoint();
     324            break;
     325        case CheckFunction:
     326            compileCheckFunction();
     327            break;
     328        case ArrayifyToStructure:
     329            compileArrayifyToStructure();
     330            break;
     331        case PutStructure:
     332            compilePutStructure();
     333            break;
     334        case PhantomPutStructure:
     335            compilePhantomPutStructure();
     336            break;
     337        case GetById:
     338            compileGetById();
     339            break;
     340        case PutById:
     341            compilePutById();
     342            break;
     343        case GetButterfly:
     344            compileGetButterfly();
     345            break;
     346        case GetIndexedPropertyStorage:
     347            compileGetIndexedPropertyStorage();
     348            break;
     349        case CheckArray:
     350            compileCheckArray();
     351            break;
     352        case GetArrayLength:
     353            compileGetArrayLength();
     354            break;
     355        case GetByVal:
     356            compileGetByVal();
     357            break;
     358        case PutByVal:
     359        case PutByValAlias:
     360        case PutByValDirect:
     361            compilePutByVal();
     362            break;
     363        case NewObject:
     364            compileNewObject();
     365            break;
     366        case NewArray:
     367            compileNewArray();
     368            break;
     369        case NewArrayBuffer:
     370            compileNewArrayBuffer();
     371            break;
     372        case AllocatePropertyStorage:
     373            compileAllocatePropertyStorage();
     374            break;
     375        case StringCharAt:
     376            compileStringCharAt();
     377            break;
     378        case StringCharCodeAt:
     379            compileStringCharCodeAt();
     380            break;
     381        case GetByOffset:
     382            compileGetByOffset();
     383            break;
     384        case PutByOffset:
     385            compilePutByOffset();
     386            break;
     387        case GetGlobalVar:
     388            compileGetGlobalVar();
     389            break;
     390        case PutGlobalVar:
     391            compilePutGlobalVar();
     392            break;
     393        case NotifyWrite:
     394            compileNotifyWrite();
     395            break;
     396        case GetMyScope:
     397            compileGetMyScope();
     398            break;
     399        case SkipScope:
     400            compileSkipScope();
     401            break;
     402        case GetClosureRegisters:
     403            compileGetClosureRegisters();
     404            break;
     405        case GetClosureVar:
     406            compileGetClosureVar();
     407            break;
     408        case PutClosureVar:
     409            compilePutClosureVar();
     410            break;
     411        case CompareEq:
     412            compileCompareEq();
     413            break;
     414        case CompareEqConstant:
     415            compileCompareEqConstant();
     416            break;
     417        case CompareStrictEq:
     418            compileCompareStrictEq();
     419            break;
     420        case CompareStrictEqConstant:
     421            compileCompareStrictEqConstant();
     422            break;
     423        case CompareLess:
     424            compileCompareLess();
     425            break;
     426        case CompareLessEq:
     427            compileCompareLessEq();
     428            break;
     429        case CompareGreater:
     430            compileCompareGreater();
     431            break;
     432        case CompareGreaterEq:
     433            compileCompareGreaterEq();
     434            break;
     435        case LogicalNot:
     436            compileLogicalNot();
     437            break;
     438        case Call:
     439        case Construct:
     440            compileCallOrConstruct();
     441            break;
     442        case Jump:
     443            compileJump();
     444            break;
     445        case Branch:
     446            compileBranch();
     447            break;
     448        case Switch:
     449            compileSwitch();
     450            break;
     451        case Return:
     452            compileReturn();
     453            break;
     454        case ForceOSRExit:
     455            compileForceOSRExit();
     456            break;
     457        case InvalidationPoint:
     458            compileInvalidationPoint();
     459            break;
     460        case ValueToInt32:
     461            compileValueToInt32();
     462            break;
     463        case Int52ToValue:
     464            compileInt52ToValue();
     465            break;
    269466        case Flush:
    270467        case PhantomLocal:
    271468        case SetArgument:
    272469        case LoopHint:
    273             break;
    274         case ArithAdd:
    275         case ValueAdd:
    276             compileAddSub();
    277             break;
    278         case ArithSub:
    279             compileAddSub();
    280             break;
    281         case ArithMul:
    282             compileArithMul();
    283             break;
    284         case ArithDiv:
    285             compileArithDivMod();
    286             break;
    287         case ArithMod:
    288             compileArithDivMod();
    289             break;
    290         case ArithMin:
    291         case ArithMax:
    292             compileArithMinOrMax();
    293             break;
    294         case ArithAbs:
    295             compileArithAbs();
    296             break;
    297         case ArithNegate:
    298             compileArithNegate();
    299             break;
    300         case BitAnd:
    301             compileBitAnd();
    302             break;
    303         case BitOr:
    304             compileBitOr();
    305             break;
    306         case BitXor:
    307             compileBitXor();
    308             break;
    309         case BitRShift:
    310             compileBitRShift();
    311             break;
    312         case BitLShift:
    313             compileBitLShift();
    314             break;
    315         case BitURShift:
    316             compileBitURShift();
    317             break;
    318         case UInt32ToNumber:
    319             compileUInt32ToNumber();
    320             break;
    321         case Int32ToDouble:
    322             compileInt32ToDouble();
    323             break;
    324         case CheckStructure:
    325             compileCheckStructure();
    326             break;
    327         case StructureTransitionWatchpoint:
    328             compileStructureTransitionWatchpoint();
    329             break;
    330         case CheckFunction:
    331             compileCheckFunction();
    332             break;
    333         case ArrayifyToStructure:
    334             compileArrayifyToStructure();
    335             break;
    336         case PutStructure:
    337             compilePutStructure();
    338             break;
    339         case PhantomPutStructure:
    340             compilePhantomPutStructure();
    341             break;
    342         case GetById:
    343             compileGetById();
    344             break;
    345         case PutById:
    346             compilePutById();
    347             break;
    348         case GetButterfly:
    349             compileGetButterfly();
    350             break;
    351         case GetIndexedPropertyStorage:
    352             compileGetIndexedPropertyStorage();
    353             break;
    354         case CheckArray:
    355             compileCheckArray();
    356             break;
    357         case GetArrayLength:
    358             compileGetArrayLength();
    359             break;
    360         case GetByVal:
    361             compileGetByVal();
    362             break;
    363         case PutByVal:
    364         case PutByValAlias:
    365         case PutByValDirect:
    366             compilePutByVal();
    367             break;
    368         case NewObject:
    369             compileNewObject();
    370             break;
    371         case NewArray:
    372             compileNewArray();
    373             break;
    374         case NewArrayBuffer:
    375             compileNewArrayBuffer();
    376             break;
    377         case AllocatePropertyStorage:
    378             compileAllocatePropertyStorage();
    379             break;
    380         case StringCharAt:
    381             compileStringCharAt();
    382             break;
    383         case StringCharCodeAt:
    384             compileStringCharCodeAt();
    385             break;
    386         case GetByOffset:
    387             compileGetByOffset();
    388             break;
    389         case PutByOffset:
    390             compilePutByOffset();
    391             break;
    392         case GetGlobalVar:
    393             compileGetGlobalVar();
    394             break;
    395         case PutGlobalVar:
    396             compilePutGlobalVar();
    397             break;
    398         case NotifyWrite:
    399             compileNotifyWrite();
    400             break;
    401470        case VariableWatchpoint:
    402             break;
    403471        case FunctionReentryWatchpoint:
    404             break;
    405         case GetMyScope:
    406             compileGetMyScope();
    407             break;
    408         case SkipScope:
    409             compileSkipScope();
    410             break;
    411         case GetClosureRegisters:
    412             compileGetClosureRegisters();
    413             break;
    414         case GetClosureVar:
    415             compileGetClosureVar();
    416             break;
    417         case PutClosureVar:
    418             compilePutClosureVar();
    419             break;
    420         case CompareEq:
    421             compileCompareEq();
    422             break;
    423         case CompareEqConstant:
    424             compileCompareEqConstant();
    425             break;
    426         case CompareStrictEq:
    427             compileCompareStrictEq();
    428             break;
    429         case CompareStrictEqConstant:
    430             compileCompareStrictEqConstant();
    431             break;
    432         case CompareLess:
    433             compileCompareLess();
    434             break;
    435         case CompareLessEq:
    436             compileCompareLessEq();
    437             break;
    438         case CompareGreater:
    439             compileCompareGreater();
    440             break;
    441         case CompareGreaterEq:
    442             compileCompareGreaterEq();
    443             break;
    444         case LogicalNot:
    445             compileLogicalNot();
    446             break;
    447         case Call:
    448         case Construct:
    449             compileCallOrConstruct();
    450             break;
    451         case Jump:
    452             compileJump();
    453             break;
    454         case Branch:
    455             compileBranch();
    456             break;
    457         case Switch:
    458             compileSwitch();
    459             break;
    460         case Return:
    461             compileReturn();
    462             break;
    463         case ForceOSRExit:
    464             compileForceOSRExit();
    465             break;
    466         case InvalidationPoint:
    467             compileInvalidationPoint();
    468             break;
    469         case ValueToInt32:
    470             compileValueToInt32();
    471             break;
    472         case Int52ToValue:
    473             compileInt52ToValue();
     472        case TypedArrayWatchpoint:
    474473            break;
    475474        default:
     
    14251424        }
    14261425       
    1427         if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node(), m_node->arrayMode())) {
     1426        if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node)) {
    14281427            if (view->mode() != FastTypedArray) {
    14291428                setStorage(m_out.constIntPtr(view->vector()));
     
    17981797                        m_out.aboveOrEqual(
    17991798                            index,
    1800                             typedArrayLength(child1.node(), m_node->arrayMode(), base)));
     1799                            typedArrayLength(child1, m_node->arrayMode(), base)));
    18011800                }
    18021801               
     
    29442943    }
    29452944   
    2946     LValue typedArrayLength(Node* baseNode, ArrayMode arrayMode, LValue base)
    2947     {
    2948         if (JSArrayBufferView* view = m_graph.tryGetFoldableView(baseNode, arrayMode))
     2945    LValue typedArrayLength(Edge baseEdge, ArrayMode arrayMode, LValue base)
     2946    {
     2947        if (JSArrayBufferView* view = m_graph.tryGetFoldableView(baseEdge.node(), arrayMode))
    29492948            return m_out.constInt32(view->length());
    29502949        return m_out.load32(base, m_heaps.JSArrayBufferView_length);
     
    29532952    LValue typedArrayLength(Edge baseEdge, ArrayMode arrayMode)
    29542953    {
    2955         return typedArrayLength(baseEdge.node(), arrayMode, lowCell(baseEdge));
     2954        return typedArrayLength(baseEdge, arrayMode, lowCell(baseEdge));
    29562955    }
    29572956   
Note: See TracChangeset for help on using the changeset viewer.