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