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