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