Ignore:
Timestamp:
Jan 29, 2014, 11:18:54 AM (11 years ago)
Author:
[email protected]
Message:

Merge the jsCStack branch
https://bugs.webkit.org/show_bug.cgi?id=127763

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

Source/WebCore:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

Source/WTF:

Changes from http://svn.webkit.org/repository/webkit/branches/jsCStack
up to changeset 162958.

File:
1 edited

Legend:

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

    r162777 r163027  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3333#include "DFGInPlaceAbstractState.h"
    3434#include "FTLAbstractHeapRepository.h"
     35#include "FTLAvailableRecovery.h"
    3536#include "FTLForOSREntryJITCode.h"
    3637#include "FTLFormattedValue.h"
     
    5253static std::atomic<int> compileCounter;
    5354
     55// FIXME: Get rid of this and introduce a real stack check.
     56// https://bugs.webkit.org/show_bug.cgi?id=125650
     57static uintptr_t stackLimit;
     58
    5459// Using this instead of typeCheck() helps to reduce the load on LLVM, by creating
    5560// significantly less dead code.
     
    9398       
    9499        m_ftlState.function = addFunction(
    95             m_ftlState.module, name.data(), functionType(m_out.int64, m_out.intPtr));
     100            m_ftlState.module, name.data(), functionType(m_out.int64));
    96101        setFunctionCallingConv(m_ftlState.function, LLVMCCallConv);
     102        if (isX86() && Options::llvmDisallowAVX()) {
     103            // AVX makes V8/raytrace 80% slower. It makes Kraken/audio-oscillator 4.5x
     104            // slower. It should be disabled.
     105            addTargetDependentFunctionAttr(m_ftlState.function, "target-features", "-avx");
     106        }
    97107       
    98108        m_out.initialize(m_ftlState.module, m_ftlState.function, m_heaps);
    99109       
    100         m_prologue = appendBasicBlock(m_ftlState.context, m_ftlState.function);
    101         m_out.appendTo(m_prologue);
    102         createPhiVariables();
    103        
    104         m_callFrame = m_out.param(0);
    105         m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
    106         m_tagMask = m_out.constInt64(TagMask);
    107        
     110        m_prologue = FTL_NEW_BLOCK(m_out, ("Prologue"));
     111        LBasicBlock stackOverflow = FTL_NEW_BLOCK(m_out, ("Stack overflow"));
     112        m_handleExceptions = FTL_NEW_BLOCK(m_out, ("Handle Exceptions"));
     113
    108114        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
    109115            m_highBlock = m_graph.block(blockIndex);
     
    113119        }
    114120       
    115         m_out.appendTo(m_prologue);
    116         m_out.jump(lowBlock(m_graph.block(0)));
     121        m_out.appendTo(m_prologue, stackOverflow);
     122        createPhiVariables();
     123        LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
     124        m_captured = m_out.add(
     125            m_out.ptrToInt(capturedAlloca, m_out.intPtr),
     126            m_out.constIntPtr(m_graph.m_nextMachineLocal * sizeof(Register)));
     127       
     128        // We should not create any alloca's after this point, since they will cease to
     129        // be mem2reg candidates.
     130       
     131        m_ftlState.capturedStackmapID = m_stackmapIDs++;
     132        m_out.call(
     133            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.capturedStackmapID),
     134            m_out.int32Zero, capturedAlloca);
     135       
     136        m_callFrame = m_out.ptrToInt(
     137            m_out.call(m_out.frameAddressIntrinsic(), m_out.int32Zero), m_out.intPtr);
     138        m_tagTypeNumber = m_out.constInt64(TagTypeNumber);
     139        m_tagMask = m_out.constInt64(TagMask);
     140       
     141        m_out.storePtr(m_out.constIntPtr(codeBlock()), addressFor(JSStack::CodeBlock));
     142        m_out.branch(
     143            m_out.below(m_callFrame, m_out.loadPtr(m_out.absolute(&stackLimit))),
     144            stackOverflow, lowBlock(m_graph.block(0)));
     145       
     146        m_out.appendTo(stackOverflow, m_handleExceptions);
     147        // FIXME: Do a real stack check and throw the exception appropriately.
     148        // https://bugs.webkit.org/show_bug.cgi?id=125650
     149        m_out.crash();
     150       
     151        m_out.appendTo(m_handleExceptions, lowBlock(m_graph.block(0)));
     152        m_ftlState.handleExceptionStackmapID = m_stackmapIDs++;
     153        m_out.call(
     154            m_out.stackmapIntrinsic(), m_out.constInt64(m_ftlState.handleExceptionStackmapID),
     155            m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
     156        m_out.unreachable();
    117157       
    118158        Vector<BasicBlock*> depthFirst;
     
    227267            dataLog("Lowering ", m_node, "\n");
    228268       
     269        m_availableRecoveries.resize(0);
     270       
    229271        bool shouldExecuteEffects = m_interpreter.startExecuting(m_node);
    230272       
     
    266308            break;
    267309        case ArithAdd:
    268             compileAddSub();
    269             break;
    270310        case ArithSub:
    271             compileAddSub();
     311            compileArithAddOrSub();
    272312            break;
    273313        case ArithMul:
     
    275315            break;
    276316        case ArithDiv:
    277             compileArithDivMod();
     317            compileArithDiv();
    278318            break;
    279319        case ArithMod:
    280             compileArithDivMod();
     320            compileArithMod();
    281321            break;
    282322        case ArithMin:
     
    287327            compileArithAbs();
    288328            break;
     329        case ArithSin:
     330            compileArithSin();
     331            break;
     332        case ArithCos:
     333            compileArithCos();
     334            break;
     335        case ArithSqrt:
     336            compileArithSqrt();
     337            break;
    289338        case ArithNegate:
    290339            compileArithNegate();
     
    323372            compileCheckFunction();
    324373            break;
     374        case CheckExecutable:
     375            compileCheckExecutable();
     376            break;
    325377        case ArrayifyToStructure:
    326378            compileArrayifyToStructure();
     
    335387            compileGetById();
    336388            break;
     389        case PutByIdDirect:
    337390        case PutById:
    338391            compilePutById();
     
    373426            compileNewArrayBuffer();
    374427            break;
     428        case NewArrayWithSize:
     429            compileNewArrayWithSize();
     430            break;
    375431        case AllocatePropertyStorage:
    376432            compileAllocatePropertyStorage();
    377433            break;
     434        case ToString:
     435            compileToString();
     436            break;
     437        case MakeRope:
     438            compileMakeRope();
     439            break;
    378440        case StringCharAt:
    379441            compileStringCharAt();
     
    396458        case NotifyWrite:
    397459            compileNotifyWrite();
     460            break;
     461        case GetCallee:
     462            compileGetCallee();
     463            break;
     464        case GetScope:
     465            compileGetScope();
    398466            break;
    399467        case GetMyScope:
     
    466534        case Int52ToValue:
    467535            compileInt52ToValue();
     536            break;
     537        case CheckArgumentsNotCreated:
     538            compileCheckArgumentsNotCreated();
     539            break;
     540        case CountExecution:
     541            compileCountExecution();
    468542            break;
    469543        case StoreBarrier:
     
    483557        case FunctionReentryWatchpoint:
    484558        case TypedArrayWatchpoint:
     559        case AllocationProfileWatchpoint:
    485560            break;
    486561        default:
     
    816891    }
    817892   
    818     void compileAddSub()
     893    void compileArithAddOrSub()
    819894    {
    820895        bool isSub =  m_node->op() == ArithSub;
     
    823898            LValue left = lowInt32(m_node->child1());
    824899            LValue right = lowInt32(m_node->child2());
    825             LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
    826900
    827901            if (!shouldCheckOverflow(m_node->arithMode())) {
    828                 setInt32(result);
     902                setInt32(isSub ? m_out.sub(left, right) : m_out.add(left, right));
    829903                break;
    830904            }
    831905
    832             LValue overflow = isSub ? m_out.subWithOverflow32(left, right) : m_out.addWithOverflow32(left, right);
    833 
    834             speculate(Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
    835             setInt32(result);
     906            LValue result;
     907            if (!isSub) {
     908                result = m_out.addWithOverflow32(left, right);
     909               
     910                if (doesKill(m_node->child2())) {
     911                    addAvailableRecovery(
     912                        m_node->child2(), SubRecovery,
     913                        m_out.extractValue(result, 0), left, ValueFormatInt32);
     914                } else if (doesKill(m_node->child1())) {
     915                    addAvailableRecovery(
     916                        m_node->child1(), SubRecovery,
     917                        m_out.extractValue(result, 0), right, ValueFormatInt32);
     918                }
     919            } else {
     920                result = m_out.subWithOverflow32(left, right);
     921               
     922                if (doesKill(m_node->child2())) {
     923                    // result = left - right
     924                    // result - left = -right
     925                    // right = left - result
     926                    addAvailableRecovery(
     927                        m_node->child2(), SubRecovery,
     928                        left, m_out.extractValue(result, 0), ValueFormatInt32);
     929                } else if (doesKill(m_node->child1())) {
     930                    // result = left - right
     931                    // result + right = left
     932                    addAvailableRecovery(
     933                        m_node->child1(), AddRecovery,
     934                        m_out.extractValue(result, 0), right, ValueFormatInt32);
     935                }
     936            }
     937
     938            speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1));
     939            setInt32(m_out.extractValue(result, 0));
    836940            break;
    837941        }
     
    849953            LValue left = lowInt52(m_node->child1());
    850954            LValue right = lowInt52(m_node->child2());
    851             LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
    852 
    853             LValue overflow = isSub ? m_out.subWithOverflow64(left, right) : m_out.addWithOverflow64(left, right);
    854             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflow, 1));
    855             setInt52(result);
     955
     956            LValue result;
     957            if (!isSub) {
     958                result = m_out.addWithOverflow64(left, right);
     959               
     960                if (doesKill(m_node->child2())) {
     961                    addAvailableRecovery(
     962                        m_node->child2(), SubRecovery,
     963                        m_out.extractValue(result, 0), left, ValueFormatInt52);
     964                } else if (doesKill(m_node->child1())) {
     965                    addAvailableRecovery(
     966                        m_node->child1(), SubRecovery,
     967                        m_out.extractValue(result, 0), right, ValueFormatInt52);
     968                }
     969            } else {
     970                result = m_out.subWithOverflow64(left, right);
     971               
     972                if (doesKill(m_node->child2())) {
     973                    // result = left - right
     974                    // result - left = -right
     975                    // right = left - result
     976                    addAvailableRecovery(
     977                        m_node->child2(), SubRecovery,
     978                        left, m_out.extractValue(result, 0), ValueFormatInt52);
     979                } else if (doesKill(m_node->child1())) {
     980                    // result = left - right
     981                    // result + right = left
     982                    addAvailableRecovery(
     983                        m_node->child1(), AddRecovery,
     984                        m_out.extractValue(result, 0), right, ValueFormatInt52);
     985                }
     986            }
     987
     988            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1));
     989            setInt52(m_out.extractValue(result, 0));
    856990            break;
    857991        }
     
    8771011            LValue left = lowInt32(m_node->child1());
    8781012            LValue right = lowInt32(m_node->child2());
    879             LValue result = m_out.mul(left, right);
    880 
    881             if (shouldCheckOverflow(m_node->arithMode())) {
     1013           
     1014            LValue result;
     1015
     1016            if (!shouldCheckOverflow(m_node->arithMode()))
     1017                result = m_out.mul(left, right);
     1018            else {
    8821019                LValue overflowResult = m_out.mulWithOverflow32(left, right);
    8831020                speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     1021                result = m_out.extractValue(overflowResult, 0);
    8841022            }
    8851023           
     
    9051043            LValue left = lowWhicheverInt52(m_node->child1(), kind);
    9061044            LValue right = lowInt52(m_node->child2(), opposite(kind));
    907             LValue result = m_out.mul(left, right);
    908 
    9091045
    9101046            LValue overflowResult = m_out.mulWithOverflow64(left, right);
    9111047            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     1048            LValue result = m_out.extractValue(overflowResult, 0);
    9121049
    9131050            if (shouldCheckNegativeZero(m_node->arithMode())) {
     
    9401077    }
    9411078
    942     void compileArithDivMod()
     1079    void compileArithDiv()
    9431080    {
    9441081        switch (m_node->binaryUseKind()) {
     
    9471084            LValue denominator = lowInt32(m_node->child2());
    9481085           
    949             LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDivMod unsafe denominator"));
    950             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDivMod continuation"));
    951             LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDivMod done"));
     1086            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithDiv unsafe denominator"));
     1087            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithDiv continuation"));
     1088            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithDiv done"));
    9521089           
    9531090            Vector<ValueFromBlock, 3> results;
     
    9921129           
    9931130            if (shouldCheckNegativeZero(m_node->arithMode())) {
    994                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDivMod zero numerator"));
    995                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDivMod numerator continuation"));
     1131                LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, ("ArithDiv zero numerator"));
     1132                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithDiv numerator continuation"));
    9961133               
    9971134                m_out.branch(m_out.isZero32(numerator), zeroNumerator, numeratorContinuation);
     
    10071144            }
    10081145           
    1009             LValue divModResult = m_node->op() == ArithDiv
    1010                 ? m_out.div(numerator, denominator)
    1011                 : m_out.rem(numerator, denominator);
     1146            LValue result = m_out.div(numerator, denominator);
    10121147           
    10131148            if (shouldCheckOverflow(m_node->arithMode())) {
    10141149                speculate(
    10151150                    Overflow, noValue(), 0,
    1016                     m_out.notEqual(m_out.mul(divModResult, denominator), numerator));
     1151                    m_out.notEqual(m_out.mul(result, denominator), numerator));
    10171152            }
    10181153           
    1019             results.append(m_out.anchor(divModResult));
     1154            results.append(m_out.anchor(result));
    10201155            m_out.jump(done);
    10211156           
     
    10271162           
    10281163        case NumberUse: {
    1029             LValue C1 = lowDouble(m_node->child1());
    1030             LValue C2 = lowDouble(m_node->child2());
    1031             setDouble(m_node->op() == ArithDiv ? m_out.doubleDiv(C1, C2) : m_out.doubleRem(C1, C2));
     1164            setDouble(m_out.doubleDiv(
     1165                lowDouble(m_node->child1()), lowDouble(m_node->child2())));
    10321166            break;
    10331167        }
     
    10391173    }
    10401174   
     1175    void compileArithMod()
     1176    {
     1177        switch (m_node->binaryUseKind()) {
     1178        case Int32Use: {
     1179            LValue numerator = lowInt32(m_node->child1());
     1180            LValue denominator = lowInt32(m_node->child2());
     1181           
     1182            LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
     1183            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
     1184            LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
     1185           
     1186            Vector<ValueFromBlock, 3> results;
     1187           
     1188            LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
     1189           
     1190            m_out.branch(m_out.above(adjustedDenominator, m_out.int32One), continuation, unsafeDenominator);
     1191           
     1192            LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
     1193           
     1194            LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
     1195           
     1196            // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
     1197            // separate case for that. But it probably doesn't matter so much.
     1198            if (shouldCheckOverflow(m_node->arithMode())) {
     1199                LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
     1200                speculate(Overflow, noValue(), 0, cond);
     1201                m_out.jump(continuation);
     1202            } else {
     1203                // This is the case where we convert the result to an int after we're done. So,
     1204                // if the denominator is zero, then the result should be result should be zero.
     1205                // If the denominator is not zero (i.e. it's -1 because we're guarded by the
     1206                // check above) and the numerator is -2^31 then the result should be -2^31.
     1207               
     1208                LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
     1209                LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
     1210                LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
     1211               
     1212                m_out.branch(m_out.isZero32(denominator), modByZero, notModByZero);
     1213               
     1214                m_out.appendTo(modByZero, notModByZero);
     1215                results.append(m_out.anchor(m_out.int32Zero));
     1216                m_out.jump(done);
     1217               
     1218                m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
     1219                m_out.branch(m_out.equal(numerator, neg2ToThe31), neg2ToThe31ByNeg1, continuation);
     1220               
     1221                m_out.appendTo(neg2ToThe31ByNeg1, continuation);
     1222                results.append(m_out.anchor(m_out.int32Zero));
     1223                m_out.jump(done);
     1224            }
     1225           
     1226            m_out.appendTo(continuation, done);
     1227           
     1228            LValue remainder = m_out.rem(numerator, denominator);
     1229           
     1230            if (shouldCheckNegativeZero(m_node->arithMode())) {
     1231                LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
     1232                LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
     1233               
     1234                m_out.branch(
     1235                    m_out.lessThan(numerator, m_out.int32Zero),
     1236                    negativeNumerator, numeratorContinuation);
     1237               
     1238                LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
     1239               
     1240                speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
     1241               
     1242                m_out.jump(numeratorContinuation);
     1243               
     1244                m_out.appendTo(numeratorContinuation, innerLastNext);
     1245            }
     1246           
     1247            results.append(m_out.anchor(remainder));
     1248            m_out.jump(done);
     1249           
     1250            m_out.appendTo(done, lastNext);
     1251           
     1252            setInt32(m_out.phi(m_out.int32, results));
     1253            break;
     1254        }
     1255           
     1256        case NumberUse: {
     1257            setDouble(
     1258                m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
     1259            break;
     1260        }
     1261           
     1262        default:
     1263            RELEASE_ASSERT_NOT_REACHED();
     1264            break;
     1265        }
     1266    }
     1267
    10411268    void compileArithMinOrMax()
    10421269    {
     
    11151342        }
    11161343    }
     1344
     1345    void compileArithSin() { setDouble(m_out.doubleSin(lowDouble(m_node->child1()))); }
     1346
     1347    void compileArithCos() { setDouble(m_out.doubleCos(lowDouble(m_node->child1()))); }
     1348
     1349    void compileArithSqrt() { setDouble(m_out.doubleSqrt(lowDouble(m_node->child1()))); }
    11171350   
    11181351    void compileArithNegate()
     
    11221355            LValue value = lowInt32(m_node->child1());
    11231356           
    1124             LValue result = m_out.neg(value);
    1125             if (shouldCheckOverflow(m_node->arithMode())) {
    1126                 if (!shouldCheckNegativeZero(m_node->arithMode())) {
    1127                     // We don't have a negate-with-overflow intrinsic. Hopefully this
    1128                     // does the trick, though.
    1129                     LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
    1130                     speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    1131                 } else
    1132                     speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
    1133 
     1357            LValue result;
     1358            if (!shouldCheckOverflow(m_node->arithMode()))
     1359                result = m_out.neg(value);
     1360            else if (!shouldCheckNegativeZero(m_node->arithMode())) {
     1361                // We don't have a negate-with-overflow intrinsic. Hopefully this
     1362                // does the trick, though.
     1363                LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
     1364                speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
     1365                result = m_out.extractValue(overflowResult, 0);
     1366            } else {
     1367                speculate(Overflow, noValue(), 0, m_out.testIsZero32(value, m_out.constInt32(0x7fffffff)));
     1368                result = m_out.neg(value);
    11341369            }
    11351370
     
    11521387            LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value);
    11531388            speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
    1154             LValue result = m_out.neg(value);
     1389            LValue result = m_out.extractValue(overflowResult, 0);
    11551390            speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
    11561391            setInt52(result);
     
    12741509            BadFunction, jsValueValue(cell), m_node->child1().node(),
    12751510            m_out.notEqual(cell, weakPointer(m_node->function())));
     1511    }
     1512   
     1513    void compileCheckExecutable()
     1514    {
     1515        LValue cell = lowCell(m_node->child1());
     1516       
     1517        speculate(
     1518            BadExecutable, jsValueValue(cell), m_node->child1().node(),
     1519            m_out.notEqual(
     1520                m_out.loadPtr(cell, m_heaps.JSFunction_executable),
     1521                weakPointer(m_node->executable())));
    12761522    }
    12771523   
     
    13711617        LValue call = m_out.call(
    13721618            m_out.patchpointInt64Intrinsic(),
    1373             m_out.constInt32(stackmapID), m_out.constInt32(sizeOfGetById()),
    1374             constNull(m_out.ref8), m_out.constInt32(2), m_callFrame, base);
     1619            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfGetById()),
     1620            constNull(m_out.ref8), m_out.constInt32(1), base);
    13751621        setInstructionCallingConvention(call, LLVMAnyRegCallConv);
    13761622        setJSValue(call);
     
    13961642        LValue call = m_out.call(
    13971643            m_out.patchpointVoidIntrinsic(),
    1398             m_out.constInt32(stackmapID), m_out.constInt32(sizeOfPutById()),
    1399             constNull(m_out.ref8), m_out.constInt32(3), m_callFrame, base, value);
     1644            m_out.constInt64(stackmapID), m_out.constInt32(sizeOfPutById()),
     1645            constNull(m_out.ref8), m_out.constInt32(2), base, value);
    14001646        setInstructionCallingConvention(call, LLVMAnyRegCallConv);
    14011647       
     
    14641710        case Array::Double:
    14651711        case Array::Contiguous: {
    1466             setInt32(m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
     1712            setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
    14671713            return;
    14681714        }
     
    14701716        case Array::String: {
    14711717            LValue string = lowCell(m_node->child1());
    1472             setInt32(m_out.load32(string, m_heaps.JSString_length));
     1718            setInt32(m_out.load32NonNegative(string, m_heaps.JSString_length));
    14731719            return;
    14741720        }
     
    14771723            if (isTypedView(m_node->arrayMode().typedArrayType())) {
    14781724                setInt32(
    1479                     m_out.load32(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
     1725                    m_out.load32NonNegative(lowCell(m_node->child1()), m_heaps.JSArrayBufferView_length));
    14801726                return;
    14811727            }
     
    15191765            m_out.branch(
    15201766                m_out.aboveOrEqual(
    1521                     index, m_out.load32(storage, m_heaps.Butterfly_publicLength)),
     1767                    index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
    15221768                slowCase, fastCase);
    15231769           
     
    15661812            m_out.branch(
    15671813                m_out.aboveOrEqual(
    1568                     index, m_out.load32(storage, m_heaps.Butterfly_publicLength)),
     1814                    index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
    15691815                slowCase, inBounds);
    15701816           
     
    16881934        Edge child3 = m_graph.varArgChild(m_node, 2);
    16891935        Edge child4 = m_graph.varArgChild(m_node, 3);
     1936        Edge child5 = m_graph.varArgChild(m_node, 4);
    16901937       
    16911938        switch (m_node->arrayMode().type()) {
     
    18012048                            m_out.zeroExt(index, m_out.intPtr),
    18022049                            m_out.constIntPtr(logElementSize(type)))));
     2050               
     2051                LType refType;
     2052                LValue valueToStore;
    18032053               
    18042054                if (isInt(type)) {
     
    18772127                    switch (elementSize(type)) {
    18782128                    case 1:
    1879                         m_out.store8(m_out.intCast(intValue, m_out.int8), pointer);
     2129                        valueToStore = m_out.intCast(intValue, m_out.int8);
     2130                        refType = m_out.ref8;
    18802131                        break;
    18812132                    case 2:
    1882                         m_out.store16(m_out.intCast(intValue, m_out.int16), pointer);
     2133                        valueToStore = m_out.intCast(intValue, m_out.int16);
     2134                        refType = m_out.ref16;
    18832135                        break;
    18842136                    case 4:
    1885                         m_out.store32(intValue, pointer);
     2137                        valueToStore = intValue;
     2138                        refType = m_out.ref32;
    18862139                        break;
    18872140                    default:
    18882141                        RELEASE_ASSERT_NOT_REACHED();
    18892142                    }
     2143                } else /* !isInt(type) */ {
     2144                    LValue value = lowDouble(child3);
     2145                    switch (type) {
     2146                    case TypeFloat32:
     2147                        valueToStore = m_out.fpCast(value, m_out.floatType);
     2148                        refType = m_out.refFloat;
     2149                        break;
     2150                    case TypeFloat64:
     2151                        valueToStore = value;
     2152                        refType = m_out.refDouble;
     2153                        break;
     2154                    default:
     2155                        RELEASE_ASSERT_NOT_REACHED();
     2156                    }
     2157                }
     2158               
     2159                if (m_node->arrayMode().isInBounds())
     2160                    m_out.store(valueToStore, pointer, refType);
     2161                else {
     2162                    LBasicBlock isInBounds = FTL_NEW_BLOCK(m_out, ("PutByVal typed array in bounds case"));
     2163                    LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("PutByVal typed array continuation"));
    18902164                   
    1891                     return;
     2165                    m_out.branch(
     2166                        m_out.aboveOrEqual(index, lowInt32(child5)),
     2167                        continuation, isInBounds);
     2168                   
     2169                    LBasicBlock lastNext = m_out.appendTo(isInBounds, continuation);
     2170                    m_out.store(valueToStore, pointer, refType);
     2171                    m_out.jump(continuation);
     2172                   
     2173                    m_out.appendTo(continuation, lastNext);
    18922174                }
    18932175               
    1894                 ASSERT(isFloat(type));
    1895                
    1896                 LValue value = lowDouble(child3);
    1897                 switch (type) {
    1898                 case TypeFloat32:
    1899                     m_out.storeFloat(m_out.fpCast(value, m_out.floatType), pointer);
    1900                     break;
    1901                 case TypeFloat64:
    1902                     m_out.storeDouble(value, pointer);
    1903                     break;
    1904                 default:
    1905                     RELEASE_ASSERT_NOT_REACHED();
    1906                 }
    19072176                return;
    19082177            }
     
    20612330    }
    20622331   
     2332    void compileNewArrayWithSize()
     2333    {
     2334        LValue publicLength = lowInt32(m_node->child1());
     2335       
     2336        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->codeOrigin);
     2337        Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(
     2338            m_node->indexingType());
     2339       
     2340        if (!globalObject->isHavingABadTime() && !hasArrayStorage(m_node->indexingType())) {
     2341            ASSERT(
     2342                hasUndecided(structure->indexingType())
     2343                || hasInt32(structure->indexingType())
     2344                || hasDouble(structure->indexingType())
     2345                || hasContiguous(structure->indexingType()));
     2346
     2347            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fast case"));
     2348            LBasicBlock largeCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize large case"));
     2349            LBasicBlock failCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize fail case"));
     2350            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize slow case"));
     2351            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize continuation"));
     2352           
     2353            m_out.branch(
     2354                m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
     2355                largeCase, fastCase);
     2356
     2357            LBasicBlock lastNext = m_out.appendTo(fastCase, largeCase);
     2358           
     2359            // We don't round up to BASE_VECTOR_LEN for new Array(blah).
     2360            LValue vectorLength = publicLength;
     2361           
     2362            LValue payloadSize =
     2363                m_out.shl(m_out.zeroExt(vectorLength, m_out.intPtr), m_out.constIntPtr(3));
     2364           
     2365            LValue butterflySize = m_out.add(
     2366                payloadSize, m_out.constIntPtr(sizeof(IndexingHeader)));
     2367           
     2368            LValue endOfStorage = allocateBasicStorageAndGetEnd(butterflySize, failCase);
     2369           
     2370            LValue butterfly = m_out.sub(endOfStorage, payloadSize);
     2371           
     2372            LValue object = allocateObject<JSArray>(
     2373                m_out.constIntPtr(structure), butterfly, failCase);
     2374           
     2375            m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
     2376            m_out.store32(vectorLength, butterfly, m_heaps.Butterfly_vectorLength);
     2377           
     2378            if (hasDouble(m_node->indexingType())) {
     2379                LBasicBlock initLoop = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init loop"));
     2380                LBasicBlock initDone = FTL_NEW_BLOCK(m_out, ("NewArrayWithSize double init done"));
     2381               
     2382                ValueFromBlock originalIndex = m_out.anchor(vectorLength);
     2383                ValueFromBlock originalPointer = m_out.anchor(butterfly);
     2384                m_out.branch(m_out.notZero32(vectorLength), initLoop, initDone);
     2385               
     2386                LBasicBlock initLastNext = m_out.appendTo(initLoop, initDone);
     2387                LValue index = m_out.phi(m_out.int32, originalIndex);
     2388                LValue pointer = m_out.phi(m_out.intPtr, originalPointer);
     2389               
     2390                m_out.store64(
     2391                    m_out.constInt64(bitwise_cast<int64_t>(QNaN)),
     2392                    TypedPointer(m_heaps.indexedDoubleProperties.atAnyIndex(), pointer));
     2393               
     2394                LValue nextIndex = m_out.sub(index, m_out.int32One);
     2395                addIncoming(index, m_out.anchor(nextIndex));
     2396                addIncoming(pointer, m_out.anchor(m_out.add(pointer, m_out.intPtrEight)));
     2397                m_out.branch(m_out.notZero32(nextIndex), initLoop, initDone);
     2398               
     2399                m_out.appendTo(initDone, initLastNext);
     2400            }
     2401           
     2402            ValueFromBlock fastResult = m_out.anchor(object);
     2403            m_out.jump(continuation);
     2404           
     2405            m_out.appendTo(largeCase, failCase);
     2406            ValueFromBlock largeStructure = m_out.anchor(m_out.constIntPtr(
     2407                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)));
     2408            m_out.jump(slowCase);
     2409           
     2410            m_out.appendTo(failCase, slowCase);
     2411            ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
     2412            m_out.jump(slowCase);
     2413           
     2414            m_out.appendTo(slowCase, continuation);
     2415            LValue structureValue = m_out.phi(
     2416                m_out.intPtr, largeStructure, failStructure);
     2417            ValueFromBlock slowResult = m_out.anchor(vmCall(
     2418                m_out.operation(operationNewArrayWithSize),
     2419                m_callFrame, structureValue, publicLength));
     2420            m_out.jump(continuation);
     2421           
     2422            m_out.appendTo(continuation, lastNext);
     2423            setJSValue(m_out.phi(m_out.intPtr, fastResult, slowResult));
     2424            return;
     2425        }
     2426       
     2427        LValue structureValue = m_out.select(
     2428            m_out.aboveOrEqual(publicLength, m_out.constInt32(MIN_SPARSE_ARRAY_INDEX)),
     2429            m_out.constIntPtr(
     2430                globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)),
     2431            m_out.constIntPtr(structure));
     2432        setJSValue(vmCall(m_out.operation(operationNewArrayWithSize), m_callFrame, structureValue, publicLength));
     2433    }
     2434   
    20632435    void compileAllocatePropertyStorage()
    20642436    {
     
    21032475    }
    21042476   
     2477    void compileToString()
     2478    {
     2479        switch (m_node->child1().useKind()) {
     2480        case StringObjectUse: {
     2481            LValue cell = lowCell(m_node->child1());
     2482            speculateStringObjectForCell(m_node->child1(), cell);
     2483            m_interpreter.filter(m_node->child1(), SpecStringObject);
     2484           
     2485            setJSValue(m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
     2486            return;
     2487        }
     2488           
     2489        case StringOrStringObjectUse: {
     2490            LValue cell = lowCell(m_node->child1());
     2491            LValue structure = m_out.loadPtr(cell, m_heaps.JSCell_structure);
     2492           
     2493            LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject not string case"));
     2494            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString StringOrStringObject continuation"));
     2495           
     2496            ValueFromBlock simpleResult = m_out.anchor(cell);
     2497            m_out.branch(
     2498                m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())),
     2499                continuation, notString);
     2500           
     2501            LBasicBlock lastNext = m_out.appendTo(notString, continuation);
     2502            speculateStringObjectForStructure(m_node->child1(), structure);
     2503            ValueFromBlock unboxedResult = m_out.anchor(
     2504                m_out.loadPtr(cell, m_heaps.JSWrapperObject_internalValue));
     2505            m_out.jump(continuation);
     2506           
     2507            m_out.appendTo(continuation, lastNext);
     2508            setJSValue(m_out.phi(m_out.int64, simpleResult, unboxedResult));
     2509           
     2510            m_interpreter.filter(m_node->child1(), SpecString | SpecStringObject);
     2511            return;
     2512        }
     2513           
     2514        case CellUse:
     2515        case UntypedUse: {
     2516            LValue value;
     2517            if (m_node->child1().useKind() == CellUse)
     2518                value = lowCell(m_node->child1());
     2519            else
     2520                value = lowJSValue(m_node->child1());
     2521           
     2522            LBasicBlock isCell = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse is cell"));
     2523            LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse not string"));
     2524            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ToString CellUse/UntypedUse continuation"));
     2525           
     2526            LValue isCellPredicate;
     2527            if (m_node->child1().useKind() == CellUse)
     2528                isCellPredicate = m_out.booleanTrue;
     2529            else
     2530                isCellPredicate = this->isCell(value);
     2531            m_out.branch(isCellPredicate, isCell, notString);
     2532           
     2533            LBasicBlock lastNext = m_out.appendTo(isCell, notString);
     2534            ValueFromBlock simpleResult = m_out.anchor(value);
     2535            LValue isStringPredicate;
     2536            if (m_node->child1()->prediction() & SpecString) {
     2537                isStringPredicate = m_out.equal(
     2538                    m_out.loadPtr(value, m_heaps.JSCell_structure),
     2539                    m_out.constIntPtr(vm().stringStructure.get()));
     2540            } else
     2541                isStringPredicate = m_out.booleanFalse;
     2542            m_out.branch(isStringPredicate, continuation, notString);
     2543           
     2544            m_out.appendTo(notString, continuation);
     2545            LValue operation;
     2546            if (m_node->child1().useKind() == CellUse)
     2547                operation = m_out.operation(operationToStringOnCell);
     2548            else
     2549                operation = m_out.operation(operationToString);
     2550            ValueFromBlock convertedResult = m_out.anchor(vmCall(operation, m_callFrame, value));
     2551            m_out.jump(continuation);
     2552           
     2553            m_out.appendTo(continuation, lastNext);
     2554            setJSValue(m_out.phi(m_out.int64, simpleResult, convertedResult));
     2555            return;
     2556        }
     2557           
     2558        default:
     2559            RELEASE_ASSERT_NOT_REACHED();
     2560            break;
     2561        }
     2562    }
     2563   
     2564    void compileMakeRope()
     2565    {
     2566        LValue kids[3];
     2567        unsigned numKids;
     2568        kids[0] = lowCell(m_node->child1());
     2569        kids[1] = lowCell(m_node->child2());
     2570        if (m_node->child3()) {
     2571            kids[2] = lowCell(m_node->child3());
     2572            numKids = 3;
     2573        } else {
     2574            kids[2] = 0;
     2575            numKids = 2;
     2576        }
     2577       
     2578        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, ("MakeRope slow path"));
     2579        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MakeRope continuation"));
     2580       
     2581        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
     2582       
     2583        MarkedAllocator& allocator =
     2584            vm().heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(JSRopeString));
     2585       
     2586        LValue result = allocateCell(
     2587            m_out.constIntPtr(&allocator),
     2588            m_out.constIntPtr(vm().stringStructure.get()),
     2589            slowPath);
     2590       
     2591        m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSString_value);
     2592        for (unsigned i = 0; i < numKids; ++i)
     2593            m_out.storePtr(kids[i], result, m_heaps.JSRopeString_fibers[i]);
     2594        for (unsigned i = numKids; i < JSRopeString::s_maxInternalRopeLength; ++i)
     2595            m_out.storePtr(m_out.intPtrZero, result, m_heaps.JSRopeString_fibers[i]);
     2596        LValue flags = m_out.load32(kids[0], m_heaps.JSString_flags);
     2597        LValue length = m_out.load32(kids[0], m_heaps.JSString_length);
     2598        for (unsigned i = 1; i < numKids; ++i) {
     2599            flags = m_out.bitAnd(flags, m_out.load32(kids[i], m_heaps.JSString_flags));
     2600            length = m_out.add(length, m_out.load32(kids[i], m_heaps.JSString_length));
     2601        }
     2602        m_out.store32(
     2603            m_out.bitAnd(m_out.constInt32(JSString::Is8Bit), flags),
     2604            result, m_heaps.JSString_flags);
     2605        m_out.store32(length, result, m_heaps.JSString_length);
     2606       
     2607        ValueFromBlock fastResult = m_out.anchor(result);
     2608        m_out.jump(continuation);
     2609       
     2610        m_out.appendTo(slowPath, continuation);
     2611        ValueFromBlock slowResult;
     2612        switch (numKids) {
     2613        case 2:
     2614            slowResult = m_out.anchor(vmCall(
     2615                m_out.operation(operationMakeRope2), m_callFrame, kids[0], kids[1]));
     2616            break;
     2617        case 3:
     2618            slowResult = m_out.anchor(vmCall(
     2619                m_out.operation(operationMakeRope3), m_callFrame, kids[0], kids[1], kids[2]));
     2620            break;
     2621        default:
     2622            RELEASE_ASSERT_NOT_REACHED();
     2623            break;
     2624        }
     2625        m_out.jump(continuation);
     2626       
     2627        m_out.appendTo(continuation, lastNext);
     2628        setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
     2629    }
     2630   
    21052631    void compileStringCharAt()
    21062632    {
     
    21152641        m_out.branch(
    21162642            m_out.aboveOrEqual(
    2117                 index, m_out.load32(base, m_heaps.JSString_length)),
     2643                index, m_out.load32NonNegative(base, m_heaps.JSString_length)),
    21182644            slowPath, fastPath);
    21192645           
     
    22112737        speculate(
    22122738            Uncountable, noValue(), 0,
    2213             m_out.aboveOrEqual(index, m_out.load32(base, m_heaps.JSString_length)));
     2739            m_out.aboveOrEqual(
     2740                index, m_out.load32NonNegative(base, m_heaps.JSString_length)));
    22142741       
    22152742        LValue stringImpl = m_out.loadPtr(base, m_heaps.JSString_value);
     
    23462873    }
    23472874   
     2875    void compileGetCallee()
     2876    {
     2877        setJSValue(m_out.loadPtr(addressFor(JSStack::Callee)));
     2878    }
     2879   
     2880    void compileGetScope()
     2881    {
     2882        setJSValue(m_out.loadPtr(lowCell(m_node->child1()), m_heaps.JSFunction_scope));
     2883    }
     2884   
    23482885    void compileGetMyScope()
    23492886    {
     
    24893026    void compileCallOrConstruct()
    24903027    {
    2491         // FIXME: This is unacceptably slow.
    2492         // https://bugs.webkit.org/show_bug.cgi?id=113621
    2493        
    2494         J_JITOperation_E function =
    2495             m_node->op() == Call ? operationFTLCall : operationFTLConstruct;
    2496        
    24973028        int dummyThisArgument = m_node->op() == Call ? 0 : 1;
    2498        
    24993029        int numPassedArgs = m_node->numChildren() - 1;
    2500        
    2501         LValue calleeFrame = m_out.add(
    2502             m_callFrame,
    2503             m_out.constIntPtr(sizeof(Register) * virtualRegisterForLocal(m_graph.frameRegisterCount()).offset()));
    2504        
    2505         m_out.store32(
    2506             m_out.constInt32(numPassedArgs + dummyThisArgument),
    2507             payloadFor(calleeFrame, JSStack::ArgumentCount));
    2508         m_out.store64(m_callFrame, calleeFrame, m_heaps.CallFrame_callerFrame);
    2509         m_out.store64(
    2510             lowJSValue(m_graph.varArgChild(m_node, 0)),
    2511             addressFor(calleeFrame, JSStack::Callee));
    2512        
    2513         for (int i = 0; i < numPassedArgs; ++i) {
    2514             m_out.store64(
    2515                 lowJSValue(m_graph.varArgChild(m_node, 1 + i)),
    2516                 addressFor(calleeFrame, virtualRegisterForArgument(i + dummyThisArgument).offset()));
    2517         }
    2518        
    2519         setJSValue(vmCall(m_out.operation(function), calleeFrame));
     3030        int numArgs = numPassedArgs + dummyThisArgument;
     3031       
     3032        LValue callee = lowJSValue(m_graph.varArgChild(m_node, 0));
     3033       
     3034        unsigned stackmapID = m_stackmapIDs++;
     3035       
     3036        Vector<LValue> arguments;
     3037        arguments.append(m_out.constInt64(stackmapID));
     3038        arguments.append(m_out.constInt32(sizeOfCall()));
     3039        arguments.append(constNull(m_out.ref8));
     3040        arguments.append(m_out.constInt32(1 + JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + numArgs));
     3041        arguments.append(callee); // callee -> %rax
     3042        arguments.append(getUndef(m_out.int64)); // code block
     3043        arguments.append(getUndef(m_out.int64)); // scope chain
     3044        arguments.append(callee); // callee -> stack
     3045        arguments.append(m_out.constInt64(numArgs)); // argument count and zeros for the tag
     3046        if (dummyThisArgument)
     3047            arguments.append(getUndef(m_out.int64));
     3048        for (int i = 0; i < numPassedArgs; ++i)
     3049            arguments.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
     3050       
     3051        callPreflight();
     3052       
     3053        LValue call = m_out.call(m_out.patchpointInt64Intrinsic(), arguments);
     3054        setInstructionCallingConvention(call, LLVMWebKitJSCallConv);
     3055       
     3056        m_ftlState.jsCalls.append(JSCall(stackmapID, m_node));
     3057       
     3058        setJSValue(call);
    25203059    }
    25213060   
     
    26283167            m_out.branch(
    26293168                m_out.notEqual(
    2630                     m_out.load32(stringValue, m_heaps.JSString_length),
     3169                    m_out.load32NonNegative(stringValue, m_heaps.JSString_length),
    26313170                    m_out.int32One),
    26323171                lowBlock(data->fallThrough), lengthIs1);
     
    27073246       
    27083247        info.m_isInvalidationPoint = true;
     3248    }
     3249   
     3250    void compileCheckArgumentsNotCreated()
     3251    {
     3252        ASSERT(!isEmptySpeculation(
     3253            m_state.variables().operand(
     3254                m_graph.argumentsRegisterFor(m_node->codeOrigin)).m_type));
     3255       
     3256        VirtualRegister reg = m_graph.machineArgumentsRegisterFor(m_node->codeOrigin);
     3257        speculate(ArgumentsEscaped, noValue(), 0, m_out.notZero64(m_out.load64(addressFor(reg))));
     3258    }
     3259   
     3260    void compileCountExecution()
     3261    {
     3262        TypedPointer counter = m_out.absolute(m_node->executionCounter()->address());
     3263        m_out.store64(m_out.add(m_out.load64(counter), m_out.constInt64(1)), counter);
    27093264    }
    27103265   
     
    29253480        if (JSArrayBufferView* view = m_graph.tryGetFoldableView(baseEdge.node(), arrayMode))
    29263481            return m_out.constInt32(view->length());
    2927         return m_out.load32(base, m_heaps.JSArrayBufferView_length);
     3482        return m_out.load32NonNegative(base, m_heaps.JSArrayBufferView_length);
    29283483    }
    29293484   
     
    29493504        case StringUse: {
    29503505            LValue stringValue = lowString(m_node->child1());
    2951             LValue length = m_out.load32(stringValue, m_heaps.JSString_length);
     3506            LValue length = m_out.load32NonNegative(stringValue, m_heaps.JSString_length);
    29523507            return m_out.notEqual(length, m_out.int32Zero);
    29533508        }
     
    30833638    {
    30843639        LValue isNotInBounds = m_out.aboveOrEqual(
    3085             index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
     3640            index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength));
    30863641        if (!m_node->arrayMode().isInBounds()) {
    30873642            LBasicBlock notInBoundsCase =
     
    30953650               
    30963651            LValue isOutOfBounds = m_out.aboveOrEqual(
    3097                 index, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
     3652                index, m_out.load32NonNegative(storage, m_heaps.Butterfly_vectorLength));
    30983653               
    30993654            if (!m_node->arrayMode().isOutOfBounds())
     
    37194274        case KnownInt32Use:
    37204275        case KnownNumberUse:
     4276        case KnownStringUse:
    37214277            ASSERT(!m_interpreter.needsTypeCheck(edge));
    37224278            break;
     
    37424298            speculateString(edge);
    37434299            break;
     4300        case StringObjectUse:
     4301            speculateStringObject(edge);
     4302            break;
     4303        case StringOrStringObjectUse:
     4304            speculateStringOrStringObject(edge);
     4305            break;
    37444306        case RealNumberUse:
    37454307            speculateRealNumber(edge);
     
    37534315        case BooleanUse:
    37544316            speculateBoolean(edge);
     4317            break;
     4318        case NotCellUse:
     4319            speculateNotCell(edge);
    37554320            break;
    37564321        default:
     
    39294494    }
    39304495   
     4496    void speculateStringObject(Edge edge)
     4497    {
     4498        if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
     4499            return;
     4500       
     4501        speculateStringObjectForCell(edge, lowCell(edge));
     4502        m_interpreter.filter(edge, SpecStringObject);
     4503    }
     4504   
     4505    void speculateStringOrStringObject(Edge edge)
     4506    {
     4507        if (!m_interpreter.needsTypeCheck(edge, SpecString | SpecStringObject))
     4508            return;
     4509       
     4510        LBasicBlock notString = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject not string case"));
     4511        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Speculate StringOrStringObject continuation"));
     4512       
     4513        LValue structure = m_out.loadPtr(lowCell(edge), m_heaps.JSCell_structure);
     4514        m_out.branch(
     4515            m_out.equal(structure, m_out.constIntPtr(vm().stringStructure.get())),
     4516            continuation, notString);
     4517       
     4518        LBasicBlock lastNext = m_out.appendTo(notString, continuation);
     4519        speculateStringObjectForStructure(edge, structure);
     4520        m_out.jump(continuation);
     4521       
     4522        m_out.appendTo(continuation, lastNext);
     4523       
     4524        m_interpreter.filter(edge, SpecString | SpecStringObject);
     4525    }
     4526   
     4527    void speculateStringObjectForCell(Edge edge, LValue cell)
     4528    {
     4529        speculateStringObjectForStructure(edge, m_out.loadPtr(cell, m_heaps.JSCell_structure));
     4530    }
     4531   
     4532    void speculateStringObjectForStructure(Edge edge, LValue structure)
     4533    {
     4534        Structure* stringObjectStructure =
     4535            m_graph.globalObjectFor(m_node->codeOrigin)->stringObjectStructure();
     4536       
     4537        if (m_state.forNode(edge).m_currentKnownStructure.isSubsetOf(StructureSet(stringObjectStructure)))
     4538            return;
     4539       
     4540        speculate(
     4541            NotStringObject, noValue(), 0,
     4542            m_out.notEqual(structure, weakPointer(stringObjectStructure)));
     4543    }
     4544   
    39314545    void speculateNonNullObject(Edge edge, LValue cell)
    39324546    {
     
    39784592    {
    39794593        lowBoolean(edge);
     4594    }
     4595   
     4596    void speculateNotCell(Edge edge)
     4597    {
     4598        if (!m_interpreter.needsTypeCheck(edge))
     4599            return;
     4600       
     4601        LValue value = lowJSValue(edge);
     4602        typeCheck(jsValueValue(value), edge, ~SpecCell, isCell(value));
    39804603    }
    39814604   
     
    41074730            return;
    41084731       
    4109         LBasicBlock didHaveException = FTL_NEW_BLOCK(m_out, ("Did have exception"));
    41104732        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Exception check continuation"));
    41114733       
    41124734        m_out.branch(
    41134735            m_out.notZero64(m_out.load64(m_out.absolute(vm().addressOfException()))),
    4114             didHaveException, continuation);
    4115        
    4116         LBasicBlock lastNext = m_out.appendTo(didHaveException, continuation);
    4117         // FIXME: Handle exceptions. https://bugs.webkit.org/show_bug.cgi?id=113622
    4118         m_out.crash();
    4119        
    4120         m_out.appendTo(continuation, lastNext);
     4736            m_handleExceptions, continuation);
     4737       
     4738        m_out.appendTo(continuation);
    41214739    }
    41224740   
     
    41344752        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
    41354753    {
    4136         if (verboseCompilationEnabled())
     4754        if (verboseCompilationEnabled()) {
    41374755            dataLog("    OSR exit #", m_ftlState.jitCode->osrExit.size(), " with availability: ", m_availability, "\n");
     4756            if (!m_availableRecoveries.isEmpty())
     4757                dataLog("        Available recoveries: ", listDump(m_availableRecoveries), "\n");
     4758        }
    41384759
    41394760        ASSERT(m_ftlState.jitCode->osrExit.size() == m_ftlState.finalizer->osrExit.size());
     
    41794800        CodeOrigin codeOrigin)
    41804801    {
    4181         arguments.append(m_callFrame);
    41824802        if (!!lowValue)
    41834803            arguments.append(lowValue.value());
     
    42474867        exit.m_stackmapID = m_stackmapIDs++;
    42484868        arguments.insert(0, m_out.constInt32(MacroAssembler::maxJumpReplacementSize()));
    4249         arguments.insert(0, m_out.constInt32(exit.m_stackmapID));
     4869        arguments.insert(0, m_out.constInt64(exit.m_stackmapID));
    42504870       
    42514871        m_out.call(m_out.stackmapIntrinsic(), arguments);
     
    42604880        if (tryToSetConstantExitArgument(exit, index, node))
    42614881            return;
     4882       
     4883        for (unsigned i = 0; i < m_availableRecoveries.size(); ++i) {
     4884            AvailableRecovery recovery = m_availableRecoveries[i];
     4885            if (recovery.node() != node)
     4886                continue;
     4887           
     4888            exit.m_values[index] = ExitValue::recovery(
     4889                recovery.opcode(), arguments.size(), arguments.size() + 1,
     4890                recovery.format());
     4891            arguments.append(recovery.left());
     4892            arguments.append(recovery.right());
     4893            return;
     4894        }
    42624895       
    42634896        LoweredNodeValue value = m_int32Values.get(node);
     
    43304963    }
    43314964   
     4965    bool doesKill(Edge edge)
     4966    {
     4967        if (edge.doesNotKill())
     4968            return false;
     4969       
     4970        if (edge->hasConstant())
     4971            return false;
     4972       
     4973        return true;
     4974    }
     4975
     4976    void addAvailableRecovery(
     4977        Node* node, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format)
     4978    {
     4979        m_availableRecoveries.append(AvailableRecovery(node, opcode, left, right, format));
     4980    }
     4981   
     4982    void addAvailableRecovery(
     4983        Edge edge, RecoveryOpcode opcode, LValue left, LValue right, ValueFormat format)
     4984    {
     4985        addAvailableRecovery(edge.node(), opcode, left, right, format);
     4986    }
     4987   
    43324988    void setInt32(Node* node, LValue value)
    43334989    {
     
    44325088    TypedPointer payloadFor(LValue base, int operand)
    44335089    {
    4434         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     5090        return addressFor(base, operand, PayloadOffset);
    44355091    }
    44365092    TypedPointer tagFor(LValue base, int operand)
    44375093    {
    4438         return addressFor(base, operand, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
    4439     }
    4440     TypedPointer addressFor(int operand)
    4441     {
    4442         return addressFor(m_callFrame, operand);
    4443     }
    4444     TypedPointer addressFor(VirtualRegister operand)
    4445     {
    4446         return addressFor(m_callFrame, operand.offset());
     5094        return addressFor(base, operand, TagOffset);
     5095    }
     5096    TypedPointer addressFor(int operand, ptrdiff_t offset = 0)
     5097    {
     5098        return addressFor(VirtualRegister(operand), offset);
     5099    }
     5100    TypedPointer addressFor(VirtualRegister operand, ptrdiff_t offset = 0)
     5101    {
     5102        if (operand.isLocal())
     5103            return addressFor(m_captured, operand.offset(), offset);
     5104        return addressFor(m_callFrame, operand.offset(), offset);
    44475105    }
    44485106    TypedPointer payloadFor(int operand)
    44495107    {
    4450         return payloadFor(m_callFrame, operand);
     5108        return payloadFor(VirtualRegister(operand));
    44515109    }
    44525110    TypedPointer payloadFor(VirtualRegister operand)
    44535111    {
    4454         return payloadFor(m_callFrame, operand.offset());
     5112        return addressFor(operand, PayloadOffset);
    44555113    }
    44565114    TypedPointer tagFor(int operand)
    44575115    {
    4458         return tagFor(m_callFrame, operand);
     5116        return tagFor(VirtualRegister(operand));
    44595117    }
    44605118    TypedPointer tagFor(VirtualRegister operand)
    44615119    {
    4462         return tagFor(m_callFrame, operand.offset());
     5120        return addressFor(operand, TagOffset);
    44635121    }
    44645122   
     
    44725130   
    44735131    LBasicBlock m_prologue;
     5132    LBasicBlock m_handleExceptions;
    44745133    HashMap<BasicBlock*, LBasicBlock> m_blocks;
    44755134   
    44765135    LValue m_callFrame;
     5136    LValue m_captured;
    44775137    LValue m_tagTypeNumber;
    44785138    LValue m_tagMask;
     
    44905150    Operands<Availability> m_availability;
    44915151   
     5152    Vector<AvailableRecovery, 3> m_availableRecoveries;
     5153   
    44925154    InPlaceAbstractState m_state;
    44935155    AbstractInterpreter<InPlaceAbstractState> m_interpreter;
Note: See TracChangeset for help on using the changeset viewer.