[JSC] Avoid cloned arguments allocation in ArrayPrototype methods
[WebKit.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "BinarySwitch.h"
32 #include "DFGAbstractInterpreterInlines.h"
33 #include "DFGArrayifySlowPathGenerator.h"
34 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
35 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
36 #include "DFGCapabilities.h"
37 #include "DFGDOMJITPatchpointParams.h"
38 #include "DFGMayExit.h"
39 #include "DFGOSRExitFuzz.h"
40 #include "DFGSaneStringGetByValSlowPathGenerator.h"
41 #include "DFGSlowPathGenerator.h"
42 #include "DOMJITPatchpoint.h"
43 #include "DirectArguments.h"
44 #include "JITAddGenerator.h"
45 #include "JITBitAndGenerator.h"
46 #include "JITBitOrGenerator.h"
47 #include "JITBitXorGenerator.h"
48 #include "JITDivGenerator.h"
49 #include "JITLeftShiftGenerator.h"
50 #include "JITMulGenerator.h"
51 #include "JITRightShiftGenerator.h"
52 #include "JITSubGenerator.h"
53 #include "JSCInlines.h"
54 #include "JSEnvironmentRecord.h"
55 #include "JSGeneratorFunction.h"
56 #include "JSLexicalEnvironment.h"
57 #include "LinkBuffer.h"
58 #include "RegExpConstructor.h"
59 #include "ScopedArguments.h"
60 #include "ScratchRegisterAllocator.h"
61 #include "WriteBarrierBuffer.h"
62 #include <wtf/Box.h>
63 #include <wtf/MathExtras.h>
64
65 namespace JSC { namespace DFG {
66
67 SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
68     : m_compileOkay(true)
69     , m_jit(jit)
70     , m_currentNode(0)
71     , m_lastGeneratedNode(LastNodeType)
72     , m_indexInBlock(0)
73     , m_generationInfo(m_jit.graph().frameRegisterCount())
74     , m_state(m_jit.graph())
75     , m_interpreter(m_jit.graph(), m_state)
76     , m_stream(&jit.jitCode()->variableEventStream)
77     , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
78 {
79 }
80
81 SpeculativeJIT::~SpeculativeJIT()
82 {
83 }
84
85 void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
86 {
87     IndexingType indexingType = structure->indexingType();
88     bool hasIndexingHeader = hasIndexedProperties(indexingType);
89
90     unsigned inlineCapacity = structure->inlineCapacity();
91     unsigned outOfLineCapacity = structure->outOfLineCapacity();
92     
93     GPRTemporary scratch(this);
94     GPRTemporary scratch2(this);
95     GPRReg scratchGPR = scratch.gpr();
96     GPRReg scratch2GPR = scratch2.gpr();
97
98     ASSERT(vectorLength >= numElements);
99     vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLength);
100     
101     JITCompiler::JumpList slowCases;
102
103     size_t size = 0;
104     if (hasIndexingHeader)
105         size += vectorLength * sizeof(JSValue) + sizeof(IndexingHeader);
106     size += outOfLineCapacity * sizeof(JSValue);
107
108     m_jit.move(TrustedImmPtr(0), storageGPR);
109     
110     if (size) {
111         if (MarkedAllocator* allocator = m_jit.vm()->heap.allocatorForAuxiliaryData(size)) {
112             m_jit.move(TrustedImmPtr(allocator), scratchGPR);
113             m_jit.emitAllocate(storageGPR, allocator, scratchGPR, scratch2GPR, slowCases);
114             
115             m_jit.addPtr(
116                 TrustedImm32(outOfLineCapacity * sizeof(JSValue) + sizeof(IndexingHeader)),
117                 storageGPR);
118             
119             if (hasIndexingHeader)
120                 m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
121         } else
122             slowCases.append(m_jit.jump());
123     }
124
125     size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
126     MarkedAllocator* allocatorPtr = m_jit.vm()->heap.allocatorForObjectWithoutDestructor(allocationSize);
127     if (allocatorPtr) {
128         m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
129         emitAllocateJSObject(resultGPR, allocatorPtr, scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
130     } else
131         slowCases.append(m_jit.jump());
132
133     // I want a slow path that also loads out the storage pointer, and that's
134     // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
135     // of work for a very small piece of functionality. :-/
136     addSlowPathGenerator(std::make_unique<CallArrayAllocatorSlowPathGenerator>(
137         slowCases, this, operationNewRawObject, resultGPR, storageGPR,
138         structure, vectorLength));
139
140     if (numElements < vectorLength) {
141 #if USE(JSVALUE64)
142         if (hasDouble(structure->indexingType()))
143             m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
144         else
145             m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
146         for (unsigned i = numElements; i < vectorLength; ++i)
147             m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
148 #else
149         EncodedValueDescriptor value;
150         if (hasDouble(structure->indexingType()))
151             value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, PNaN));
152         else
153             value.asInt64 = JSValue::encode(JSValue());
154         for (unsigned i = numElements; i < vectorLength; ++i) {
155             m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
156             m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
157         }
158 #endif
159     }
160     
161     if (hasIndexingHeader)
162         m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
163 }
164
165 void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis)
166 {
167     if (inlineCallFrame && !inlineCallFrame->isVarargs())
168         m_jit.move(TrustedImm32(inlineCallFrame->arguments.size() - !includeThis), lengthGPR);
169     else {
170         VirtualRegister argumentCountRegister = m_jit.argumentCount(inlineCallFrame);
171         m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR);
172         if (!includeThis)
173             m_jit.sub32(TrustedImm32(1), lengthGPR);
174     }
175 }
176
177 void SpeculativeJIT::emitGetLength(CodeOrigin origin, GPRReg lengthGPR, bool includeThis)
178 {
179     emitGetLength(origin.inlineCallFrame, lengthGPR, includeThis);
180 }
181
182 void SpeculativeJIT::emitGetCallee(CodeOrigin origin, GPRReg calleeGPR)
183 {
184     if (origin.inlineCallFrame) {
185         if (origin.inlineCallFrame->isClosureCall) {
186             m_jit.loadPtr(
187                 JITCompiler::addressFor(origin.inlineCallFrame->calleeRecovery.virtualRegister()),
188                 calleeGPR);
189         } else {
190             m_jit.move(
191                 TrustedImmPtr(origin.inlineCallFrame->calleeRecovery.constant().asCell()),
192                 calleeGPR);
193         }
194     } else
195         m_jit.loadPtr(JITCompiler::addressFor(CallFrameSlot::callee), calleeGPR);
196 }
197
198 void SpeculativeJIT::emitGetArgumentStart(CodeOrigin origin, GPRReg startGPR)
199 {
200     m_jit.addPtr(
201         TrustedImm32(
202             JITCompiler::argumentsStart(origin).offset() * static_cast<int>(sizeof(Register))),
203         GPRInfo::callFrameRegister, startGPR);
204 }
205
206 MacroAssembler::Jump SpeculativeJIT::emitOSRExitFuzzCheck()
207 {
208     if (!Options::useOSRExitFuzz()
209         || !canUseOSRExitFuzzing(m_jit.graph().baselineCodeBlockFor(m_origin.semantic))
210         || !doOSRExitFuzzing())
211         return MacroAssembler::Jump();
212     
213     MacroAssembler::Jump result;
214     
215     m_jit.pushToSave(GPRInfo::regT0);
216     m_jit.load32(&g_numberOfOSRExitFuzzChecks, GPRInfo::regT0);
217     m_jit.add32(TrustedImm32(1), GPRInfo::regT0);
218     m_jit.store32(GPRInfo::regT0, &g_numberOfOSRExitFuzzChecks);
219     unsigned atOrAfter = Options::fireOSRExitFuzzAtOrAfter();
220     unsigned at = Options::fireOSRExitFuzzAt();
221     if (at || atOrAfter) {
222         unsigned threshold;
223         MacroAssembler::RelationalCondition condition;
224         if (atOrAfter) {
225             threshold = atOrAfter;
226             condition = MacroAssembler::Below;
227         } else {
228             threshold = at;
229             condition = MacroAssembler::NotEqual;
230         }
231         MacroAssembler::Jump ok = m_jit.branch32(
232             condition, GPRInfo::regT0, MacroAssembler::TrustedImm32(threshold));
233         m_jit.popToRestore(GPRInfo::regT0);
234         result = m_jit.jump();
235         ok.link(&m_jit);
236     }
237     m_jit.popToRestore(GPRInfo::regT0);
238     
239     return result;
240 }
241
242 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
243 {
244     if (!m_compileOkay)
245         return;
246     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
247     if (fuzzJump.isSet()) {
248         JITCompiler::JumpList jumpsToFail;
249         jumpsToFail.append(fuzzJump);
250         jumpsToFail.append(jumpToFail);
251         m_jit.appendExitInfo(jumpsToFail);
252     } else
253         m_jit.appendExitInfo(jumpToFail);
254     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
255 }
256
257 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail)
258 {
259     if (!m_compileOkay)
260         return;
261     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
262     if (fuzzJump.isSet()) {
263         JITCompiler::JumpList myJumpsToFail;
264         myJumpsToFail.append(jumpsToFail);
265         myJumpsToFail.append(fuzzJump);
266         m_jit.appendExitInfo(myJumpsToFail);
267     } else
268         m_jit.appendExitInfo(jumpsToFail);
269     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
270 }
271
272 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
273 {
274     if (!m_compileOkay)
275         return OSRExitJumpPlaceholder();
276     unsigned index = m_jit.jitCode()->osrExit.size();
277     m_jit.appendExitInfo();
278     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
279     return OSRExitJumpPlaceholder(index);
280 }
281
282 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
283 {
284     return speculationCheck(kind, jsValueSource, nodeUse.node());
285 }
286
287 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
288 {
289     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
290 }
291
292 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
293 {
294     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
295 }
296
297 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
298 {
299     if (!m_compileOkay)
300         return;
301     unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
302     m_jit.appendExitInfo(jumpToFail);
303     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size(), recoveryIndex));
304 }
305
306 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
307 {
308     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
309 }
310
311 void SpeculativeJIT::emitInvalidationPoint(Node* node)
312 {
313     if (!m_compileOkay)
314         return;
315     OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
316     m_jit.jitCode()->appendOSRExit(OSRExit(
317         UncountableInvalidation, JSValueSource(),
318         m_jit.graph().methodOfGettingAValueProfileFor(node),
319         this, m_stream->size()));
320     info.m_replacementSource = m_jit.watchpointLabel();
321     ASSERT(info.m_replacementSource.isSet());
322     noResult(node);
323 }
324
325 void SpeculativeJIT::unreachable(Node* node)
326 {
327     m_compileOkay = false;
328     m_jit.abortWithReason(DFGUnreachableNode, node->op());
329 }
330
331 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
332 {
333     if (!m_compileOkay)
334         return;
335     speculationCheck(kind, jsValueRegs, node, m_jit.jump());
336     m_compileOkay = false;
337     if (verboseCompilationEnabled())
338         dataLog("Bailing compilation.\n");
339 }
340
341 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
342 {
343     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
344 }
345
346 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind exitKind)
347 {
348     ASSERT(needsTypeCheck(edge, typesPassedThrough));
349     m_interpreter.filter(edge, typesPassedThrough);
350     speculationCheck(exitKind, source, edge.node(), jumpToFail);
351 }
352
353 RegisterSet SpeculativeJIT::usedRegisters()
354 {
355     RegisterSet result;
356     
357     for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
358         GPRReg gpr = GPRInfo::toRegister(i);
359         if (m_gprs.isInUse(gpr))
360             result.set(gpr);
361     }
362     for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
363         FPRReg fpr = FPRInfo::toRegister(i);
364         if (m_fprs.isInUse(fpr))
365             result.set(fpr);
366     }
367     
368     result.merge(RegisterSet::stubUnavailableRegisters());
369     
370     return result;
371 }
372
373 void SpeculativeJIT::addSlowPathGenerator(std::unique_ptr<SlowPathGenerator> slowPathGenerator)
374 {
375     m_slowPathGenerators.append(WTFMove(slowPathGenerator));
376 }
377
378 void SpeculativeJIT::addSlowPathGenerator(std::function<void()> lambda)
379 {
380     m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast<unsigned>(m_stream->size()) });
381 }
382
383 void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder& pcToCodeOriginMapBuilder)
384 {
385     for (auto& slowPathGenerator : m_slowPathGenerators) {
386         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), slowPathGenerator->origin().semantic);
387         slowPathGenerator->generate(this);
388     }
389     for (auto& slowPathLambda : m_slowPathLambdas) {
390         Node* currentNode = slowPathLambda.currentNode;
391         m_currentNode = currentNode;
392         m_outOfLineStreamIndex = slowPathLambda.streamIndex;
393         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), currentNode->origin.semantic);
394         slowPathLambda.generator();
395         m_outOfLineStreamIndex = Nullopt;
396     }
397 }
398
399 void SpeculativeJIT::clearGenerationInfo()
400 {
401     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
402         m_generationInfo[i] = GenerationInfo();
403     m_gprs = RegisterBank<GPRInfo>();
404     m_fprs = RegisterBank<FPRInfo>();
405 }
406
407 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source)
408 {
409     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
410     Node* node = info.node();
411     DataFormat registerFormat = info.registerFormat();
412     ASSERT(registerFormat != DataFormatNone);
413     ASSERT(registerFormat != DataFormatDouble);
414         
415     SilentSpillAction spillAction;
416     SilentFillAction fillAction;
417         
418     if (!info.needsSpill())
419         spillAction = DoNothingForSpill;
420     else {
421 #if USE(JSVALUE64)
422         ASSERT(info.gpr() == source);
423         if (registerFormat == DataFormatInt32)
424             spillAction = Store32Payload;
425         else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
426             spillAction = StorePtr;
427         else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52)
428             spillAction = Store64;
429         else {
430             ASSERT(registerFormat & DataFormatJS);
431             spillAction = Store64;
432         }
433 #elif USE(JSVALUE32_64)
434         if (registerFormat & DataFormatJS) {
435             ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
436             spillAction = source == info.tagGPR() ? Store32Tag : Store32Payload;
437         } else {
438             ASSERT(info.gpr() == source);
439             spillAction = Store32Payload;
440         }
441 #endif
442     }
443         
444     if (registerFormat == DataFormatInt32) {
445         ASSERT(info.gpr() == source);
446         ASSERT(isJSInt32(info.registerFormat()));
447         if (node->hasConstant()) {
448             ASSERT(node->isInt32Constant());
449             fillAction = SetInt32Constant;
450         } else
451             fillAction = Load32Payload;
452     } else if (registerFormat == DataFormatBoolean) {
453 #if USE(JSVALUE64)
454         RELEASE_ASSERT_NOT_REACHED();
455 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
456         fillAction = DoNothingForFill;
457 #endif
458 #elif USE(JSVALUE32_64)
459         ASSERT(info.gpr() == source);
460         if (node->hasConstant()) {
461             ASSERT(node->isBooleanConstant());
462             fillAction = SetBooleanConstant;
463         } else
464             fillAction = Load32Payload;
465 #endif
466     } else if (registerFormat == DataFormatCell) {
467         ASSERT(info.gpr() == source);
468         if (node->hasConstant()) {
469             DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant());
470             node->asCell(); // To get the assertion.
471             fillAction = SetCellConstant;
472         } else {
473 #if USE(JSVALUE64)
474             fillAction = LoadPtr;
475 #else
476             fillAction = Load32Payload;
477 #endif
478         }
479     } else if (registerFormat == DataFormatStorage) {
480         ASSERT(info.gpr() == source);
481         fillAction = LoadPtr;
482     } else if (registerFormat == DataFormatInt52) {
483         if (node->hasConstant())
484             fillAction = SetInt52Constant;
485         else if (info.spillFormat() == DataFormatInt52)
486             fillAction = Load64;
487         else if (info.spillFormat() == DataFormatStrictInt52)
488             fillAction = Load64ShiftInt52Left;
489         else if (info.spillFormat() == DataFormatNone)
490             fillAction = Load64;
491         else {
492             RELEASE_ASSERT_NOT_REACHED();
493 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
494             fillAction = Load64; // Make GCC happy.
495 #endif
496         }
497     } else if (registerFormat == DataFormatStrictInt52) {
498         if (node->hasConstant())
499             fillAction = SetStrictInt52Constant;
500         else if (info.spillFormat() == DataFormatInt52)
501             fillAction = Load64ShiftInt52Right;
502         else if (info.spillFormat() == DataFormatStrictInt52)
503             fillAction = Load64;
504         else if (info.spillFormat() == DataFormatNone)
505             fillAction = Load64;
506         else {
507             RELEASE_ASSERT_NOT_REACHED();
508 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
509             fillAction = Load64; // Make GCC happy.
510 #endif
511         }
512     } else {
513         ASSERT(registerFormat & DataFormatJS);
514 #if USE(JSVALUE64)
515         ASSERT(info.gpr() == source);
516         if (node->hasConstant()) {
517             if (node->isCellConstant())
518                 fillAction = SetTrustedJSConstant;
519             else
520                 fillAction = SetJSConstant;
521         } else if (info.spillFormat() == DataFormatInt32) {
522             ASSERT(registerFormat == DataFormatJSInt32);
523             fillAction = Load32PayloadBoxInt;
524         } else
525             fillAction = Load64;
526 #else
527         ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
528         if (node->hasConstant())
529             fillAction = info.tagGPR() == source ? SetJSConstantTag : SetJSConstantPayload;
530         else if (info.payloadGPR() == source)
531             fillAction = Load32Payload;
532         else { // Fill the Tag
533             switch (info.spillFormat()) {
534             case DataFormatInt32:
535                 ASSERT(registerFormat == DataFormatJSInt32);
536                 fillAction = SetInt32Tag;
537                 break;
538             case DataFormatCell:
539                 ASSERT(registerFormat == DataFormatJSCell);
540                 fillAction = SetCellTag;
541                 break;
542             case DataFormatBoolean:
543                 ASSERT(registerFormat == DataFormatJSBoolean);
544                 fillAction = SetBooleanTag;
545                 break;
546             default:
547                 fillAction = Load32Tag;
548                 break;
549             }
550         }
551 #endif
552     }
553         
554     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
555 }
556     
557 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForFPR(VirtualRegister spillMe, FPRReg source)
558 {
559     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
560     Node* node = info.node();
561     ASSERT(info.registerFormat() == DataFormatDouble);
562
563     SilentSpillAction spillAction;
564     SilentFillAction fillAction;
565         
566     if (!info.needsSpill())
567         spillAction = DoNothingForSpill;
568     else {
569         ASSERT(!node->hasConstant());
570         ASSERT(info.spillFormat() == DataFormatNone);
571         ASSERT(info.fpr() == source);
572         spillAction = StoreDouble;
573     }
574         
575 #if USE(JSVALUE64)
576     if (node->hasConstant()) {
577         node->asNumber(); // To get the assertion.
578         fillAction = SetDoubleConstant;
579     } else {
580         ASSERT(info.spillFormat() == DataFormatNone || info.spillFormat() == DataFormatDouble);
581         fillAction = LoadDouble;
582     }
583 #elif USE(JSVALUE32_64)
584     ASSERT(info.registerFormat() == DataFormatDouble);
585     if (node->hasConstant()) {
586         node->asNumber(); // To get the assertion.
587         fillAction = SetDoubleConstant;
588     } else
589         fillAction = LoadDouble;
590 #endif
591
592     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
593 }
594     
595 void SpeculativeJIT::silentSpill(const SilentRegisterSavePlan& plan)
596 {
597     switch (plan.spillAction()) {
598     case DoNothingForSpill:
599         break;
600     case Store32Tag:
601         m_jit.store32(plan.gpr(), JITCompiler::tagFor(plan.node()->virtualRegister()));
602         break;
603     case Store32Payload:
604         m_jit.store32(plan.gpr(), JITCompiler::payloadFor(plan.node()->virtualRegister()));
605         break;
606     case StorePtr:
607         m_jit.storePtr(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
608         break;
609 #if USE(JSVALUE64)
610     case Store64:
611         m_jit.store64(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
612         break;
613 #endif
614     case StoreDouble:
615         m_jit.storeDouble(plan.fpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
616         break;
617     default:
618         RELEASE_ASSERT_NOT_REACHED();
619     }
620 }
621     
622 void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan, GPRReg canTrample)
623 {
624 #if USE(JSVALUE32_64)
625     UNUSED_PARAM(canTrample);
626 #endif
627     switch (plan.fillAction()) {
628     case DoNothingForFill:
629         break;
630     case SetInt32Constant:
631         m_jit.move(Imm32(plan.node()->asInt32()), plan.gpr());
632         break;
633 #if USE(JSVALUE64)
634     case SetInt52Constant:
635         m_jit.move(Imm64(plan.node()->asAnyInt() << JSValue::int52ShiftAmount), plan.gpr());
636         break;
637     case SetStrictInt52Constant:
638         m_jit.move(Imm64(plan.node()->asAnyInt()), plan.gpr());
639         break;
640 #endif // USE(JSVALUE64)
641     case SetBooleanConstant:
642         m_jit.move(TrustedImm32(plan.node()->asBoolean()), plan.gpr());
643         break;
644     case SetCellConstant:
645         m_jit.move(TrustedImmPtr(plan.node()->asCell()), plan.gpr());
646         break;
647 #if USE(JSVALUE64)
648     case SetTrustedJSConstant:
649         m_jit.move(valueOfJSConstantAsImm64(plan.node()).asTrustedImm64(), plan.gpr());
650         break;
651     case SetJSConstant:
652         m_jit.move(valueOfJSConstantAsImm64(plan.node()), plan.gpr());
653         break;
654     case SetDoubleConstant:
655         m_jit.move(Imm64(reinterpretDoubleToInt64(plan.node()->asNumber())), canTrample);
656         m_jit.move64ToDouble(canTrample, plan.fpr());
657         break;
658     case Load32PayloadBoxInt:
659         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
660         m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr());
661         break;
662     case Load32PayloadConvertToInt52:
663         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
664         m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
665         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
666         break;
667     case Load32PayloadSignExtend:
668         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
669         m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr());
670         break;
671 #else
672     case SetJSConstantTag:
673         m_jit.move(Imm32(plan.node()->asJSValue().tag()), plan.gpr());
674         break;
675     case SetJSConstantPayload:
676         m_jit.move(Imm32(plan.node()->asJSValue().payload()), plan.gpr());
677         break;
678     case SetInt32Tag:
679         m_jit.move(TrustedImm32(JSValue::Int32Tag), plan.gpr());
680         break;
681     case SetCellTag:
682         m_jit.move(TrustedImm32(JSValue::CellTag), plan.gpr());
683         break;
684     case SetBooleanTag:
685         m_jit.move(TrustedImm32(JSValue::BooleanTag), plan.gpr());
686         break;
687     case SetDoubleConstant:
688         m_jit.loadDouble(TrustedImmPtr(m_jit.addressOfDoubleConstant(plan.node())), plan.fpr());
689         break;
690 #endif
691     case Load32Tag:
692         m_jit.load32(JITCompiler::tagFor(plan.node()->virtualRegister()), plan.gpr());
693         break;
694     case Load32Payload:
695         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
696         break;
697     case LoadPtr:
698         m_jit.loadPtr(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
699         break;
700 #if USE(JSVALUE64)
701     case Load64:
702         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
703         break;
704     case Load64ShiftInt52Right:
705         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
706         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
707         break;
708     case Load64ShiftInt52Left:
709         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
710         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr());
711         break;
712 #endif
713     case LoadDouble:
714         m_jit.loadDouble(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.fpr());
715         break;
716     default:
717         RELEASE_ASSERT_NOT_REACHED();
718     }
719 }
720     
721 JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape)
722 {
723     switch (arrayMode.arrayClass()) {
724     case Array::OriginalArray: {
725         CRASH();
726 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
727         JITCompiler::Jump result; // I already know that VC++ takes unkindly to the expression "return Jump()", so I'm doing it this way in anticipation of someone eventually using VC++ to compile the DFG.
728         return result;
729 #endif
730     }
731         
732     case Array::Array:
733         m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
734         return m_jit.branch32(
735             MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape));
736         
737     case Array::NonArray:
738     case Array::OriginalNonArray:
739         m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
740         return m_jit.branch32(
741             MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
742         
743     case Array::PossiblyArray:
744         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
745         return m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
746     }
747     
748     RELEASE_ASSERT_NOT_REACHED();
749     return JITCompiler::Jump();
750 }
751
752 JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode)
753 {
754     JITCompiler::JumpList result;
755     
756     switch (arrayMode.type()) {
757     case Array::Int32:
758         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, Int32Shape);
759
760     case Array::Double:
761         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, DoubleShape);
762
763     case Array::Contiguous:
764         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, ContiguousShape);
765
766     case Array::Undecided:
767         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, UndecidedShape);
768
769     case Array::ArrayStorage:
770     case Array::SlowPutArrayStorage: {
771         ASSERT(!arrayMode.isJSArrayWithOriginalStructure());
772         
773         if (arrayMode.isJSArray()) {
774             if (arrayMode.isSlowPut()) {
775                 result.append(
776                     m_jit.branchTest32(
777                         MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
778                 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
779                 m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
780                 result.append(
781                     m_jit.branch32(
782                         MacroAssembler::Above, tempGPR,
783                         TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
784                 break;
785             }
786             m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
787             result.append(
788                 m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | ArrayStorageShape)));
789             break;
790         }
791         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
792         if (arrayMode.isSlowPut()) {
793             m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
794             result.append(
795                 m_jit.branch32(
796                     MacroAssembler::Above, tempGPR,
797                     TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
798             break;
799         }
800         result.append(
801             m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
802         break;
803     }
804     default:
805         CRASH();
806         break;
807     }
808     
809     return result;
810 }
811
812 void SpeculativeJIT::checkArray(Node* node)
813 {
814     ASSERT(node->arrayMode().isSpecific());
815     ASSERT(!node->arrayMode().doesConversion());
816     
817     SpeculateCellOperand base(this, node->child1());
818     GPRReg baseReg = base.gpr();
819     
820     if (node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))) {
821         noResult(m_currentNode);
822         return;
823     }
824     
825     const ClassInfo* expectedClassInfo = 0;
826     
827     switch (node->arrayMode().type()) {
828     case Array::AnyTypedArray:
829     case Array::String:
830         RELEASE_ASSERT_NOT_REACHED(); // Should have been a Phantom(String:)
831         break;
832     case Array::Int32:
833     case Array::Double:
834     case Array::Contiguous:
835     case Array::Undecided:
836     case Array::ArrayStorage:
837     case Array::SlowPutArrayStorage: {
838         GPRTemporary temp(this);
839         GPRReg tempGPR = temp.gpr();
840         m_jit.load8(MacroAssembler::Address(baseReg, JSCell::indexingTypeOffset()), tempGPR);
841         speculationCheck(
842             BadIndexingType, JSValueSource::unboxedCell(baseReg), 0,
843             jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
844         
845         noResult(m_currentNode);
846         return;
847     }
848     case Array::DirectArguments:
849         speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, DirectArgumentsType);
850         noResult(m_currentNode);
851         return;
852     case Array::ScopedArguments:
853         speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, ScopedArgumentsType);
854         noResult(m_currentNode);
855         return;
856     default:
857         speculateCellTypeWithoutTypeFiltering(
858             node->child1(), baseReg,
859             typeForTypedArrayType(node->arrayMode().typedArrayType()));
860         noResult(m_currentNode);
861         return;
862     }
863     
864     RELEASE_ASSERT(expectedClassInfo);
865     
866     GPRTemporary temp(this);
867     GPRTemporary temp2(this);
868     m_jit.emitLoadStructure(baseReg, temp.gpr(), temp2.gpr());
869     speculationCheck(
870         BadType, JSValueSource::unboxedCell(baseReg), node,
871         m_jit.branchPtr(
872             MacroAssembler::NotEqual,
873             MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
874             MacroAssembler::TrustedImmPtr(expectedClassInfo)));
875     
876     noResult(m_currentNode);
877 }
878
879 void SpeculativeJIT::arrayify(Node* node, GPRReg baseReg, GPRReg propertyReg)
880 {
881     ASSERT(node->arrayMode().doesConversion());
882     
883     GPRTemporary temp(this);
884     GPRTemporary structure;
885     GPRReg tempGPR = temp.gpr();
886     GPRReg structureGPR = InvalidGPRReg;
887     
888     if (node->op() != ArrayifyToStructure) {
889         GPRTemporary realStructure(this);
890         structure.adopt(realStructure);
891         structureGPR = structure.gpr();
892     }
893         
894     // We can skip all that comes next if we already have array storage.
895     MacroAssembler::JumpList slowPath;
896     
897     if (node->op() == ArrayifyToStructure) {
898         slowPath.append(m_jit.branchWeakStructure(
899             JITCompiler::NotEqual,
900             JITCompiler::Address(baseReg, JSCell::structureIDOffset()),
901             node->structure()));
902     } else {
903         m_jit.load8(
904             MacroAssembler::Address(baseReg, JSCell::indexingTypeOffset()), tempGPR);
905         
906         slowPath.append(jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
907     }
908     
909     addSlowPathGenerator(std::make_unique<ArrayifySlowPathGenerator>(
910         slowPath, this, node, baseReg, propertyReg, tempGPR, structureGPR));
911     
912     noResult(m_currentNode);
913 }
914
915 void SpeculativeJIT::arrayify(Node* node)
916 {
917     ASSERT(node->arrayMode().isSpecific());
918     
919     SpeculateCellOperand base(this, node->child1());
920     
921     if (!node->child2()) {
922         arrayify(node, base.gpr(), InvalidGPRReg);
923         return;
924     }
925     
926     SpeculateInt32Operand property(this, node->child2());
927     
928     arrayify(node, base.gpr(), property.gpr());
929 }
930
931 GPRReg SpeculativeJIT::fillStorage(Edge edge)
932 {
933     VirtualRegister virtualRegister = edge->virtualRegister();
934     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
935     
936     switch (info.registerFormat()) {
937     case DataFormatNone: {
938         if (info.spillFormat() == DataFormatStorage) {
939             GPRReg gpr = allocate();
940             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
941             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
942             info.fillStorage(*m_stream, gpr);
943             return gpr;
944         }
945         
946         // Must be a cell; fill it as a cell and then return the pointer.
947         return fillSpeculateCell(edge);
948     }
949         
950     case DataFormatStorage: {
951         GPRReg gpr = info.gpr();
952         m_gprs.lock(gpr);
953         return gpr;
954     }
955         
956     default:
957         return fillSpeculateCell(edge);
958     }
959 }
960
961 void SpeculativeJIT::useChildren(Node* node)
962 {
963     if (node->flags() & NodeHasVarArgs) {
964         for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
965             if (!!m_jit.graph().m_varArgChildren[childIdx])
966                 use(m_jit.graph().m_varArgChildren[childIdx]);
967         }
968     } else {
969         Edge child1 = node->child1();
970         if (!child1) {
971             ASSERT(!node->child2() && !node->child3());
972             return;
973         }
974         use(child1);
975         
976         Edge child2 = node->child2();
977         if (!child2) {
978             ASSERT(!node->child3());
979             return;
980         }
981         use(child2);
982         
983         Edge child3 = node->child3();
984         if (!child3)
985             return;
986         use(child3);
987     }
988 }
989
990 void SpeculativeJIT::compileTryGetById(Node* node)
991 {
992     switch (node->child1().useKind()) {
993     case CellUse: {
994         SpeculateCellOperand base(this, node->child1());
995         JSValueRegsTemporary result(this, Reuse, base);
996
997         JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
998         JSValueRegs resultRegs = result.regs();
999
1000         base.use();
1001
1002         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::TryGet);
1003
1004         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
1005         break;
1006     }
1007
1008     case UntypedUse: {
1009         JSValueOperand base(this, node->child1());
1010         JSValueRegsTemporary result(this, Reuse, base);
1011
1012         JSValueRegs baseRegs = base.jsValueRegs();
1013         JSValueRegs resultRegs = result.regs();
1014
1015         base.use();
1016
1017         JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
1018
1019         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, AccessType::TryGet);
1020
1021         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
1022         break;
1023     }
1024
1025     default:
1026         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1027         break;
1028     } 
1029 }
1030
1031 void SpeculativeJIT::compilePureGetById(Node* node)
1032 {
1033     ASSERT(node->op() == PureGetById);
1034
1035     switch (node->child1().useKind()) {
1036     case CellUse: {
1037         SpeculateCellOperand base(this, node->child1());
1038         JSValueRegsTemporary result(this, Reuse, base);
1039
1040         JSValueRegs baseRegs = JSValueRegs::payloadOnly(base.gpr());
1041         JSValueRegs resultRegs = result.regs();
1042
1043         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), JITCompiler::Jump(), NeedToSpill, AccessType::PureGet);
1044
1045         jsValueResult(resultRegs, node);
1046         break;
1047     }
1048     case UntypedUse: {
1049         JSValueOperand base(this, node->child1());
1050         JSValueRegsTemporary result(this, Reuse, base);
1051
1052         JSValueRegs baseRegs = base.jsValueRegs();
1053         JSValueRegs resultRegs = result.regs();
1054     
1055         JITCompiler::Jump notCell = m_jit.branchIfNotCell(baseRegs);
1056     
1057         cachedGetById(node->origin.semantic, baseRegs, resultRegs, node->identifierNumber(), notCell, NeedToSpill, AccessType::PureGet);
1058     
1059         jsValueResult(resultRegs, node);
1060         break;
1061     }
1062     default:
1063         RELEASE_ASSERT_NOT_REACHED();
1064     }
1065 }
1066
1067 void SpeculativeJIT::compileIn(Node* node)
1068 {
1069     SpeculateCellOperand base(this, node->child2());
1070     GPRReg baseGPR = base.gpr();
1071     
1072     if (JSString* string = node->child1()->dynamicCastConstant<JSString*>()) {
1073         if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
1074             StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo(AccessType::In);
1075             
1076             GPRTemporary result(this);
1077             GPRReg resultGPR = result.gpr();
1078
1079             use(node->child1());
1080             
1081             MacroAssembler::PatchableJump jump = m_jit.patchableJump();
1082             MacroAssembler::Label done = m_jit.label();
1083             
1084             // Since this block is executed only when the result of string->tryGetValueImpl() is atomic,
1085             // we can cast it to const AtomicStringImpl* safely.
1086             auto slowPath = slowPathCall(
1087                 jump.m_jump, this, operationInOptimize,
1088                 JSValueRegs::payloadOnly(resultGPR), stubInfo, baseGPR,
1089                 static_cast<const AtomicStringImpl*>(string->tryGetValueImpl()));
1090             
1091             stubInfo->callSiteIndex = m_jit.addCallSite(node->origin.semantic);
1092             stubInfo->codeOrigin = node->origin.semantic;
1093             stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR);
1094             stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR);
1095 #if USE(JSVALUE32_64)
1096             stubInfo->patch.valueTagGPR = static_cast<int8_t>(InvalidGPRReg);
1097             stubInfo->patch.baseTagGPR = static_cast<int8_t>(InvalidGPRReg);
1098 #endif
1099             stubInfo->patch.usedRegisters = usedRegisters();
1100
1101             m_jit.addIn(InRecord(jump, done, slowPath.get(), stubInfo));
1102             addSlowPathGenerator(WTFMove(slowPath));
1103
1104             base.use();
1105
1106             blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1107             return;
1108         }
1109     }
1110
1111     JSValueOperand key(this, node->child1());
1112     JSValueRegs regs = key.jsValueRegs();
1113         
1114     GPRFlushedCallResult result(this);
1115     GPRReg resultGPR = result.gpr();
1116         
1117     base.use();
1118     key.use();
1119         
1120     flushRegisters();
1121     callOperation(
1122         operationGenericIn, extractResult(JSValueRegs::payloadOnly(resultGPR)),
1123         baseGPR, regs);
1124     m_jit.exceptionCheck();
1125     blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1126 }
1127
1128 void SpeculativeJIT::compileDeleteById(Node* node)
1129 {
1130     JSValueOperand value(this, node->child1());
1131     GPRFlushedCallResult result(this);
1132
1133     JSValueRegs valueRegs = value.jsValueRegs();
1134     GPRReg resultGPR = result.gpr();
1135
1136     value.use();
1137
1138     flushRegisters();
1139     callOperation(operationDeleteById, resultGPR, valueRegs, identifierUID(node->identifierNumber()));
1140     m_jit.exceptionCheck();
1141
1142     unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1143 }
1144
1145 void SpeculativeJIT::compileDeleteByVal(Node* node)
1146 {
1147     JSValueOperand base(this, node->child1());
1148     JSValueOperand key(this, node->child2());
1149     GPRFlushedCallResult result(this);
1150
1151     JSValueRegs baseRegs = base.jsValueRegs();
1152     JSValueRegs keyRegs = key.jsValueRegs();
1153     GPRReg resultGPR = result.gpr();
1154
1155     base.use();
1156     key.use();
1157
1158     flushRegisters();
1159     callOperation(operationDeleteByVal, resultGPR, baseRegs, keyRegs);
1160     m_jit.exceptionCheck();
1161
1162     unblessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
1163 }
1164
1165 bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
1166 {
1167     unsigned branchIndexInBlock = detectPeepHoleBranch();
1168     if (branchIndexInBlock != UINT_MAX) {
1169         Node* branchNode = m_block->at(branchIndexInBlock);
1170
1171         ASSERT(node->adjustedRefCount() == 1);
1172         
1173         nonSpeculativePeepholeBranch(node, branchNode, cond, helperFunction);
1174     
1175         m_indexInBlock = branchIndexInBlock;
1176         m_currentNode = branchNode;
1177         
1178         return true;
1179     }
1180     
1181     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
1182     
1183     return false;
1184 }
1185
1186 bool SpeculativeJIT::nonSpeculativeStrictEq(Node* node, bool invert)
1187 {
1188     unsigned branchIndexInBlock = detectPeepHoleBranch();
1189     if (branchIndexInBlock != UINT_MAX) {
1190         Node* branchNode = m_block->at(branchIndexInBlock);
1191
1192         ASSERT(node->adjustedRefCount() == 1);
1193         
1194         nonSpeculativePeepholeStrictEq(node, branchNode, invert);
1195     
1196         m_indexInBlock = branchIndexInBlock;
1197         m_currentNode = branchNode;
1198         
1199         return true;
1200     }
1201     
1202     nonSpeculativeNonPeepholeStrictEq(node, invert);
1203     
1204     return false;
1205 }
1206
1207 static const char* dataFormatString(DataFormat format)
1208 {
1209     // These values correspond to the DataFormat enum.
1210     const char* strings[] = {
1211         "[  ]",
1212         "[ i]",
1213         "[ d]",
1214         "[ c]",
1215         "Err!",
1216         "Err!",
1217         "Err!",
1218         "Err!",
1219         "[J ]",
1220         "[Ji]",
1221         "[Jd]",
1222         "[Jc]",
1223         "Err!",
1224         "Err!",
1225         "Err!",
1226         "Err!",
1227     };
1228     return strings[format];
1229 }
1230
1231 void SpeculativeJIT::dump(const char* label)
1232 {
1233     if (label)
1234         dataLogF("<%s>\n", label);
1235
1236     dataLogF("  gprs:\n");
1237     m_gprs.dump();
1238     dataLogF("  fprs:\n");
1239     m_fprs.dump();
1240     dataLogF("  VirtualRegisters:\n");
1241     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1242         GenerationInfo& info = m_generationInfo[i];
1243         if (info.alive())
1244             dataLogF("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
1245         else
1246             dataLogF("    % 3d:[__][__]", i);
1247         if (info.registerFormat() == DataFormatDouble)
1248             dataLogF(":fpr%d\n", info.fpr());
1249         else if (info.registerFormat() != DataFormatNone
1250 #if USE(JSVALUE32_64)
1251             && !(info.registerFormat() & DataFormatJS)
1252 #endif
1253             ) {
1254             ASSERT(info.gpr() != InvalidGPRReg);
1255             dataLogF(":%s\n", GPRInfo::debugName(info.gpr()));
1256         } else
1257             dataLogF("\n");
1258     }
1259     if (label)
1260         dataLogF("</%s>\n", label);
1261 }
1262
1263 GPRTemporary::GPRTemporary()
1264     : m_jit(0)
1265     , m_gpr(InvalidGPRReg)
1266 {
1267 }
1268
1269 GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
1270     : m_jit(jit)
1271     , m_gpr(InvalidGPRReg)
1272 {
1273     m_gpr = m_jit->allocate();
1274 }
1275
1276 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
1277     : m_jit(jit)
1278     , m_gpr(InvalidGPRReg)
1279 {
1280     m_gpr = m_jit->allocate(specific);
1281 }
1282
1283 #if USE(JSVALUE32_64)
1284 GPRTemporary::GPRTemporary(
1285     SpeculativeJIT* jit, ReuseTag, JSValueOperand& op1, WhichValueWord which)
1286     : m_jit(jit)
1287     , m_gpr(InvalidGPRReg)
1288 {
1289     if (!op1.isDouble() && m_jit->canReuse(op1.node()))
1290         m_gpr = m_jit->reuse(op1.gpr(which));
1291     else
1292         m_gpr = m_jit->allocate();
1293 }
1294 #endif // USE(JSVALUE32_64)
1295
1296 JSValueRegsTemporary::JSValueRegsTemporary() { }
1297
1298 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit)
1299 #if USE(JSVALUE64)
1300     : m_gpr(jit)
1301 #else
1302     : m_payloadGPR(jit)
1303     , m_tagGPR(jit)
1304 #endif
1305 {
1306 }
1307
1308 #if USE(JSVALUE64)
1309 template<typename T>
1310 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord)
1311     : m_gpr(jit, Reuse, operand)
1312 {
1313 }
1314 #else
1315 template<typename T>
1316 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, T& operand, WhichValueWord resultWord)
1317 {
1318     if (resultWord == PayloadWord) {
1319         m_payloadGPR = GPRTemporary(jit, Reuse, operand);
1320         m_tagGPR = GPRTemporary(jit);
1321     } else {
1322         m_payloadGPR = GPRTemporary(jit);
1323         m_tagGPR = GPRTemporary(jit, Reuse, operand);
1324     }
1325 }
1326 #endif
1327
1328 #if USE(JSVALUE64)
1329 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& operand)
1330 {
1331     m_gpr = GPRTemporary(jit, Reuse, operand);
1332 }
1333 #else
1334 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit, ReuseTag, JSValueOperand& operand)
1335 {
1336     if (jit->canReuse(operand.node())) {
1337         m_payloadGPR = GPRTemporary(jit, Reuse, operand, PayloadWord);
1338         m_tagGPR = GPRTemporary(jit, Reuse, operand, TagWord);
1339     } else {
1340         m_payloadGPR = GPRTemporary(jit);
1341         m_tagGPR = GPRTemporary(jit);
1342     }
1343 }
1344 #endif
1345
1346 JSValueRegsTemporary::~JSValueRegsTemporary() { }
1347
1348 JSValueRegs JSValueRegsTemporary::regs()
1349 {
1350 #if USE(JSVALUE64)
1351     return JSValueRegs(m_gpr.gpr());
1352 #else
1353     return JSValueRegs(m_tagGPR.gpr(), m_payloadGPR.gpr());
1354 #endif
1355 }
1356
1357 void GPRTemporary::adopt(GPRTemporary& other)
1358 {
1359     ASSERT(!m_jit);
1360     ASSERT(m_gpr == InvalidGPRReg);
1361     ASSERT(other.m_jit);
1362     ASSERT(other.m_gpr != InvalidGPRReg);
1363     m_jit = other.m_jit;
1364     m_gpr = other.m_gpr;
1365     other.m_jit = 0;
1366     other.m_gpr = InvalidGPRReg;
1367 }
1368
1369 FPRTemporary::FPRTemporary(FPRTemporary&& other)
1370 {
1371     ASSERT(other.m_jit);
1372     ASSERT(other.m_fpr != InvalidFPRReg);
1373     m_jit = other.m_jit;
1374     m_fpr = other.m_fpr;
1375
1376     other.m_jit = nullptr;
1377 }
1378
1379 FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
1380     : m_jit(jit)
1381     , m_fpr(InvalidFPRReg)
1382 {
1383     m_fpr = m_jit->fprAllocate();
1384 }
1385
1386 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
1387     : m_jit(jit)
1388     , m_fpr(InvalidFPRReg)
1389 {
1390     if (m_jit->canReuse(op1.node()))
1391         m_fpr = m_jit->reuse(op1.fpr());
1392     else
1393         m_fpr = m_jit->fprAllocate();
1394 }
1395
1396 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
1397     : m_jit(jit)
1398     , m_fpr(InvalidFPRReg)
1399 {
1400     if (m_jit->canReuse(op1.node()))
1401         m_fpr = m_jit->reuse(op1.fpr());
1402     else if (m_jit->canReuse(op2.node()))
1403         m_fpr = m_jit->reuse(op2.fpr());
1404     else if (m_jit->canReuse(op1.node(), op2.node()) && op1.fpr() == op2.fpr())
1405         m_fpr = m_jit->reuse(op1.fpr());
1406     else
1407         m_fpr = m_jit->fprAllocate();
1408 }
1409
1410 #if USE(JSVALUE32_64)
1411 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
1412     : m_jit(jit)
1413     , m_fpr(InvalidFPRReg)
1414 {
1415     if (op1.isDouble() && m_jit->canReuse(op1.node()))
1416         m_fpr = m_jit->reuse(op1.fpr());
1417     else
1418         m_fpr = m_jit->fprAllocate();
1419 }
1420 #endif
1421
1422 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node* node, Node* branchNode, JITCompiler::DoubleCondition condition)
1423 {
1424     BasicBlock* taken = branchNode->branchData()->taken.block;
1425     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1426
1427     if (taken == nextBlock()) {
1428         condition = MacroAssembler::invert(condition);
1429         std::swap(taken, notTaken);
1430     }
1431
1432     SpeculateDoubleOperand op1(this, node->child1());
1433     SpeculateDoubleOperand op2(this, node->child2());
1434     
1435     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
1436     jump(notTaken);
1437 }
1438
1439 void SpeculativeJIT::compilePeepHoleObjectEquality(Node* node, Node* branchNode)
1440 {
1441     BasicBlock* taken = branchNode->branchData()->taken.block;
1442     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1443
1444     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
1445     
1446     if (taken == nextBlock()) {
1447         condition = MacroAssembler::NotEqual;
1448         BasicBlock* tmp = taken;
1449         taken = notTaken;
1450         notTaken = tmp;
1451     }
1452
1453     SpeculateCellOperand op1(this, node->child1());
1454     SpeculateCellOperand op2(this, node->child2());
1455     
1456     GPRReg op1GPR = op1.gpr();
1457     GPRReg op2GPR = op2.gpr();
1458     
1459     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1460         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1461             speculationCheck(
1462                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), m_jit.branchIfNotObject(op1GPR));
1463         }
1464         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1465             speculationCheck(
1466                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), m_jit.branchIfNotObject(op2GPR));
1467         }
1468     } else {
1469         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1470             speculationCheck(
1471                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1472                 m_jit.branchIfNotObject(op1GPR));
1473         }
1474         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1475             m_jit.branchTest8(
1476                 MacroAssembler::NonZero, 
1477                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1478                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1479
1480         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1481             speculationCheck(
1482                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1483                 m_jit.branchIfNotObject(op2GPR));
1484         }
1485         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1486             m_jit.branchTest8(
1487                 MacroAssembler::NonZero, 
1488                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1489                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1490     }
1491
1492     branchPtr(condition, op1GPR, op2GPR, taken);
1493     jump(notTaken);
1494 }
1495
1496 void SpeculativeJIT::compilePeepHoleBooleanBranch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1497 {
1498     BasicBlock* taken = branchNode->branchData()->taken.block;
1499     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1500
1501     // The branch instruction will branch to the taken block.
1502     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1503     if (taken == nextBlock()) {
1504         condition = JITCompiler::invert(condition);
1505         BasicBlock* tmp = taken;
1506         taken = notTaken;
1507         notTaken = tmp;
1508     }
1509
1510     if (node->child1()->isInt32Constant()) {
1511         int32_t imm = node->child1()->asInt32();
1512         SpeculateBooleanOperand op2(this, node->child2());
1513         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1514     } else if (node->child2()->isInt32Constant()) {
1515         SpeculateBooleanOperand op1(this, node->child1());
1516         int32_t imm = node->child2()->asInt32();
1517         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1518     } else {
1519         SpeculateBooleanOperand op1(this, node->child1());
1520         SpeculateBooleanOperand op2(this, node->child2());
1521         branch32(condition, op1.gpr(), op2.gpr(), taken);
1522     }
1523
1524     jump(notTaken);
1525 }
1526
1527 void SpeculativeJIT::compileToLowerCase(Node* node)
1528 {
1529     ASSERT(node->op() == ToLowerCase);
1530     SpeculateCellOperand string(this, node->child1());
1531     GPRTemporary temp(this);
1532     GPRTemporary index(this);
1533     GPRTemporary charReg(this);
1534     GPRTemporary length(this);
1535
1536     GPRReg stringGPR = string.gpr();
1537     GPRReg tempGPR = temp.gpr();
1538     GPRReg indexGPR = index.gpr();
1539     GPRReg charGPR = charReg.gpr();
1540     GPRReg lengthGPR = length.gpr();
1541
1542     speculateString(node->child1(), stringGPR);
1543
1544     CCallHelpers::JumpList slowPath;
1545
1546     m_jit.move(TrustedImmPtr(0), indexGPR);
1547
1548     m_jit.loadPtr(MacroAssembler::Address(stringGPR, JSString::offsetOfValue()), tempGPR);
1549     slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR));
1550
1551     slowPath.append(m_jit.branchTest32(
1552         MacroAssembler::Zero, MacroAssembler::Address(tempGPR, StringImpl::flagsOffset()),
1553         MacroAssembler::TrustedImm32(StringImpl::flagIs8Bit())));
1554     m_jit.load32(MacroAssembler::Address(tempGPR, StringImpl::lengthMemoryOffset()), lengthGPR);
1555     m_jit.loadPtr(MacroAssembler::Address(tempGPR, StringImpl::dataOffset()), tempGPR);
1556
1557     auto loopStart = m_jit.label();
1558     auto loopDone = m_jit.branch32(CCallHelpers::AboveOrEqual, indexGPR, lengthGPR);
1559     m_jit.load8(MacroAssembler::BaseIndex(tempGPR, indexGPR, MacroAssembler::TimesOne), charGPR);
1560     slowPath.append(m_jit.branchTest32(CCallHelpers::NonZero, charGPR, TrustedImm32(~0x7F)));
1561     m_jit.sub32(TrustedImm32('A'), charGPR);
1562     slowPath.append(m_jit.branch32(CCallHelpers::BelowOrEqual, charGPR, TrustedImm32('Z' - 'A')));
1563
1564     m_jit.add32(TrustedImm32(1), indexGPR);
1565     m_jit.jump().linkTo(loopStart, &m_jit);
1566     
1567     slowPath.link(&m_jit);
1568     silentSpillAllRegisters(lengthGPR);
1569     callOperation(operationToLowerCase, lengthGPR, stringGPR, indexGPR);
1570     silentFillAllRegisters(lengthGPR);
1571     m_jit.exceptionCheck();
1572     auto done = m_jit.jump();
1573
1574     loopDone.link(&m_jit);
1575     m_jit.move(stringGPR, lengthGPR);
1576
1577     done.link(&m_jit);
1578     cellResult(lengthGPR, node);
1579 }
1580
1581 void SpeculativeJIT::compilePeepHoleInt32Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1582 {
1583     BasicBlock* taken = branchNode->branchData()->taken.block;
1584     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1585
1586     // The branch instruction will branch to the taken block.
1587     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1588     if (taken == nextBlock()) {
1589         condition = JITCompiler::invert(condition);
1590         BasicBlock* tmp = taken;
1591         taken = notTaken;
1592         notTaken = tmp;
1593     }
1594
1595     if (node->child1()->isInt32Constant()) {
1596         int32_t imm = node->child1()->asInt32();
1597         SpeculateInt32Operand op2(this, node->child2());
1598         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1599     } else if (node->child2()->isInt32Constant()) {
1600         SpeculateInt32Operand op1(this, node->child1());
1601         int32_t imm = node->child2()->asInt32();
1602         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1603     } else {
1604         SpeculateInt32Operand op1(this, node->child1());
1605         SpeculateInt32Operand op2(this, node->child2());
1606         branch32(condition, op1.gpr(), op2.gpr(), taken);
1607     }
1608
1609     jump(notTaken);
1610 }
1611
1612 // Returns true if the compare is fused with a subsequent branch.
1613 bool SpeculativeJIT::compilePeepHoleBranch(Node* node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_JITOperation_EJJ operation)
1614 {
1615     // Fused compare & branch.
1616     unsigned branchIndexInBlock = detectPeepHoleBranch();
1617     if (branchIndexInBlock != UINT_MAX) {
1618         Node* branchNode = m_block->at(branchIndexInBlock);
1619
1620         // detectPeepHoleBranch currently only permits the branch to be the very next node,
1621         // so can be no intervening nodes to also reference the compare. 
1622         ASSERT(node->adjustedRefCount() == 1);
1623
1624         if (node->isBinaryUseKind(Int32Use))
1625             compilePeepHoleInt32Branch(node, branchNode, condition);
1626 #if USE(JSVALUE64)
1627         else if (node->isBinaryUseKind(Int52RepUse))
1628             compilePeepHoleInt52Branch(node, branchNode, condition);
1629 #endif // USE(JSVALUE64)
1630         else if (node->isBinaryUseKind(StringUse) || node->isBinaryUseKind(StringIdentUse)) {
1631             // Use non-peephole comparison, for now.
1632             return false;
1633         } else if (node->isBinaryUseKind(DoubleRepUse))
1634             compilePeepHoleDoubleBranch(node, branchNode, doubleCondition);
1635         else if (node->op() == CompareEq) {
1636             if (node->isBinaryUseKind(BooleanUse))
1637                 compilePeepHoleBooleanBranch(node, branchNode, condition);
1638             else if (node->isBinaryUseKind(SymbolUse))
1639                 compilePeepHoleSymbolEquality(node, branchNode);
1640             else if (node->isBinaryUseKind(ObjectUse))
1641                 compilePeepHoleObjectEquality(node, branchNode);
1642             else if (node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse))
1643                 compilePeepHoleObjectToObjectOrOtherEquality(node->child1(), node->child2(), branchNode);
1644             else if (node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse))
1645                 compilePeepHoleObjectToObjectOrOtherEquality(node->child2(), node->child1(), branchNode);
1646             else if (!needsTypeCheck(node->child1(), SpecOther))
1647                 nonSpeculativePeepholeBranchNullOrUndefined(node->child2(), branchNode);
1648             else if (!needsTypeCheck(node->child2(), SpecOther))
1649                 nonSpeculativePeepholeBranchNullOrUndefined(node->child1(), branchNode);
1650             else {
1651                 nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1652                 return true;
1653             }
1654         } else {
1655             nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1656             return true;
1657         }
1658
1659         use(node->child1());
1660         use(node->child2());
1661         m_indexInBlock = branchIndexInBlock;
1662         m_currentNode = branchNode;
1663         return true;
1664     }
1665     return false;
1666 }
1667
1668 void SpeculativeJIT::noticeOSRBirth(Node* node)
1669 {
1670     if (!node->hasVirtualRegister())
1671         return;
1672     
1673     VirtualRegister virtualRegister = node->virtualRegister();
1674     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1675     
1676     info.noticeOSRBirth(*m_stream, node, virtualRegister);
1677 }
1678
1679 void SpeculativeJIT::compileMovHint(Node* node)
1680 {
1681     ASSERT(node->containsMovHint() && node->op() != ZombieHint);
1682     
1683     Node* child = node->child1().node();
1684     noticeOSRBirth(child);
1685     
1686     m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->unlinkedLocal()));
1687 }
1688
1689 void SpeculativeJIT::bail(AbortReason reason)
1690 {
1691     if (verboseCompilationEnabled())
1692         dataLog("Bailing compilation.\n");
1693     m_compileOkay = true;
1694     m_jit.abortWithReason(reason, m_lastGeneratedNode);
1695     clearGenerationInfo();
1696 }
1697
1698 void SpeculativeJIT::compileCurrentBlock()
1699 {
1700     ASSERT(m_compileOkay);
1701     
1702     if (!m_block)
1703         return;
1704     
1705     ASSERT(m_block->isReachable);
1706     
1707     m_jit.blockHeads()[m_block->index] = m_jit.label();
1708
1709     if (!m_block->intersectionOfCFAHasVisited) {
1710         // Don't generate code for basic blocks that are unreachable according to CFA.
1711         // But to be sure that nobody has generated a jump to this block, drop in a
1712         // breakpoint here.
1713         m_jit.abortWithReason(DFGUnreachableBasicBlock);
1714         return;
1715     }
1716
1717     m_stream->appendAndLog(VariableEvent::reset());
1718     
1719     m_jit.jitAssertHasValidCallFrame();
1720     m_jit.jitAssertTagsInPlace();
1721     m_jit.jitAssertArgumentCountSane();
1722
1723     m_state.reset();
1724     m_state.beginBasicBlock(m_block);
1725     
1726     for (size_t i = m_block->variablesAtHead.size(); i--;) {
1727         int operand = m_block->variablesAtHead.operandForIndex(i);
1728         Node* node = m_block->variablesAtHead[i];
1729         if (!node)
1730             continue; // No need to record dead SetLocal's.
1731         
1732         VariableAccessData* variable = node->variableAccessData();
1733         DataFormat format;
1734         if (!node->refCount())
1735             continue; // No need to record dead SetLocal's.
1736         format = dataFormatFor(variable->flushFormat());
1737         m_stream->appendAndLog(
1738             VariableEvent::setLocal(
1739                 VirtualRegister(operand),
1740                 variable->machineLocal(),
1741                 format));
1742     }
1743
1744     m_origin = NodeOrigin();
1745     
1746     for (m_indexInBlock = 0; m_indexInBlock < m_block->size(); ++m_indexInBlock) {
1747         m_currentNode = m_block->at(m_indexInBlock);
1748         
1749         // We may have hit a contradiction that the CFA was aware of but that the JIT
1750         // didn't cause directly.
1751         if (!m_state.isValid()) {
1752             bail(DFGBailedAtTopOfBlock);
1753             return;
1754         }
1755
1756         m_interpreter.startExecuting();
1757         m_interpreter.executeKnownEdgeTypes(m_currentNode);
1758         m_jit.setForNode(m_currentNode);
1759         m_origin = m_currentNode->origin;
1760         if (validationEnabled())
1761             m_origin.exitOK &= mayExit(m_jit.graph(), m_currentNode) == Exits;
1762         m_lastGeneratedNode = m_currentNode->op();
1763         
1764         ASSERT(m_currentNode->shouldGenerate());
1765         
1766         if (verboseCompilationEnabled()) {
1767             dataLogF(
1768                 "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
1769                 (int)m_currentNode->index(),
1770                 m_currentNode->origin.semantic.bytecodeIndex, m_jit.debugOffset());
1771             dataLog("\n");
1772         }
1773
1774         if (Options::validateDFGExceptionHandling() && (mayExit(m_jit.graph(), m_currentNode) != DoesNotExit || m_currentNode->isTerminal()))
1775             m_jit.jitReleaseAssertNoException();
1776
1777         m_jit.pcToCodeOriginMapBuilder().appendItem(m_jit.labelIgnoringWatchpoints(), m_origin.semantic);
1778
1779         compile(m_currentNode);
1780         
1781         if (belongsInMinifiedGraph(m_currentNode->op()))
1782             m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1783         
1784 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1785         m_jit.clearRegisterAllocationOffsets();
1786 #endif
1787         
1788         if (!m_compileOkay) {
1789             bail(DFGBailedAtEndOfNode);
1790             return;
1791         }
1792         
1793         // Make sure that the abstract state is rematerialized for the next node.
1794         m_interpreter.executeEffects(m_indexInBlock);
1795     }
1796     
1797     // Perform the most basic verification that children have been used correctly.
1798     if (!ASSERT_DISABLED) {
1799         for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1800             GenerationInfo& info = m_generationInfo[index];
1801             RELEASE_ASSERT(!info.alive());
1802         }
1803     }
1804 }
1805
1806 // If we are making type predictions about our arguments then
1807 // we need to check that they are correct on function entry.
1808 void SpeculativeJIT::checkArgumentTypes()
1809 {
1810     ASSERT(!m_currentNode);
1811     m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
1812
1813     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1814         Node* node = m_jit.graph().m_arguments[i];
1815         if (!node) {
1816             // The argument is dead. We don't do any checks for such arguments.
1817             continue;
1818         }
1819         
1820         ASSERT(node->op() == SetArgument);
1821         ASSERT(node->shouldGenerate());
1822
1823         VariableAccessData* variableAccessData = node->variableAccessData();
1824         FlushFormat format = variableAccessData->flushFormat();
1825         
1826         if (format == FlushedJSValue)
1827             continue;
1828         
1829         VirtualRegister virtualRegister = variableAccessData->local();
1830
1831         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1832         
1833 #if USE(JSVALUE64)
1834         switch (format) {
1835         case FlushedInt32: {
1836             speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1837             break;
1838         }
1839         case FlushedBoolean: {
1840             GPRTemporary temp(this);
1841             m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
1842             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1843             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1844             break;
1845         }
1846         case FlushedCell: {
1847             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
1848             break;
1849         }
1850         default:
1851             RELEASE_ASSERT_NOT_REACHED();
1852             break;
1853         }
1854 #else
1855         switch (format) {
1856         case FlushedInt32: {
1857             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1858             break;
1859         }
1860         case FlushedBoolean: {
1861             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1862             break;
1863         }
1864         case FlushedCell: {
1865             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1866             break;
1867         }
1868         default:
1869             RELEASE_ASSERT_NOT_REACHED();
1870             break;
1871         }
1872 #endif
1873     }
1874
1875     m_origin = NodeOrigin();
1876 }
1877
1878 bool SpeculativeJIT::compile()
1879 {
1880     checkArgumentTypes();
1881     
1882     ASSERT(!m_currentNode);
1883     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1884         m_jit.setForBlockIndex(blockIndex);
1885         m_block = m_jit.graph().block(blockIndex);
1886         compileCurrentBlock();
1887     }
1888     linkBranches();
1889     return true;
1890 }
1891
1892 void SpeculativeJIT::createOSREntries()
1893 {
1894     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1895         BasicBlock* block = m_jit.graph().block(blockIndex);
1896         if (!block)
1897             continue;
1898         if (!block->isOSRTarget)
1899             continue;
1900         
1901         // Currently we don't have OSR entry trampolines. We could add them
1902         // here if need be.
1903         m_osrEntryHeads.append(m_jit.blockHeads()[blockIndex]);
1904     }
1905 }
1906
1907 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1908 {
1909     unsigned osrEntryIndex = 0;
1910     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1911         BasicBlock* block = m_jit.graph().block(blockIndex);
1912         if (!block)
1913             continue;
1914         if (!block->isOSRTarget)
1915             continue;
1916         m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1917     }
1918     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1919     
1920     if (verboseCompilationEnabled()) {
1921         DumpContext dumpContext;
1922         dataLog("OSR Entries:\n");
1923         for (OSREntryData& entryData : m_jit.jitCode()->osrEntry)
1924             dataLog("    ", inContext(entryData, &dumpContext), "\n");
1925         if (!dumpContext.isEmpty())
1926             dumpContext.dump(WTF::dataFile());
1927     }
1928 }
1929
1930 void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
1931 {
1932     Edge child3 = m_jit.graph().varArgChild(node, 2);
1933     Edge child4 = m_jit.graph().varArgChild(node, 3);
1934
1935     ArrayMode arrayMode = node->arrayMode();
1936     
1937     GPRReg baseReg = base.gpr();
1938     GPRReg propertyReg = property.gpr();
1939     
1940     SpeculateDoubleOperand value(this, child3);
1941
1942     FPRReg valueReg = value.fpr();
1943     
1944     DFG_TYPE_CHECK(
1945         JSValueRegs(), child3, SpecFullRealNumber,
1946         m_jit.branchDouble(
1947             MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
1948     
1949     if (!m_compileOkay)
1950         return;
1951     
1952     StorageOperand storage(this, child4);
1953     GPRReg storageReg = storage.gpr();
1954
1955     if (node->op() == PutByValAlias) {
1956         // Store the value to the array.
1957         GPRReg propertyReg = property.gpr();
1958         FPRReg valueReg = value.fpr();
1959         m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1960         
1961         noResult(m_currentNode);
1962         return;
1963     }
1964     
1965     GPRTemporary temporary;
1966     GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
1967
1968     MacroAssembler::Jump slowCase;
1969     
1970     if (arrayMode.isInBounds()) {
1971         speculationCheck(
1972             OutOfBounds, JSValueRegs(), 0,
1973             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1974     } else {
1975         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1976         
1977         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1978         
1979         if (!arrayMode.isOutOfBounds())
1980             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1981         
1982         m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
1983         m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1984         
1985         inBounds.link(&m_jit);
1986     }
1987     
1988     m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1989
1990     base.use();
1991     property.use();
1992     value.use();
1993     storage.use();
1994     
1995     if (arrayMode.isOutOfBounds()) {
1996         addSlowPathGenerator(
1997             slowPathCall(
1998                 slowCase, this,
1999                 m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
2000                 NoResult, baseReg, propertyReg, valueReg));
2001     }
2002
2003     noResult(m_currentNode, UseChildrenCalledExplicitly);
2004 }
2005
2006 void SpeculativeJIT::compileGetCharCodeAt(Node* node)
2007 {
2008     SpeculateCellOperand string(this, node->child1());
2009     SpeculateStrictInt32Operand index(this, node->child2());
2010     StorageOperand storage(this, node->child3());
2011
2012     GPRReg stringReg = string.gpr();
2013     GPRReg indexReg = index.gpr();
2014     GPRReg storageReg = storage.gpr();
2015     
2016     ASSERT(speculationChecked(m_state.forNode(node->child1()).m_type, SpecString));
2017
2018     // unsigned comparison so we can filter out negative indices and indices that are too large
2019     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
2020
2021     GPRTemporary scratch(this);
2022     GPRReg scratchReg = scratch.gpr();
2023
2024     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
2025
2026     // Load the character into scratchReg
2027     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2028
2029     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
2030     JITCompiler::Jump cont8Bit = m_jit.jump();
2031
2032     is16Bit.link(&m_jit);
2033
2034     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
2035
2036     cont8Bit.link(&m_jit);
2037
2038     int32Result(scratchReg, m_currentNode);
2039 }
2040
2041 void SpeculativeJIT::compileGetByValOnString(Node* node)
2042 {
2043     SpeculateCellOperand base(this, node->child1());
2044     SpeculateStrictInt32Operand property(this, node->child2());
2045     StorageOperand storage(this, node->child3());
2046     GPRReg baseReg = base.gpr();
2047     GPRReg propertyReg = property.gpr();
2048     GPRReg storageReg = storage.gpr();
2049
2050     GPRTemporary scratch(this);
2051     GPRReg scratchReg = scratch.gpr();
2052 #if USE(JSVALUE32_64)
2053     GPRTemporary resultTag;
2054     GPRReg resultTagReg = InvalidGPRReg;
2055     if (node->arrayMode().isOutOfBounds()) {
2056         GPRTemporary realResultTag(this);
2057         resultTag.adopt(realResultTag);
2058         resultTagReg = resultTag.gpr();
2059     }
2060 #endif
2061
2062     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2063
2064     // unsigned comparison so we can filter out negative indices and indices that are too large
2065     JITCompiler::Jump outOfBounds = m_jit.branch32(
2066         MacroAssembler::AboveOrEqual, propertyReg,
2067         MacroAssembler::Address(baseReg, JSString::offsetOfLength()));
2068     if (node->arrayMode().isInBounds())
2069         speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
2070
2071     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
2072
2073     // Load the character into scratchReg
2074     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2075
2076     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
2077     JITCompiler::Jump cont8Bit = m_jit.jump();
2078
2079     is16Bit.link(&m_jit);
2080
2081     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
2082
2083     JITCompiler::Jump bigCharacter =
2084         m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100));
2085
2086     // 8 bit string values don't need the isASCII check.
2087     cont8Bit.link(&m_jit);
2088
2089     m_jit.lshift32(MacroAssembler::TrustedImm32(sizeof(void*) == 4 ? 2 : 3), scratchReg);
2090     m_jit.addPtr(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), scratchReg);
2091     m_jit.loadPtr(scratchReg, scratchReg);
2092
2093     addSlowPathGenerator(
2094         slowPathCall(
2095             bigCharacter, this, operationSingleCharacterString, scratchReg, scratchReg));
2096
2097     if (node->arrayMode().isOutOfBounds()) {
2098 #if USE(JSVALUE32_64)
2099         m_jit.move(TrustedImm32(JSValue::CellTag), resultTagReg);
2100 #endif
2101
2102         JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic);
2103         bool prototypeChainIsSane = false;
2104         if (globalObject->stringPrototypeChainIsSane()) {
2105             // FIXME: This could be captured using a Speculation mode that means "out-of-bounds
2106             // loads return a trivial value". Something like SaneChainOutOfBounds. This should
2107             // speculate that we don't take negative out-of-bounds, or better yet, it should rely
2108             // on a stringPrototypeChainIsSane() guaranteeing that the prototypes have no negative
2109             // indexed properties either.
2110             // https://bugs.webkit.org/show_bug.cgi?id=144668
2111             m_jit.graph().watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet());
2112             m_jit.graph().watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2113             prototypeChainIsSane = globalObject->stringPrototypeChainIsSane();
2114         }
2115         if (prototypeChainIsSane) {
2116             m_jit.graph().watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet());
2117             m_jit.graph().watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2118             
2119 #if USE(JSVALUE64)
2120             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2121                 outOfBounds, this, JSValueRegs(scratchReg), baseReg, propertyReg));
2122 #else
2123             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2124                 outOfBounds, this, JSValueRegs(resultTagReg, scratchReg),
2125                 baseReg, propertyReg));
2126 #endif
2127         } else {
2128 #if USE(JSVALUE64)
2129             addSlowPathGenerator(
2130                 slowPathCall(
2131                     outOfBounds, this, operationGetByValStringInt,
2132                     scratchReg, baseReg, propertyReg));
2133 #else
2134             addSlowPathGenerator(
2135                 slowPathCall(
2136                     outOfBounds, this, operationGetByValStringInt,
2137                     JSValueRegs(resultTagReg, scratchReg), baseReg, propertyReg));
2138 #endif
2139         }
2140         
2141 #if USE(JSVALUE64)
2142         jsValueResult(scratchReg, m_currentNode);
2143 #else
2144         jsValueResult(resultTagReg, scratchReg, m_currentNode);
2145 #endif
2146     } else
2147         cellResult(scratchReg, m_currentNode);
2148 }
2149
2150 void SpeculativeJIT::compileFromCharCode(Node* node)
2151 {
2152     Edge& child = node->child1();
2153     if (child.useKind() == UntypedUse) {
2154         JSValueOperand opr(this, child);
2155         JSValueRegs oprRegs = opr.jsValueRegs();
2156 #if USE(JSVALUE64)
2157         GPRTemporary result(this);
2158         JSValueRegs resultRegs = JSValueRegs(result.gpr());
2159 #else
2160         GPRTemporary resultTag(this);
2161         GPRTemporary resultPayload(this);
2162         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
2163 #endif
2164         flushRegisters();
2165         callOperation(operationStringFromCharCodeUntyped, resultRegs, oprRegs);
2166         m_jit.exceptionCheck();
2167         
2168         jsValueResult(resultRegs, node);
2169         return;
2170     }
2171
2172     SpeculateStrictInt32Operand property(this, child);
2173     GPRReg propertyReg = property.gpr();
2174     GPRTemporary smallStrings(this);
2175     GPRTemporary scratch(this);
2176     GPRReg scratchReg = scratch.gpr();
2177     GPRReg smallStringsReg = smallStrings.gpr();
2178
2179     JITCompiler::JumpList slowCases;
2180     slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(0xff)));
2181     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
2182     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, propertyReg, MacroAssembler::ScalePtr, 0), scratchReg);
2183
2184     slowCases.append(m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2185     addSlowPathGenerator(slowPathCall(slowCases, this, operationStringFromCharCode, scratchReg, propertyReg));
2186     cellResult(scratchReg, m_currentNode);
2187 }
2188
2189 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)
2190 {
2191     VirtualRegister virtualRegister = node->virtualRegister();
2192     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2193
2194     switch (info.registerFormat()) {
2195     case DataFormatStorage:
2196         RELEASE_ASSERT_NOT_REACHED();
2197
2198     case DataFormatBoolean:
2199     case DataFormatCell:
2200         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2201         return GeneratedOperandTypeUnknown;
2202
2203     case DataFormatNone:
2204     case DataFormatJSCell:
2205     case DataFormatJS:
2206     case DataFormatJSBoolean:
2207     case DataFormatJSDouble:
2208         return GeneratedOperandJSValue;
2209
2210     case DataFormatJSInt32:
2211     case DataFormatInt32:
2212         return GeneratedOperandInteger;
2213
2214     default:
2215         RELEASE_ASSERT_NOT_REACHED();
2216         return GeneratedOperandTypeUnknown;
2217     }
2218 }
2219
2220 void SpeculativeJIT::compileValueToInt32(Node* node)
2221 {
2222     switch (node->child1().useKind()) {
2223 #if USE(JSVALUE64)
2224     case Int52RepUse: {
2225         SpeculateStrictInt52Operand op1(this, node->child1());
2226         GPRTemporary result(this, Reuse, op1);
2227         GPRReg op1GPR = op1.gpr();
2228         GPRReg resultGPR = result.gpr();
2229         m_jit.zeroExtend32ToPtr(op1GPR, resultGPR);
2230         int32Result(resultGPR, node, DataFormatInt32);
2231         return;
2232     }
2233 #endif // USE(JSVALUE64)
2234         
2235     case DoubleRepUse: {
2236         GPRTemporary result(this);
2237         SpeculateDoubleOperand op1(this, node->child1());
2238         FPRReg fpr = op1.fpr();
2239         GPRReg gpr = result.gpr();
2240         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
2241         
2242         addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, operationToInt32, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded, gpr, fpr));
2243         
2244         int32Result(gpr, node);
2245         return;
2246     }
2247     
2248     case NumberUse:
2249     case NotCellUse: {
2250         switch (checkGeneratedTypeForToInt32(node->child1().node())) {
2251         case GeneratedOperandInteger: {
2252             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2253             GPRTemporary result(this, Reuse, op1);
2254             m_jit.move(op1.gpr(), result.gpr());
2255             int32Result(result.gpr(), node, op1.format());
2256             return;
2257         }
2258         case GeneratedOperandJSValue: {
2259             GPRTemporary result(this);
2260 #if USE(JSVALUE64)
2261             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2262
2263             GPRReg gpr = op1.gpr();
2264             GPRReg resultGpr = result.gpr();
2265             FPRTemporary tempFpr(this);
2266             FPRReg fpr = tempFpr.fpr();
2267
2268             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
2269             JITCompiler::JumpList converted;
2270
2271             if (node->child1().useKind() == NumberUse) {
2272                 DFG_TYPE_CHECK(
2273                     JSValueRegs(gpr), node->child1(), SpecBytecodeNumber,
2274                     m_jit.branchTest64(
2275                         MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
2276             } else {
2277                 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
2278                 
2279                 DFG_TYPE_CHECK(
2280                     JSValueRegs(gpr), node->child1(), ~SpecCell, m_jit.branchIfCell(JSValueRegs(gpr)));
2281                 
2282                 // It's not a cell: so true turns into 1 and all else turns into 0.
2283                 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
2284                 converted.append(m_jit.jump());
2285                 
2286                 isNumber.link(&m_jit);
2287             }
2288
2289             // First, if we get here we have a double encoded as a JSValue
2290             unboxDouble(gpr, resultGpr, fpr);
2291
2292             silentSpillAllRegisters(resultGpr);
2293             callOperation(operationToInt32, resultGpr, fpr);
2294             silentFillAllRegisters(resultGpr);
2295
2296             converted.append(m_jit.jump());
2297
2298             isInteger.link(&m_jit);
2299             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
2300
2301             converted.link(&m_jit);
2302 #else
2303             Node* childNode = node->child1().node();
2304             VirtualRegister virtualRegister = childNode->virtualRegister();
2305             GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2306
2307             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2308
2309             GPRReg payloadGPR = op1.payloadGPR();
2310             GPRReg resultGpr = result.gpr();
2311         
2312             JITCompiler::JumpList converted;
2313
2314             if (info.registerFormat() == DataFormatJSInt32)
2315                 m_jit.move(payloadGPR, resultGpr);
2316             else {
2317                 GPRReg tagGPR = op1.tagGPR();
2318                 FPRTemporary tempFpr(this);
2319                 FPRReg fpr = tempFpr.fpr();
2320                 FPRTemporary scratch(this);
2321
2322                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
2323
2324                 if (node->child1().useKind() == NumberUse) {
2325                     DFG_TYPE_CHECK(
2326                         op1.jsValueRegs(), node->child1(), SpecBytecodeNumber,
2327                         m_jit.branch32(
2328                             MacroAssembler::AboveOrEqual, tagGPR,
2329                             TrustedImm32(JSValue::LowestTag)));
2330                 } else {
2331                     JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
2332                     
2333                     DFG_TYPE_CHECK(
2334                         op1.jsValueRegs(), node->child1(), ~SpecCell,
2335                         m_jit.branchIfCell(op1.jsValueRegs()));
2336                     
2337                     // It's not a cell: so true turns into 1 and all else turns into 0.
2338                     JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
2339                     m_jit.move(TrustedImm32(0), resultGpr);
2340                     converted.append(m_jit.jump());
2341                     
2342                     isBoolean.link(&m_jit);
2343                     m_jit.move(payloadGPR, resultGpr);
2344                     converted.append(m_jit.jump());
2345                     
2346                     isNumber.link(&m_jit);
2347                 }
2348
2349                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
2350
2351                 silentSpillAllRegisters(resultGpr);
2352                 callOperation(operationToInt32, resultGpr, fpr);
2353                 silentFillAllRegisters(resultGpr);
2354
2355                 converted.append(m_jit.jump());
2356
2357                 isInteger.link(&m_jit);
2358                 m_jit.move(payloadGPR, resultGpr);
2359
2360                 converted.link(&m_jit);
2361             }
2362 #endif
2363             int32Result(resultGpr, node);
2364             return;
2365         }
2366         case GeneratedOperandTypeUnknown:
2367             RELEASE_ASSERT(!m_compileOkay);
2368             return;
2369         }
2370         RELEASE_ASSERT_NOT_REACHED();
2371         return;
2372     }
2373     
2374     default:
2375         ASSERT(!m_compileOkay);
2376         return;
2377     }
2378 }
2379
2380 void SpeculativeJIT::compileUInt32ToNumber(Node* node)
2381 {
2382     if (doesOverflow(node->arithMode())) {
2383         if (enableInt52()) {
2384             SpeculateInt32Operand op1(this, node->child1());
2385             GPRTemporary result(this, Reuse, op1);
2386             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2387             strictInt52Result(result.gpr(), node);
2388             return;
2389         }
2390         SpeculateInt32Operand op1(this, node->child1());
2391         FPRTemporary result(this);
2392             
2393         GPRReg inputGPR = op1.gpr();
2394         FPRReg outputFPR = result.fpr();
2395             
2396         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2397             
2398         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2399         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
2400         positive.link(&m_jit);
2401             
2402         doubleResult(outputFPR, node);
2403         return;
2404     }
2405     
2406     RELEASE_ASSERT(node->arithMode() == Arith::CheckOverflow);
2407
2408     SpeculateInt32Operand op1(this, node->child1());
2409     GPRTemporary result(this);
2410
2411     m_jit.move(op1.gpr(), result.gpr());
2412
2413     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)));
2414
2415     int32Result(result.gpr(), node, op1.format());
2416 }
2417
2418 void SpeculativeJIT::compileDoubleAsInt32(Node* node)
2419 {
2420     SpeculateDoubleOperand op1(this, node->child1());
2421     FPRTemporary scratch(this);
2422     GPRTemporary result(this);
2423     
2424     FPRReg valueFPR = op1.fpr();
2425     FPRReg scratchFPR = scratch.fpr();
2426     GPRReg resultGPR = result.gpr();
2427
2428     JITCompiler::JumpList failureCases;
2429     RELEASE_ASSERT(shouldCheckOverflow(node->arithMode()));
2430     m_jit.branchConvertDoubleToInt32(
2431         valueFPR, resultGPR, failureCases, scratchFPR,
2432         shouldCheckNegativeZero(node->arithMode()));
2433     speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
2434
2435     int32Result(resultGPR, node);
2436 }
2437
2438 void SpeculativeJIT::compileDoubleRep(Node* node)
2439 {
2440     switch (node->child1().useKind()) {
2441     case RealNumberUse: {
2442         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2443         FPRTemporary result(this);
2444         
2445         JSValueRegs op1Regs = op1.jsValueRegs();
2446         FPRReg resultFPR = result.fpr();
2447         
2448 #if USE(JSVALUE64)
2449         GPRTemporary temp(this);
2450         GPRReg tempGPR = temp.gpr();
2451         m_jit.unboxDoubleWithoutAssertions(op1Regs.gpr(), tempGPR, resultFPR);
2452 #else
2453         FPRTemporary temp(this);
2454         FPRReg tempFPR = temp.fpr();
2455         unboxDouble(op1Regs.tagGPR(), op1Regs.payloadGPR(), resultFPR, tempFPR);
2456 #endif
2457         
2458         JITCompiler::Jump done = m_jit.branchDouble(
2459             JITCompiler::DoubleEqual, resultFPR, resultFPR);
2460         
2461         DFG_TYPE_CHECK(
2462             op1Regs, node->child1(), SpecBytecodeRealNumber, m_jit.branchIfNotInt32(op1Regs));
2463         m_jit.convertInt32ToDouble(op1Regs.payloadGPR(), resultFPR);
2464         
2465         done.link(&m_jit);
2466         
2467         doubleResult(resultFPR, node);
2468         return;
2469     }
2470     
2471     case NotCellUse:
2472     case NumberUse: {
2473         ASSERT(!node->child1()->isNumberConstant()); // This should have been constant folded.
2474
2475         SpeculatedType possibleTypes = m_state.forNode(node->child1()).m_type;
2476         if (isInt32Speculation(possibleTypes)) {
2477             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2478             FPRTemporary result(this);
2479             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
2480             doubleResult(result.fpr(), node);
2481             return;
2482         }
2483
2484         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2485         FPRTemporary result(this);
2486
2487 #if USE(JSVALUE64)
2488         GPRTemporary temp(this);
2489
2490         GPRReg op1GPR = op1.gpr();
2491         GPRReg tempGPR = temp.gpr();
2492         FPRReg resultFPR = result.fpr();
2493         JITCompiler::JumpList done;
2494
2495         JITCompiler::Jump isInteger = m_jit.branch64(
2496             MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
2497
2498         if (node->child1().useKind() == NotCellUse) {
2499             JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagTypeNumberRegister);
2500             JITCompiler::Jump isUndefined = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueUndefined));
2501
2502             static const double zero = 0;
2503             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
2504
2505             JITCompiler::Jump isNull = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueNull));
2506             done.append(isNull);
2507
2508             DFG_TYPE_CHECK(JSValueRegs(op1GPR), node->child1(), ~SpecCell,
2509                 m_jit.branchTest64(JITCompiler::Zero, op1GPR, TrustedImm32(static_cast<int32_t>(TagBitBool))));
2510
2511             JITCompiler::Jump isFalse = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueFalse));
2512             static const double one = 1;
2513             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
2514             done.append(m_jit.jump());
2515             done.append(isFalse);
2516
2517             isUndefined.link(&m_jit);
2518             static const double NaN = PNaN;
2519             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
2520             done.append(m_jit.jump());
2521
2522             isNumber.link(&m_jit);
2523         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2524             typeCheck(
2525                 JSValueRegs(op1GPR), node->child1(), SpecBytecodeNumber,
2526                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
2527         }
2528
2529         unboxDouble(op1GPR, tempGPR, resultFPR);
2530         done.append(m_jit.jump());
2531     
2532         isInteger.link(&m_jit);
2533         m_jit.convertInt32ToDouble(op1GPR, resultFPR);
2534         done.link(&m_jit);
2535 #else // USE(JSVALUE64) -> this is the 32_64 case
2536         FPRTemporary temp(this);
2537     
2538         GPRReg op1TagGPR = op1.tagGPR();
2539         GPRReg op1PayloadGPR = op1.payloadGPR();
2540         FPRReg tempFPR = temp.fpr();
2541         FPRReg resultFPR = result.fpr();
2542         JITCompiler::JumpList done;
2543     
2544         JITCompiler::Jump isInteger = m_jit.branch32(
2545             MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
2546
2547         if (node->child1().useKind() == NotCellUse) {
2548             JITCompiler::Jump isNumber = m_jit.branch32(JITCompiler::Below, op1TagGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
2549             JITCompiler::Jump isUndefined = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::UndefinedTag));
2550
2551             static const double zero = 0;
2552             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
2553
2554             JITCompiler::Jump isNull = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::NullTag));
2555             done.append(isNull);
2556
2557             DFG_TYPE_CHECK(JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), ~SpecCell, m_jit.branch32(JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::BooleanTag)));
2558
2559             JITCompiler::Jump isFalse = m_jit.branchTest32(JITCompiler::Zero, op1PayloadGPR, TrustedImm32(1));
2560             static const double one = 1;
2561             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
2562             done.append(m_jit.jump());
2563             done.append(isFalse);
2564
2565             isUndefined.link(&m_jit);
2566             static const double NaN = PNaN;
2567             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
2568             done.append(m_jit.jump());
2569
2570             isNumber.link(&m_jit);
2571         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2572             typeCheck(
2573                 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecBytecodeNumber,
2574                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
2575         }
2576
2577         unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
2578         done.append(m_jit.jump());
2579     
2580         isInteger.link(&m_jit);
2581         m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
2582         done.link(&m_jit);
2583 #endif // USE(JSVALUE64)
2584     
2585         doubleResult(resultFPR, node);
2586         return;
2587     }
2588         
2589 #if USE(JSVALUE64)
2590     case Int52RepUse: {
2591         SpeculateStrictInt52Operand value(this, node->child1());
2592         FPRTemporary result(this);
2593         
2594         GPRReg valueGPR = value.gpr();
2595         FPRReg resultFPR = result.fpr();
2596
2597         m_jit.convertInt64ToDouble(valueGPR, resultFPR);
2598         
2599         doubleResult(resultFPR, node);
2600         return;
2601     }
2602 #endif // USE(JSVALUE64)
2603         
2604     default:
2605         RELEASE_ASSERT_NOT_REACHED();
2606         return;
2607     }
2608 }
2609
2610 void SpeculativeJIT::compileValueRep(Node* node)
2611 {
2612     switch (node->child1().useKind()) {
2613     case DoubleRepUse: {
2614         SpeculateDoubleOperand value(this, node->child1());
2615         JSValueRegsTemporary result(this);
2616         
2617         FPRReg valueFPR = value.fpr();
2618         JSValueRegs resultRegs = result.regs();
2619         
2620         // It's very tempting to in-place filter the value to indicate that it's not impure NaN
2621         // anymore. Unfortunately, this would be unsound. If it's a GetLocal or if the value was
2622         // subject to a prior SetLocal, filtering the value would imply that the corresponding
2623         // local was purified.
2624         if (needsTypeCheck(node->child1(), ~SpecDoubleImpureNaN))
2625             m_jit.purifyNaN(valueFPR);
2626
2627         boxDouble(valueFPR, resultRegs);
2628         
2629         jsValueResult(resultRegs, node);
2630         return;
2631     }
2632         
2633 #if USE(JSVALUE64)
2634     case Int52RepUse: {
2635         SpeculateStrictInt52Operand value(this, node->child1());
2636         GPRTemporary result(this);
2637         
2638         GPRReg valueGPR = value.gpr();
2639         GPRReg resultGPR = result.gpr();
2640         
2641         boxInt52(valueGPR, resultGPR, DataFormatStrictInt52);
2642         
2643         jsValueResult(resultGPR, node);
2644         return;
2645     }
2646 #endif // USE(JSVALUE64)
2647         
2648     default:
2649         RELEASE_ASSERT_NOT_REACHED();
2650         return;
2651     }
2652 }
2653
2654 static double clampDoubleToByte(double d)
2655 {
2656     d += 0.5;
2657     if (!(d > 0))
2658         d = 0;
2659     else if (d > 255)
2660         d = 255;
2661     return d;
2662 }
2663
2664 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
2665 {
2666     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
2667     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
2668     jit.xorPtr(result, result);
2669     MacroAssembler::Jump clamped = jit.jump();
2670     tooBig.link(&jit);
2671     jit.move(JITCompiler::TrustedImm32(255), result);
2672     clamped.link(&jit);
2673     inBounds.link(&jit);
2674 }
2675
2676 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
2677 {
2678     // Unordered compare so we pick up NaN
2679     static const double zero = 0;
2680     static const double byteMax = 255;
2681     static const double half = 0.5;
2682     jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), scratch);
2683     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
2684     jit.loadDouble(MacroAssembler::TrustedImmPtr(&byteMax), scratch);
2685     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
2686     
2687     jit.loadDouble(MacroAssembler::TrustedImmPtr(&half), scratch);
2688     // FIXME: This should probably just use a floating point round!
2689     // https://bugs.webkit.org/show_bug.cgi?id=72054
2690     jit.addDouble(source, scratch);
2691     jit.truncateDoubleToInt32(scratch, result);   
2692     MacroAssembler::Jump truncatedInt = jit.jump();
2693     
2694     tooSmall.link(&jit);
2695     jit.xorPtr(result, result);
2696     MacroAssembler::Jump zeroed = jit.jump();
2697     
2698     tooBig.link(&jit);
2699     jit.move(JITCompiler::TrustedImm32(255), result);
2700     
2701     truncatedInt.link(&jit);
2702     zeroed.link(&jit);
2703
2704 }
2705
2706 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2707 {
2708     if (node->op() == PutByValAlias)
2709         return JITCompiler::Jump();
2710     JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(
2711         m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode());
2712     if (view) {
2713         uint32_t length = view->length();
2714         Node* indexNode = m_jit.graph().child(node, 1).node();
2715         if (indexNode->isInt32Constant() && indexNode->asUInt32() < length)
2716             return JITCompiler::Jump();
2717         return m_jit.branch32(
2718             MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length));
2719     }
2720     return m_jit.branch32(
2721         MacroAssembler::AboveOrEqual, indexGPR,
2722         MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
2723 }
2724
2725 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2726 {
2727     JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR);
2728     if (!jump.isSet())
2729         return;
2730     speculationCheck(OutOfBounds, JSValueRegs(), 0, jump);
2731 }
2732
2733 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds(Node* node, GPRReg base, JITCompiler::Jump outOfBounds)
2734 {
2735     JITCompiler::Jump done;
2736     if (outOfBounds.isSet()) {
2737         done = m_jit.jump();
2738         if (node->arrayMode().isInBounds())
2739             speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
2740         else {
2741             outOfBounds.link(&m_jit);
2742
2743             JITCompiler::Jump notWasteful = m_jit.branch32(
2744                 MacroAssembler::NotEqual,
2745                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfMode()),
2746                 TrustedImm32(WastefulTypedArray));
2747
2748             JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
2749                 MacroAssembler::Zero,
2750                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
2751             speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
2752             notWasteful.link(&m_jit);
2753         }
2754     }
2755     return done;
2756 }
2757
2758 void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type)
2759 {
2760     ASSERT(isInt(type));
2761     
2762     SpeculateCellOperand base(this, node->child1());
2763     SpeculateStrictInt32Operand property(this, node->child2());
2764     StorageOperand storage(this, node->child3());
2765
2766     GPRReg baseReg = base.gpr();
2767     GPRReg propertyReg = property.gpr();
2768     GPRReg storageReg = storage.gpr();
2769
2770     GPRTemporary result(this);
2771     GPRReg resultReg = result.gpr();
2772
2773     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2774
2775     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
2776     switch (elementSize(type)) {
2777     case 1:
2778         if (isSigned(type))
2779             m_jit.load8SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2780         else
2781             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2782         break;
2783     case 2:
2784         if (isSigned(type))
2785             m_jit.load16SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2786         else
2787             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2788         break;
2789     case 4:
2790         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2791         break;
2792     default:
2793         CRASH();
2794     }
2795     if (elementSize(type) < 4 || isSigned(type)) {
2796         int32Result(resultReg, node);
2797         return;
2798     }
2799     
2800     ASSERT(elementSize(type) == 4 && !isSigned(type));
2801     if (node->shouldSpeculateInt32()) {
2802         speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)));
2803         int32Result(resultReg, node);
2804         return;
2805     }
2806     
2807 #if USE(JSVALUE64)
2808     if (node->shouldSpeculateAnyInt()) {
2809         m_jit.zeroExtend32ToPtr(resultReg, resultReg);
2810         strictInt52Result(resultReg, node);
2811         return;
2812     }
2813 #endif
2814     
2815     FPRTemporary fresult(this);
2816     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
2817     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
2818     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
2819     positive.link(&m_jit);
2820     doubleResult(fresult.fpr(), node);
2821 }
2822
2823 void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
2824 {
2825     ASSERT(isInt(type));
2826     
2827     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2828     GPRReg storageReg = storage.gpr();
2829     
2830     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2831     
2832     GPRTemporary value;
2833 #if USE(JSVALUE32_64)
2834     GPRTemporary propertyTag;
2835     GPRTemporary valueTag;
2836 #endif
2837
2838     GPRReg valueGPR = InvalidGPRReg;
2839 #if USE(JSVALUE32_64)
2840     GPRReg propertyTagGPR = InvalidGPRReg;
2841     GPRReg valueTagGPR = InvalidGPRReg;
2842 #endif
2843
2844     JITCompiler::JumpList slowPathCases;
2845
2846     if (valueUse->isConstant()) {
2847         JSValue jsValue = valueUse->asJSValue();
2848         if (!jsValue.isNumber()) {
2849             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2850             noResult(node);
2851             return;
2852         }
2853         double d = jsValue.asNumber();
2854         if (isClamped(type)) {
2855             ASSERT(elementSize(type) == 1);
2856             d = clampDoubleToByte(d);
2857         }
2858         GPRTemporary scratch(this);
2859         GPRReg scratchReg = scratch.gpr();
2860         m_jit.move(Imm32(toInt32(d)), scratchReg);
2861         value.adopt(scratch);
2862         valueGPR = scratchReg;
2863     } else {
2864         switch (valueUse.useKind()) {
2865         case Int32Use: {
2866             SpeculateInt32Operand valueOp(this, valueUse);
2867             GPRTemporary scratch(this);
2868             GPRReg scratchReg = scratch.gpr();
2869             m_jit.move(valueOp.gpr(), scratchReg);
2870             if (isClamped(type)) {
2871                 ASSERT(elementSize(type) == 1);
2872                 compileClampIntegerToByte(m_jit, scratchReg);
2873             }
2874             value.adopt(scratch);
2875             valueGPR = scratchReg;
2876             break;
2877         }
2878             
2879 #if USE(JSVALUE64)
2880         case Int52RepUse: {
2881             SpeculateStrictInt52Operand valueOp(this, valueUse);
2882             GPRTemporary scratch(this);
2883             GPRReg scratchReg = scratch.gpr();
2884             m_jit.move(valueOp.gpr(), scratchReg);
2885             if (isClamped(type)) {
2886                 ASSERT(elementSize(type) == 1);
2887                 MacroAssembler::Jump inBounds = m_jit.branch64(
2888                     MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff));
2889                 MacroAssembler::Jump tooBig = m_jit.branch64(
2890                     MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff));
2891                 m_jit.move(TrustedImm32(0), scratchReg);
2892                 MacroAssembler::Jump clamped = m_jit.jump();
2893                 tooBig.link(&m_jit);
2894                 m_jit.move(JITCompiler::TrustedImm32(255), scratchReg);
2895                 clamped.link(&m_jit);
2896                 inBounds.link(&m_jit);
2897             }
2898             value.adopt(scratch);
2899             valueGPR = scratchReg;
2900             break;
2901         }
2902 #endif // USE(JSVALUE64)
2903             
2904         case DoubleRepUse: {
2905             if (isClamped(type)) {
2906                 ASSERT(elementSize(type) == 1);
2907                 SpeculateDoubleOperand valueOp(this, valueUse);
2908                 GPRTemporary result(this);
2909                 FPRTemporary floatScratch(this);
2910                 FPRReg fpr = valueOp.fpr();
2911                 GPRReg gpr = result.gpr();
2912                 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
2913                 value.adopt(result);
2914                 valueGPR = gpr;
2915             } else {
2916 #if USE(JSVALUE32_64)
2917                 GPRTemporary realPropertyTag(this);
2918                 propertyTag.adopt(realPropertyTag);
2919                 propertyTagGPR = propertyTag.gpr();
2920
2921                 GPRTemporary realValueTag(this);
2922                 valueTag.adopt(realValueTag);
2923                 valueTagGPR = valueTag.gpr();
2924 #endif
2925                 SpeculateDoubleOperand valueOp(this, valueUse);
2926                 GPRTemporary result(this);
2927                 FPRReg fpr = valueOp.fpr();
2928                 GPRReg gpr = result.gpr();
2929                 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
2930                 m_jit.xorPtr(gpr, gpr);
2931                 MacroAssembler::JumpList fixed(m_jit.jump());
2932                 notNaN.link(&m_jit);
2933
2934                 fixed.append(m_jit.branchTruncateDoubleToInt32(
2935                     fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful));
2936
2937 #if USE(JSVALUE64)
2938                 m_jit.or64(GPRInfo::tagTypeNumberRegister, property);
2939                 boxDouble(fpr, gpr);
2940 #else
2941                 m_jit.move(TrustedImm32(JSValue::Int32Tag), propertyTagGPR);
2942                 boxDouble(fpr, valueTagGPR, gpr);
2943 #endif
2944                 slowPathCases.append(m_jit.jump());
2945
2946                 fixed.link(&m_jit);
2947                 value.adopt(result);
2948                 valueGPR = gpr;
2949             }
2950             break;
2951         }
2952             
2953         default:
2954             RELEASE_ASSERT_NOT_REACHED();
2955             break;
2956         }
2957     }
2958     
2959     ASSERT_UNUSED(valueGPR, valueGPR != property);
2960     ASSERT(valueGPR != base);
2961     ASSERT(valueGPR != storageReg);
2962     JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
2963
2964     switch (elementSize(type)) {
2965     case 1:
2966         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
2967         break;
2968     case 2:
2969         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
2970         break;
2971     case 4:
2972         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2973         break;
2974     default:
2975         CRASH();
2976     }
2977
2978     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
2979     if (done.isSet())
2980         done.link(&m_jit);
2981
2982     if (!slowPathCases.empty()) {
2983 #if USE(JSVALUE64)
2984         if (node->op() == PutByValDirect) {
2985             addSlowPathGenerator(slowPathCall(
2986                 slowPathCases, this,
2987                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict,
2988                 NoResult, base, property, valueGPR));
2989         } else {
2990             addSlowPathGenerator(slowPathCall(
2991                 slowPathCases, this,
2992                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict,
2993                 NoResult, base, property, valueGPR));
2994         }
2995 #else // not USE(JSVALUE64)
2996         if (node->op() == PutByValDirect) {
2997             addSlowPathGenerator(slowPathCall(
2998                 slowPathCases, this,
2999                 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict,
3000                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
3001         } else {
3002             addSlowPathGenerator(slowPathCall(
3003                 slowPathCases, this,
3004                 m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict,
3005                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
3006         }
3007 #endif
3008     }
3009     noResult(node);
3010 }
3011
3012 void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type)
3013 {
3014     ASSERT(isFloat(type));
3015     
3016     SpeculateCellOperand base(this, node->child1());
3017     SpeculateStrictInt32Operand property(this, node->child2());
3018     StorageOperand storage(this, node->child3());
3019
3020     GPRReg baseReg = base.gpr();
3021     GPRReg propertyReg = property.gpr();
3022     GPRReg storageReg = storage.gpr();
3023
3024     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
3025
3026     FPRTemporary result(this);
3027     FPRReg resultReg = result.fpr();
3028     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
3029     switch (elementSize(type)) {
3030     case 4:
3031         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
3032         m_jit.convertFloatToDouble(resultReg, resultReg);
3033         break;
3034     case 8: {
3035         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
3036         break;
3037     }
3038     default:
3039         RELEASE_ASSERT_NOT_REACHED();
3040     }
3041     
3042     doubleResult(resultReg, node);
3043 }
3044
3045 void SpeculativeJIT::compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
3046 {
3047     ASSERT(isFloat(type));
3048     
3049     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
3050     GPRReg storageReg = storage.gpr();
3051     
3052     Edge baseUse = m_jit.graph().varArgChild(node, 0);
3053     Edge valueUse = m_jit.graph().varArgChild(node, 2);
3054
3055     SpeculateDoubleOperand valueOp(this, valueUse);
3056     FPRTemporary scratch(this);
3057     FPRReg valueFPR = valueOp.fpr();
3058     FPRReg scratchFPR = scratch.fpr();
3059
3060     ASSERT_UNUSED(baseUse, node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(baseUse)));
3061     
3062     MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
3063     
3064     switch (elementSize(type)) {
3065     case 4: {
3066         m_jit.moveDouble(valueFPR, scratchFPR);
3067         m_jit.convertDoubleToFloat(valueFPR, scratchFPR);
3068         m_jit.storeFloat(scratchFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
3069         break;
3070     }
3071     case 8:
3072         m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
3073         break;
3074     default:
3075         RELEASE_ASSERT_NOT_REACHED();
3076     }
3077
3078     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
3079     if (done.isSet())
3080         done.link(&m_jit);
3081     noResult(node);
3082 }
3083
3084 void SpeculativeJIT::compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg, GPRReg scratch2Reg)
3085 {
3086     // Check that prototype is an object.
3087     speculationCheck(BadType, JSValueRegs(), 0, m_jit.branchIfNotObject(prototypeReg));
3088     
3089     // Initialize scratchReg with the value being checked.
3090     m_jit.move(valueReg, scratchReg);
3091     
3092     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
3093     MacroAssembler::Label loop(&m_jit);
3094     MacroAssembler::Jump performDefaultHasInstance = m_jit.branch8(MacroAssembler::Equal,
3095         MacroAssembler::Address(scratchReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ProxyObjectType));
3096     m_jit.emitLoadStructure(scratchReg, scratchReg, scratch2Reg);
3097     m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + CellPayloadOffset), scratchReg);
3098     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
3099 #if USE(JSVALUE64)
3100     m_jit.branchIfCell(JSValueRegs(scratchReg)).linkTo(loop, &m_jit);
3101 #else
3102     m_jit.branchTestPtr(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
3103 #endif
3104     
3105     // No match - result is false.
3106 #if USE(JSVALUE64)
3107     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
3108 #else
3109     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
3110 #endif
3111     MacroAssembler::JumpList doneJumps; 
3112     doneJumps.append(m_jit.jump());
3113
3114     performDefaultHasInstance.link(&m_jit);
3115     silentSpillAllRegisters(scratchReg);
3116     callOperation(operationDefaultHasInstance, scratchReg, valueReg, prototypeReg); 
3117     silentFillAllRegisters(scratchReg);
3118     m_jit.exceptionCheck();
3119 #if USE(JSVALUE64)
3120     m_jit.or32(TrustedImm32(ValueFalse), scratchReg);
3121 #endif
3122     doneJumps.append(m_jit.jump());
3123     
3124     isInstance.link(&m_jit);
3125 #if USE(JSVALUE64)
3126     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), scratchReg);
3127 #else
3128     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
3129 #endif
3130     
3131     doneJumps.link(&m_jit);
3132 }
3133
3134 void SpeculativeJIT::compileCheckTypeInfoFlags(Node* node)
3135 {
3136     SpeculateCellOperand base(this, node->child1());
3137
3138     GPRReg baseGPR = base.gpr();
3139
3140     speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
3141
3142     noResult(node);
3143 }
3144
3145 void SpeculativeJIT::compileInstanceOf(Node* node)
3146 {
3147     if (node->child1().useKind() == UntypedUse) {
3148         // It might not be a cell. Speculate less aggressively.
3149         // Or: it might only be used once (i.e. by us), so we get zero benefit
3150         // from speculating any more aggressively than we absolutely need to.
3151         
3152         JSValueOperand value(this, node->child1());
3153         SpeculateCellOperand prototype(this, node->child2());
3154         GPRTemporary scratch(this);
3155         GPRTemporary scratch2(this);
3156         
3157         GPRReg prototypeReg = prototype.gpr();
3158         GPRReg scratchReg = scratch.gpr();
3159         GPRReg scratch2Reg = scratch2.gpr();
3160         
3161         MacroAssembler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3162         GPRReg valueReg = value.jsValueRegs().payloadGPR();
3163         moveFalseTo(scratchReg);
3164
3165         MacroAssembler::Jump done = m_jit.jump();
3166         
3167         isCell.link(&m_jit);
3168         
3169         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg);
3170         
3171         done.link(&m_jit);
3172
3173         blessedBooleanResult(scratchReg, node);
3174         return;
3175     }
3176     
3177     SpeculateCellOperand value(this, node->child1());
3178     SpeculateCellOperand prototype(this, node->child2());
3179     
3180     GPRTemporary scratch(this);
3181     GPRTemporary scratch2(this);
3182     
3183     GPRReg valueReg = value.gpr();
3184     GPRReg prototypeReg = prototype.gpr();
3185     GPRReg scratchReg = scratch.gpr();
3186     GPRReg scratch2Reg = scratch2.gpr();
3187     
3188     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg);
3189
3190     blessedBooleanResult(scratchReg, node);
3191 }
3192
3193 template<typename SnippetGenerator, J_JITOperation_EJJ snippetSlowPathFunction>
3194 void SpeculativeJIT::emitUntypedBitOp(Node* node)
3195 {
3196     Edge& leftChild = node->child1();
3197     Edge& rightChild = node->child2();
3198
3199     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3200         JSValueOperand left(this, leftChild);
3201         JSValueOperand right(this, rightChild);
3202         JSValueRegs leftRegs = left.jsValueRegs();
3203         JSValueRegs rightRegs = right.jsValueRegs();
3204 #if USE(JSVALUE64)
3205         GPRTemporary result(this);
3206         JSValueRegs resultRegs = JSValueRegs(result.gpr());
3207 #else
3208         GPRTemporary resultTag(this);
3209         GPRTemporary resultPayload(this);
3210         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3211 #endif
3212         flushRegisters();
3213         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3214         m_jit.exceptionCheck();
3215
3216         jsValueResult(resultRegs, node);
3217         return;
3218     }
3219
3220     Optional<JSValueOperand> left;
3221     Optional<JSValueOperand> right;
3222
3223     JSValueRegs leftRegs;
3224     JSValueRegs rightRegs;
3225
3226 #if USE(JSVALUE64)
3227     GPRTemporary result(this);
3228     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3229     GPRTemporary scratch(this);
3230     GPRReg scratchGPR = scratch.gpr();
3231 #else
3232     GPRTemporary resultTag(this);
3233     GPRTemporary resultPayload(this);
3234     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3235     GPRReg scratchGPR = resultTag.gpr();
3236 #endif
3237
3238     SnippetOperand leftOperand;
3239     SnippetOperand rightOperand;
3240
3241     // The snippet generator does not support both operands being constant. If the left
3242     // operand is already const, we'll ignore the right operand's constness.
3243     if (leftChild->isInt32Constant())
3244         leftOperand.setConstInt32(leftChild->asInt32());
3245     else if (rightChild->isInt32Constant())
3246         rightOperand.setConstInt32(rightChild->asInt32());
3247
3248     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3249
3250     if (!leftOperand.isConst()) {
3251         left = JSValueOperand(this, leftChild);
3252         leftRegs = left->jsValueRegs();
3253     }
3254     if (!rightOperand.isConst()) {
3255         right = JSValueOperand(this, rightChild);
3256         rightRegs = right->jsValueRegs();
3257     }
3258
3259     SnippetGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, scratchGPR);
3260     gen.generateFastPath(m_jit);
3261
3262     ASSERT(gen.didEmitFastPath());
3263     gen.endJumpList().append(m_jit.jump());
3264
3265     gen.slowPathJumpList().link(&m_jit);
3266     silentSpillAllRegisters(resultRegs);
3267
3268     if (leftOperand.isConst()) {
3269         leftRegs = resultRegs;
3270         m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3271     } else if (rightOperand.isConst()) {
3272         rightRegs = resultRegs;
3273         m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3274     }
3275
3276     callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3277
3278     silentFillAllRegisters(resultRegs);
3279     m_jit.exceptionCheck();
3280
3281     gen.endJumpList().link(&m_jit);
3282     jsValueResult(resultRegs, node);
3283 }
3284
3285 void SpeculativeJIT::compileBitwiseOp(Node* node)
3286 {
3287     NodeType op = node->op();
3288     Edge& leftChild = node->child1();
3289     Edge& rightChild = node->child2();
3290
3291     if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
3292         switch (op) {
3293         case BitAnd:
3294             emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
3295             return;
3296         case BitOr:
3297             emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
3298             return;
3299         case BitXor:
3300             emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
3301             return;
3302         default:
3303             RELEASE_ASSERT_NOT_REACHED();
3304         }
3305     }
3306
3307     if (leftChild->isInt32Constant()) {
3308         SpeculateInt32Operand op2(this, rightChild);
3309         GPRTemporary result(this, Reuse, op2);
3310
3311         bitOp(op, leftChild->asInt32(), op2.gpr(), result.gpr());
3312
3313         int32Result(result.gpr(), node);
3314
3315     } else if (rightChild->isInt32Constant()) {
3316         SpeculateInt32Operand op1(this, leftChild);
3317         GPRTemporary result(this, Reuse, op1);
3318
3319         bitOp(op, rightChild->asInt32(), op1.gpr(), result.gpr());
3320
3321         int32Result(result.gpr(), node);
3322
3323     } else {
3324         SpeculateInt32Operand op1(this, leftChild);
3325         SpeculateInt32Operand op2(this, rightChild);
3326         GPRTemporary result(this, Reuse, op1, op2);
3327         
3328         GPRReg reg1 = op1.gpr();
3329         GPRReg reg2 = op2.gpr();
3330         bitOp(op, reg1, reg2, result.gpr());
3331         
3332         int32Result(result.gpr(), node);
3333     }
3334 }
3335
3336 void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
3337 {
3338     J_JITOperation_EJJ snippetSlowPathFunction = node->op() == BitRShift
3339         ? operationValueBitRShift : operationValueBitURShift;
3340     JITRightShiftGenerator::ShiftType shiftType = node->op() == BitRShift
3341         ? JITRightShiftGenerator::SignedShift : JITRightShiftGenerator::UnsignedShift;
3342
3343     Edge& leftChild = node->child1();
3344     Edge& rightChild = node->child2();
3345
3346     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3347         JSValueOperand left(this, leftChild);
3348         JSValueOperand right(this, rightChild);
3349         JSValueRegs leftRegs = left.jsValueRegs();
3350         JSValueRegs rightRegs = right.jsValueRegs();
3351 #if USE(JSVALUE64)
3352         GPRTemporary result(this);
3353         JSValueRegs resultRegs = JSValueRegs(result.gpr());
3354 #else
3355         GPRTemporary resultTag(this);
3356         GPRTemporary resultPayload(this);
3357         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3358 #endif
3359         flushRegisters();
3360         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3361         m_jit.exceptionCheck();
3362
3363         jsValueResult(resultRegs, node);
3364         return;
3365     }
3366
3367     Optional<JSValueOperand> left;
3368     Optional<JSValueOperand> right;
3369
3370     JSValueRegs leftRegs;
3371     JSValueRegs rightRegs;
3372
3373     FPRTemporary leftNumber(this);
3374     FPRReg leftFPR = leftNumber.fpr();
3375
3376 #if USE(JSVALUE64)
3377     GPRTemporary result(this);
3378     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3379     GPRTemporary scratch(this);
3380     GPRReg scratchGPR = scratch.gpr();
3381     FPRReg scratchFPR = InvalidFPRReg;
3382 #else
3383     GPRTemporary resultTag(this);
3384     GPRTemporary resultPayload(this);
3385     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3386     GPRReg scratchGPR = resultTag.gpr();
3387     FPRTemporary fprScratch(this);
3388     FPRReg scratchFPR = fprScratch.fpr();
3389 #endif
3390
3391     SnippetOperand leftOperand;
3392     SnippetOperand rightOperand;
3393
3394     // The snippet generator does not support both operands being constant. If the left
3395     // operand is already const, we'll ignore the right operand's constness.
3396     if (leftChild->isInt32Constant())
3397         leftOperand.setConstInt32(leftChild->asInt32());
3398     else if (rightChild->isInt32Constant())
3399         rightOperand.setConstInt32(rightChild->asInt32());
3400
3401     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3402
3403     if (!leftOperand.isConst()) {
3404         left = JSValueOperand(this, leftChild);
3405         leftRegs = left->jsValueRegs();
3406     }
3407     if (!rightOperand.isConst()) {
3408         right = JSValueOperand(this, rightChild);
3409         rightRegs = right->jsValueRegs();
3410     }
3411
3412     JITRightShiftGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
3413         leftFPR, scratchGPR, scratchFPR, shiftType);
3414     gen.generateFastPath(m_jit);
3415
3416     ASSERT(gen.didE