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