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