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