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