Enable concurrent GC on ARM64
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "BinarySwitch.h"
32 #include "DFGAbstractInterpreterInlines.h"
33 #include "DFGArrayifySlowPathGenerator.h"
34 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
35 #include "DFGCallCreateDirectArgumentsSlowPathGenerator.h"
36 #include "DFGCapabilities.h"
37 #include "DFGDOMJITPatchpointParams.h"
38 #include "DFGMayExit.h"
39 #include "DFGOSRExitFuzz.h"
40 #include "DFGSaneStringGetByValSlowPathGenerator.h"
41 #include "DFGSlowPathGenerator.h"
42 #include "DOMJITPatchpoint.h"
43 #include "DirectArguments.h"
44 #include "JITAddGenerator.h"
45 #include "JITBitAndGenerator.h"
46 #include "JITBitOrGenerator.h"
47 #include "JITBitXorGenerator.h"
48 #include "JITDivGenerator.h"
49 #include "JITLeftShiftGenerator.h"
50 #include "JITMulGenerator.h"
51 #include "JITRightShiftGenerator.h"
52 #include "JITSubGenerator.h"
53 #include "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 "WriteBarrierBuffer.h"
64 #include <wtf/BitVector.h>
65 #include <wtf/Box.h>
66 #include <wtf/MathExtras.h>
67
68 namespace JSC { namespace DFG {
69
70 SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
71     : m_compileOkay(true)
72     , m_jit(jit)
73     , m_currentNode(0)
74     , m_lastGeneratedNode(LastNodeType)
75     , m_indexInBlock(0)
76     , m_generationInfo(m_jit.graph().frameRegisterCount())
77     , m_state(m_jit.graph())
78     , m_interpreter(m_jit.graph(), m_state)
79     , m_stream(&jit.jitCode()->variableEventStream)
80     , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
81 {
82 }
83
84 SpeculativeJIT::~SpeculativeJIT()
85 {
86 }
87
88 void SpeculativeJIT::emitAllocateRawObject(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements, unsigned vectorLength)
89 {
90     IndexingType indexingType = structure->indexingType();
91     bool hasIndexingHeader = hasIndexedProperties(indexingType);
92
93     unsigned inlineCapacity = structure->inlineCapacity();
94     unsigned outOfLineCapacity = structure->outOfLineCapacity();
95     
96     GPRTemporary scratch(this);
97     GPRTemporary scratch2(this);
98     GPRReg scratchGPR = scratch.gpr();
99     GPRReg scratch2GPR = scratch2.gpr();
100
101     ASSERT(vectorLength >= numElements);
102     vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLength);
103     
104     JITCompiler::JumpList slowCases;
105
106     size_t size = 0;
107     if (hasIndexingHeader)
108         size += vectorLength * sizeof(JSValue) + sizeof(IndexingHeader);
109     size += outOfLineCapacity * sizeof(JSValue);
110
111     m_jit.move(TrustedImmPtr(0), storageGPR);
112     
113     if (size) {
114         if (MarkedAllocator* allocator = m_jit.vm()->heap.allocatorForAuxiliaryData(size)) {
115             m_jit.move(TrustedImmPtr(allocator), scratchGPR);
116             m_jit.emitAllocate(storageGPR, allocator, scratchGPR, scratch2GPR, slowCases);
117             
118             m_jit.addPtr(
119                 TrustedImm32(outOfLineCapacity * sizeof(JSValue) + sizeof(IndexingHeader)),
120                 storageGPR);
121             
122             if (hasIndexingHeader)
123                 m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
124         } else
125             slowCases.append(m_jit.jump());
126     }
127
128     size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
129     MarkedAllocator* allocatorPtr = m_jit.vm()->heap.allocatorForObjectWithoutDestructor(allocationSize);
130     if (allocatorPtr) {
131         m_jit.move(TrustedImmPtr(allocatorPtr), scratchGPR);
132         emitAllocateJSObject(resultGPR, allocatorPtr, scratchGPR, TrustedImmPtr(structure), storageGPR, scratch2GPR, slowCases);
133         m_jit.emitInitializeInlineStorage(resultGPR, structure->inlineCapacity());
134     } else
135         slowCases.append(m_jit.jump());
136
137     // I want a slow path that also loads out the storage pointer, and that's
138     // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
139     // of work for a very small piece of functionality. :-/
140     addSlowPathGenerator(std::make_unique<CallArrayAllocatorSlowPathGenerator>(
141         slowCases, this, operationNewRawObject, resultGPR, storageGPR,
142         structure, vectorLength));
143
144     if (numElements < vectorLength) {
145 #if USE(JSVALUE64)
146         if (hasDouble(structure->indexingType()))
147             m_jit.move(TrustedImm64(bitwise_cast<int64_t>(PNaN)), scratchGPR);
148         else
149             m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
150         for (unsigned i = numElements; i < vectorLength; ++i)
151             m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
152 #else
153         EncodedValueDescriptor value;
154         if (hasDouble(structure->indexingType()))
155             value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, PNaN));
156         else
157             value.asInt64 = JSValue::encode(JSValue());
158         for (unsigned i = numElements; i < vectorLength; ++i) {
159             m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
160             m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
161         }
162 #endif
163     }
164     
165     if (hasIndexingHeader)
166         m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
167     
168     m_jit.emitInitializeOutOfLineStorage(storageGPR, structure->outOfLineCapacity());
169     
170     m_jit.mutatorFence();
171 }
172
173 void SpeculativeJIT::emitGetLength(InlineCallFrame* inlineCallFrame, GPRReg lengthGPR, bool includeThis)
174 {
175     if (inlineCallFrame && !inlineCallFrame->isVarargs())
176         m_jit.move(TrustedImm32(inlineCallFrame->arguments.size() - !includeThis), lengthGPR);
177     else {
178         VirtualRegister argumentCountRegister = m_jit.argumentCount(inlineCallFrame);
179         m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), lengthGPR);
180         if (!includeThis)
181             m_jit.sub32(TrustedImm32(1), lengthGPR);
182     }
183 }
184
185 void SpeculativeJIT::emitGetLength(CodeOrigin origin, GPRReg lengthGPR, bool includeThis)
186 {
187     emitGetLength(origin.inlineCallFrame, lengthGPR, includeThis);
188 }
189
190 void SpeculativeJIT::emitGetCallee(CodeOrigin origin, GPRReg calleeGPR)
191 {
192     if (origin.inlineCallFrame) {
193         if (origin.inlineCallFrame->isClosureCall) {
194             m_jit.loadPtr(
195                 JITCompiler::addressFor(origin.inlineCallFrame->calleeRecovery.virtualRegister()),
196                 calleeGPR);
197         } else {
198             m_jit.move(
199                 TrustedImmPtr(origin.inlineCallFrame->calleeRecovery.constant().asCell()),
200                 calleeGPR);
201         }
202     } else
203         m_jit.loadPtr(JITCompiler::addressFor(CallFrameSlot::callee), calleeGPR);
204 }
205
206 void SpeculativeJIT::emitGetArgumentStart(CodeOrigin origin, GPRReg startGPR)
207 {
208     m_jit.addPtr(
209         TrustedImm32(
210             JITCompiler::argumentsStart(origin).offset() * static_cast<int>(sizeof(Register))),
211         GPRInfo::callFrameRegister, startGPR);
212 }
213
214 MacroAssembler::Jump SpeculativeJIT::emitOSRExitFuzzCheck()
215 {
216     if (!Options::useOSRExitFuzz()
217         || !canUseOSRExitFuzzing(m_jit.graph().baselineCodeBlockFor(m_origin.semantic))
218         || !doOSRExitFuzzing())
219         return MacroAssembler::Jump();
220     
221     MacroAssembler::Jump result;
222     
223     m_jit.pushToSave(GPRInfo::regT0);
224     m_jit.load32(&g_numberOfOSRExitFuzzChecks, GPRInfo::regT0);
225     m_jit.add32(TrustedImm32(1), GPRInfo::regT0);
226     m_jit.store32(GPRInfo::regT0, &g_numberOfOSRExitFuzzChecks);
227     unsigned atOrAfter = Options::fireOSRExitFuzzAtOrAfter();
228     unsigned at = Options::fireOSRExitFuzzAt();
229     if (at || atOrAfter) {
230         unsigned threshold;
231         MacroAssembler::RelationalCondition condition;
232         if (atOrAfter) {
233             threshold = atOrAfter;
234             condition = MacroAssembler::Below;
235         } else {
236             threshold = at;
237             condition = MacroAssembler::NotEqual;
238         }
239         MacroAssembler::Jump ok = m_jit.branch32(
240             condition, GPRInfo::regT0, MacroAssembler::TrustedImm32(threshold));
241         m_jit.popToRestore(GPRInfo::regT0);
242         result = m_jit.jump();
243         ok.link(&m_jit);
244     }
245     m_jit.popToRestore(GPRInfo::regT0);
246     
247     return result;
248 }
249
250 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
251 {
252     if (!m_compileOkay)
253         return;
254     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
255     if (fuzzJump.isSet()) {
256         JITCompiler::JumpList jumpsToFail;
257         jumpsToFail.append(fuzzJump);
258         jumpsToFail.append(jumpToFail);
259         m_jit.appendExitInfo(jumpsToFail);
260     } else
261         m_jit.appendExitInfo(jumpToFail);
262     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
263 }
264
265 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail)
266 {
267     if (!m_compileOkay)
268         return;
269     JITCompiler::Jump fuzzJump = emitOSRExitFuzzCheck();
270     if (fuzzJump.isSet()) {
271         JITCompiler::JumpList myJumpsToFail;
272         myJumpsToFail.append(jumpsToFail);
273         myJumpsToFail.append(fuzzJump);
274         m_jit.appendExitInfo(myJumpsToFail);
275     } else
276         m_jit.appendExitInfo(jumpsToFail);
277     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
278 }
279
280 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
281 {
282     if (!m_compileOkay)
283         return OSRExitJumpPlaceholder();
284     unsigned index = m_jit.jitCode()->osrExit.size();
285     m_jit.appendExitInfo();
286     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size()));
287     return OSRExitJumpPlaceholder(index);
288 }
289
290 OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
291 {
292     return speculationCheck(kind, jsValueSource, nodeUse.node());
293 }
294
295 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
296 {
297     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
298 }
299
300 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
301 {
302     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
303 }
304
305 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
306 {
307     if (!m_compileOkay)
308         return;
309     unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
310     m_jit.appendExitInfo(jumpToFail);
311     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(m_currentNode, node), this, m_stream->size(), recoveryIndex));
312 }
313
314 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
315 {
316     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
317 }
318
319 void SpeculativeJIT::emitInvalidationPoint(Node* node)
320 {
321     if (!m_compileOkay)
322         return;
323     OSRExitCompilationInfo& info = m_jit.appendExitInfo(JITCompiler::JumpList());
324     m_jit.jitCode()->appendOSRExit(OSRExit(
325         UncountableInvalidation, JSValueSource(), MethodOfGettingAValueProfile(),
326         this, m_stream->size()));
327     info.m_replacementSource = m_jit.watchpointLabel();
328     ASSERT(info.m_replacementSource.isSet());
329     noResult(node);
330 }
331
332 void SpeculativeJIT::unreachable(Node* node)
333 {
334     m_compileOkay = false;
335     m_jit.abortWithReason(DFGUnreachableNode, node->op());
336 }
337
338 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
339 {
340     if (!m_compileOkay)
341         return;
342     speculationCheck(kind, jsValueRegs, node, m_jit.jump());
343     m_compileOkay = false;
344     if (verboseCompilationEnabled())
345         dataLog("Bailing compilation.\n");
346 }
347
348 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
349 {
350     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
351 }
352
353 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, ExitKind exitKind)
354 {
355     ASSERT(needsTypeCheck(edge, typesPassedThrough));
356     m_interpreter.filter(edge, typesPassedThrough);
357     speculationCheck(exitKind, source, edge.node(), jumpToFail);
358 }
359
360 RegisterSet SpeculativeJIT::usedRegisters()
361 {
362     RegisterSet result;
363     
364     for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
365         GPRReg gpr = GPRInfo::toRegister(i);
366         if (m_gprs.isInUse(gpr))
367             result.set(gpr);
368     }
369     for (unsigned i = FPRInfo::numberOfRegisters; i--;) {
370         FPRReg fpr = FPRInfo::toRegister(i);
371         if (m_fprs.isInUse(fpr))
372             result.set(fpr);
373     }
374     
375     result.merge(RegisterSet::stubUnavailableRegisters());
376     
377     return result;
378 }
379
380 void SpeculativeJIT::addSlowPathGenerator(std::unique_ptr<SlowPathGenerator> slowPathGenerator)
381 {
382     m_slowPathGenerators.append(WTFMove(slowPathGenerator));
383 }
384
385 void SpeculativeJIT::addSlowPathGenerator(std::function<void()> lambda)
386 {
387     m_slowPathLambdas.append(SlowPathLambda{ lambda, m_currentNode, static_cast<unsigned>(m_stream->size()) });
388 }
389
390 void SpeculativeJIT::runSlowPathGenerators(PCToCodeOriginMapBuilder& pcToCodeOriginMapBuilder)
391 {
392     for (auto& slowPathGenerator : m_slowPathGenerators) {
393         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), slowPathGenerator->origin().semantic);
394         slowPathGenerator->generate(this);
395     }
396     for (auto& slowPathLambda : m_slowPathLambdas) {
397         Node* currentNode = slowPathLambda.currentNode;
398         m_currentNode = currentNode;
399         m_outOfLineStreamIndex = slowPathLambda.streamIndex;
400         pcToCodeOriginMapBuilder.appendItem(m_jit.labelIgnoringWatchpoints(), currentNode->origin.semantic);
401         slowPathLambda.generator();
402         m_outOfLineStreamIndex = std::nullopt;
403     }
404 }
405
406 void SpeculativeJIT::clearGenerationInfo()
407 {
408     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
409         m_generationInfo[i] = GenerationInfo();
410     m_gprs = RegisterBank<GPRInfo>();
411     m_fprs = RegisterBank<FPRInfo>();
412 }
413
414 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source)
415 {
416     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
417     Node* node = info.node();
418     DataFormat registerFormat = info.registerFormat();
419     ASSERT(registerFormat != DataFormatNone);
420     ASSERT(registerFormat != DataFormatDouble);
421         
422     SilentSpillAction spillAction;
423     SilentFillAction fillAction;
424         
425     if (!info.needsSpill())
426         spillAction = DoNothingForSpill;
427     else {
428 #if USE(JSVALUE64)
429         ASSERT(info.gpr() == source);
430         if (registerFormat == DataFormatInt32)
431             spillAction = Store32Payload;
432         else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
433             spillAction = StorePtr;
434         else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52)
435             spillAction = Store64;
436         else {
437             ASSERT(registerFormat & DataFormatJS);
438             spillAction = Store64;
439         }
440 #elif USE(JSVALUE32_64)
441         if (registerFormat & DataFormatJS) {
442             ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
443             spillAction = source == info.tagGPR() ? Store32Tag : Store32Payload;
444         } else {
445             ASSERT(info.gpr() == source);
446             spillAction = Store32Payload;
447         }
448 #endif
449     }
450         
451     if (registerFormat == DataFormatInt32) {
452         ASSERT(info.gpr() == source);
453         ASSERT(isJSInt32(info.registerFormat()));
454         if (node->hasConstant()) {
455             ASSERT(node->isInt32Constant());
456             fillAction = SetInt32Constant;
457         } else
458             fillAction = Load32Payload;
459     } else if (registerFormat == DataFormatBoolean) {
460 #if USE(JSVALUE64)
461         RELEASE_ASSERT_NOT_REACHED();
462 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
463         fillAction = DoNothingForFill;
464 #endif
465 #elif USE(JSVALUE32_64)
466         ASSERT(info.gpr() == source);
467         if (node->hasConstant()) {
468             ASSERT(node->isBooleanConstant());
469             fillAction = SetBooleanConstant;
470         } else
471             fillAction = Load32Payload;
472 #endif
473     } else if (registerFormat == DataFormatCell) {
474         ASSERT(info.gpr() == source);
475         if (node->hasConstant()) {
476             DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant());
477             node->asCell(); // To get the assertion.
478             fillAction = SetCellConstant;
479         } else {
480 #if USE(JSVALUE64)
481             fillAction = LoadPtr;
482 #else
483             fillAction = Load32Payload;
484 #endif
485         }
486     } else if (registerFormat == DataFormatStorage) {
487         ASSERT(info.gpr() == source);
488         fillAction = LoadPtr;
489     } else if (registerFormat == DataFormatInt52) {
490         if (node->hasConstant())
491             fillAction = SetInt52Constant;
492         else if (info.spillFormat() == DataFormatInt52)
493             fillAction = Load64;
494         else if (info.spillFormat() == DataFormatStrictInt52)
495             fillAction = Load64ShiftInt52Left;
496         else if (info.spillFormat() == DataFormatNone)
497             fillAction = Load64;
498         else {
499             RELEASE_ASSERT_NOT_REACHED();
500 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
501             fillAction = Load64; // Make GCC happy.
502 #endif
503         }
504     } else if (registerFormat == DataFormatStrictInt52) {
505         if (node->hasConstant())
506             fillAction = SetStrictInt52Constant;
507         else if (info.spillFormat() == DataFormatInt52)
508             fillAction = Load64ShiftInt52Right;
509         else if (info.spillFormat() == DataFormatStrictInt52)
510             fillAction = Load64;
511         else if (info.spillFormat() == DataFormatNone)
512             fillAction = Load64;
513         else {
514             RELEASE_ASSERT_NOT_REACHED();
515 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
516             fillAction = Load64; // Make GCC happy.
517 #endif
518         }
519     } else {
520         ASSERT(registerFormat & DataFormatJS);
521 #if USE(JSVALUE64)
522         ASSERT(info.gpr() == source);
523         if (node->hasConstant()) {
524             if (node->isCellConstant())
525                 fillAction = SetTrustedJSConstant;
526             else
527                 fillAction = SetJSConstant;
528         } else if (info.spillFormat() == DataFormatInt32) {
529             ASSERT(registerFormat == DataFormatJSInt32);
530             fillAction = Load32PayloadBoxInt;
531         } else
532             fillAction = Load64;
533 #else
534         ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
535         if (node->hasConstant())
536             fillAction = info.tagGPR() == source ? SetJSConstantTag : SetJSConstantPayload;
537         else if (info.payloadGPR() == source)
538             fillAction = Load32Payload;
539         else { // Fill the Tag
540             switch (info.spillFormat()) {
541             case DataFormatInt32:
542                 ASSERT(registerFormat == DataFormatJSInt32);
543                 fillAction = SetInt32Tag;
544                 break;
545             case DataFormatCell:
546                 ASSERT(registerFormat == DataFormatJSCell);
547                 fillAction = SetCellTag;
548                 break;
549             case DataFormatBoolean:
550                 ASSERT(registerFormat == DataFormatJSBoolean);
551                 fillAction = SetBooleanTag;
552                 break;
553             default:
554                 fillAction = Load32Tag;
555                 break;
556             }
557         }
558 #endif
559     }
560         
561     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
562 }
563     
564 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForFPR(VirtualRegister spillMe, FPRReg source)
565 {
566     GenerationInfo& info = generationInfoFromVirtualRegister(spillMe);
567     Node* node = info.node();
568     ASSERT(info.registerFormat() == DataFormatDouble);
569
570     SilentSpillAction spillAction;
571     SilentFillAction fillAction;
572         
573     if (!info.needsSpill())
574         spillAction = DoNothingForSpill;
575     else {
576         ASSERT(!node->hasConstant());
577         ASSERT(info.spillFormat() == DataFormatNone);
578         ASSERT(info.fpr() == source);
579         spillAction = StoreDouble;
580     }
581         
582 #if USE(JSVALUE64)
583     if (node->hasConstant()) {
584         node->asNumber(); // To get the assertion.
585         fillAction = SetDoubleConstant;
586     } else {
587         ASSERT(info.spillFormat() == DataFormatNone || info.spillFormat() == DataFormatDouble);
588         fillAction = LoadDouble;
589     }
590 #elif USE(JSVALUE32_64)
591     ASSERT(info.registerFormat() == DataFormatDouble);
592     if (node->hasConstant()) {
593         node->asNumber(); // To get the assertion.
594         fillAction = SetDoubleConstant;
595     } else
596         fillAction = LoadDouble;
597 #endif
598
599     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
600 }
601     
602 void SpeculativeJIT::silentSpill(const SilentRegisterSavePlan& plan)
603 {
604     switch (plan.spillAction()) {
605     case DoNothingForSpill:
606         break;
607     case Store32Tag:
608         m_jit.store32(plan.gpr(), JITCompiler::tagFor(plan.node()->virtualRegister()));
609         break;
610     case Store32Payload:
611         m_jit.store32(plan.gpr(), JITCompiler::payloadFor(plan.node()->virtualRegister()));
612         break;
613     case StorePtr:
614         m_jit.storePtr(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
615         break;
616 #if USE(JSVALUE64)
617     case Store64:
618         m_jit.store64(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
619         break;
620 #endif
621     case StoreDouble:
622         m_jit.storeDouble(plan.fpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
623         break;
624     default:
625         RELEASE_ASSERT_NOT_REACHED();
626     }
627 }
628     
629 void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan, GPRReg canTrample)
630 {
631 #if USE(JSVALUE32_64)
632     UNUSED_PARAM(canTrample);
633 #endif
634     switch (plan.fillAction()) {
635     case DoNothingForFill:
636         break;
637     case SetInt32Constant:
638         m_jit.move(Imm32(plan.node()->asInt32()), plan.gpr());
639         break;
640 #if USE(JSVALUE64)
641     case SetInt52Constant:
642         m_jit.move(Imm64(plan.node()->asAnyInt() << JSValue::int52ShiftAmount), plan.gpr());
643         break;
644     case SetStrictInt52Constant:
645         m_jit.move(Imm64(plan.node()->asAnyInt()), plan.gpr());
646         break;
647 #endif // USE(JSVALUE64)
648     case SetBooleanConstant:
649         m_jit.move(TrustedImm32(plan.node()->asBoolean()), plan.gpr());
650         break;
651     case SetCellConstant:
652         m_jit.move(TrustedImmPtr(plan.node()->asCell()), 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             MacroAssembler::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*>()) {
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 (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1771             GenerationInfo& info = m_generationInfo[index];
1772             RELEASE_ASSERT(!info.alive());
1773         }
1774     }
1775 }
1776
1777 // If we are making type predictions about our arguments then
1778 // we need to check that they are correct on function entry.
1779 void SpeculativeJIT::checkArgumentTypes()
1780 {
1781     ASSERT(!m_currentNode);
1782     m_origin = NodeOrigin(CodeOrigin(0), CodeOrigin(0), true);
1783
1784     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1785         Node* node = m_jit.graph().m_arguments[i];
1786         if (!node) {
1787             // The argument is dead. We don't do any checks for such arguments.
1788             continue;
1789         }
1790         
1791         ASSERT(node->op() == SetArgument);
1792         ASSERT(node->shouldGenerate());
1793
1794         VariableAccessData* variableAccessData = node->variableAccessData();
1795         FlushFormat format = variableAccessData->flushFormat();
1796         
1797         if (format == FlushedJSValue)
1798             continue;
1799         
1800         VirtualRegister virtualRegister = variableAccessData->local();
1801
1802         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1803         
1804 #if USE(JSVALUE64)
1805         switch (format) {
1806         case FlushedInt32: {
1807             speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1808             break;
1809         }
1810         case FlushedBoolean: {
1811             GPRTemporary temp(this);
1812             m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
1813             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1814             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1815             break;
1816         }
1817         case FlushedCell: {
1818             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
1819             break;
1820         }
1821         default:
1822             RELEASE_ASSERT_NOT_REACHED();
1823             break;
1824         }
1825 #else
1826         switch (format) {
1827         case FlushedInt32: {
1828             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1829             break;
1830         }
1831         case FlushedBoolean: {
1832             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1833             break;
1834         }
1835         case FlushedCell: {
1836             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1837             break;
1838         }
1839         default:
1840             RELEASE_ASSERT_NOT_REACHED();
1841             break;
1842         }
1843 #endif
1844     }
1845
1846     m_origin = NodeOrigin();
1847 }
1848
1849 bool SpeculativeJIT::compile()
1850 {
1851     checkArgumentTypes();
1852     
1853     ASSERT(!m_currentNode);
1854     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1855         m_jit.setForBlockIndex(blockIndex);
1856         m_block = m_jit.graph().block(blockIndex);
1857         compileCurrentBlock();
1858     }
1859     linkBranches();
1860     return true;
1861 }
1862
1863 void SpeculativeJIT::createOSREntries()
1864 {
1865     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1866         BasicBlock* block = m_jit.graph().block(blockIndex);
1867         if (!block)
1868             continue;
1869         if (!block->isOSRTarget)
1870             continue;
1871         
1872         // Currently we don't have OSR entry trampolines. We could add them
1873         // here if need be.
1874         m_osrEntryHeads.append(m_jit.blockHeads()[blockIndex]);
1875     }
1876 }
1877
1878 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1879 {
1880     unsigned osrEntryIndex = 0;
1881     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().numBlocks(); ++blockIndex) {
1882         BasicBlock* block = m_jit.graph().block(blockIndex);
1883         if (!block)
1884             continue;
1885         if (!block->isOSRTarget)
1886             continue;
1887         m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1888     }
1889     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1890     
1891     if (verboseCompilationEnabled()) {
1892         DumpContext dumpContext;
1893         dataLog("OSR Entries:\n");
1894         for (OSREntryData& entryData : m_jit.jitCode()->osrEntry)
1895             dataLog("    ", inContext(entryData, &dumpContext), "\n");
1896         if (!dumpContext.isEmpty())
1897             dumpContext.dump(WTF::dataFile());
1898     }
1899 }
1900
1901 void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
1902 {
1903     Edge child3 = m_jit.graph().varArgChild(node, 2);
1904     Edge child4 = m_jit.graph().varArgChild(node, 3);
1905
1906     ArrayMode arrayMode = node->arrayMode();
1907     
1908     GPRReg baseReg = base.gpr();
1909     GPRReg propertyReg = property.gpr();
1910     
1911     SpeculateDoubleOperand value(this, child3);
1912
1913     FPRReg valueReg = value.fpr();
1914     
1915     DFG_TYPE_CHECK(
1916         JSValueRegs(), child3, SpecFullRealNumber,
1917         m_jit.branchDouble(
1918             MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
1919     
1920     if (!m_compileOkay)
1921         return;
1922     
1923     StorageOperand storage(this, child4);
1924     GPRReg storageReg = storage.gpr();
1925
1926     if (node->op() == PutByValAlias) {
1927         // Store the value to the array.
1928         GPRReg propertyReg = property.gpr();
1929         FPRReg valueReg = value.fpr();
1930         m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1931         
1932         noResult(m_currentNode);
1933         return;
1934     }
1935     
1936     GPRTemporary temporary;
1937     GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
1938
1939     MacroAssembler::Jump slowCase;
1940     
1941     if (arrayMode.isInBounds()) {
1942         speculationCheck(
1943             OutOfBounds, JSValueRegs(), 0,
1944             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1945     } else {
1946         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1947         
1948         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1949         
1950         if (!arrayMode.isOutOfBounds())
1951             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1952         
1953         m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
1954         m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1955         
1956         inBounds.link(&m_jit);
1957     }
1958     
1959     m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1960
1961     base.use();
1962     property.use();
1963     value.use();
1964     storage.use();
1965     
1966     if (arrayMode.isOutOfBounds()) {
1967         addSlowPathGenerator(
1968             slowPathCall(
1969                 slowCase, this,
1970                 m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1971                 NoResult, baseReg, propertyReg, valueReg));
1972     }
1973
1974     noResult(m_currentNode, UseChildrenCalledExplicitly);
1975 }
1976
1977 void SpeculativeJIT::compileGetCharCodeAt(Node* node)
1978 {
1979     SpeculateCellOperand string(this, node->child1());
1980     SpeculateStrictInt32Operand index(this, node->child2());
1981     StorageOperand storage(this, node->child3());
1982
1983     GPRReg stringReg = string.gpr();
1984     GPRReg indexReg = index.gpr();
1985     GPRReg storageReg = storage.gpr();
1986     
1987     ASSERT(speculationChecked(m_state.forNode(node->child1()).m_type, SpecString));
1988
1989     // unsigned comparison so we can filter out negative indices and indices that are too large
1990     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1991
1992     GPRTemporary scratch(this);
1993     GPRReg scratchReg = scratch.gpr();
1994
1995     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
1996
1997     // Load the character into scratchReg
1998     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1999
2000     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
2001     JITCompiler::Jump cont8Bit = m_jit.jump();
2002
2003     is16Bit.link(&m_jit);
2004
2005     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
2006
2007     cont8Bit.link(&m_jit);
2008
2009     int32Result(scratchReg, m_currentNode);
2010 }
2011
2012 void SpeculativeJIT::compileGetByValOnString(Node* node)
2013 {
2014     SpeculateCellOperand base(this, node->child1());
2015     SpeculateStrictInt32Operand property(this, node->child2());
2016     StorageOperand storage(this, node->child3());
2017     GPRReg baseReg = base.gpr();
2018     GPRReg propertyReg = property.gpr();
2019     GPRReg storageReg = storage.gpr();
2020
2021     GPRTemporary scratch(this);
2022     GPRReg scratchReg = scratch.gpr();
2023 #if USE(JSVALUE32_64)
2024     GPRTemporary resultTag;
2025     GPRReg resultTagReg = InvalidGPRReg;
2026     if (node->arrayMode().isOutOfBounds()) {
2027         GPRTemporary realResultTag(this);
2028         resultTag.adopt(realResultTag);
2029         resultTagReg = resultTag.gpr();
2030     }
2031 #endif
2032
2033     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2034
2035     // unsigned comparison so we can filter out negative indices and indices that are too large
2036     JITCompiler::Jump outOfBounds = m_jit.branch32(
2037         MacroAssembler::AboveOrEqual, propertyReg,
2038         MacroAssembler::Address(baseReg, JSString::offsetOfLength()));
2039     if (node->arrayMode().isInBounds())
2040         speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
2041
2042     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
2043
2044     // Load the character into scratchReg
2045     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2046
2047     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
2048     JITCompiler::Jump cont8Bit = m_jit.jump();
2049
2050     is16Bit.link(&m_jit);
2051
2052     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
2053
2054     JITCompiler::Jump bigCharacter =
2055         m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100));
2056
2057     // 8 bit string values don't need the isASCII check.
2058     cont8Bit.link(&m_jit);
2059
2060     m_jit.lshift32(MacroAssembler::TrustedImm32(sizeof(void*) == 4 ? 2 : 3), scratchReg);
2061     m_jit.addPtr(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), scratchReg);
2062     m_jit.loadPtr(scratchReg, scratchReg);
2063
2064     addSlowPathGenerator(
2065         slowPathCall(
2066             bigCharacter, this, operationSingleCharacterString, scratchReg, scratchReg));
2067
2068     if (node->arrayMode().isOutOfBounds()) {
2069 #if USE(JSVALUE32_64)
2070         m_jit.move(TrustedImm32(JSValue::CellTag), resultTagReg);
2071 #endif
2072
2073         JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic);
2074         bool prototypeChainIsSane = false;
2075         if (globalObject->stringPrototypeChainIsSane()) {
2076             // FIXME: This could be captured using a Speculation mode that means "out-of-bounds
2077             // loads return a trivial value". Something like SaneChainOutOfBounds. This should
2078             // speculate that we don't take negative out-of-bounds, or better yet, it should rely
2079             // on a stringPrototypeChainIsSane() guaranteeing that the prototypes have no negative
2080             // indexed properties either.
2081             // https://bugs.webkit.org/show_bug.cgi?id=144668
2082             m_jit.graph().watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet());
2083             m_jit.graph().watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2084             prototypeChainIsSane = globalObject->stringPrototypeChainIsSane();
2085         }
2086         if (prototypeChainIsSane) {
2087             m_jit.graph().watchpoints().addLazily(globalObject->stringPrototype()->structure()->transitionWatchpointSet());
2088             m_jit.graph().watchpoints().addLazily(globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2089             
2090 #if USE(JSVALUE64)
2091             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2092                 outOfBounds, this, JSValueRegs(scratchReg), baseReg, propertyReg));
2093 #else
2094             addSlowPathGenerator(std::make_unique<SaneStringGetByValSlowPathGenerator>(
2095                 outOfBounds, this, JSValueRegs(resultTagReg, scratchReg),
2096                 baseReg, propertyReg));
2097 #endif
2098         } else {
2099 #if USE(JSVALUE64)
2100             addSlowPathGenerator(
2101                 slowPathCall(
2102                     outOfBounds, this, operationGetByValStringInt,
2103                     scratchReg, baseReg, propertyReg));
2104 #else
2105             addSlowPathGenerator(
2106                 slowPathCall(
2107                     outOfBounds, this, operationGetByValStringInt,
2108                     JSValueRegs(resultTagReg, scratchReg), baseReg, propertyReg));
2109 #endif
2110         }
2111         
2112 #if USE(JSVALUE64)
2113         jsValueResult(scratchReg, m_currentNode);
2114 #else
2115         jsValueResult(resultTagReg, scratchReg, m_currentNode);
2116 #endif
2117     } else
2118         cellResult(scratchReg, m_currentNode);
2119 }
2120
2121 void SpeculativeJIT::compileFromCharCode(Node* node)
2122 {
2123     Edge& child = node->child1();
2124     if (child.useKind() == UntypedUse) {
2125         JSValueOperand opr(this, child);
2126         JSValueRegs oprRegs = opr.jsValueRegs();
2127 #if USE(JSVALUE64)
2128         GPRTemporary result(this);
2129         JSValueRegs resultRegs = JSValueRegs(result.gpr());
2130 #else
2131         GPRTemporary resultTag(this);
2132         GPRTemporary resultPayload(this);
2133         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
2134 #endif
2135         flushRegisters();
2136         callOperation(operationStringFromCharCodeUntyped, resultRegs, oprRegs);
2137         m_jit.exceptionCheck();
2138         
2139         jsValueResult(resultRegs, node);
2140         return;
2141     }
2142
2143     SpeculateStrictInt32Operand property(this, child);
2144     GPRReg propertyReg = property.gpr();
2145     GPRTemporary smallStrings(this);
2146     GPRTemporary scratch(this);
2147     GPRReg scratchReg = scratch.gpr();
2148     GPRReg smallStringsReg = smallStrings.gpr();
2149
2150     JITCompiler::JumpList slowCases;
2151     slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(0xff)));
2152     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
2153     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, propertyReg, MacroAssembler::ScalePtr, 0), scratchReg);
2154
2155     slowCases.append(m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2156     addSlowPathGenerator(slowPathCall(slowCases, this, operationStringFromCharCode, scratchReg, propertyReg));
2157     cellResult(scratchReg, m_currentNode);
2158 }
2159
2160 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)
2161 {
2162     VirtualRegister virtualRegister = node->virtualRegister();
2163     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2164
2165     switch (info.registerFormat()) {
2166     case DataFormatStorage:
2167         RELEASE_ASSERT_NOT_REACHED();
2168
2169     case DataFormatBoolean:
2170     case DataFormatCell:
2171         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2172         return GeneratedOperandTypeUnknown;
2173
2174     case DataFormatNone:
2175     case DataFormatJSCell:
2176     case DataFormatJS:
2177     case DataFormatJSBoolean:
2178     case DataFormatJSDouble:
2179         return GeneratedOperandJSValue;
2180
2181     case DataFormatJSInt32:
2182     case DataFormatInt32:
2183         return GeneratedOperandInteger;
2184
2185     default:
2186         RELEASE_ASSERT_NOT_REACHED();
2187         return GeneratedOperandTypeUnknown;
2188     }
2189 }
2190
2191 void SpeculativeJIT::compileValueToInt32(Node* node)
2192 {
2193     switch (node->child1().useKind()) {
2194 #if USE(JSVALUE64)
2195     case Int52RepUse: {
2196         SpeculateStrictInt52Operand op1(this, node->child1());
2197         GPRTemporary result(this, Reuse, op1);
2198         GPRReg op1GPR = op1.gpr();
2199         GPRReg resultGPR = result.gpr();
2200         m_jit.zeroExtend32ToPtr(op1GPR, resultGPR);
2201         int32Result(resultGPR, node, DataFormatInt32);
2202         return;
2203     }
2204 #endif // USE(JSVALUE64)
2205         
2206     case DoubleRepUse: {
2207         GPRTemporary result(this);
2208         SpeculateDoubleOperand op1(this, node->child1());
2209         FPRReg fpr = op1.fpr();
2210         GPRReg gpr = result.gpr();
2211         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
2212         
2213         addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, operationToInt32, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded, gpr, fpr));
2214         
2215         int32Result(gpr, node);
2216         return;
2217     }
2218     
2219     case NumberUse:
2220     case NotCellUse: {
2221         switch (checkGeneratedTypeForToInt32(node->child1().node())) {
2222         case GeneratedOperandInteger: {
2223             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2224             GPRTemporary result(this, Reuse, op1);
2225             m_jit.move(op1.gpr(), result.gpr());
2226             int32Result(result.gpr(), node, op1.format());
2227             return;
2228         }
2229         case GeneratedOperandJSValue: {
2230             GPRTemporary result(this);
2231 #if USE(JSVALUE64)
2232             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2233
2234             GPRReg gpr = op1.gpr();
2235             GPRReg resultGpr = result.gpr();
2236             FPRTemporary tempFpr(this);
2237             FPRReg fpr = tempFpr.fpr();
2238
2239             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
2240             JITCompiler::JumpList converted;
2241
2242             if (node->child1().useKind() == NumberUse) {
2243                 DFG_TYPE_CHECK(
2244                     JSValueRegs(gpr), node->child1(), SpecBytecodeNumber,
2245                     m_jit.branchTest64(
2246                         MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
2247             } else {
2248                 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
2249                 
2250                 DFG_TYPE_CHECK(
2251                     JSValueRegs(gpr), node->child1(), ~SpecCell, m_jit.branchIfCell(JSValueRegs(gpr)));
2252                 
2253                 // It's not a cell: so true turns into 1 and all else turns into 0.
2254                 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
2255                 converted.append(m_jit.jump());
2256                 
2257                 isNumber.link(&m_jit);
2258             }
2259
2260             // First, if we get here we have a double encoded as a JSValue
2261             unboxDouble(gpr, resultGpr, fpr);
2262
2263             silentSpillAllRegisters(resultGpr);
2264             callOperation(operationToInt32, resultGpr, fpr);
2265             silentFillAllRegisters(resultGpr);
2266
2267             converted.append(m_jit.jump());
2268
2269             isInteger.link(&m_jit);
2270             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
2271
2272             converted.link(&m_jit);
2273 #else
2274             Node* childNode = node->child1().node();
2275             VirtualRegister virtualRegister = childNode->virtualRegister();
2276             GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
2277
2278             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2279
2280             GPRReg payloadGPR = op1.payloadGPR();
2281             GPRReg resultGpr = result.gpr();
2282         
2283             JITCompiler::JumpList converted;
2284
2285             if (info.registerFormat() == DataFormatJSInt32)
2286                 m_jit.move(payloadGPR, resultGpr);
2287             else {
2288                 GPRReg tagGPR = op1.tagGPR();
2289                 FPRTemporary tempFpr(this);
2290                 FPRReg fpr = tempFpr.fpr();
2291                 FPRTemporary scratch(this);
2292
2293                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
2294
2295                 if (node->child1().useKind() == NumberUse) {
2296                     DFG_TYPE_CHECK(
2297                         op1.jsValueRegs(), node->child1(), SpecBytecodeNumber,
2298                         m_jit.branch32(
2299                             MacroAssembler::AboveOrEqual, tagGPR,
2300                             TrustedImm32(JSValue::LowestTag)));
2301                 } else {
2302                     JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
2303                     
2304                     DFG_TYPE_CHECK(
2305                         op1.jsValueRegs(), node->child1(), ~SpecCell,
2306                         m_jit.branchIfCell(op1.jsValueRegs()));
2307                     
2308                     // It's not a cell: so true turns into 1 and all else turns into 0.
2309                     JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
2310                     m_jit.move(TrustedImm32(0), resultGpr);
2311                     converted.append(m_jit.jump());
2312                     
2313                     isBoolean.link(&m_jit);
2314                     m_jit.move(payloadGPR, resultGpr);
2315                     converted.append(m_jit.jump());
2316                     
2317                     isNumber.link(&m_jit);
2318                 }
2319
2320                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
2321
2322                 silentSpillAllRegisters(resultGpr);
2323                 callOperation(operationToInt32, resultGpr, fpr);
2324                 silentFillAllRegisters(resultGpr);
2325
2326                 converted.append(m_jit.jump());
2327
2328                 isInteger.link(&m_jit);
2329                 m_jit.move(payloadGPR, resultGpr);
2330
2331                 converted.link(&m_jit);
2332             }
2333 #endif
2334             int32Result(resultGpr, node);
2335             return;
2336         }
2337         case GeneratedOperandTypeUnknown:
2338             RELEASE_ASSERT(!m_compileOkay);
2339             return;
2340         }
2341         RELEASE_ASSERT_NOT_REACHED();
2342         return;
2343     }
2344     
2345     default:
2346         ASSERT(!m_compileOkay);
2347         return;
2348     }
2349 }
2350
2351 void SpeculativeJIT::compileUInt32ToNumber(Node* node)
2352 {
2353     if (doesOverflow(node->arithMode())) {
2354         if (enableInt52()) {
2355             SpeculateInt32Operand op1(this, node->child1());
2356             GPRTemporary result(this, Reuse, op1);
2357             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2358             strictInt52Result(result.gpr(), node);
2359             return;
2360         }
2361         SpeculateInt32Operand op1(this, node->child1());
2362         FPRTemporary result(this);
2363             
2364         GPRReg inputGPR = op1.gpr();
2365         FPRReg outputFPR = result.fpr();
2366             
2367         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2368             
2369         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2370         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
2371         positive.link(&m_jit);
2372             
2373         doubleResult(outputFPR, node);
2374         return;
2375     }
2376     
2377     RELEASE_ASSERT(node->arithMode() == Arith::CheckOverflow);
2378
2379     SpeculateInt32Operand op1(this, node->child1());
2380     GPRTemporary result(this);
2381
2382     m_jit.move(op1.gpr(), result.gpr());
2383
2384     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)));
2385
2386     int32Result(result.gpr(), node, op1.format());
2387 }
2388
2389 void SpeculativeJIT::compileDoubleAsInt32(Node* node)
2390 {
2391     SpeculateDoubleOperand op1(this, node->child1());
2392     FPRTemporary scratch(this);
2393     GPRTemporary result(this);
2394     
2395     FPRReg valueFPR = op1.fpr();
2396     FPRReg scratchFPR = scratch.fpr();
2397     GPRReg resultGPR = result.gpr();
2398
2399     JITCompiler::JumpList failureCases;
2400     RELEASE_ASSERT(shouldCheckOverflow(node->arithMode()));
2401     m_jit.branchConvertDoubleToInt32(
2402         valueFPR, resultGPR, failureCases, scratchFPR,
2403         shouldCheckNegativeZero(node->arithMode()));
2404     speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
2405
2406     int32Result(resultGPR, node);
2407 }
2408
2409 void SpeculativeJIT::compileDoubleRep(Node* node)
2410 {
2411     switch (node->child1().useKind()) {
2412     case RealNumberUse: {
2413         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2414         FPRTemporary result(this);
2415         
2416         JSValueRegs op1Regs = op1.jsValueRegs();
2417         FPRReg resultFPR = result.fpr();
2418         
2419 #if USE(JSVALUE64)
2420         GPRTemporary temp(this);
2421         GPRReg tempGPR = temp.gpr();
2422         m_jit.unboxDoubleWithoutAssertions(op1Regs.gpr(), tempGPR, resultFPR);
2423 #else
2424         FPRTemporary temp(this);
2425         FPRReg tempFPR = temp.fpr();
2426         unboxDouble(op1Regs.tagGPR(), op1Regs.payloadGPR(), resultFPR, tempFPR);
2427 #endif
2428         
2429         JITCompiler::Jump done = m_jit.branchDouble(
2430             JITCompiler::DoubleEqual, resultFPR, resultFPR);
2431         
2432         DFG_TYPE_CHECK(
2433             op1Regs, node->child1(), SpecBytecodeRealNumber, m_jit.branchIfNotInt32(op1Regs));
2434         m_jit.convertInt32ToDouble(op1Regs.payloadGPR(), resultFPR);
2435         
2436         done.link(&m_jit);
2437         
2438         doubleResult(resultFPR, node);
2439         return;
2440     }
2441     
2442     case NotCellUse:
2443     case NumberUse: {
2444         ASSERT(!node->child1()->isNumberConstant()); // This should have been constant folded.
2445
2446         SpeculatedType possibleTypes = m_state.forNode(node->child1()).m_type;
2447         if (isInt32Speculation(possibleTypes)) {
2448             SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation);
2449             FPRTemporary result(this);
2450             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
2451             doubleResult(result.fpr(), node);
2452             return;
2453         }
2454
2455         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2456         FPRTemporary result(this);
2457
2458 #if USE(JSVALUE64)
2459         GPRTemporary temp(this);
2460
2461         GPRReg op1GPR = op1.gpr();
2462         GPRReg tempGPR = temp.gpr();
2463         FPRReg resultFPR = result.fpr();
2464         JITCompiler::JumpList done;
2465
2466         JITCompiler::Jump isInteger = m_jit.branch64(
2467             MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
2468
2469         if (node->child1().useKind() == NotCellUse) {
2470             JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagTypeNumberRegister);
2471             JITCompiler::Jump isUndefined = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueUndefined));
2472
2473             static const double zero = 0;
2474             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
2475
2476             JITCompiler::Jump isNull = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueNull));
2477             done.append(isNull);
2478
2479             DFG_TYPE_CHECK(JSValueRegs(op1GPR), node->child1(), ~SpecCell,
2480                 m_jit.branchTest64(JITCompiler::Zero, op1GPR, TrustedImm32(static_cast<int32_t>(TagBitBool))));
2481
2482             JITCompiler::Jump isFalse = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueFalse));
2483             static const double one = 1;
2484             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
2485             done.append(m_jit.jump());
2486             done.append(isFalse);
2487
2488             isUndefined.link(&m_jit);
2489             static const double NaN = PNaN;
2490             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
2491             done.append(m_jit.jump());
2492
2493             isNumber.link(&m_jit);
2494         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2495             typeCheck(
2496                 JSValueRegs(op1GPR), node->child1(), SpecBytecodeNumber,
2497                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
2498         }
2499
2500         unboxDouble(op1GPR, tempGPR, resultFPR);
2501         done.append(m_jit.jump());
2502     
2503         isInteger.link(&m_jit);
2504         m_jit.convertInt32ToDouble(op1GPR, resultFPR);
2505         done.link(&m_jit);
2506 #else // USE(JSVALUE64) -> this is the 32_64 case
2507         FPRTemporary temp(this);
2508     
2509         GPRReg op1TagGPR = op1.tagGPR();
2510         GPRReg op1PayloadGPR = op1.payloadGPR();
2511         FPRReg tempFPR = temp.fpr();
2512         FPRReg resultFPR = result.fpr();
2513         JITCompiler::JumpList done;
2514     
2515         JITCompiler::Jump isInteger = m_jit.branch32(
2516             MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
2517
2518         if (node->child1().useKind() == NotCellUse) {
2519             JITCompiler::Jump isNumber = m_jit.branch32(JITCompiler::Below, op1TagGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
2520             JITCompiler::Jump isUndefined = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::UndefinedTag));
2521
2522             static const double zero = 0;
2523             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), resultFPR);
2524
2525             JITCompiler::Jump isNull = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::NullTag));
2526             done.append(isNull);
2527
2528             DFG_TYPE_CHECK(JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), ~SpecCell, m_jit.branch32(JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::BooleanTag)));
2529
2530             JITCompiler::Jump isFalse = m_jit.branchTest32(JITCompiler::Zero, op1PayloadGPR, TrustedImm32(1));
2531             static const double one = 1;
2532             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&one), resultFPR);
2533             done.append(m_jit.jump());
2534             done.append(isFalse);
2535
2536             isUndefined.link(&m_jit);
2537             static const double NaN = PNaN;
2538             m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&NaN), resultFPR);
2539             done.append(m_jit.jump());
2540
2541             isNumber.link(&m_jit);
2542         } else if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) {
2543             typeCheck(
2544                 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecBytecodeNumber,
2545                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
2546         }
2547
2548         unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
2549         done.append(m_jit.jump());
2550     
2551         isInteger.link(&m_jit);
2552         m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
2553         done.link(&m_jit);
2554 #endif // USE(JSVALUE64)
2555     
2556         doubleResult(resultFPR, node);
2557         return;
2558     }
2559         
2560 #if USE(JSVALUE64)
2561     case Int52RepUse: {
2562         SpeculateStrictInt52Operand value(this, node->child1());
2563         FPRTemporary result(this);
2564         
2565         GPRReg valueGPR = value.gpr();
2566         FPRReg resultFPR = result.fpr();
2567
2568         m_jit.convertInt64ToDouble(valueGPR, resultFPR);
2569         
2570         doubleResult(resultFPR, node);
2571         return;
2572     }
2573 #endif // USE(JSVALUE64)
2574         
2575     default:
2576         RELEASE_ASSERT_NOT_REACHED();
2577         return;
2578     }
2579 }
2580
2581 void SpeculativeJIT::compileValueRep(Node* node)
2582 {
2583     switch (node->child1().useKind()) {
2584     case DoubleRepUse: {
2585         SpeculateDoubleOperand value(this, node->child1());
2586         JSValueRegsTemporary result(this);
2587         
2588         FPRReg valueFPR = value.fpr();
2589         JSValueRegs resultRegs = result.regs();
2590         
2591         // It's very tempting to in-place filter the value to indicate that it's not impure NaN
2592         // anymore. Unfortunately, this would be unsound. If it's a GetLocal or if the value was
2593         // subject to a prior SetLocal, filtering the value would imply that the corresponding
2594         // local was purified.
2595         if (needsTypeCheck(node->child1(), ~SpecDoubleImpureNaN))
2596             m_jit.purifyNaN(valueFPR);
2597
2598         boxDouble(valueFPR, resultRegs);
2599         
2600         jsValueResult(resultRegs, node);
2601         return;
2602     }
2603         
2604 #if USE(JSVALUE64)
2605     case Int52RepUse: {
2606         SpeculateStrictInt52Operand value(this, node->child1());
2607         GPRTemporary result(this);
2608         
2609         GPRReg valueGPR = value.gpr();
2610         GPRReg resultGPR = result.gpr();
2611         
2612         boxInt52(valueGPR, resultGPR, DataFormatStrictInt52);
2613         
2614         jsValueResult(resultGPR, node);
2615         return;
2616     }
2617 #endif // USE(JSVALUE64)
2618         
2619     default:
2620         RELEASE_ASSERT_NOT_REACHED();
2621         return;
2622     }
2623 }
2624
2625 static double clampDoubleToByte(double d)
2626 {
2627     d += 0.5;
2628     if (!(d > 0))
2629         d = 0;
2630     else if (d > 255)
2631         d = 255;
2632     return d;
2633 }
2634
2635 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
2636 {
2637     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
2638     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
2639     jit.xorPtr(result, result);
2640     MacroAssembler::Jump clamped = jit.jump();
2641     tooBig.link(&jit);
2642     jit.move(JITCompiler::TrustedImm32(255), result);
2643     clamped.link(&jit);
2644     inBounds.link(&jit);
2645 }
2646
2647 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
2648 {
2649     // Unordered compare so we pick up NaN
2650     static const double zero = 0;
2651     static const double byteMax = 255;
2652     static const double half = 0.5;
2653     jit.loadDouble(MacroAssembler::TrustedImmPtr(&zero), scratch);
2654     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
2655     jit.loadDouble(MacroAssembler::TrustedImmPtr(&byteMax), scratch);
2656     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
2657     
2658     jit.loadDouble(MacroAssembler::TrustedImmPtr(&half), scratch);
2659     // FIXME: This should probably just use a floating point round!
2660     // https://bugs.webkit.org/show_bug.cgi?id=72054
2661     jit.addDouble(source, scratch);
2662     jit.truncateDoubleToInt32(scratch, result);   
2663     MacroAssembler::Jump truncatedInt = jit.jump();
2664     
2665     tooSmall.link(&jit);
2666     jit.xorPtr(result, result);
2667     MacroAssembler::Jump zeroed = jit.jump();
2668     
2669     tooBig.link(&jit);
2670     jit.move(JITCompiler::TrustedImm32(255), result);
2671     
2672     truncatedInt.link(&jit);
2673     zeroed.link(&jit);
2674
2675 }
2676
2677 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2678 {
2679     if (node->op() == PutByValAlias)
2680         return JITCompiler::Jump();
2681     JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(
2682         m_state.forNode(m_jit.graph().child(node, 0)).m_value, node->arrayMode());
2683     if (view) {
2684         uint32_t length = view->length();
2685         Node* indexNode = m_jit.graph().child(node, 1).node();
2686         if (indexNode->isInt32Constant() && indexNode->asUInt32() < length)
2687             return JITCompiler::Jump();
2688         return m_jit.branch32(
2689             MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Imm32(length));
2690     }
2691     return m_jit.branch32(
2692         MacroAssembler::AboveOrEqual, indexGPR,
2693         MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfLength()));
2694 }
2695
2696 void SpeculativeJIT::emitTypedArrayBoundsCheck(Node* node, GPRReg baseGPR, GPRReg indexGPR)
2697 {
2698     JITCompiler::Jump jump = jumpForTypedArrayOutOfBounds(node, baseGPR, indexGPR);
2699     if (!jump.isSet())
2700         return;
2701     speculationCheck(OutOfBounds, JSValueRegs(), 0, jump);
2702 }
2703
2704 JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayIsNeuteredIfOutOfBounds(Node* node, GPRReg base, JITCompiler::Jump outOfBounds)
2705 {
2706     JITCompiler::Jump done;
2707     if (outOfBounds.isSet()) {
2708         done = m_jit.jump();
2709         if (node->arrayMode().isInBounds())
2710             speculationCheck(OutOfBounds, JSValueSource(), 0, outOfBounds);
2711         else {
2712             outOfBounds.link(&m_jit);
2713
2714             JITCompiler::Jump notWasteful = m_jit.branch32(
2715                 MacroAssembler::NotEqual,
2716                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfMode()),
2717                 TrustedImm32(WastefulTypedArray));
2718
2719             JITCompiler::Jump hasNullVector = m_jit.branchTestPtr(
2720                 MacroAssembler::Zero,
2721                 MacroAssembler::Address(base, JSArrayBufferView::offsetOfVector()));
2722             speculationCheck(Uncountable, JSValueSource(), node, hasNullVector);
2723             notWasteful.link(&m_jit);
2724         }
2725     }
2726     return done;
2727 }
2728
2729 void SpeculativeJIT::compileGetByValOnIntTypedArray(Node* node, TypedArrayType type)
2730 {
2731     ASSERT(isInt(type));
2732     
2733     SpeculateCellOperand base(this, node->child1());
2734     SpeculateStrictInt32Operand property(this, node->child2());
2735     StorageOperand storage(this, node->child3());
2736
2737     GPRReg baseReg = base.gpr();
2738     GPRReg propertyReg = property.gpr();
2739     GPRReg storageReg = storage.gpr();
2740
2741     GPRTemporary result(this);
2742     GPRReg resultReg = result.gpr();
2743
2744     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2745
2746     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
2747     switch (elementSize(type)) {
2748     case 1:
2749         if (isSigned(type))
2750             m_jit.load8SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2751         else
2752             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2753         break;
2754     case 2:
2755         if (isSigned(type))
2756             m_jit.load16SignedExtendTo32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2757         else
2758             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2759         break;
2760     case 4:
2761         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2762         break;
2763     default:
2764         CRASH();
2765     }
2766     if (elementSize(type) < 4 || isSigned(type)) {
2767         int32Result(resultReg, node);
2768         return;
2769     }
2770     
2771     ASSERT(elementSize(type) == 4 && !isSigned(type));
2772     if (node->shouldSpeculateInt32()) {
2773         speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)));
2774         int32Result(resultReg, node);
2775         return;
2776     }
2777     
2778 #if USE(JSVALUE64)
2779     if (node->shouldSpeculateAnyInt()) {
2780         m_jit.zeroExtend32ToPtr(resultReg, resultReg);
2781         strictInt52Result(resultReg, node);
2782         return;
2783     }
2784 #endif
2785     
2786     FPRTemporary fresult(this);
2787     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
2788     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
2789     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
2790     positive.link(&m_jit);
2791     doubleResult(fresult.fpr(), node);
2792 }
2793
2794 void SpeculativeJIT::compilePutByValForIntTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
2795 {
2796     ASSERT(isInt(type));
2797     
2798     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2799     GPRReg storageReg = storage.gpr();
2800     
2801     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2802     
2803     GPRTemporary value;
2804 #if USE(JSVALUE32_64)
2805     GPRTemporary propertyTag;
2806     GPRTemporary valueTag;
2807 #endif
2808
2809     GPRReg valueGPR = InvalidGPRReg;
2810 #if USE(JSVALUE32_64)
2811     GPRReg propertyTagGPR = InvalidGPRReg;
2812     GPRReg valueTagGPR = InvalidGPRReg;
2813 #endif
2814
2815     JITCompiler::JumpList slowPathCases;
2816
2817     if (valueUse->isConstant()) {
2818         JSValue jsValue = valueUse->asJSValue();
2819         if (!jsValue.isNumber()) {
2820             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2821             noResult(node);
2822             return;
2823         }
2824         double d = jsValue.asNumber();
2825         if (isClamped(type)) {
2826             ASSERT(elementSize(type) == 1);
2827             d = clampDoubleToByte(d);
2828         }
2829         GPRTemporary scratch(this);
2830         GPRReg scratchReg = scratch.gpr();
2831         m_jit.move(Imm32(toInt32(d)), scratchReg);
2832         value.adopt(scratch);
2833         valueGPR = scratchReg;
2834     } else {
2835         switch (valueUse.useKind()) {
2836         case Int32Use: {
2837             SpeculateInt32Operand valueOp(this, valueUse);
2838             GPRTemporary scratch(this);
2839             GPRReg scratchReg = scratch.gpr();
2840             m_jit.move(valueOp.gpr(), scratchReg);
2841             if (isClamped(type)) {
2842                 ASSERT(elementSize(type) == 1);
2843                 compileClampIntegerToByte(m_jit, scratchReg);
2844             }
2845             value.adopt(scratch);
2846             valueGPR = scratchReg;
2847             break;
2848         }
2849             
2850 #if USE(JSVALUE64)
2851         case Int52RepUse: {
2852             SpeculateStrictInt52Operand valueOp(this, valueUse);
2853             GPRTemporary scratch(this);
2854             GPRReg scratchReg = scratch.gpr();
2855             m_jit.move(valueOp.gpr(), scratchReg);
2856             if (isClamped(type)) {
2857                 ASSERT(elementSize(type) == 1);
2858                 MacroAssembler::Jump inBounds = m_jit.branch64(
2859                     MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff));
2860                 MacroAssembler::Jump tooBig = m_jit.branch64(
2861                     MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff));
2862                 m_jit.move(TrustedImm32(0), scratchReg);
2863                 MacroAssembler::Jump clamped = m_jit.jump();
2864                 tooBig.link(&m_jit);
2865                 m_jit.move(JITCompiler::TrustedImm32(255), scratchReg);
2866                 clamped.link(&m_jit);
2867                 inBounds.link(&m_jit);
2868             }
2869             value.adopt(scratch);
2870             valueGPR = scratchReg;
2871             break;
2872         }
2873 #endif // USE(JSVALUE64)
2874             
2875         case DoubleRepUse: {
2876             if (isClamped(type)) {
2877                 ASSERT(elementSize(type) == 1);
2878                 SpeculateDoubleOperand valueOp(this, valueUse);
2879                 GPRTemporary result(this);
2880                 FPRTemporary floatScratch(this);
2881                 FPRReg fpr = valueOp.fpr();
2882                 GPRReg gpr = result.gpr();
2883                 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
2884                 value.adopt(result);
2885                 valueGPR = gpr;
2886             } else {
2887 #if USE(JSVALUE32_64)
2888                 GPRTemporary realPropertyTag(this);
2889                 propertyTag.adopt(realPropertyTag);
2890                 propertyTagGPR = propertyTag.gpr();
2891
2892                 GPRTemporary realValueTag(this);
2893                 valueTag.adopt(realValueTag);
2894                 valueTagGPR = valueTag.gpr();
2895 #endif
2896                 SpeculateDoubleOperand valueOp(this, valueUse);
2897                 GPRTemporary result(this);
2898                 FPRReg fpr = valueOp.fpr();
2899                 GPRReg gpr = result.gpr();
2900                 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
2901                 m_jit.xorPtr(gpr, gpr);
2902                 MacroAssembler::JumpList fixed(m_jit.jump());
2903                 notNaN.link(&m_jit);
2904
2905                 fixed.append(m_jit.branchTruncateDoubleToInt32(
2906                     fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful));
2907
2908 #if USE(JSVALUE64)
2909                 m_jit.or64(GPRInfo::tagTypeNumberRegister, property);
2910                 boxDouble(fpr, gpr);
2911 #else
2912                 m_jit.move(TrustedImm32(JSValue::Int32Tag), propertyTagGPR);
2913                 boxDouble(fpr, valueTagGPR, gpr);
2914 #endif
2915                 slowPathCases.append(m_jit.jump());
2916
2917                 fixed.link(&m_jit);
2918                 value.adopt(result);
2919                 valueGPR = gpr;
2920             }
2921             break;
2922         }
2923             
2924         default:
2925             RELEASE_ASSERT_NOT_REACHED();
2926             break;
2927         }
2928     }
2929     
2930     ASSERT_UNUSED(valueGPR, valueGPR != property);
2931     ASSERT(valueGPR != base);
2932     ASSERT(valueGPR != storageReg);
2933     JITCompiler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
2934
2935     switch (elementSize(type)) {
2936     case 1:
2937         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
2938         break;
2939     case 2:
2940         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
2941         break;
2942     case 4:
2943         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2944         break;
2945     default:
2946         CRASH();
2947     }
2948
2949     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
2950     if (done.isSet())
2951         done.link(&m_jit);
2952
2953     if (!slowPathCases.empty()) {
2954 #if USE(JSVALUE64)
2955         if (node->op() == PutByValDirect) {
2956             addSlowPathGenerator(slowPathCall(
2957                 slowPathCases, this,
2958                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict,
2959                 NoResult, base, property, valueGPR));
2960         } else {
2961             addSlowPathGenerator(slowPathCall(
2962                 slowPathCases, this,
2963                 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict,
2964                 NoResult, base, property, valueGPR));
2965         }
2966 #else // not USE(JSVALUE64)
2967         if (node->op() == PutByValDirect) {
2968             addSlowPathGenerator(slowPathCall(
2969                 slowPathCases, this,
2970                 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict,
2971                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
2972         } else {
2973             addSlowPathGenerator(slowPathCall(
2974                 slowPathCases, this,
2975                 m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict,
2976                 NoResult, base, JSValueRegs(propertyTagGPR, property), JSValueRegs(valueTagGPR, valueGPR)));
2977         }
2978 #endif
2979     }
2980     noResult(node);
2981 }
2982
2983 void SpeculativeJIT::compileGetByValOnFloatTypedArray(Node* node, TypedArrayType type)
2984 {
2985     ASSERT(isFloat(type));
2986     
2987     SpeculateCellOperand base(this, node->child1());
2988     SpeculateStrictInt32Operand property(this, node->child2());
2989     StorageOperand storage(this, node->child3());
2990
2991     GPRReg baseReg = base.gpr();
2992     GPRReg propertyReg = property.gpr();
2993     GPRReg storageReg = storage.gpr();
2994
2995     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2996
2997     FPRTemporary result(this);
2998     FPRReg resultReg = result.fpr();
2999     emitTypedArrayBoundsCheck(node, baseReg, propertyReg);
3000     switch (elementSize(type)) {
3001     case 4:
3002         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
3003         m_jit.convertFloatToDouble(resultReg, resultReg);
3004         break;
3005     case 8: {
3006         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
3007         break;
3008     }
3009     default:
3010         RELEASE_ASSERT_NOT_REACHED();
3011     }
3012     
3013     doubleResult(resultReg, node);
3014 }
3015
3016 void SpeculativeJIT::compilePutByValForFloatTypedArray(GPRReg base, GPRReg property, Node* node, TypedArrayType type)
3017 {
3018     ASSERT(isFloat(type));
3019     
3020     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
3021     GPRReg storageReg = storage.gpr();
3022     
3023     Edge baseUse = m_jit.graph().varArgChild(node, 0);
3024     Edge valueUse = m_jit.graph().varArgChild(node, 2);
3025
3026     SpeculateDoubleOperand valueOp(this, valueUse);
3027     FPRTemporary scratch(this);
3028     FPRReg valueFPR = valueOp.fpr();
3029     FPRReg scratchFPR = scratch.fpr();
3030
3031     ASSERT_UNUSED(baseUse, node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(baseUse)));
3032     
3033     MacroAssembler::Jump outOfBounds = jumpForTypedArrayOutOfBounds(node, base, property);
3034     
3035     switch (elementSize(type)) {
3036     case 4: {
3037         m_jit.moveDouble(valueFPR, scratchFPR);
3038         m_jit.convertDoubleToFloat(valueFPR, scratchFPR);
3039         m_jit.storeFloat(scratchFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
3040         break;
3041     }
3042     case 8:
3043         m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
3044         break;
3045     default:
3046         RELEASE_ASSERT_NOT_REACHED();
3047     }
3048
3049     JITCompiler::Jump done = jumpForTypedArrayIsNeuteredIfOutOfBounds(node, base, outOfBounds);
3050     if (done.isSet())
3051         done.link(&m_jit);
3052     noResult(node);
3053 }
3054
3055 void SpeculativeJIT::compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg, GPRReg scratch2Reg)
3056 {
3057     // Check that prototype is an object.
3058     speculationCheck(BadType, JSValueRegs(), 0, m_jit.branchIfNotObject(prototypeReg));
3059     
3060     // Initialize scratchReg with the value being checked.
3061     m_jit.move(valueReg, scratchReg);
3062     
3063     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
3064     MacroAssembler::Label loop(&m_jit);
3065     MacroAssembler::Jump performDefaultHasInstance = m_jit.branch8(MacroAssembler::Equal,
3066         MacroAssembler::Address(scratchReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ProxyObjectType));
3067     m_jit.emitLoadStructure(scratchReg, scratchReg, scratch2Reg);
3068     m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + CellPayloadOffset), scratchReg);
3069     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
3070 #if USE(JSVALUE64)
3071     m_jit.branchIfCell(JSValueRegs(scratchReg)).linkTo(loop, &m_jit);
3072 #else
3073     m_jit.branchTestPtr(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
3074 #endif
3075     
3076     // No match - result is false.
3077 #if USE(JSVALUE64)
3078     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
3079 #else
3080     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
3081 #endif
3082     MacroAssembler::JumpList doneJumps; 
3083     doneJumps.append(m_jit.jump());
3084
3085     performDefaultHasInstance.link(&m_jit);
3086     silentSpillAllRegisters(scratchReg);
3087     callOperation(operationDefaultHasInstance, scratchReg, valueReg, prototypeReg); 
3088     silentFillAllRegisters(scratchReg);
3089     m_jit.exceptionCheck();
3090 #if USE(JSVALUE64)
3091     m_jit.or32(TrustedImm32(ValueFalse), scratchReg);
3092 #endif
3093     doneJumps.append(m_jit.jump());
3094     
3095     isInstance.link(&m_jit);
3096 #if USE(JSVALUE64)
3097     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), scratchReg);
3098 #else
3099     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
3100 #endif
3101     
3102     doneJumps.link(&m_jit);
3103 }
3104
3105 void SpeculativeJIT::compileCheckTypeInfoFlags(Node* node)
3106 {
3107     SpeculateCellOperand base(this, node->child1());
3108
3109     GPRReg baseGPR = base.gpr();
3110
3111     speculationCheck(BadTypeInfoFlags, JSValueRegs(), 0, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(baseGPR, JSCell::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(node->typeInfoOperand())));
3112
3113     noResult(node);
3114 }
3115
3116 void SpeculativeJIT::compileInstanceOf(Node* node)
3117 {
3118     if (node->child1().useKind() == UntypedUse) {
3119         // It might not be a cell. Speculate less aggressively.
3120         // Or: it might only be used once (i.e. by us), so we get zero benefit
3121         // from speculating any more aggressively than we absolutely need to.
3122         
3123         JSValueOperand value(this, node->child1());
3124         SpeculateCellOperand prototype(this, node->child2());
3125         GPRTemporary scratch(this);
3126         GPRTemporary scratch2(this);
3127         
3128         GPRReg prototypeReg = prototype.gpr();
3129         GPRReg scratchReg = scratch.gpr();
3130         GPRReg scratch2Reg = scratch2.gpr();
3131         
3132         MacroAssembler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3133         GPRReg valueReg = value.jsValueRegs().payloadGPR();
3134         moveFalseTo(scratchReg);
3135
3136         MacroAssembler::Jump done = m_jit.jump();
3137         
3138         isCell.link(&m_jit);
3139         
3140         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg);
3141         
3142         done.link(&m_jit);
3143
3144         blessedBooleanResult(scratchReg, node);
3145         return;
3146     }
3147     
3148     SpeculateCellOperand value(this, node->child1());
3149     SpeculateCellOperand prototype(this, node->child2());
3150     
3151     GPRTemporary scratch(this);
3152     GPRTemporary scratch2(this);
3153     
3154     GPRReg valueReg = value.gpr();
3155     GPRReg prototypeReg = prototype.gpr();
3156     GPRReg scratchReg = scratch.gpr();
3157     GPRReg scratch2Reg = scratch2.gpr();
3158     
3159     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg);
3160
3161     blessedBooleanResult(scratchReg, node);
3162 }
3163
3164 template<typename SnippetGenerator, J_JITOperation_EJJ snippetSlowPathFunction>
3165 void SpeculativeJIT::emitUntypedBitOp(Node* node)
3166 {
3167     Edge& leftChild = node->child1();
3168     Edge& rightChild = node->child2();
3169
3170     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3171         JSValueOperand left(this, leftChild);
3172         JSValueOperand right(this, rightChild);
3173         JSValueRegs leftRegs = left.jsValueRegs();
3174         JSValueRegs rightRegs = right.jsValueRegs();
3175 #if USE(JSVALUE64)
3176         GPRTemporary result(this);
3177         JSValueRegs resultRegs = JSValueRegs(result.gpr());
3178 #else
3179         GPRTemporary resultTag(this);
3180         GPRTemporary resultPayload(this);
3181         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3182 #endif
3183         flushRegisters();
3184         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3185         m_jit.exceptionCheck();
3186
3187         jsValueResult(resultRegs, node);
3188         return;
3189     }
3190
3191     std::optional<JSValueOperand> left;
3192     std::optional<JSValueOperand> right;
3193
3194     JSValueRegs leftRegs;
3195     JSValueRegs rightRegs;
3196
3197 #if USE(JSVALUE64)
3198     GPRTemporary result(this);
3199     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3200     GPRTemporary scratch(this);
3201     GPRReg scratchGPR = scratch.gpr();
3202 #else
3203     GPRTemporary resultTag(this);
3204     GPRTemporary resultPayload(this);
3205     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3206     GPRReg scratchGPR = resultTag.gpr();
3207 #endif
3208
3209     SnippetOperand leftOperand;
3210     SnippetOperand rightOperand;
3211
3212     // The snippet generator does not support both operands being constant. If the left
3213     // operand is already const, we'll ignore the right operand's constness.
3214     if (leftChild->isInt32Constant())
3215         leftOperand.setConstInt32(leftChild->asInt32());
3216     else if (rightChild->isInt32Constant())
3217         rightOperand.setConstInt32(rightChild->asInt32());
3218
3219     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3220
3221     if (!leftOperand.isConst()) {
3222         left.emplace(this, leftChild);
3223         leftRegs = left->jsValueRegs();
3224     }
3225     if (!rightOperand.isConst()) {
3226         right.emplace(this, rightChild);
3227         rightRegs = right->jsValueRegs();
3228     }
3229
3230     SnippetGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, scratchGPR);
3231     gen.generateFastPath(m_jit);
3232
3233     ASSERT(gen.didEmitFastPath());
3234     gen.endJumpList().append(m_jit.jump());
3235
3236     gen.slowPathJumpList().link(&m_jit);
3237     silentSpillAllRegisters(resultRegs);
3238
3239     if (leftOperand.isConst()) {
3240         leftRegs = resultRegs;
3241         m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3242     } else if (rightOperand.isConst()) {
3243         rightRegs = resultRegs;
3244         m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3245     }
3246
3247     callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3248
3249     silentFillAllRegisters(resultRegs);
3250     m_jit.exceptionCheck();
3251
3252     gen.endJumpList().link(&m_jit);
3253     jsValueResult(resultRegs, node);
3254 }
3255
3256 void SpeculativeJIT::compileBitwiseOp(Node* node)
3257 {
3258     NodeType op = node->op();
3259     Edge& leftChild = node->child1();
3260     Edge& rightChild = node->child2();
3261
3262     if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
3263         switch (op) {
3264         case BitAnd:
3265             emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
3266             return;
3267         case BitOr:
3268             emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
3269             return;
3270         case BitXor:
3271             emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
3272             return;
3273         default:
3274             RELEASE_ASSERT_NOT_REACHED();
3275         }
3276     }
3277
3278     if (leftChild->isInt32Constant()) {
3279         SpeculateInt32Operand op2(this, rightChild);
3280         GPRTemporary result(this, Reuse, op2);
3281
3282         bitOp(op, leftChild->asInt32(), op2.gpr(), result.gpr());
3283
3284         int32Result(result.gpr(), node);
3285
3286     } else if (rightChild->isInt32Constant()) {
3287         SpeculateInt32Operand op1(this, leftChild);
3288         GPRTemporary result(this, Reuse, op1);
3289
3290         bitOp(op, rightChild->asInt32(), op1.gpr(), result.gpr());
3291
3292         int32Result(result.gpr(), node);
3293
3294     } else {
3295         SpeculateInt32Operand op1(this, leftChild);
3296         SpeculateInt32Operand op2(this, rightChild);
3297         GPRTemporary result(this, Reuse, op1, op2);
3298         
3299         GPRReg reg1 = op1.gpr();
3300         GPRReg reg2 = op2.gpr();
3301         bitOp(op, reg1, reg2, result.gpr());
3302         
3303         int32Result(result.gpr(), node);
3304     }
3305 }
3306
3307 void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
3308 {
3309     J_JITOperation_EJJ snippetSlowPathFunction = node->op() == BitRShift
3310         ? operationValueBitRShift : operationValueBitURShift;
3311     JITRightShiftGenerator::ShiftType shiftType = node->op() == BitRShift
3312         ? JITRightShiftGenerator::SignedShift : JITRightShiftGenerator::UnsignedShift;
3313
3314     Edge& leftChild = node->child1();
3315     Edge& rightChild = node->child2();
3316
3317     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3318         JSValueOperand left(this, leftChild);
3319         JSValueOperand right(this, rightChild);
3320         JSValueRegs leftRegs = left.jsValueRegs();
3321         JSValueRegs rightRegs = right.jsValueRegs();
3322 #if USE(JSVALUE64)
3323         GPRTemporary result(this);
3324         JSValueRegs resultRegs = JSValueRegs(result.gpr());
3325 #else
3326         GPRTemporary resultTag(this);
3327         GPRTemporary resultPayload(this);
3328         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3329 #endif
3330         flushRegisters();
3331         callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3332         m_jit.exceptionCheck();
3333
3334         jsValueResult(resultRegs, node);
3335         return;
3336     }
3337
3338     std::optional<JSValueOperand> left;
3339     std::optional<JSValueOperand> right;
3340
3341     JSValueRegs leftRegs;
3342     JSValueRegs rightRegs;
3343
3344     FPRTemporary leftNumber(this);
3345     FPRReg leftFPR = leftNumber.fpr();
3346
3347 #if USE(JSVALUE64)
3348     GPRTemporary result(this);
3349     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3350     GPRTemporary scratch(this);
3351     GPRReg scratchGPR = scratch.gpr();
3352     FPRReg scratchFPR = InvalidFPRReg;
3353 #else
3354     GPRTemporary resultTag(this);
3355     GPRTemporary resultPayload(this);
3356     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3357     GPRReg scratchGPR = resultTag.gpr();
3358     FPRTemporary fprScratch(this);
3359     FPRReg scratchFPR = fprScratch.fpr();
3360 #endif
3361
3362     SnippetOperand leftOperand;
3363     SnippetOperand rightOperand;
3364
3365     // The snippet generator does not support both operands being constant. If the left
3366     // operand is already const, we'll ignore the right operand's constness.
3367     if (leftChild->isInt32Constant())
3368         leftOperand.setConstInt32(leftChild->asInt32());
3369     else if (rightChild->isInt32Constant())
3370         rightOperand.setConstInt32(rightChild->asInt32());
3371
3372     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3373
3374     if (!leftOperand.isConst()) {
3375         left.emplace(this, leftChild);
3376         leftRegs = left->jsValueRegs();
3377     }
3378     if (!rightOperand.isConst()) {
3379         right.emplace(this, rightChild);
3380         rightRegs = right->jsValueRegs();
3381     }
3382
3383     JITRightShiftGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
3384         leftFPR, scratchGPR, scratchFPR, shiftType);
3385     gen.generateFastPath(m_jit);
3386
3387     ASSERT(gen.didEmitFastPath());
3388     gen.endJumpList().append(m_jit.jump());
3389
3390     gen.slowPathJumpList().link(&m_jit);
3391     silentSpillAllRegisters(resultRegs);
3392
3393     if (leftOperand.isConst()) {
3394         leftRegs = resultRegs;
3395         m_jit.moveValue(leftChild->asJSValue(), leftRegs);
3396     } else if (rightOperand.isConst()) {
3397         rightRegs = resultRegs;
3398         m_jit.moveValue(rightChild->asJSValue(), rightRegs);
3399     }
3400
3401     callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
3402
3403     silentFillAllRegisters(resultRegs);
3404     m_jit.exceptionCheck();
3405
3406     gen.endJumpList().link(&m_jit);
3407     jsValueResult(resultRegs, node);
3408     return;
3409 }
3410
3411 void SpeculativeJIT::compileShiftOp(Node* node)
3412 {
3413     NodeType op = node->op();
3414     Edge& leftChild = node->child1();
3415     Edge& rightChild = node->child2();
3416
3417     if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
3418         switch (op) {
3419         case BitLShift:
3420             emitUntypedBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
3421             return;
3422         case BitRShift:
3423         case BitURShift:
3424             emitUntypedRightShiftBitOp(node);
3425             return;
3426         default:
3427             RELEASE_ASSERT_NOT_REACHED();
3428         }
3429     }
3430
3431     if (rightChild->isInt32Constant()) {
3432         SpeculateInt32Operand op1(this, leftChild);
3433         GPRTemporary result(this, Reuse, op1);
3434
3435         shiftOp(op, op1.gpr(), rightChild->asInt32() & 0x1f, result.gpr());
3436
3437         int32Result(result.gpr(), node);
3438     } else {
3439         // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
3440         SpeculateInt32Operand op1(this, leftChild);
3441         SpeculateInt32Operand op2(this, rightChild);
3442         GPRTemporary result(this, Reuse, op1);
3443
3444         GPRReg reg1 = op1.gpr();
3445         GPRReg reg2 = op2.gpr();
3446         shiftOp(op, reg1, reg2, result.gpr());
3447
3448         int32Result(result.gpr(), node);
3449     }
3450 }
3451
3452 void SpeculativeJIT::compileValueAdd(Node* node)
3453 {
3454     Edge& leftChild = node->child1();
3455     Edge& rightChild = node->child2();
3456
3457     if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
3458         JSValueOperand left(this, leftChild);
3459         JSValueOperand right(this, rightChild);
3460         JSValueRegs leftRegs = left.jsValueRegs();
3461         JSValueRegs rightRegs = right.jsValueRegs();
3462 #if USE(JSVALUE64)
3463         GPRTemporary result(this);
3464         JSValueRegs resultRegs = JSValueRegs(result.gpr());
3465 #else
3466         GPRTemporary resultTag(this);
3467         GPRTemporary resultPayload(this);
3468         JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3469 #endif
3470         flushRegisters();
3471         callOperation(operationValueAddNotNumber, resultRegs, leftRegs, rightRegs);
3472         m_jit.exceptionCheck();
3473     
3474         jsValueResult(resultRegs, node);
3475         return;
3476     }
3477
3478 #if USE(JSVALUE64)
3479     bool needsScratchGPRReg = true;
3480     bool needsScratchFPRReg = false;
3481 #else
3482     bool needsScratchGPRReg = true;
3483     bool needsScratchFPRReg = true;
3484 #endif
3485
3486     ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node->origin.semantic)->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex);
3487     JITAddIC* addIC = m_jit.codeBlock()->addJITAddIC(arithProfile);
3488     auto repatchingFunction = operationValueAddOptimize;
3489     auto nonRepatchingFunction = operationValueAdd;
3490     
3491     compileMathIC(node, addIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
3492 }
3493
3494 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction>
3495 void SpeculativeJIT::compileMathIC(Node* node, JITBinaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
3496 {
3497     Edge& leftChild = node->child1();
3498     Edge& rightChild = node->child2();
3499
3500     std::optional<JSValueOperand> left;
3501     std::optional<JSValueOperand> right;
3502
3503     JSValueRegs leftRegs;
3504     JSValueRegs rightRegs;
3505
3506     FPRTemporary leftNumber(this);
3507     FPRTemporary rightNumber(this);
3508     FPRReg leftFPR = leftNumber.fpr();
3509     FPRReg rightFPR = rightNumber.fpr();
3510
3511     GPRReg scratchGPR = InvalidGPRReg;
3512     FPRReg scratchFPR = InvalidFPRReg;
3513
3514     std::optional<FPRTemporary> fprScratch;
3515     if (needsScratchFPRReg) {
3516         fprScratch.emplace(this);
3517         scratchFPR = fprScratch->fpr();
3518     }
3519
3520 #if USE(JSVALUE64)
3521     std::optional<GPRTemporary> gprScratch;
3522     if (needsScratchGPRReg) {
3523         gprScratch.emplace(this);
3524         scratchGPR = gprScratch->gpr();
3525     }
3526     GPRTemporary result(this);
3527     JSValueRegs resultRegs = JSValueRegs(result.gpr());
3528 #else
3529     GPRTemporary resultTag(this);
3530     GPRTemporary resultPayload(this);
3531     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
3532     if (needsScratchGPRReg)
3533         scratchGPR = resultRegs.tagGPR();
3534 #endif
3535
3536     SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
3537     SnippetOperand rightOperand(m_state.forNode(rightChild).resultType());
3538
3539     // The snippet generator does not support both operands being constant. If the left
3540     // operand is already const, we'll ignore the right operand's constness.
3541     if (leftChild->isInt32Constant())
3542         leftOperand.setConstInt32(leftChild->asInt32());
3543     else if (rightChild->isInt32Constant())
3544         rightOperand.setConstInt32(rightChild->asInt32());
3545
3546     ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
3547     ASSERT(!(Generator::isLeftOperandValidConstant(leftOperand) && Generator::isRightOperandValidConstant(rightOperand)));
3548
3549     if (!Generator::isLeftOperandValidConstant(leftOperand)) {
3550         left.emplace(this, leftChild);
3551         leftRegs = left->jsValueRegs();
3552     }
3553     if (!Generator::isRightOperandValidConstant(rightOperand)) {
3554         right.emplace(this, rightChild);
3555         rightRegs = right->jsValueRegs();
3556     }
3557
3558 #if ENABLE(MATH_IC_STATS)
3559     auto inlineStart = m_jit.label();
3560 #endif
3561
3562     Box<MathICGenerationState> addICGenerationState = Box<MathICGenerationState>::create();
3563     mathIC->m_generator = Generator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, leftFPR, rightFPR, scratchGPR, scratchFPR);
3564
3565     bool shouldEmitProfiling = false;
3566     bool generatedInline = mathIC->generateInline(m_jit, *addICGenerationState, shouldEmitProfiling);
3567
3568     if (generatedInline) {
3569         ASSERT(!addICGenerationState->slowPathJumps.empty());
3570
3571         Vector<SilentRegisterSavePlan> savePlans;
3572         silentSpillAllRegistersImpl(false, savePlans, resultRegs);
3573
3574         auto done = m_jit.label();
3575
3576         addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () {
3577             addICGenerationState->slowPathJumps.link(&m_jit);
3578             addICGenerationState->slowPathStart = m_jit.label();
3579 #if ENABLE(MATH_IC_STATS)
3580             auto slowPathStart = m_jit.label();
3581 #endif
3582
3583             silentSpill(savePlans);
3584
3585             auto innerLeftRegs = leftRegs;
3586             auto innerRightRegs = rightRegs;
3587             if (Generator::isLeftOperandValidConstant(leftOperand)) {
3588                 innerLeftRegs = resultRegs;
3589                 m_jit.moveValue(leftChild->asJSValue(), innerLeftRegs);
3590             } else if (Generator::isRightOperandValidConstant(rightOperand)) {
3591                 innerRightRegs = resultRegs;
3592                 m_jit.moveValue(rightChild->asJSValue(), innerRightRegs);
3593             }
3594
3595             if (addICGenerationState->shouldSlowPathRepatch)
3596                 addICGenerationState->slowPathCall = callOperation(bitwise_cast<J_JITOperation_EJJMic>(repatchingFunction), resultRegs, innerLeftRegs, innerRightRegs, TrustedImmPtr(mathIC));
3597             else
3598                 addICGenerationState->slowPathCall = callOperation(nonRepatchingFunction, resultRegs, innerLeftRegs, innerRightRegs);
3599
3600             silentFill(savePlans);
3601             m_jit.exceptionCheck();
3602             m_jit.jump().linkTo(done, &m_jit);
3603
3604             m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
3605                 mathIC->finalizeInlineCode(*addICGenerationState, linkBuffer);
3606             });
3607
3608 #if ENABLE(MATH_IC_STATS)
3609             auto slowPathEnd = m_jit.label();
3610             m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
3611                 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress());
3612                 mathIC->m_generatedCodeSize += size;
3613             });
3614 #endif
3615
3616         });
3617     } else {
3618         if (Generator::isLeftOperandValidConstant(leftOperand)) {
3619             left.emplace(this, leftChild);
3620             leftRegs = left->jsValueRegs();
3621         } else if (Generator::isRightOperandValidConstant(rightOperand)) {
3622             right.emplace(this, rightChild);
3623             rightRegs = right->jsValueRegs();
3624         }
3625
3626         flushRegisters();
3627         callOperation(nonRepatchingFunction, resultRegs, leftRegs, rightRegs);
3628         m_jit.exceptionCheck();
3629     }
3630
3631 #if ENABLE(MATH_IC_STATS)
3632     auto inlineEnd = m_jit.label();
3633     m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
3634         size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress());
3635         mathIC->m_generatedCodeSize += size;
3636     });
3637 #endif
3638
3639     jsValueResult(resultRegs, node);
3640     return;
3641 }
3642
3643 void SpeculativeJIT::compileInstanceOfCustom(Node* node)
3644 {
3645     // We could do something smarter here but this case is currently super rare and unless
3646     // Symbol.hasInstance becomes popular will likely remain that way.
3647
3648     JSValueOperand value(this, node->child1());
3649     SpeculateCellOperand constructor(this, node->child2());
3650     JSValueOperand hasInstanceValue(this, node->child3());
3651     GPRTemporary result(this);
3652
3653     JSValueRegs valueRegs = value.jsValueRegs();
3654     GPRReg constructorGPR = constructor.gpr();
3655     JSValueRegs hasInstanceRegs = hasInstanceValue.jsValueRegs();
3656     GPRReg resultGPR = result.gpr();
3657
3658     MacroAssembler::Jump slowCase = m_jit.jump();
3659
3660     addSlowPathGenerator(slowPathCall(slowCase, this, operationInstanceOfCustom, resultGPR, valueRegs, constructorGPR, hasInstanceRegs));
3661
3662     unblessedBooleanResult(resultGPR, node);
3663 }
3664
3665 void SpeculativeJIT::compileIsCellWithType(Node* node)
3666 {
3667     switch (node->child1().useKind()) {
3668     case UntypedUse: {
3669         JSValueOperand value(this, node->child1());
3670 #if USE(JSVALUE64)
3671         GPRTemporary result(this, Reuse, value);
3672 #else
3673         GPRTemporary result(this, Reuse, value, PayloadWord);
3674 #endif
3675
3676         JSValueRegs valueRegs = value.jsValueRegs();
3677         GPRReg resultGPR = result.gpr();
3678
3679         JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
3680
3681         m_jit.compare8(JITCompiler::Equal,
3682             JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()),
3683             TrustedImm32(node->queriedType()),
3684             resultGPR);
3685         blessBoolean(resultGPR);
3686         JITCompiler::Jump done = m_jit.jump();
3687
3688         isNotCell.link(&m_jit);
3689         moveFalseTo(resultGPR);
3690
3691         done.link(&m_jit);
3692         blessedBooleanResult(resultGPR, node);
3693         return;
3694     }
3695
3696     case CellUse: {
3697         SpeculateCellOperand cell(this, node->child1());
3698         GPRTemporary result(this, Reuse, cell);
3699
3700         GPRReg cellGPR = cell.gpr();
3701         GPRReg resultGPR = result.gpr();
3702
3703         m_jit.compare8(JITCompiler::Equal,
3704             JITCompiler::Address(cellGPR, JSCell::typeInfoTypeOffset()),
3705             TrustedImm32(node->queriedType()),
3706             resultGPR);
3707         blessBoolean(resultGPR);
3708         blessedBooleanResult(resultGPR, node);
3709         return;
3710     }
3711
3712     default:
3713         RELEASE_ASSERT_NOT_REACHED();
3714         break;
3715     }
3716 }
3717
3718 void SpeculativeJIT::compileIsTypedArrayView(Node* node)
3719 {
3720     JSValueOperand value(this, node->child1());
3721 #if USE(JSVALUE64)
3722     GPRTemporary result(this, Reuse, value);
3723 #else
3724     GPRTemporary result(this, Reuse, value, PayloadWord);
3725 #endif
3726
3727     JSValueRegs valueRegs = value.jsValueRegs();
3728     GPRReg resultGPR = result.gpr();
3729
3730     JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
3731
3732     m_jit.load8(JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()), resultGPR);
3733     m_jit.sub32(TrustedImm32(Int8ArrayType), resultGPR);
3734     m_jit.compare32(JITCompiler::BelowOrEqual,
3735         resultGPR,
3736         TrustedImm32(Float64ArrayType - Int8ArrayType),
3737         resultGPR);
3738     blessBoolean(resultGPR);
3739     JITCompiler::Jump done = m_jit.jump();
3740
3741     isNotCell.link(&m_jit);
3742     moveFalseTo(resultGPR);
3743
3744     done.link(&m_jit);
3745     blessedBooleanResult(resultGPR, node);
3746 }
3747
3748 void SpeculativeJIT::compileCallObjectConstructor(Node* node)
3749 {
3750     RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
3751     JSValueOperand value(this, node->child1());
3752 #if USE(JSVALUE64)
3753     GPRTemporary result(this, Reuse, value);
3754 #else
3755     GPRTemporary result(this, Reuse, value, PayloadWord);
3756 #endif
3757
3758     JSValueRegs valueRegs = value.jsValueRegs();
3759     GPRReg resultGPR = result.gpr();
3760
3761     MacroAssembler::JumpList slowCases;
3762     slowCases.append(m_jit.branchIfNotCell(valueRegs));
3763     slowCases.append(m_jit.branchIfNotObject(valueRegs.payloadGPR()));
3764     m_jit.move(valueRegs.payloadGPR(), resultGPR);
3765
3766     addSlowPathGenerator(slowPathCall(slowCases, this, operationObjectConstructor, resultGPR, m_jit.globalObjectFor(node->origin.semantic), valueRegs));
3767     cellResult(resultGPR, node);
3768 }
3769
3770 void SpeculativeJIT::compileArithAdd(Node* node)
3771 {
3772     switch (node->binaryUseKind()) {
3773     case Int32Use: {
3774         ASSERT(!shouldCheckNegativeZero(node->arithMode()));
3775
3776         if (node->child2()->isInt32Constant()) {
3777             SpeculateInt32Operand op1(this, node->child1());
3778             GPRTemporary result(this, Reuse, op1);
3779
3780             GPRReg gpr1 = op1.gpr();
3781             int32_t imm2 = node->child2()->asInt32();
3782             GPRReg gprResult = result.gpr();
3783
3784             if (!shouldCheckOverflow(node->arithMode())) {
3785                 m_jit.add32(Imm32(imm2), gpr1, gprResult);
3786                 int32Result(gprResult, node);
3787                 return;
3788             }
3789
3790             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, Imm32(imm2), gprResult);
3791             if (gpr1 == gprResult) {
3792                 speculationCheck(Overflow, JSValueRegs(), 0, check,
3793                     SpeculationRecovery(SpeculativeAddImmediate, gpr1, imm2));
3794             } else
3795                 speculationCheck(Overflow, JSValueRegs(), 0, check);
3796
3797             int32Result(gprResult, node);
3798             return;
3799         }
3800                 
3801         SpeculateInt32Operand op1(this, node->child1());
3802         SpeculateInt32Operand op2(this, node->child2());
3803         GPRTemporary result(this, Reuse, op1, op2);
3804
3805         GPRReg gpr1 = op1.gpr();
3806         GPRReg gpr2 = op2.gpr();
3807         GPRReg gprResult = result.gpr();
3808
3809         if (!shouldCheckOverflow(node->arithMode()))
3810             m_jit.add32(gpr1, gpr2, gprResult);
3811         else {
3812             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
3813                 
3814             if (gpr1 == gprResult)
3815                 speculationCheck(Overflow, JSValueRegs(), 0, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
3816             else if (gpr2 == gprResult)
3817                 speculationCheck(Overflow, JSValueRegs(), 0, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
3818             else
3819                 speculationCheck(Overflow, JSValueRegs(), 0, check);
3820         }
3821
3822         int32Result(gprResult, node);
3823         return;
3824     }
3825         
3826 #if USE(JSVALUE64)
3827     case Int52RepUse: {
3828         ASSERT(shouldCheckOverflow(node->arithMode()));
3829         ASSERT(!shouldCheckNegativeZero(node->arithMode()));
3830
3831         // Will we need an overflow check? If we can prove that neither input can be
3832         // Int52 then the overflow check will not be necessary.
3833         if (!m_state.forNode(node->child1()).couldBeType(SpecInt52Only)
3834             && !m_state.forNode(node->child2()).couldBeType(SpecInt52Only)) {
3835             SpeculateWhicheverInt52Operand op1(this, node->child1());
3836             SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
3837             GPRTemporary result(this, Reuse, op1);
3838             m_jit.add64(op1.gpr(), op2.gpr(), result.gpr());
3839             int52Result(result.gpr(), node, op1.format());
3840             return;
3841         }
3842         
3843         SpeculateInt52Operand op1(this, node->child1());
3844         SpeculateInt52Operand op2(this, node->child2());
3845         GPRTemporary result(this);
3846         m_jit.move(op1.gpr(), result.gpr());
3847         speculationCheck(
3848             Int52Overflow, JSValueRegs(), 0,
3849             m_jit.branchAdd64(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
3850         int52Result(result.gpr(), node);
3851         return;
3852     }
3853 #endif // USE(JSVALUE64)
3854     
3855     case DoubleRepUse: {
3856         SpeculateDoubleOperand op1(this, node->child1());
3857         SpeculateDoubleOperand op2(this, node->child2());
3858         FPRTemporary result(this, op1, op2);
3859
3860         FPRReg reg1 = op1.fpr();
3861         FPRReg reg2 = op2.fpr();
3862         m_jit.addDouble(reg1, reg2, result.fpr());
3863
3864         doubleResult(result.fpr(), node);
3865         return;
3866     }
3867         
3868     default:
3869         RELEASE_ASSERT_NOT_REACHED();
3870         break;
3871     }
3872 }
3873
3874 void SpeculativeJIT::compileMakeRope(Node* node)
3875 {
3876     ASSERT(node->child1().useKind() == KnownStringUse);
3877     ASSERT(node->child2().useKind() == KnownStringUse);
3878     ASSERT(!node->child3() || node->child3().useKind() == KnownStringUse);
3879     
3880     SpeculateCellOperand op1(this, node->child1());
3881     SpeculateCellOperand op2(this, node->child2());
3882     SpeculateCellOperand op3(this, node->child3());
3883     GPRTemporary result(this);
3884     GPRTemporary allocator(this);
3885     GPRTemporary scratch(this);
3886     
3887     GPRReg opGPRs[3];
3888     unsigned numOpGPRs;
3889     opGPRs[0] = op1.gpr();