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