Changeset 240229 in webkit


Ignore:
Timestamp:
Jan 20, 2019 10:13:08 PM (5 years ago)
Author:
sbarati@apple.com
Message:

DFG: When inlining DataView set* intrinsics we need to set undefined as our result
https://bugs.webkit.org/show_bug.cgi?id=193644
<rdar://problem/46209745>

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/data-view-set-intrinsic-undefined-result-2.js: Added.

(foo):

  • stress/data-view-set-intrinsic-undefined-result.js: Added.

(foo):
(bar):

Source/JavaScriptCore:

This patch also makes it so we fail fast when we make this mistake.
I've made this mistake more than once.

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

Location:
trunk
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r240223 r240229  
     12019-01-20  Saam Barati  <sbarati@apple.com>
     2
     3        DFG: When inlining DataView set* intrinsics we need to set undefined as our result
     4        https://bugs.webkit.org/show_bug.cgi?id=193644
     5        <rdar://problem/46209745>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        * stress/data-view-set-intrinsic-undefined-result-2.js: Added.
     10        (foo):
     11        * stress/data-view-set-intrinsic-undefined-result.js: Added.
     12        (foo):
     13        (bar):
     14
    1152019-01-20  Saam Barati  <sbarati@apple.com>
    216
  • trunk/Source/JavaScriptCore/ChangeLog

    r240228 r240229  
     12019-01-20  Saam Barati  <sbarati@apple.com>
     2
     3        DFG: When inlining DataView set* intrinsics we need to set undefined as our result
     4        https://bugs.webkit.org/show_bug.cgi?id=193644
     5        <rdar://problem/46209745>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        This patch also makes it so we fail fast when we make this mistake.
     10        I've made this mistake more than once.
     11
     12        * dfg/DFGByteCodeParser.cpp:
     13        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     14
    1152019-01-20  Yusuke Suzuki  <ysuzuki@apple.com>
    216
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r240220 r240229  
    21282128    if (!result.isValid())
    21292129        return false;
    2130    
    2131     switch (intrinsic) {
    2132 
    2133     // Intrinsic Functions:
    2134 
    2135     case AbsIntrinsic: {
    2136         if (argumentCountIncludingThis == 1) { // Math.abs()
     2130
     2131    bool didSetResult = false;
     2132    auto setResult = [&] (Node* node) {
     2133        RELEASE_ASSERT(!didSetResult);
     2134        set(result, node);
     2135        didSetResult = true;
     2136    };
     2137
     2138    auto inlineIntrinsic = [&] {
     2139        switch (intrinsic) {
     2140
     2141        // Intrinsic Functions:
     2142
     2143        case AbsIntrinsic: {
     2144            if (argumentCountIncludingThis == 1) { // Math.abs()
     2145                insertChecks();
     2146                setResult(addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2147                return true;
     2148            }
     2149
     2150            if (!MacroAssembler::supportsFloatingPointAbs())
     2151                return false;
     2152
    21372153            insertChecks();
    2138             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2154            Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
     2155            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
     2156                node->mergeFlags(NodeMayOverflowInt32InDFG);
     2157            setResult(node);
    21392158            return true;
    21402159        }
    21412160
    2142         if (!MacroAssembler::supportsFloatingPointAbs())
     2161        case MinIntrinsic:
     2162        case MaxIntrinsic:
     2163            if (handleMinMax(result, intrinsic == MinIntrinsic ? ArithMin : ArithMax, registerOffset, argumentCountIncludingThis, insertChecks)) {
     2164                didSetResult = true;
     2165                return true;
     2166            }
    21432167            return false;
    21442168
    2145         insertChecks();
    2146         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
    2147         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
    2148             node->mergeFlags(NodeMayOverflowInt32InDFG);
    2149         set(result, node);
    2150         return true;
    2151     }
    2152 
    2153     case MinIntrinsic:
    2154         return handleMinMax(result, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
    2155        
    2156     case MaxIntrinsic:
    2157         return handleMinMax(result, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
    2158 
    21592169#define DFG_ARITH_UNARY(capitalizedName, lowerName) \
    2160     case capitalizedName##Intrinsic:
    2161     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
     2170        case capitalizedName##Intrinsic:
     2171        FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
    21622172#undef DFG_ARITH_UNARY
    2163     {
    2164         if (argumentCountIncludingThis == 1) {
     2173        {
     2174            if (argumentCountIncludingThis == 1) {
     2175                insertChecks();
     2176                setResult(addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2177                return true;
     2178            }
     2179            Arith::UnaryType type = Arith::UnaryType::Sin;
     2180            switch (intrinsic) {
     2181#define DFG_ARITH_UNARY(capitalizedName, lowerName) \
     2182            case capitalizedName##Intrinsic: \
     2183                type = Arith::UnaryType::capitalizedName; \
     2184                break;
     2185        FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
     2186#undef DFG_ARITH_UNARY
     2187            default:
     2188                RELEASE_ASSERT_NOT_REACHED();
     2189            }
    21652190            insertChecks();
    2166             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2191            setResult(addToGraph(ArithUnary, OpInfo(static_cast<std::underlying_type<Arith::UnaryType>::type>(type)), get(virtualRegisterForArgument(1, registerOffset))));
    21672192            return true;
    21682193        }
    2169         Arith::UnaryType type = Arith::UnaryType::Sin;
    2170         switch (intrinsic) {
    2171 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
    2172         case capitalizedName##Intrinsic: \
    2173             type = Arith::UnaryType::capitalizedName; \
    2174             break;
    2175     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
    2176 #undef DFG_ARITH_UNARY
    2177         default:
     2194
     2195        case FRoundIntrinsic:
     2196        case SqrtIntrinsic: {
     2197            if (argumentCountIncludingThis == 1) {
     2198                insertChecks();
     2199                setResult(addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2200                return true;
     2201            }
     2202
     2203            NodeType nodeType = Unreachable;
     2204            switch (intrinsic) {
     2205            case FRoundIntrinsic:
     2206                nodeType = ArithFRound;
     2207                break;
     2208            case SqrtIntrinsic:
     2209                nodeType = ArithSqrt;
     2210                break;
     2211            default:
     2212                RELEASE_ASSERT_NOT_REACHED();
     2213            }
     2214            insertChecks();
     2215            setResult(addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
     2216            return true;
     2217        }
     2218
     2219        case PowIntrinsic: {
     2220            if (argumentCountIncludingThis < 3) {
     2221                // Math.pow() and Math.pow(x) return NaN.
     2222                insertChecks();
     2223                setResult(addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2224                return true;
     2225            }
     2226            insertChecks();
     2227            VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
     2228            VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
     2229            setResult(addToGraph(ArithPow, get(xOperand), get(yOperand)));
     2230            return true;
     2231        }
     2232           
     2233        case ArrayPushIntrinsic: {
     2234#if USE(JSVALUE32_64)
     2235            if (isX86()) {
     2236                if (argumentCountIncludingThis > 2)
     2237                    return false;
     2238            }
     2239#endif
     2240
     2241            if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
     2242                return false;
     2243           
     2244            ArrayMode arrayMode = getArrayMode(Array::Write);
     2245            if (!arrayMode.isJSArray())
     2246                return false;
     2247            switch (arrayMode.type()) {
     2248            case Array::Int32:
     2249            case Array::Double:
     2250            case Array::Contiguous:
     2251            case Array::ArrayStorage: {
     2252                insertChecks();
     2253
     2254                addVarArgChild(nullptr); // For storage.
     2255                for (int i = 0; i < argumentCountIncludingThis; ++i)
     2256                    addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
     2257                Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
     2258                setResult(arrayPush);
     2259                return true;
     2260            }
     2261               
     2262            default:
     2263                return false;
     2264            }
     2265        }
     2266
     2267        case ArraySliceIntrinsic: {
     2268#if USE(JSVALUE32_64)
     2269            if (isX86()) {
     2270                // There aren't enough registers for this to be done easily.
     2271                return false;
     2272            }
     2273#endif
     2274            if (argumentCountIncludingThis < 1)
     2275                return false;
     2276
     2277            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
     2278                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
     2279                return false;
     2280
     2281            ArrayMode arrayMode = getArrayMode(Array::Read);
     2282            if (!arrayMode.isJSArray())
     2283                return false;
     2284
     2285            if (!arrayMode.isJSArrayWithOriginalStructure())
     2286                return false;
     2287
     2288            switch (arrayMode.type()) {
     2289            case Array::Double:
     2290            case Array::Int32:
     2291            case Array::Contiguous: {
     2292                JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
     2293
     2294                Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
     2295                Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
     2296
     2297                // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
     2298                // https://bugs.webkit.org/show_bug.cgi?id=173171
     2299                if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
     2300                    && globalObject->havingABadTimeWatchpoint()->isStillValid()
     2301                    && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
     2302                    && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
     2303                    && globalObject->arrayPrototypeChainIsSane()) {
     2304
     2305                    m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
     2306                    m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
     2307                    m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
     2308                    m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
     2309
     2310                    insertChecks();
     2311
     2312                    Node* array = get(virtualRegisterForArgument(0, registerOffset));
     2313                    // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
     2314                    // 1. We ensure that the "constructor" property hasn't been changed (because the observable
     2315                    // effects of slice require that we perform a Get(array, "constructor") and we can skip
     2316                    // that if we're an original array structure. (We can relax this in the future by using
     2317                    // TryGetById and CheckCell).
     2318                    //
     2319                    // 2. We check that the array we're calling slice on has the same global object as the lexical
     2320                    // global object that this code is running in. This requirement is necessary because we setup the
     2321                    // watchpoints above on the lexical global object. This means that code that calls slice on
     2322                    // arrays produced by other global objects won't get this optimization. We could relax this
     2323                    // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
     2324                    // we generate instead of registering it as a watchpoint that would invalidate the compilation.
     2325                    //
     2326                    // 3. By proving we're an original array structure, we guarantee that the incoming array
     2327                    // isn't a subclass of Array.
     2328
     2329                    StructureSet structureSet;
     2330                    structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
     2331                    structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
     2332                    structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
     2333                    structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithInt32));
     2334                    structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
     2335                    structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithDouble));
     2336                    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
     2337
     2338                    addVarArgChild(array);
     2339                    if (argumentCountIncludingThis >= 2)
     2340                        addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
     2341                    if (argumentCountIncludingThis >= 3)
     2342                        addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
     2343                    addVarArgChild(addToGraph(GetButterfly, array));
     2344
     2345                    Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
     2346                    setResult(arraySlice);
     2347                    return true;
     2348                }
     2349
     2350                return false;
     2351            }
     2352            default:
     2353                return false;
     2354            }
     2355
    21782356            RELEASE_ASSERT_NOT_REACHED();
    2179         }
    2180         insertChecks();
    2181         set(result, addToGraph(ArithUnary, OpInfo(static_cast<std::underlying_type<Arith::UnaryType>::type>(type)), get(virtualRegisterForArgument(1, registerOffset))));
    2182         return true;
    2183     }
    2184 
    2185     case FRoundIntrinsic:
    2186     case SqrtIntrinsic: {
    2187         if (argumentCountIncludingThis == 1) {
     2357            return false;
     2358        }
     2359
     2360        case ArrayIndexOfIntrinsic: {
     2361            if (argumentCountIncludingThis < 2)
     2362                return false;
     2363
     2364            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
     2365                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
     2366                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
     2367                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     2368                return false;
     2369
     2370            ArrayMode arrayMode = getArrayMode(Array::Read);
     2371            if (!arrayMode.isJSArray())
     2372                return false;
     2373
     2374            if (!arrayMode.isJSArrayWithOriginalStructure())
     2375                return false;
     2376
     2377            // We do not want to convert arrays into one type just to perform indexOf.
     2378            if (arrayMode.doesConversion())
     2379                return false;
     2380
     2381            switch (arrayMode.type()) {
     2382            case Array::Double:
     2383            case Array::Int32:
     2384            case Array::Contiguous: {
     2385                JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
     2386
     2387                Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
     2388                Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
     2389
     2390                // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
     2391                // https://bugs.webkit.org/show_bug.cgi?id=173171
     2392                if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
     2393                    && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
     2394                    && globalObject->arrayPrototypeChainIsSane()) {
     2395
     2396                    m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
     2397                    m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
     2398
     2399                    insertChecks();
     2400
     2401                    Node* array = get(virtualRegisterForArgument(0, registerOffset));
     2402                    addVarArgChild(array);
     2403                    addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element.
     2404                    if (argumentCountIncludingThis >= 3)
     2405                        addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index.
     2406                    addVarArgChild(nullptr);
     2407
     2408                    Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo());
     2409                    setResult(node);
     2410                    return true;
     2411                }
     2412
     2413                return false;
     2414            }
     2415            default:
     2416                return false;
     2417            }
     2418
     2419            RELEASE_ASSERT_NOT_REACHED();
     2420            return false;
     2421
     2422        }
     2423           
     2424        case ArrayPopIntrinsic: {
     2425            if (argumentCountIncludingThis != 1)
     2426                return false;
     2427           
     2428            ArrayMode arrayMode = getArrayMode(Array::Write);
     2429            if (!arrayMode.isJSArray())
     2430                return false;
     2431            switch (arrayMode.type()) {
     2432            case Array::Int32:
     2433            case Array::Double:
     2434            case Array::Contiguous:
     2435            case Array::ArrayStorage: {
     2436                insertChecks();
     2437                Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
     2438                setResult(arrayPop);
     2439                return true;
     2440            }
     2441               
     2442            default:
     2443                return false;
     2444            }
     2445        }
     2446           
     2447        case AtomicsAddIntrinsic:
     2448        case AtomicsAndIntrinsic:
     2449        case AtomicsCompareExchangeIntrinsic:
     2450        case AtomicsExchangeIntrinsic:
     2451        case AtomicsIsLockFreeIntrinsic:
     2452        case AtomicsLoadIntrinsic:
     2453        case AtomicsOrIntrinsic:
     2454        case AtomicsStoreIntrinsic:
     2455        case AtomicsSubIntrinsic:
     2456        case AtomicsXorIntrinsic: {
     2457            if (!is64Bit())
     2458                return false;
     2459           
     2460            NodeType op = LastNodeType;
     2461            Array::Action action = Array::Write;
     2462            unsigned numArgs = 0; // Number of actual args; we add one for the backing store pointer.
     2463            switch (intrinsic) {
     2464            case AtomicsAddIntrinsic:
     2465                op = AtomicsAdd;
     2466                numArgs = 3;
     2467                break;
     2468            case AtomicsAndIntrinsic:
     2469                op = AtomicsAnd;
     2470                numArgs = 3;
     2471                break;
     2472            case AtomicsCompareExchangeIntrinsic:
     2473                op = AtomicsCompareExchange;
     2474                numArgs = 4;
     2475                break;
     2476            case AtomicsExchangeIntrinsic:
     2477                op = AtomicsExchange;
     2478                numArgs = 3;
     2479                break;
     2480            case AtomicsIsLockFreeIntrinsic:
     2481                // This gets no backing store, but we need no special logic for this since this also does
     2482                // not need varargs.
     2483                op = AtomicsIsLockFree;
     2484                numArgs = 1;
     2485                break;
     2486            case AtomicsLoadIntrinsic:
     2487                op = AtomicsLoad;
     2488                numArgs = 2;
     2489                action = Array::Read;
     2490                break;
     2491            case AtomicsOrIntrinsic:
     2492                op = AtomicsOr;
     2493                numArgs = 3;
     2494                break;
     2495            case AtomicsStoreIntrinsic:
     2496                op = AtomicsStore;
     2497                numArgs = 3;
     2498                break;
     2499            case AtomicsSubIntrinsic:
     2500                op = AtomicsSub;
     2501                numArgs = 3;
     2502                break;
     2503            case AtomicsXorIntrinsic:
     2504                op = AtomicsXor;
     2505                numArgs = 3;
     2506                break;
     2507            default:
     2508                RELEASE_ASSERT_NOT_REACHED();
     2509                break;
     2510            }
     2511           
     2512            if (static_cast<unsigned>(argumentCountIncludingThis) < 1 + numArgs)
     2513                return false;
     2514           
    21882515            insertChecks();
    2189             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2516           
     2517            Vector<Node*, 3> args;
     2518            for (unsigned i = 0; i < numArgs; ++i)
     2519                args.append(get(virtualRegisterForArgument(1 + i, registerOffset)));
     2520           
     2521            Node* resultNode;
     2522            if (numArgs + 1 <= 3) {
     2523                while (args.size() < 3)
     2524                    args.append(nullptr);
     2525                resultNode = addToGraph(op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction), args[0], args[1], args[2]);
     2526            } else {
     2527                for (Node* node : args)
     2528                    addVarArgChild(node);
     2529                addVarArgChild(nullptr);
     2530                resultNode = addToGraph(Node::VarArg, op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction));
     2531            }
     2532           
     2533            setResult(resultNode);
    21902534            return true;
    21912535        }
    21922536
    2193         NodeType nodeType = Unreachable;
    2194         switch (intrinsic) {
    2195         case FRoundIntrinsic:
    2196             nodeType = ArithFRound;
    2197             break;
    2198         case SqrtIntrinsic:
    2199             nodeType = ArithSqrt;
    2200             break;
    2201         default:
    2202             RELEASE_ASSERT_NOT_REACHED();
    2203         }
    2204         insertChecks();
    2205         set(result, addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
    2206         return true;
    2207     }
    2208 
    2209     case PowIntrinsic: {
    2210         if (argumentCountIncludingThis < 3) {
    2211             // Math.pow() and Math.pow(x) return NaN.
     2537        case ParseIntIntrinsic: {
     2538            if (argumentCountIncludingThis < 2)
     2539                return false;
     2540
     2541            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     2542                return false;
     2543
    22122544            insertChecks();
    2213             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2545            VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
     2546            Node* parseInt;
     2547            if (argumentCountIncludingThis == 2)
     2548                parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
     2549            else {
     2550                ASSERT(argumentCountIncludingThis > 2);
     2551                VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
     2552                parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
     2553            }
     2554            setResult(parseInt);
    22142555            return true;
    22152556        }
    2216         insertChecks();
    2217         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
    2218         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
    2219         set(result, addToGraph(ArithPow, get(xOperand), get(yOperand)));
    2220         return true;
    2221     }
    2222        
    2223     case ArrayPushIntrinsic: {
    2224 #if USE(JSVALUE32_64)
    2225         if (isX86()) {
    2226             if (argumentCountIncludingThis > 2)
    2227                 return false;
    2228         }
    2229 #endif
    2230 
    2231         if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
    2232             return false;
    2233        
    2234         ArrayMode arrayMode = getArrayMode(Array::Write);
    2235         if (!arrayMode.isJSArray())
    2236             return false;
    2237         switch (arrayMode.type()) {
    2238         case Array::Int32:
    2239         case Array::Double:
    2240         case Array::Contiguous:
    2241         case Array::ArrayStorage: {
     2557
     2558        case CharCodeAtIntrinsic: {
     2559            if (argumentCountIncludingThis != 2)
     2560                return false;
     2561
    22422562            insertChecks();
    2243 
    2244             addVarArgChild(nullptr); // For storage.
    2245             for (int i = 0; i < argumentCountIncludingThis; ++i)
    2246                 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
    2247             Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
    2248             set(result, arrayPush);
     2563            VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
     2564            VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
     2565            Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
     2566
     2567            setResult(charCode);
     2568            return true;
     2569        }
     2570
     2571        case CharAtIntrinsic: {
     2572            if (argumentCountIncludingThis != 2)
     2573                return false;
     2574
     2575            insertChecks();
     2576            VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
     2577            VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
     2578            Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
     2579
     2580            setResult(charCode);
     2581            return true;
     2582        }
     2583        case Clz32Intrinsic: {
     2584            insertChecks();
     2585            if (argumentCountIncludingThis == 1)
     2586                setResult(addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
     2587            else {
     2588                Node* operand = get(virtualRegisterForArgument(1, registerOffset));
     2589                setResult(addToGraph(ArithClz32, operand));
     2590            }
     2591            return true;
     2592        }
     2593        case FromCharCodeIntrinsic: {
     2594            if (argumentCountIncludingThis != 2)
     2595                return false;
     2596
     2597            insertChecks();
     2598            VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
     2599            Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
     2600
     2601            setResult(charCode);
     2602
     2603            return true;
     2604        }
     2605
     2606        case RegExpExecIntrinsic: {
     2607            if (argumentCountIncludingThis != 2)
     2608                return false;
     2609           
     2610            insertChecks();
     2611            Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
     2612            setResult(regExpExec);
    22492613           
    22502614            return true;
    22512615        }
    22522616           
    2253         default:
    2254             return false;
    2255         }
    2256     }
    2257 
    2258     case ArraySliceIntrinsic: {
    2259 #if USE(JSVALUE32_64)
    2260         if (isX86()) {
    2261             // There aren't enough registers for this to be done easily.
    2262             return false;
    2263         }
    2264 #endif
    2265         if (argumentCountIncludingThis < 1)
    2266             return false;
    2267 
    2268         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
    2269             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
    2270             return false;
    2271 
    2272         ArrayMode arrayMode = getArrayMode(Array::Read);
    2273         if (!arrayMode.isJSArray())
    2274             return false;
    2275 
    2276         if (!arrayMode.isJSArrayWithOriginalStructure())
    2277             return false;
    2278 
    2279         switch (arrayMode.type()) {
    2280         case Array::Double:
    2281         case Array::Int32:
    2282         case Array::Contiguous: {
    2283             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
    2284 
    2285             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
    2286             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
    2287 
    2288             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
    2289             // https://bugs.webkit.org/show_bug.cgi?id=173171
    2290             if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
    2291                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
    2292                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
    2293                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
    2294                 && globalObject->arrayPrototypeChainIsSane()) {
    2295 
    2296                 m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
    2297                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
    2298                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
    2299                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
    2300 
    2301                 insertChecks();
    2302 
    2303                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
    2304                 // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
    2305                 // 1. We ensure that the "constructor" property hasn't been changed (because the observable
    2306                 // effects of slice require that we perform a Get(array, "constructor") and we can skip
    2307                 // that if we're an original array structure. (We can relax this in the future by using
    2308                 // TryGetById and CheckCell).
    2309                 //
    2310                 // 2. We check that the array we're calling slice on has the same global object as the lexical
    2311                 // global object that this code is running in. This requirement is necessary because we setup the
    2312                 // watchpoints above on the lexical global object. This means that code that calls slice on
    2313                 // arrays produced by other global objects won't get this optimization. We could relax this
    2314                 // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
    2315                 // we generate instead of registering it as a watchpoint that would invalidate the compilation.
    2316                 //
    2317                 // 3. By proving we're an original array structure, we guarantee that the incoming array
    2318                 // isn't a subclass of Array.
    2319 
    2320                 StructureSet structureSet;
    2321                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
    2322                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
    2323                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
    2324                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithInt32));
    2325                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
    2326                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithDouble));
    2327                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
    2328 
    2329                 addVarArgChild(array);
    2330                 if (argumentCountIncludingThis >= 2)
    2331                     addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
    2332                 if (argumentCountIncludingThis >= 3)
    2333                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
    2334                 addVarArgChild(addToGraph(GetButterfly, array));
    2335 
    2336                 Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
    2337                 set(result, arraySlice);
    2338                 return true;
    2339             }
    2340 
    2341             return false;
    2342         }
    2343         default:
    2344             return false;
    2345         }
    2346 
    2347         RELEASE_ASSERT_NOT_REACHED();
    2348         return false;
    2349     }
    2350 
    2351     case ArrayIndexOfIntrinsic: {
    2352         if (argumentCountIncludingThis < 2)
    2353             return false;
    2354 
    2355         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
    2356             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
    2357             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
    2358             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    2359             return false;
    2360 
    2361         ArrayMode arrayMode = getArrayMode(Array::Read);
    2362         if (!arrayMode.isJSArray())
    2363             return false;
    2364 
    2365         if (!arrayMode.isJSArrayWithOriginalStructure())
    2366             return false;
    2367 
    2368         // We do not want to convert arrays into one type just to perform indexOf.
    2369         if (arrayMode.doesConversion())
    2370             return false;
    2371 
    2372         switch (arrayMode.type()) {
    2373         case Array::Double:
    2374         case Array::Int32:
    2375         case Array::Contiguous: {
    2376             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
    2377 
    2378             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
    2379             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
    2380 
    2381             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
    2382             // https://bugs.webkit.org/show_bug.cgi?id=173171
    2383             if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
    2384                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
    2385                 && globalObject->arrayPrototypeChainIsSane()) {
    2386 
    2387                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
    2388                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
    2389 
    2390                 insertChecks();
    2391 
    2392                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
    2393                 addVarArgChild(array);
    2394                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element.
    2395                 if (argumentCountIncludingThis >= 3)
    2396                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index.
    2397                 addVarArgChild(nullptr);
    2398 
    2399                 Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo());
    2400                 set(result, node);
    2401                 return true;
    2402             }
    2403 
    2404             return false;
    2405         }
    2406         default:
    2407             return false;
    2408         }
    2409 
    2410         RELEASE_ASSERT_NOT_REACHED();
    2411         return false;
    2412 
    2413     }
    2414        
    2415     case ArrayPopIntrinsic: {
    2416         if (argumentCountIncludingThis != 1)
    2417             return false;
    2418        
    2419         ArrayMode arrayMode = getArrayMode(Array::Write);
    2420         if (!arrayMode.isJSArray())
    2421             return false;
    2422         switch (arrayMode.type()) {
    2423         case Array::Int32:
    2424         case Array::Double:
    2425         case Array::Contiguous:
    2426         case Array::ArrayStorage: {
     2617        case RegExpTestIntrinsic:
     2618        case RegExpTestFastIntrinsic: {
     2619            if (argumentCountIncludingThis != 2)
     2620                return false;
     2621
     2622            if (intrinsic == RegExpTestIntrinsic) {
     2623                // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
     2624                if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
     2625                    return false;
     2626
     2627                JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
     2628                Structure* regExpStructure = globalObject->regExpStructure();
     2629                m_graph.registerStructure(regExpStructure);
     2630                ASSERT(regExpStructure->storedPrototype().isObject());
     2631                ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
     2632
     2633                FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
     2634                Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
     2635
     2636                auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
     2637                    JSValue currentProperty;
     2638                    if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
     2639                        return false;
     2640                   
     2641                    return currentProperty == primordialProperty;
     2642                };
     2643
     2644                // Check that RegExp.exec is still the primordial RegExp.prototype.exec
     2645                if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
     2646                    return false;
     2647
     2648                // Check that regExpObject is actually a RegExp object.
     2649                Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
     2650                addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
     2651
     2652                // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
     2653                UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
     2654                unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
     2655                Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
     2656                FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
     2657                addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
     2658            }
     2659
    24272660            insertChecks();
    2428             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
    2429             set(result, arrayPop);
     2661            Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
     2662            Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
     2663            setResult(regExpExec);
     2664           
    24302665            return true;
    24312666        }
    2432            
    2433         default:
    2434             return false;
    2435         }
    2436     }
    2437        
    2438     case AtomicsAddIntrinsic:
    2439     case AtomicsAndIntrinsic:
    2440     case AtomicsCompareExchangeIntrinsic:
    2441     case AtomicsExchangeIntrinsic:
    2442     case AtomicsIsLockFreeIntrinsic:
    2443     case AtomicsLoadIntrinsic:
    2444     case AtomicsOrIntrinsic:
    2445     case AtomicsStoreIntrinsic:
    2446     case AtomicsSubIntrinsic:
    2447     case AtomicsXorIntrinsic: {
    2448         if (!is64Bit())
    2449             return false;
    2450        
    2451         NodeType op = LastNodeType;
    2452         Array::Action action = Array::Write;
    2453         unsigned numArgs = 0; // Number of actual args; we add one for the backing store pointer.
    2454         switch (intrinsic) {
    2455         case AtomicsAddIntrinsic:
    2456             op = AtomicsAdd;
    2457             numArgs = 3;
    2458             break;
    2459         case AtomicsAndIntrinsic:
    2460             op = AtomicsAnd;
    2461             numArgs = 3;
    2462             break;
    2463         case AtomicsCompareExchangeIntrinsic:
    2464             op = AtomicsCompareExchange;
    2465             numArgs = 4;
    2466             break;
    2467         case AtomicsExchangeIntrinsic:
    2468             op = AtomicsExchange;
    2469             numArgs = 3;
    2470             break;
    2471         case AtomicsIsLockFreeIntrinsic:
    2472             // This gets no backing store, but we need no special logic for this since this also does
    2473             // not need varargs.
    2474             op = AtomicsIsLockFree;
    2475             numArgs = 1;
    2476             break;
    2477         case AtomicsLoadIntrinsic:
    2478             op = AtomicsLoad;
    2479             numArgs = 2;
    2480             action = Array::Read;
    2481             break;
    2482         case AtomicsOrIntrinsic:
    2483             op = AtomicsOr;
    2484             numArgs = 3;
    2485             break;
    2486         case AtomicsStoreIntrinsic:
    2487             op = AtomicsStore;
    2488             numArgs = 3;
    2489             break;
    2490         case AtomicsSubIntrinsic:
    2491             op = AtomicsSub;
    2492             numArgs = 3;
    2493             break;
    2494         case AtomicsXorIntrinsic:
    2495             op = AtomicsXor;
    2496             numArgs = 3;
    2497             break;
    2498         default:
    2499             RELEASE_ASSERT_NOT_REACHED();
    2500             break;
    2501         }
    2502        
    2503         if (static_cast<unsigned>(argumentCountIncludingThis) < 1 + numArgs)
    2504             return false;
    2505        
    2506         insertChecks();
    2507        
    2508         Vector<Node*, 3> args;
    2509         for (unsigned i = 0; i < numArgs; ++i)
    2510             args.append(get(virtualRegisterForArgument(1 + i, registerOffset)));
    2511        
    2512         Node* resultNode;
    2513         if (numArgs + 1 <= 3) {
    2514             while (args.size() < 3)
    2515                 args.append(nullptr);
    2516             resultNode = addToGraph(op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction), args[0], args[1], args[2]);
    2517         } else {
    2518             for (Node* node : args)
    2519                 addVarArgChild(node);
    2520             addVarArgChild(nullptr);
    2521             resultNode = addToGraph(Node::VarArg, op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction));
    2522         }
    2523        
    2524         set(result, resultNode);
    2525         return true;
    2526     }
    2527 
    2528     case ParseIntIntrinsic: {
    2529         if (argumentCountIncludingThis < 2)
    2530             return false;
    2531 
    2532         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    2533             return false;
    2534 
    2535         insertChecks();
    2536         VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
    2537         Node* parseInt;
    2538         if (argumentCountIncludingThis == 2)
    2539             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
    2540         else {
    2541             ASSERT(argumentCountIncludingThis > 2);
    2542             VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
    2543             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
    2544         }
    2545         set(result, parseInt);
    2546         return true;
    2547     }
    2548 
    2549     case CharCodeAtIntrinsic: {
    2550         if (argumentCountIncludingThis != 2)
    2551             return false;
    2552 
    2553         insertChecks();
    2554         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
    2555         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
    2556         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
    2557 
    2558         set(result, charCode);
    2559         return true;
    2560     }
    2561 
    2562     case CharAtIntrinsic: {
    2563         if (argumentCountIncludingThis != 2)
    2564             return false;
    2565 
    2566         insertChecks();
    2567         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
    2568         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
    2569         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
    2570 
    2571         set(result, charCode);
    2572         return true;
    2573     }
    2574     case Clz32Intrinsic: {
    2575         insertChecks();
    2576         if (argumentCountIncludingThis == 1)
    2577             set(result, addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
    2578         else {
    2579             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
    2580             set(result, addToGraph(ArithClz32, operand));
    2581         }
    2582         return true;
    2583     }
    2584     case FromCharCodeIntrinsic: {
    2585         if (argumentCountIncludingThis != 2)
    2586             return false;
    2587 
    2588         insertChecks();
    2589         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
    2590         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
    2591 
    2592         set(result, charCode);
    2593 
    2594         return true;
    2595     }
    2596 
    2597     case RegExpExecIntrinsic: {
    2598         if (argumentCountIncludingThis != 2)
    2599             return false;
    2600        
    2601         insertChecks();
    2602         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
    2603         set(result, regExpExec);
    2604        
    2605         return true;
    2606     }
    2607        
    2608     case RegExpTestIntrinsic:
    2609     case RegExpTestFastIntrinsic: {
    2610         if (argumentCountIncludingThis != 2)
    2611             return false;
    2612 
    2613         if (intrinsic == RegExpTestIntrinsic) {
     2667
     2668        case RegExpMatchFastIntrinsic: {
     2669            RELEASE_ASSERT(argumentCountIncludingThis == 2);
     2670
     2671            insertChecks();
     2672            Node* regExpMatch = addToGraph(RegExpMatchFast, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
     2673            setResult(regExpMatch);
     2674            return true;
     2675        }
     2676
     2677        case ObjectCreateIntrinsic: {
     2678            if (argumentCountIncludingThis != 2)
     2679                return false;
     2680
     2681            insertChecks();
     2682            setResult(addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
     2683            return true;
     2684        }
     2685
     2686        case ObjectGetPrototypeOfIntrinsic: {
     2687            if (argumentCountIncludingThis != 2)
     2688                return false;
     2689
     2690            insertChecks();
     2691            setResult(addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
     2692            return true;
     2693        }
     2694
     2695        case ObjectIsIntrinsic: {
     2696            if (argumentCountIncludingThis < 3)
     2697                return false;
     2698
     2699            insertChecks();
     2700            setResult(addToGraph(SameValue, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
     2701            return true;
     2702        }
     2703
     2704        case ObjectKeysIntrinsic: {
     2705            if (argumentCountIncludingThis < 2)
     2706                return false;
     2707
     2708            insertChecks();
     2709            setResult(addToGraph(ObjectKeys, get(virtualRegisterForArgument(1, registerOffset))));
     2710            return true;
     2711        }
     2712
     2713        case ObjectPrototypeToStringIntrinsic: {
     2714            insertChecks();
     2715            Node* value = get(virtualRegisterForArgument(0, registerOffset));
     2716            setResult(addToGraph(ObjectToString, value));
     2717            return true;
     2718        }
     2719
     2720        case ReflectGetPrototypeOfIntrinsic: {
     2721            if (argumentCountIncludingThis != 2)
     2722                return false;
     2723
     2724            insertChecks();
     2725            setResult(addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), Edge(get(virtualRegisterForArgument(1, registerOffset)), ObjectUse)));
     2726            return true;
     2727        }
     2728
     2729        case IsTypedArrayViewIntrinsic: {
     2730            ASSERT(argumentCountIncludingThis == 2);
     2731
     2732            insertChecks();
     2733            setResult(addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
     2734            return true;
     2735        }
     2736
     2737        case StringPrototypeValueOfIntrinsic: {
     2738            insertChecks();
     2739            Node* value = get(virtualRegisterForArgument(0, registerOffset));
     2740            setResult(addToGraph(StringValueOf, value));
     2741            return true;
     2742        }
     2743
     2744        case StringPrototypeReplaceIntrinsic: {
     2745            if (argumentCountIncludingThis != 3)
     2746                return false;
     2747
     2748            // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
     2749            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     2750                return false;
     2751
    26142752            // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
    26152753            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
     
    26292767                if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
    26302768                    return false;
    2631                
     2769
    26322770                return currentProperty == primordialProperty;
    26332771            };
    26342772
    2635             // Check that RegExp.exec is still the primordial RegExp.prototype.exec
     2773            // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
    26362774            if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
    26372775                return false;
    26382776
    2639             // Check that regExpObject is actually a RegExp object.
    2640             Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
    2641             addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
    2642 
    2643             // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
    2644             UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
    2645             unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
    2646             Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
    2647             FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
    2648             addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
    2649         }
    2650 
    2651         insertChecks();
    2652         Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
    2653         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
    2654         set(result, regExpExec);
    2655        
     2777            // Check that searchRegExp.global is still the primordial RegExp.prototype.global
     2778            if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
     2779                return false;
     2780
     2781            // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
     2782            if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
     2783                return false;
     2784
     2785            // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
     2786            if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
     2787                return false;
     2788
     2789            insertChecks();
     2790
     2791            Node* resultNode = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
     2792            setResult(resultNode);
     2793            return true;
     2794        }
     2795           
     2796        case StringPrototypeReplaceRegExpIntrinsic: {
     2797            if (argumentCountIncludingThis != 3)
     2798                return false;
     2799           
     2800            insertChecks();
     2801            Node* resultNode = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
     2802            setResult(resultNode);
     2803            return true;
     2804        }
     2805           
     2806        case RoundIntrinsic:
     2807        case FloorIntrinsic:
     2808        case CeilIntrinsic:
     2809        case TruncIntrinsic: {
     2810            if (argumentCountIncludingThis == 1) {
     2811                insertChecks();
     2812                setResult(addToGraph(JSConstant, OpInfo(m_constantNaN)));
     2813                return true;
     2814            }
     2815            insertChecks();
     2816            Node* operand = get(virtualRegisterForArgument(1, registerOffset));
     2817            NodeType op;
     2818            if (intrinsic == RoundIntrinsic)
     2819                op = ArithRound;
     2820            else if (intrinsic == FloorIntrinsic)
     2821                op = ArithFloor;
     2822            else if (intrinsic == CeilIntrinsic)
     2823                op = ArithCeil;
     2824            else {
     2825                ASSERT(intrinsic == TruncIntrinsic);
     2826                op = ArithTrunc;
     2827            }
     2828            Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
     2829            setResult(roundNode);
     2830            return true;
     2831        }
     2832        case IMulIntrinsic: {
     2833            if (argumentCountIncludingThis != 3)
     2834                return false;
     2835            insertChecks();
     2836            VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
     2837            VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
     2838            Node* left = get(leftOperand);
     2839            Node* right = get(rightOperand);
     2840            setResult(addToGraph(ArithIMul, left, right));
     2841            return true;
     2842        }
     2843
     2844        case RandomIntrinsic: {
     2845            if (argumentCountIncludingThis != 1)
     2846                return false;
     2847            insertChecks();
     2848            setResult(addToGraph(ArithRandom));
     2849            return true;
     2850        }
     2851           
     2852        case DFGTrueIntrinsic: {
     2853            insertChecks();
     2854            setResult(jsConstant(jsBoolean(true)));
     2855            return true;
     2856        }
     2857
     2858        case FTLTrueIntrinsic: {
     2859            insertChecks();
     2860            setResult(jsConstant(jsBoolean(m_graph.m_plan.isFTL())));
     2861            return true;
     2862        }
     2863           
     2864        case OSRExitIntrinsic: {
     2865            insertChecks();
     2866            addToGraph(ForceOSRExit);
     2867            setResult(addToGraph(JSConstant, OpInfo(m_constantUndefined)));
     2868            return true;
     2869        }
     2870           
     2871        case IsFinalTierIntrinsic: {
     2872            insertChecks();
     2873            setResult(jsConstant(jsBoolean(Options::useFTLJIT() ? m_graph.m_plan.isFTL() : true)));
     2874            return true;
     2875        }
     2876           
     2877        case SetInt32HeapPredictionIntrinsic: {
     2878            insertChecks();
     2879            for (int i = 1; i < argumentCountIncludingThis; ++i) {
     2880                Node* node = get(virtualRegisterForArgument(i, registerOffset));
     2881                if (node->hasHeapPrediction())
     2882                    node->setHeapPrediction(SpecInt32Only);
     2883            }
     2884            setResult(addToGraph(JSConstant, OpInfo(m_constantUndefined)));
     2885            return true;
     2886        }
     2887           
     2888        case CheckInt32Intrinsic: {
     2889            insertChecks();
     2890            for (int i = 1; i < argumentCountIncludingThis; ++i) {
     2891                Node* node = get(virtualRegisterForArgument(i, registerOffset));
     2892                addToGraph(Phantom, Edge(node, Int32Use));
     2893            }
     2894            setResult(jsConstant(jsBoolean(true)));
     2895            return true;
     2896        }
     2897           
     2898        case FiatInt52Intrinsic: {
     2899            if (argumentCountIncludingThis != 2)
     2900                return false;
     2901            insertChecks();
     2902            VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
     2903            if (enableInt52())
     2904                setResult(addToGraph(FiatInt52, get(operand)));
     2905            else
     2906                setResult(get(operand));
     2907            return true;
     2908        }
     2909
     2910        case JSMapGetIntrinsic: {
     2911            if (argumentCountIncludingThis != 2)
     2912                return false;
     2913
     2914            insertChecks();
     2915            Node* map = get(virtualRegisterForArgument(0, registerOffset));
     2916            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2917            Node* normalizedKey = addToGraph(NormalizeMapKey, key);
     2918            Node* hash = addToGraph(MapHash, normalizedKey);
     2919            Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(normalizedKey), Edge(hash));
     2920            Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
     2921            setResult(resultNode);
     2922            return true;
     2923        }
     2924
     2925        case JSSetHasIntrinsic:
     2926        case JSMapHasIntrinsic: {
     2927            if (argumentCountIncludingThis != 2)
     2928                return false;
     2929
     2930            insertChecks();
     2931            Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
     2932            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2933            Node* normalizedKey = addToGraph(NormalizeMapKey, key);
     2934            Node* hash = addToGraph(MapHash, normalizedKey);
     2935            UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
     2936            Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
     2937            JSCell* sentinel = nullptr;
     2938            if (intrinsic == JSMapHasIntrinsic)
     2939                sentinel = m_vm->sentinelMapBucket.get();
     2940            else
     2941                sentinel = m_vm->sentinelSetBucket.get();
     2942
     2943            FrozenValue* frozenPointer = m_graph.freeze(sentinel);
     2944            Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
     2945            Node* resultNode = addToGraph(LogicalNot, invertedResult);
     2946            setResult(resultNode);
     2947            return true;
     2948        }
     2949
     2950        case JSSetAddIntrinsic: {
     2951            if (argumentCountIncludingThis != 2)
     2952                return false;
     2953
     2954            insertChecks();
     2955            Node* base = get(virtualRegisterForArgument(0, registerOffset));
     2956            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2957            Node* normalizedKey = addToGraph(NormalizeMapKey, key);
     2958            Node* hash = addToGraph(MapHash, normalizedKey);
     2959            addToGraph(SetAdd, base, normalizedKey, hash);
     2960            setResult(base);
     2961            return true;
     2962        }
     2963
     2964        case JSMapSetIntrinsic: {
     2965            if (argumentCountIncludingThis != 3)
     2966                return false;
     2967
     2968            insertChecks();
     2969            Node* base = get(virtualRegisterForArgument(0, registerOffset));
     2970            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2971            Node* value = get(virtualRegisterForArgument(2, registerOffset));
     2972
     2973            Node* normalizedKey = addToGraph(NormalizeMapKey, key);
     2974            Node* hash = addToGraph(MapHash, normalizedKey);
     2975
     2976            addVarArgChild(base);
     2977            addVarArgChild(normalizedKey);
     2978            addVarArgChild(value);
     2979            addVarArgChild(hash);
     2980            addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
     2981            setResult(base);
     2982            return true;
     2983        }
     2984
     2985        case JSSetBucketHeadIntrinsic:
     2986        case JSMapBucketHeadIntrinsic: {
     2987            ASSERT(argumentCountIncludingThis == 2);
     2988
     2989            insertChecks();
     2990            Node* map = get(virtualRegisterForArgument(1, registerOffset));
     2991            UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
     2992            Node* resultNode = addToGraph(GetMapBucketHead, Edge(map, useKind));
     2993            setResult(resultNode);
     2994            return true;
     2995        }
     2996
     2997        case JSSetBucketNextIntrinsic:
     2998        case JSMapBucketNextIntrinsic: {
     2999            ASSERT(argumentCountIncludingThis == 2);
     3000
     3001            insertChecks();
     3002            Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     3003            BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
     3004            Node* resultNode = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
     3005            setResult(resultNode);
     3006            return true;
     3007        }
     3008
     3009        case JSSetBucketKeyIntrinsic:
     3010        case JSMapBucketKeyIntrinsic: {
     3011            ASSERT(argumentCountIncludingThis == 2);
     3012
     3013            insertChecks();
     3014            Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     3015            BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
     3016            Node* resultNode = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
     3017            setResult(resultNode);
     3018            return true;
     3019        }
     3020
     3021        case JSMapBucketValueIntrinsic: {
     3022            ASSERT(argumentCountIncludingThis == 2);
     3023
     3024            insertChecks();
     3025            Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     3026            Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
     3027            setResult(resultNode);
     3028            return true;
     3029        }
     3030
     3031        case JSWeakMapGetIntrinsic: {
     3032            if (argumentCountIncludingThis != 2)
     3033                return false;
     3034
     3035            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3036                return false;
     3037
     3038            insertChecks();
     3039            Node* map = get(virtualRegisterForArgument(0, registerOffset));
     3040            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3041            addToGraph(Check, Edge(key, ObjectUse));
     3042            Node* hash = addToGraph(MapHash, key);
     3043            Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
     3044            Node* resultNode = addToGraph(ExtractValueFromWeakMapGet, OpInfo(), OpInfo(prediction), holder);
     3045
     3046            setResult(resultNode);
     3047            return true;
     3048        }
     3049
     3050        case JSWeakMapHasIntrinsic: {
     3051            if (argumentCountIncludingThis != 2)
     3052                return false;
     3053
     3054            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3055                return false;
     3056
     3057            insertChecks();
     3058            Node* map = get(virtualRegisterForArgument(0, registerOffset));
     3059            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3060            addToGraph(Check, Edge(key, ObjectUse));
     3061            Node* hash = addToGraph(MapHash, key);
     3062            Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
     3063            Node* invertedResult = addToGraph(IsEmpty, holder);
     3064            Node* resultNode = addToGraph(LogicalNot, invertedResult);
     3065
     3066            setResult(resultNode);
     3067            return true;
     3068        }
     3069
     3070        case JSWeakSetHasIntrinsic: {
     3071            if (argumentCountIncludingThis != 2)
     3072                return false;
     3073
     3074            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3075                return false;
     3076
     3077            insertChecks();
     3078            Node* map = get(virtualRegisterForArgument(0, registerOffset));
     3079            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3080            addToGraph(Check, Edge(key, ObjectUse));
     3081            Node* hash = addToGraph(MapHash, key);
     3082            Node* holder = addToGraph(WeakMapGet, Edge(map, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
     3083            Node* invertedResult = addToGraph(IsEmpty, holder);
     3084            Node* resultNode = addToGraph(LogicalNot, invertedResult);
     3085
     3086            setResult(resultNode);
     3087            return true;
     3088        }
     3089
     3090        case JSWeakSetAddIntrinsic: {
     3091            if (argumentCountIncludingThis != 2)
     3092                return false;
     3093
     3094            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3095                return false;
     3096
     3097            insertChecks();
     3098            Node* base = get(virtualRegisterForArgument(0, registerOffset));
     3099            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3100            addToGraph(Check, Edge(key, ObjectUse));
     3101            Node* hash = addToGraph(MapHash, key);
     3102            addToGraph(WeakSetAdd, Edge(base, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
     3103            setResult(base);
     3104            return true;
     3105        }
     3106
     3107        case JSWeakMapSetIntrinsic: {
     3108            if (argumentCountIncludingThis != 3)
     3109                return false;
     3110
     3111            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3112                return false;
     3113
     3114            insertChecks();
     3115            Node* base = get(virtualRegisterForArgument(0, registerOffset));
     3116            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3117            Node* value = get(virtualRegisterForArgument(2, registerOffset));
     3118
     3119            addToGraph(Check, Edge(key, ObjectUse));
     3120            Node* hash = addToGraph(MapHash, key);
     3121
     3122            addVarArgChild(Edge(base, WeakMapObjectUse));
     3123            addVarArgChild(Edge(key, ObjectUse));
     3124            addVarArgChild(Edge(value));
     3125            addVarArgChild(Edge(hash, Int32Use));
     3126            addToGraph(Node::VarArg, WeakMapSet, OpInfo(0), OpInfo(0));
     3127            setResult(base);
     3128            return true;
     3129        }
     3130
     3131        case DataViewGetInt8:
     3132        case DataViewGetUint8:
     3133        case DataViewGetInt16:
     3134        case DataViewGetUint16:
     3135        case DataViewGetInt32:
     3136        case DataViewGetUint32:
     3137        case DataViewGetFloat32:
     3138        case DataViewGetFloat64: {
     3139            if (!is64Bit())
     3140                return false;
     3141
     3142            // To inline data view accesses, we assume the architecture we're running on:
     3143            // - Is little endian.
     3144            // - Allows unaligned loads/stores without crashing.
     3145
     3146            if (argumentCountIncludingThis < 2)
     3147                return false;
     3148            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3149                return false;
     3150
     3151            insertChecks();
     3152
     3153            uint8_t byteSize;
     3154            NodeType op = DataViewGetInt;
     3155            bool isSigned = false;
     3156            switch (intrinsic) {
     3157            case DataViewGetInt8:
     3158                isSigned = true;
     3159                FALLTHROUGH;
     3160            case DataViewGetUint8:
     3161                byteSize = 1;
     3162                break;
     3163
     3164            case DataViewGetInt16:
     3165                isSigned = true;
     3166                FALLTHROUGH;
     3167            case DataViewGetUint16:
     3168                byteSize = 2;
     3169                break;
     3170
     3171            case DataViewGetInt32:
     3172                isSigned = true;
     3173                FALLTHROUGH;
     3174            case DataViewGetUint32:
     3175                byteSize = 4;
     3176                break;
     3177
     3178            case DataViewGetFloat32:
     3179                byteSize = 4;
     3180                op = DataViewGetFloat;
     3181                break;
     3182            case DataViewGetFloat64:
     3183                byteSize = 8;
     3184                op = DataViewGetFloat;
     3185                break;
     3186            default:
     3187                RELEASE_ASSERT_NOT_REACHED();
     3188            }
     3189
     3190            TriState isLittleEndian = MixedTriState;
     3191            Node* littleEndianChild = nullptr;
     3192            if (byteSize > 1) {
     3193                if (argumentCountIncludingThis < 3)
     3194                    isLittleEndian = FalseTriState;
     3195                else {
     3196                    littleEndianChild = get(virtualRegisterForArgument(2, registerOffset));
     3197                    if (littleEndianChild->hasConstant()) {
     3198                        JSValue constant = littleEndianChild->constant()->value();
     3199                        isLittleEndian = constant.pureToBoolean();
     3200                        if (isLittleEndian != MixedTriState)
     3201                            littleEndianChild = nullptr;
     3202                    } else
     3203                        isLittleEndian = MixedTriState;
     3204                }
     3205            }
     3206
     3207            DataViewData data { };
     3208            data.isLittleEndian = isLittleEndian;
     3209            data.isSigned = isSigned;
     3210            data.byteSize = byteSize;
     3211
     3212            setResult(
     3213                addToGraph(op, OpInfo(data.asQuadWord), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), littleEndianChild));
     3214            return true;
     3215        }
     3216
     3217        case DataViewSetInt8:
     3218        case DataViewSetUint8:
     3219        case DataViewSetInt16:
     3220        case DataViewSetUint16:
     3221        case DataViewSetInt32:
     3222        case DataViewSetUint32:
     3223        case DataViewSetFloat32:
     3224        case DataViewSetFloat64: {
     3225            if (!is64Bit())
     3226                return false;
     3227
     3228            if (argumentCountIncludingThis < 3)
     3229                return false;
     3230
     3231            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3232                return false;
     3233
     3234            insertChecks();
     3235
     3236            uint8_t byteSize;
     3237            bool isFloatingPoint = false;
     3238            bool isSigned = false;
     3239            switch (intrinsic) {
     3240            case DataViewSetInt8:
     3241                isSigned = true;
     3242                FALLTHROUGH;
     3243            case DataViewSetUint8:
     3244                byteSize = 1;
     3245                break;
     3246
     3247            case DataViewSetInt16:
     3248                isSigned = true;
     3249                FALLTHROUGH;
     3250            case DataViewSetUint16:
     3251                byteSize = 2;
     3252                break;
     3253
     3254            case DataViewSetInt32:
     3255                isSigned = true;
     3256                FALLTHROUGH;
     3257            case DataViewSetUint32:
     3258                byteSize = 4;
     3259                break;
     3260
     3261            case DataViewSetFloat32:
     3262                isFloatingPoint = true;
     3263                byteSize = 4;
     3264                break;
     3265            case DataViewSetFloat64:
     3266                isFloatingPoint = true;
     3267                byteSize = 8;
     3268                break;
     3269            default:
     3270                RELEASE_ASSERT_NOT_REACHED();
     3271            }
     3272
     3273            TriState isLittleEndian = MixedTriState;
     3274            Node* littleEndianChild = nullptr;
     3275            if (byteSize > 1) {
     3276                if (argumentCountIncludingThis < 4)
     3277                    isLittleEndian = FalseTriState;
     3278                else {
     3279                    littleEndianChild = get(virtualRegisterForArgument(3, registerOffset));
     3280                    if (littleEndianChild->hasConstant()) {
     3281                        JSValue constant = littleEndianChild->constant()->value();
     3282                        isLittleEndian = constant.pureToBoolean();
     3283                        if (isLittleEndian != MixedTriState)
     3284                            littleEndianChild = nullptr;
     3285                    } else
     3286                        isLittleEndian = MixedTriState;
     3287                }
     3288            }
     3289
     3290            DataViewData data { };
     3291            data.isLittleEndian = isLittleEndian;
     3292            data.isSigned = isSigned;
     3293            data.byteSize = byteSize;
     3294            data.isFloatingPoint = isFloatingPoint;
     3295
     3296            addVarArgChild(get(virtualRegisterForArgument(0, registerOffset)));
     3297            addVarArgChild(get(virtualRegisterForArgument(1, registerOffset)));
     3298            addVarArgChild(get(virtualRegisterForArgument(2, registerOffset)));
     3299            addVarArgChild(littleEndianChild);
     3300
     3301            addToGraph(Node::VarArg, DataViewSet, OpInfo(data.asQuadWord), OpInfo());
     3302            setResult(addToGraph(JSConstant, OpInfo(m_constantUndefined)));
     3303            return true;
     3304        }
     3305
     3306        case HasOwnPropertyIntrinsic: {
     3307            if (argumentCountIncludingThis != 2)
     3308                return false;
     3309
     3310            // This can be racy, that's fine. We know that once we observe that this is created,
     3311            // that it will never be destroyed until the VM is destroyed. It's unlikely that
     3312            // we'd ever get to the point where we inline this as an intrinsic without the
     3313            // cache being created, however, it's possible if we always throw exceptions inside
     3314            // hasOwnProperty.
     3315            if (!m_vm->hasOwnPropertyCache())
     3316                return false;
     3317
     3318            insertChecks();
     3319            Node* object = get(virtualRegisterForArgument(0, registerOffset));
     3320            Node* key = get(virtualRegisterForArgument(1, registerOffset));
     3321            Node* resultNode = addToGraph(HasOwnProperty, object, key);
     3322            setResult(resultNode);
     3323            return true;
     3324        }
     3325
     3326        case StringPrototypeSliceIntrinsic: {
     3327            if (argumentCountIncludingThis < 2)
     3328                return false;
     3329
     3330            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3331                return false;
     3332
     3333            insertChecks();
     3334            Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
     3335            Node* start = get(virtualRegisterForArgument(1, registerOffset));
     3336            Node* end = nullptr;
     3337            if (argumentCountIncludingThis > 2)
     3338                end = get(virtualRegisterForArgument(2, registerOffset));
     3339            Node* resultNode = addToGraph(StringSlice, thisString, start, end);
     3340            setResult(resultNode);
     3341            return true;
     3342        }
     3343
     3344        case StringPrototypeToLowerCaseIntrinsic: {
     3345            if (argumentCountIncludingThis != 1)
     3346                return false;
     3347
     3348            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3349                return false;
     3350
     3351            insertChecks();
     3352            Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
     3353            Node* resultNode = addToGraph(ToLowerCase, thisString);
     3354            setResult(resultNode);
     3355            return true;
     3356        }
     3357
     3358        case NumberPrototypeToStringIntrinsic: {
     3359            if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
     3360                return false;
     3361
     3362            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
     3363                return false;
     3364
     3365            insertChecks();
     3366            Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
     3367            if (argumentCountIncludingThis == 1) {
     3368                Node* resultNode = addToGraph(ToString, thisNumber);
     3369                setResult(resultNode);
     3370            } else {
     3371                Node* radix = get(virtualRegisterForArgument(1, registerOffset));
     3372                Node* resultNode = addToGraph(NumberToStringWithRadix, thisNumber, radix);
     3373                setResult(resultNode);
     3374            }
     3375            return true;
     3376        }
     3377
     3378        case NumberIsIntegerIntrinsic: {
     3379            if (argumentCountIncludingThis < 2)
     3380                return false;
     3381
     3382            insertChecks();
     3383            Node* input = get(virtualRegisterForArgument(1, registerOffset));
     3384            Node* resultNode = addToGraph(NumberIsInteger, input);
     3385            setResult(resultNode);
     3386            return true;
     3387        }
     3388
     3389        case CPUMfenceIntrinsic:
     3390        case CPURdtscIntrinsic:
     3391        case CPUCpuidIntrinsic:
     3392        case CPUPauseIntrinsic: {
     3393#if CPU(X86_64)
     3394            if (!m_graph.m_plan.isFTL())
     3395                return false;
     3396            insertChecks();
     3397            setResult(addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
     3398            return true;
     3399#else
     3400            return false;
     3401#endif
     3402        }
     3403
     3404        default:
     3405            return false;
     3406        }
     3407    };
     3408
     3409    if (inlineIntrinsic()) {
     3410        RELEASE_ASSERT(didSetResult);
    26563411        return true;
    26573412    }
    26583413
    2659     case RegExpMatchFastIntrinsic: {
    2660         RELEASE_ASSERT(argumentCountIncludingThis == 2);
    2661 
    2662         insertChecks();
    2663         Node* regExpMatch = addToGraph(RegExpMatchFast, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
    2664         set(result, regExpMatch);
    2665         return true;
    2666     }
    2667 
    2668     case ObjectCreateIntrinsic: {
    2669         if (argumentCountIncludingThis != 2)
    2670             return false;
    2671 
    2672         insertChecks();
    2673         set(result, addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
    2674         return true;
    2675     }
    2676 
    2677     case ObjectGetPrototypeOfIntrinsic: {
    2678         if (argumentCountIncludingThis != 2)
    2679             return false;
    2680 
    2681         insertChecks();
    2682         set(result, addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
    2683         return true;
    2684     }
    2685 
    2686     case ObjectIsIntrinsic: {
    2687         if (argumentCountIncludingThis < 3)
    2688             return false;
    2689 
    2690         insertChecks();
    2691         set(result, addToGraph(SameValue, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
    2692         return true;
    2693     }
    2694 
    2695     case ObjectKeysIntrinsic: {
    2696         if (argumentCountIncludingThis < 2)
    2697             return false;
    2698 
    2699         insertChecks();
    2700         set(result, addToGraph(ObjectKeys, get(virtualRegisterForArgument(1, registerOffset))));
    2701         return true;
    2702     }
    2703 
    2704     case ObjectPrototypeToStringIntrinsic: {
    2705         insertChecks();
    2706         Node* value = get(virtualRegisterForArgument(0, registerOffset));
    2707         set(result, addToGraph(ObjectToString, value));
    2708         return true;
    2709     }
    2710 
    2711     case ReflectGetPrototypeOfIntrinsic: {
    2712         if (argumentCountIncludingThis != 2)
    2713             return false;
    2714 
    2715         insertChecks();
    2716         set(result, addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), Edge(get(virtualRegisterForArgument(1, registerOffset)), ObjectUse)));
    2717         return true;
    2718     }
    2719 
    2720     case IsTypedArrayViewIntrinsic: {
    2721         ASSERT(argumentCountIncludingThis == 2);
    2722 
    2723         insertChecks();
    2724         set(result, addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
    2725         return true;
    2726     }
    2727 
    2728     case StringPrototypeValueOfIntrinsic: {
    2729         insertChecks();
    2730         Node* value = get(virtualRegisterForArgument(0, registerOffset));
    2731         set(result, addToGraph(StringValueOf, value));
    2732         return true;
    2733     }
    2734 
    2735     case StringPrototypeReplaceIntrinsic: {
    2736         if (argumentCountIncludingThis != 3)
    2737             return false;
    2738 
    2739         // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
    2740         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    2741             return false;
    2742 
    2743         // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
    2744         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
    2745             return false;
    2746 
    2747         JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
    2748         Structure* regExpStructure = globalObject->regExpStructure();
    2749         m_graph.registerStructure(regExpStructure);
    2750         ASSERT(regExpStructure->storedPrototype().isObject());
    2751         ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
    2752 
    2753         FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
    2754         Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
    2755 
    2756         auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
    2757             JSValue currentProperty;
    2758             if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
    2759                 return false;
    2760 
    2761             return currentProperty == primordialProperty;
    2762         };
    2763 
    2764         // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
    2765         if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
    2766             return false;
    2767 
    2768         // Check that searchRegExp.global is still the primordial RegExp.prototype.global
    2769         if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
    2770             return false;
    2771 
    2772         // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
    2773         if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
    2774             return false;
    2775 
    2776         // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
    2777         if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
    2778             return false;
    2779 
    2780         insertChecks();
    2781 
    2782         Node* resultNode = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
    2783         set(result, resultNode);
    2784         return true;
    2785     }
    2786        
    2787     case StringPrototypeReplaceRegExpIntrinsic: {
    2788         if (argumentCountIncludingThis != 3)
    2789             return false;
    2790        
    2791         insertChecks();
    2792         Node* resultNode = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
    2793         set(result, resultNode);
    2794         return true;
    2795     }
    2796        
    2797     case RoundIntrinsic:
    2798     case FloorIntrinsic:
    2799     case CeilIntrinsic:
    2800     case TruncIntrinsic: {
    2801         if (argumentCountIncludingThis == 1) {
    2802             insertChecks();
    2803             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
    2804             return true;
    2805         }
    2806         insertChecks();
    2807         Node* operand = get(virtualRegisterForArgument(1, registerOffset));
    2808         NodeType op;
    2809         if (intrinsic == RoundIntrinsic)
    2810             op = ArithRound;
    2811         else if (intrinsic == FloorIntrinsic)
    2812             op = ArithFloor;
    2813         else if (intrinsic == CeilIntrinsic)
    2814             op = ArithCeil;
    2815         else {
    2816             ASSERT(intrinsic == TruncIntrinsic);
    2817             op = ArithTrunc;
    2818         }
    2819         Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
    2820         set(result, roundNode);
    2821         return true;
    2822     }
    2823     case IMulIntrinsic: {
    2824         if (argumentCountIncludingThis != 3)
    2825             return false;
    2826         insertChecks();
    2827         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
    2828         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
    2829         Node* left = get(leftOperand);
    2830         Node* right = get(rightOperand);
    2831         set(result, addToGraph(ArithIMul, left, right));
    2832         return true;
    2833     }
    2834 
    2835     case RandomIntrinsic: {
    2836         if (argumentCountIncludingThis != 1)
    2837             return false;
    2838         insertChecks();
    2839         set(result, addToGraph(ArithRandom));
    2840         return true;
    2841     }
    2842        
    2843     case DFGTrueIntrinsic: {
    2844         insertChecks();
    2845         set(result, jsConstant(jsBoolean(true)));
    2846         return true;
    2847     }
    2848 
    2849     case FTLTrueIntrinsic: {
    2850         insertChecks();
    2851         set(result, jsConstant(jsBoolean(m_graph.m_plan.isFTL())));
    2852         return true;
    2853     }
    2854        
    2855     case OSRExitIntrinsic: {
    2856         insertChecks();
    2857         addToGraph(ForceOSRExit);
    2858         set(result, addToGraph(JSConstant, OpInfo(m_constantUndefined)));
    2859         return true;
    2860     }
    2861        
    2862     case IsFinalTierIntrinsic: {
    2863         insertChecks();
    2864         set(result,
    2865             jsConstant(jsBoolean(Options::useFTLJIT() ? m_graph.m_plan.isFTL() : true)));
    2866         return true;
    2867     }
    2868        
    2869     case SetInt32HeapPredictionIntrinsic: {
    2870         insertChecks();
    2871         for (int i = 1; i < argumentCountIncludingThis; ++i) {
    2872             Node* node = get(virtualRegisterForArgument(i, registerOffset));
    2873             if (node->hasHeapPrediction())
    2874                 node->setHeapPrediction(SpecInt32Only);
    2875         }
    2876         set(result, addToGraph(JSConstant, OpInfo(m_constantUndefined)));
    2877         return true;
    2878     }
    2879        
    2880     case CheckInt32Intrinsic: {
    2881         insertChecks();
    2882         for (int i = 1; i < argumentCountIncludingThis; ++i) {
    2883             Node* node = get(virtualRegisterForArgument(i, registerOffset));
    2884             addToGraph(Phantom, Edge(node, Int32Use));
    2885         }
    2886         set(result, jsConstant(jsBoolean(true)));
    2887         return true;
    2888     }
    2889        
    2890     case FiatInt52Intrinsic: {
    2891         if (argumentCountIncludingThis != 2)
    2892             return false;
    2893         insertChecks();
    2894         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
    2895         if (enableInt52())
    2896             set(result, addToGraph(FiatInt52, get(operand)));
    2897         else
    2898             set(result, get(operand));
    2899         return true;
    2900     }
    2901 
    2902     case JSMapGetIntrinsic: {
    2903         if (argumentCountIncludingThis != 2)
    2904             return false;
    2905 
    2906         insertChecks();
    2907         Node* map = get(virtualRegisterForArgument(0, registerOffset));
    2908         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    2909         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
    2910         Node* hash = addToGraph(MapHash, normalizedKey);
    2911         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(normalizedKey), Edge(hash));
    2912         Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
    2913         set(result, resultNode);
    2914         return true;
    2915     }
    2916 
    2917     case JSSetHasIntrinsic:
    2918     case JSMapHasIntrinsic: {
    2919         if (argumentCountIncludingThis != 2)
    2920             return false;
    2921 
    2922         insertChecks();
    2923         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
    2924         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    2925         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
    2926         Node* hash = addToGraph(MapHash, normalizedKey);
    2927         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
    2928         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
    2929         JSCell* sentinel = nullptr;
    2930         if (intrinsic == JSMapHasIntrinsic)
    2931             sentinel = m_vm->sentinelMapBucket.get();
    2932         else
    2933             sentinel = m_vm->sentinelSetBucket.get();
    2934 
    2935         FrozenValue* frozenPointer = m_graph.freeze(sentinel);
    2936         Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
    2937         Node* resultNode = addToGraph(LogicalNot, invertedResult);
    2938         set(result, resultNode);
    2939         return true;
    2940     }
    2941 
    2942     case JSSetAddIntrinsic: {
    2943         if (argumentCountIncludingThis != 2)
    2944             return false;
    2945 
    2946         insertChecks();
    2947         Node* base = get(virtualRegisterForArgument(0, registerOffset));
    2948         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    2949         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
    2950         Node* hash = addToGraph(MapHash, normalizedKey);
    2951         addToGraph(SetAdd, base, normalizedKey, hash);
    2952         set(result, base);
    2953         return true;
    2954     }
    2955 
    2956     case JSMapSetIntrinsic: {
    2957         if (argumentCountIncludingThis != 3)
    2958             return false;
    2959 
    2960         insertChecks();
    2961         Node* base = get(virtualRegisterForArgument(0, registerOffset));
    2962         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    2963         Node* value = get(virtualRegisterForArgument(2, registerOffset));
    2964 
    2965         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
    2966         Node* hash = addToGraph(MapHash, normalizedKey);
    2967 
    2968         addVarArgChild(base);
    2969         addVarArgChild(normalizedKey);
    2970         addVarArgChild(value);
    2971         addVarArgChild(hash);
    2972         addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
    2973         set(result, base);
    2974         return true;
    2975     }
    2976 
    2977     case JSSetBucketHeadIntrinsic:
    2978     case JSMapBucketHeadIntrinsic: {
    2979         ASSERT(argumentCountIncludingThis == 2);
    2980 
    2981         insertChecks();
    2982         Node* map = get(virtualRegisterForArgument(1, registerOffset));
    2983         UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
    2984         Node* resultNode = addToGraph(GetMapBucketHead, Edge(map, useKind));
    2985         set(result, resultNode);
    2986         return true;
    2987     }
    2988 
    2989     case JSSetBucketNextIntrinsic:
    2990     case JSMapBucketNextIntrinsic: {
    2991         ASSERT(argumentCountIncludingThis == 2);
    2992 
    2993         insertChecks();
    2994         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
    2995         BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
    2996         Node* resultNode = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
    2997         set(result, resultNode);
    2998         return true;
    2999     }
    3000 
    3001     case JSSetBucketKeyIntrinsic:
    3002     case JSMapBucketKeyIntrinsic: {
    3003         ASSERT(argumentCountIncludingThis == 2);
    3004 
    3005         insertChecks();
    3006         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
    3007         BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
    3008         Node* resultNode = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
    3009         set(result, resultNode);
    3010         return true;
    3011     }
    3012 
    3013     case JSMapBucketValueIntrinsic: {
    3014         ASSERT(argumentCountIncludingThis == 2);
    3015 
    3016         insertChecks();
    3017         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
    3018         Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
    3019         set(result, resultNode);
    3020         return true;
    3021     }
    3022 
    3023     case JSWeakMapGetIntrinsic: {
    3024         if (argumentCountIncludingThis != 2)
    3025             return false;
    3026 
    3027         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3028             return false;
    3029 
    3030         insertChecks();
    3031         Node* map = get(virtualRegisterForArgument(0, registerOffset));
    3032         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3033         addToGraph(Check, Edge(key, ObjectUse));
    3034         Node* hash = addToGraph(MapHash, key);
    3035         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
    3036         Node* resultNode = addToGraph(ExtractValueFromWeakMapGet, OpInfo(), OpInfo(prediction), holder);
    3037 
    3038         set(result, resultNode);
    3039         return true;
    3040     }
    3041 
    3042     case JSWeakMapHasIntrinsic: {
    3043         if (argumentCountIncludingThis != 2)
    3044             return false;
    3045 
    3046         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3047             return false;
    3048 
    3049         insertChecks();
    3050         Node* map = get(virtualRegisterForArgument(0, registerOffset));
    3051         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3052         addToGraph(Check, Edge(key, ObjectUse));
    3053         Node* hash = addToGraph(MapHash, key);
    3054         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
    3055         Node* invertedResult = addToGraph(IsEmpty, holder);
    3056         Node* resultNode = addToGraph(LogicalNot, invertedResult);
    3057 
    3058         set(result, resultNode);
    3059         return true;
    3060     }
    3061 
    3062     case JSWeakSetHasIntrinsic: {
    3063         if (argumentCountIncludingThis != 2)
    3064             return false;
    3065 
    3066         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3067             return false;
    3068 
    3069         insertChecks();
    3070         Node* map = get(virtualRegisterForArgument(0, registerOffset));
    3071         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3072         addToGraph(Check, Edge(key, ObjectUse));
    3073         Node* hash = addToGraph(MapHash, key);
    3074         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
    3075         Node* invertedResult = addToGraph(IsEmpty, holder);
    3076         Node* resultNode = addToGraph(LogicalNot, invertedResult);
    3077 
    3078         set(result, resultNode);
    3079         return true;
    3080     }
    3081 
    3082     case JSWeakSetAddIntrinsic: {
    3083         if (argumentCountIncludingThis != 2)
    3084             return false;
    3085 
    3086         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3087             return false;
    3088 
    3089         insertChecks();
    3090         Node* base = get(virtualRegisterForArgument(0, registerOffset));
    3091         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3092         addToGraph(Check, Edge(key, ObjectUse));
    3093         Node* hash = addToGraph(MapHash, key);
    3094         addToGraph(WeakSetAdd, Edge(base, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
    3095         set(result, base);
    3096         return true;
    3097     }
    3098 
    3099     case JSWeakMapSetIntrinsic: {
    3100         if (argumentCountIncludingThis != 3)
    3101             return false;
    3102 
    3103         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3104             return false;
    3105 
    3106         insertChecks();
    3107         Node* base = get(virtualRegisterForArgument(0, registerOffset));
    3108         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3109         Node* value = get(virtualRegisterForArgument(2, registerOffset));
    3110 
    3111         addToGraph(Check, Edge(key, ObjectUse));
    3112         Node* hash = addToGraph(MapHash, key);
    3113 
    3114         addVarArgChild(Edge(base, WeakMapObjectUse));
    3115         addVarArgChild(Edge(key, ObjectUse));
    3116         addVarArgChild(Edge(value));
    3117         addVarArgChild(Edge(hash, Int32Use));
    3118         addToGraph(Node::VarArg, WeakMapSet, OpInfo(0), OpInfo(0));
    3119         set(result, base);
    3120         return true;
    3121     }
    3122 
    3123     case DataViewGetInt8:
    3124     case DataViewGetUint8:
    3125     case DataViewGetInt16:
    3126     case DataViewGetUint16:
    3127     case DataViewGetInt32:
    3128     case DataViewGetUint32:
    3129     case DataViewGetFloat32:
    3130     case DataViewGetFloat64: {
    3131         if (!is64Bit())
    3132             return false;
    3133 
    3134         // To inline data view accesses, we assume the architecture we're running on:
    3135         // - Is little endian.
    3136         // - Allows unaligned loads/stores without crashing.
    3137 
    3138         if (argumentCountIncludingThis < 2)
    3139             return false;
    3140         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3141             return false;
    3142 
    3143         insertChecks();
    3144 
    3145         uint8_t byteSize;
    3146         NodeType op = DataViewGetInt;
    3147         bool isSigned = false;
    3148         switch (intrinsic) {
    3149         case DataViewGetInt8:
    3150             isSigned = true;
    3151             FALLTHROUGH;
    3152         case DataViewGetUint8:
    3153             byteSize = 1;
    3154             break;
    3155 
    3156         case DataViewGetInt16:
    3157             isSigned = true;
    3158             FALLTHROUGH;
    3159         case DataViewGetUint16:
    3160             byteSize = 2;
    3161             break;
    3162 
    3163         case DataViewGetInt32:
    3164             isSigned = true;
    3165             FALLTHROUGH;
    3166         case DataViewGetUint32:
    3167             byteSize = 4;
    3168             break;
    3169 
    3170         case DataViewGetFloat32:
    3171             byteSize = 4;
    3172             op = DataViewGetFloat;
    3173             break;
    3174         case DataViewGetFloat64:
    3175             byteSize = 8;
    3176             op = DataViewGetFloat;
    3177             break;
    3178         default:
    3179             RELEASE_ASSERT_NOT_REACHED();
    3180         }
    3181 
    3182         TriState isLittleEndian = MixedTriState;
    3183         Node* littleEndianChild = nullptr;
    3184         if (byteSize > 1) {
    3185             if (argumentCountIncludingThis < 3)
    3186                 isLittleEndian = FalseTriState;
    3187             else {
    3188                 littleEndianChild = get(virtualRegisterForArgument(2, registerOffset));
    3189                 if (littleEndianChild->hasConstant()) {
    3190                     JSValue constant = littleEndianChild->constant()->value();
    3191                     isLittleEndian = constant.pureToBoolean();
    3192                     if (isLittleEndian != MixedTriState)
    3193                         littleEndianChild = nullptr;
    3194                 } else
    3195                     isLittleEndian = MixedTriState;
    3196             }
    3197         }
    3198 
    3199         DataViewData data { };
    3200         data.isLittleEndian = isLittleEndian;
    3201         data.isSigned = isSigned;
    3202         data.byteSize = byteSize;
    3203 
    3204         set(VirtualRegister(result),
    3205             addToGraph(op, OpInfo(data.asQuadWord), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), littleEndianChild));
    3206         return true;
    3207     }
    3208 
    3209     case DataViewSetInt8:
    3210     case DataViewSetUint8:
    3211     case DataViewSetInt16:
    3212     case DataViewSetUint16:
    3213     case DataViewSetInt32:
    3214     case DataViewSetUint32:
    3215     case DataViewSetFloat32:
    3216     case DataViewSetFloat64: {
    3217         if (!is64Bit())
    3218             return false;
    3219 
    3220         if (argumentCountIncludingThis < 3)
    3221             return false;
    3222 
    3223         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3224             return false;
    3225 
    3226         insertChecks();
    3227 
    3228         uint8_t byteSize;
    3229         bool isFloatingPoint = false;
    3230         bool isSigned = false;
    3231         switch (intrinsic) {
    3232         case DataViewSetInt8:
    3233             isSigned = true;
    3234             FALLTHROUGH;
    3235         case DataViewSetUint8:
    3236             byteSize = 1;
    3237             break;
    3238 
    3239         case DataViewSetInt16:
    3240             isSigned = true;
    3241             FALLTHROUGH;
    3242         case DataViewSetUint16:
    3243             byteSize = 2;
    3244             break;
    3245 
    3246         case DataViewSetInt32:
    3247             isSigned = true;
    3248             FALLTHROUGH;
    3249         case DataViewSetUint32:
    3250             byteSize = 4;
    3251             break;
    3252 
    3253         case DataViewSetFloat32:
    3254             isFloatingPoint = true;
    3255             byteSize = 4;
    3256             break;
    3257         case DataViewSetFloat64:
    3258             isFloatingPoint = true;
    3259             byteSize = 8;
    3260             break;
    3261         default:
    3262             RELEASE_ASSERT_NOT_REACHED();
    3263         }
    3264 
    3265         TriState isLittleEndian = MixedTriState;
    3266         Node* littleEndianChild = nullptr;
    3267         if (byteSize > 1) {
    3268             if (argumentCountIncludingThis < 4)
    3269                 isLittleEndian = FalseTriState;
    3270             else {
    3271                 littleEndianChild = get(virtualRegisterForArgument(3, registerOffset));
    3272                 if (littleEndianChild->hasConstant()) {
    3273                     JSValue constant = littleEndianChild->constant()->value();
    3274                     isLittleEndian = constant.pureToBoolean();
    3275                     if (isLittleEndian != MixedTriState)
    3276                         littleEndianChild = nullptr;
    3277                 } else
    3278                     isLittleEndian = MixedTriState;
    3279             }
    3280         }
    3281 
    3282         DataViewData data { };
    3283         data.isLittleEndian = isLittleEndian;
    3284         data.isSigned = isSigned;
    3285         data.byteSize = byteSize;
    3286         data.isFloatingPoint = isFloatingPoint;
    3287 
    3288         addVarArgChild(get(virtualRegisterForArgument(0, registerOffset)));
    3289         addVarArgChild(get(virtualRegisterForArgument(1, registerOffset)));
    3290         addVarArgChild(get(virtualRegisterForArgument(2, registerOffset)));
    3291         addVarArgChild(littleEndianChild);
    3292 
    3293         addToGraph(Node::VarArg, DataViewSet, OpInfo(data.asQuadWord), OpInfo());
    3294         return true;
    3295     }
    3296 
    3297     case HasOwnPropertyIntrinsic: {
    3298         if (argumentCountIncludingThis != 2)
    3299             return false;
    3300 
    3301         // This can be racy, that's fine. We know that once we observe that this is created,
    3302         // that it will never be destroyed until the VM is destroyed. It's unlikely that
    3303         // we'd ever get to the point where we inline this as an intrinsic without the
    3304         // cache being created, however, it's possible if we always throw exceptions inside
    3305         // hasOwnProperty.
    3306         if (!m_vm->hasOwnPropertyCache())
    3307             return false;
    3308 
    3309         insertChecks();
    3310         Node* object = get(virtualRegisterForArgument(0, registerOffset));
    3311         Node* key = get(virtualRegisterForArgument(1, registerOffset));
    3312         Node* resultNode = addToGraph(HasOwnProperty, object, key);
    3313         set(result, resultNode);
    3314         return true;
    3315     }
    3316 
    3317     case StringPrototypeSliceIntrinsic: {
    3318         if (argumentCountIncludingThis < 2)
    3319             return false;
    3320 
    3321         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3322             return false;
    3323 
    3324         insertChecks();
    3325         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
    3326         Node* start = get(virtualRegisterForArgument(1, registerOffset));
    3327         Node* end = nullptr;
    3328         if (argumentCountIncludingThis > 2)
    3329             end = get(virtualRegisterForArgument(2, registerOffset));
    3330         Node* resultNode = addToGraph(StringSlice, thisString, start, end);
    3331         set(result, resultNode);
    3332         return true;
    3333     }
    3334 
    3335     case StringPrototypeToLowerCaseIntrinsic: {
    3336         if (argumentCountIncludingThis != 1)
    3337             return false;
    3338 
    3339         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3340             return false;
    3341 
    3342         insertChecks();
    3343         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
    3344         Node* resultNode = addToGraph(ToLowerCase, thisString);
    3345         set(result, resultNode);
    3346         return true;
    3347     }
    3348 
    3349     case NumberPrototypeToStringIntrinsic: {
    3350         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
    3351             return false;
    3352 
    3353         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
    3354             return false;
    3355 
    3356         insertChecks();
    3357         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
    3358         if (argumentCountIncludingThis == 1) {
    3359             Node* resultNode = addToGraph(ToString, thisNumber);
    3360             set(result, resultNode);
    3361         } else {
    3362             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
    3363             Node* resultNode = addToGraph(NumberToStringWithRadix, thisNumber, radix);
    3364             set(result, resultNode);
    3365         }
    3366         return true;
    3367     }
    3368 
    3369     case NumberIsIntegerIntrinsic: {
    3370         if (argumentCountIncludingThis < 2)
    3371             return false;
    3372 
    3373         insertChecks();
    3374         Node* input = get(virtualRegisterForArgument(1, registerOffset));
    3375         Node* resultNode = addToGraph(NumberIsInteger, input);
    3376         set(result, resultNode);
    3377         return true;
    3378     }
    3379 
    3380     case CPUMfenceIntrinsic:
    3381     case CPURdtscIntrinsic:
    3382     case CPUCpuidIntrinsic:
    3383     case CPUPauseIntrinsic: {
    3384 #if CPU(X86_64)
    3385         if (!m_graph.m_plan.isFTL())
    3386             return false;
    3387         insertChecks();
    3388         set(result,
    3389             addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
    3390         return true;
    3391 #else
    3392         return false;
    3393 #endif
    3394     }
    3395 
    3396 
    3397     default:
    3398         return false;
    3399     }
     3414    return false;
    34003415}
    34013416
Note: See TracChangeset for help on using the changeset viewer.