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