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