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