1/*
2 * Copyright (C) 2011-2019 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 "ArrayPrototype.h"
32#include "AtomicsObject.h"
33#include "CallFrameShuffler.h"
34#include "DFGAbstractInterpreterInlines.h"
35#include "DFGCallArrayAllocatorSlowPathGenerator.h"
36#include "DFGDoesGC.h"
37#include "DFGOperations.h"
38#include "DFGSlowPathGenerator.h"
39#include "DirectArguments.h"
40#include "GetterSetter.h"
41#include "HasOwnPropertyCache.h"
42#include "JSCInlines.h"
43#include "JSLexicalEnvironment.h"
44#include "JSMap.h"
45#include "JSPropertyNameEnumerator.h"
46#include "JSSet.h"
47#include "ObjectPrototype.h"
48#include "SetupVarargsFrame.h"
49#include "SpillRegistersMode.h"
50#include "StringPrototype.h"
51#include "SuperSampler.h"
52#include "Watchdog.h"
53
54namespace JSC { namespace DFG {
55
56#if USE(JSVALUE64)
57
58void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format)
59{
60 GPRReg tempGPR;
61 if (sourceGPR == targetGPR)
62 tempGPR = allocate();
63 else
64 tempGPR = targetGPR;
65
66 FPRReg fpr = fprAllocate();
67
68 if (format == DataFormatInt52)
69 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
70 else
71 ASSERT(format == DataFormatStrictInt52);
72
73 m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr);
74
75 if (format == DataFormatInt52 && sourceGPR != targetGPR)
76 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
77
78 if (tempGPR != targetGPR)
79 unlock(tempGPR);
80
81 unlock(fpr);
82}
83
84GPRReg SpeculativeJIT::fillJSValue(Edge edge)
85{
86 VirtualRegister virtualRegister = edge->virtualRegister();
87 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
88
89 switch (info.registerFormat()) {
90 case DataFormatNone: {
91 GPRReg gpr = allocate();
92
93 if (edge->hasConstant()) {
94 JSValue jsValue = edge->asJSValue();
95 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
96 info.fillJSValue(*m_stream, gpr, DataFormatJS);
97 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
98 } else {
99 DataFormat spillFormat = info.spillFormat();
100 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
101 switch (spillFormat) {
102 case DataFormatInt32: {
103 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
104 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
105 spillFormat = DataFormatJSInt32;
106 break;
107 }
108
109 default:
110 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
111 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS, spillFormat);
112 break;
113 }
114 info.fillJSValue(*m_stream, gpr, spillFormat);
115 }
116 return gpr;
117 }
118
119 case DataFormatInt32: {
120 GPRReg gpr = info.gpr();
121 // If the register has already been locked we need to take a copy.
122 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
123 if (m_gprs.isLocked(gpr)) {
124 GPRReg result = allocate();
125 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
126 return result;
127 }
128 m_gprs.lock(gpr);
129 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
130 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
131 return gpr;
132 }
133
134 case DataFormatCell:
135 // No retag required on JSVALUE64!
136 case DataFormatJS:
137 case DataFormatJSInt32:
138 case DataFormatJSDouble:
139 case DataFormatJSCell:
140 case DataFormatJSBoolean: {
141 GPRReg gpr = info.gpr();
142 m_gprs.lock(gpr);
143 return gpr;
144 }
145
146 case DataFormatBoolean:
147 case DataFormatStorage:
148 case DataFormatDouble:
149 case DataFormatInt52:
150 // this type currently never occurs
151 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
152
153 default:
154 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
155 return InvalidGPRReg;
156 }
157}
158
159void SpeculativeJIT::cachedGetById(CodeOrigin origin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget , SpillRegistersMode mode, AccessType type)
160{
161 cachedGetById(origin, base.gpr(), result.gpr(), identifierNumber, slowPathTarget, mode, type);
162}
163
164void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode, AccessType type)
165{
166 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
167 RegisterSet usedRegisters = this->usedRegisters();
168 if (spillMode == DontSpill) {
169 // We've already flushed registers to the stack, we don't need to spill these.
170 usedRegisters.set(baseGPR, false);
171 usedRegisters.set(resultGPR, false);
172 }
173 JITGetByIdGenerator gen(
174 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
175 JSValueRegs(baseGPR), JSValueRegs(resultGPR), type);
176 gen.generateFastPath(m_jit);
177
178 JITCompiler::JumpList slowCases;
179 slowCases.append(slowPathTarget);
180 slowCases.append(gen.slowPathJump());
181
182 std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
183 slowCases, this, appropriateOptimizingGetByIdFunction(type),
184 spillMode, ExceptionCheckRequirement::CheckNeeded,
185 resultGPR, gen.stubInfo(), baseGPR, identifierUID(identifierNumber));
186
187 m_jit.addGetById(gen, slowPath.get());
188 addSlowPathGenerator(WTFMove(slowPath));
189}
190
191void SpeculativeJIT::cachedGetByIdWithThis(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg thisGPR, GPRReg resultGPR, unsigned identifierNumber, const JITCompiler::JumpList& slowPathTarget)
192{
193 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
194 RegisterSet usedRegisters = this->usedRegisters();
195 // We've already flushed registers to the stack, we don't need to spill these.
196 usedRegisters.set(baseGPR, false);
197 usedRegisters.set(thisGPR, false);
198 usedRegisters.set(resultGPR, false);
199
200 JITGetByIdWithThisGenerator gen(
201 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
202 JSValueRegs(resultGPR), JSValueRegs(baseGPR), JSValueRegs(thisGPR), AccessType::GetWithThis);
203 gen.generateFastPath(m_jit);
204
205 JITCompiler::JumpList slowCases;
206 slowCases.append(slowPathTarget);
207 slowCases.append(gen.slowPathJump());
208
209 std::unique_ptr<SlowPathGenerator> slowPath = slowPathCall(
210 slowCases, this, operationGetByIdWithThisOptimize,
211 DontSpill, ExceptionCheckRequirement::CheckNeeded,
212 resultGPR, gen.stubInfo(), baseGPR, thisGPR, identifierUID(identifierNumber));
213
214 m_jit.addGetByIdWithThis(gen, slowPath.get());
215 addSlowPathGenerator(WTFMove(slowPath));
216}
217
218void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
219{
220 JSValueOperand arg(this, operand, ManualOperandSpeculation);
221 GPRReg argGPR = arg.gpr();
222
223 GPRTemporary result(this);
224 GPRReg resultGPR = result.gpr();
225
226 m_jit.move(TrustedImm32(0), resultGPR);
227
228 JITCompiler::JumpList done;
229 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
230 if (!isKnownNotCell(operand.node()))
231 done.append(m_jit.branchIfCell(JSValueRegs(argGPR)));
232 } else {
233 GPRTemporary localGlobalObject(this);
234 GPRTemporary remoteGlobalObject(this);
235 GPRTemporary scratch(this);
236
237 JITCompiler::Jump notCell;
238 if (!isKnownCell(operand.node()))
239 notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
240
241 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
242 JITCompiler::Zero,
243 JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()),
244 JITCompiler::TrustedImm32(MasqueradesAsUndefined));
245 done.append(isNotMasqueradesAsUndefined);
246
247 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
248 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
249 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
250 m_jit.emitLoadStructure(*m_jit.vm(), argGPR, resultGPR, scratch.gpr());
251 m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
252 m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
253 done.append(m_jit.jump());
254 if (!isKnownCell(operand.node()))
255 notCell.link(&m_jit);
256 }
257
258 if (!isKnownNotOther(operand.node())) {
259 m_jit.move(argGPR, resultGPR);
260 m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
261 m_jit.compare64(JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
262 }
263
264 done.link(&m_jit);
265
266 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
267 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
268}
269
270void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode)
271{
272 BasicBlock* taken = branchNode->branchData()->taken.block;
273 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
274
275 JSValueOperand arg(this, operand, ManualOperandSpeculation);
276 GPRReg argGPR = arg.gpr();
277
278 GPRTemporary result(this, Reuse, arg);
279 GPRReg resultGPR = result.gpr();
280
281 // First, handle the case where "operand" is a cell.
282 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
283 if (!isKnownNotCell(operand.node())) {
284 JITCompiler::Jump isCell = m_jit.branchIfCell(JSValueRegs(argGPR));
285 addBranch(isCell, notTaken);
286 }
287 } else {
288 GPRTemporary localGlobalObject(this);
289 GPRTemporary remoteGlobalObject(this);
290 GPRTemporary scratch(this);
291
292 JITCompiler::Jump notCell;
293 if (!isKnownCell(operand.node()))
294 notCell = m_jit.branchIfNotCell(JSValueRegs(argGPR));
295
296 branchTest8(JITCompiler::Zero,
297 JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()),
298 JITCompiler::TrustedImm32(MasqueradesAsUndefined), notTaken);
299
300 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
301 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
302 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
303 m_jit.emitLoadStructure(*m_jit.vm(), argGPR, resultGPR, scratch.gpr());
304 m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
305 branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, taken);
306
307 if (!isKnownCell(operand.node())) {
308 jump(notTaken, ForceJump);
309 notCell.link(&m_jit);
310 }
311 }
312
313 if (isKnownNotOther(operand.node()))
314 jump(notTaken);
315 else {
316 JITCompiler::RelationalCondition condition = JITCompiler::Equal;
317 if (taken == nextBlock()) {
318 condition = JITCompiler::NotEqual;
319 std::swap(taken, notTaken);
320 }
321 m_jit.move(argGPR, resultGPR);
322 m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
323 branch64(condition, resultGPR, JITCompiler::TrustedImm64(ValueNull), taken);
324 jump(notTaken);
325 }
326}
327
328void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
329{
330 BasicBlock* taken = branchNode->branchData()->taken.block;
331 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
332
333 // The branch instruction will branch to the taken block.
334 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
335 if (taken == nextBlock()) {
336 invert = !invert;
337 BasicBlock* tmp = taken;
338 taken = notTaken;
339 notTaken = tmp;
340 }
341
342 JSValueOperand arg1(this, node->child1());
343 JSValueOperand arg2(this, node->child2());
344 GPRReg arg1GPR = arg1.gpr();
345 GPRReg arg2GPR = arg2.gpr();
346
347 GPRTemporary result(this);
348 GPRReg resultGPR = result.gpr();
349
350 arg1.use();
351 arg2.use();
352
353 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
354 // see if we get lucky: if the arguments are cells and they reference the same
355 // cell, then they must be strictly equal.
356 branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
357
358 silentSpillAllRegisters(resultGPR);
359 callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
360 silentFillAllRegisters();
361 m_jit.exceptionCheck();
362
363 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
364 } else {
365 m_jit.or64(arg1GPR, arg2GPR, resultGPR);
366
367 JITCompiler::Jump twoCellsCase = m_jit.branchIfCell(resultGPR);
368
369 JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1GPR);
370 JITCompiler::Jump leftDouble = m_jit.branchIfNumber(arg1GPR);
371 leftOK.link(&m_jit);
372 JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2GPR);
373 JITCompiler::Jump rightDouble = m_jit.branchIfNumber(arg2GPR);
374 rightOK.link(&m_jit);
375
376 branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
377 jump(notTaken, ForceJump);
378
379 twoCellsCase.link(&m_jit);
380 branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
381
382 leftDouble.link(&m_jit);
383 rightDouble.link(&m_jit);
384
385 silentSpillAllRegisters(resultGPR);
386 callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
387 silentFillAllRegisters();
388 m_jit.exceptionCheck();
389
390 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
391 }
392
393 jump(notTaken);
394}
395
396void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
397{
398 JSValueOperand arg1(this, node->child1());
399 JSValueOperand arg2(this, node->child2());
400 JSValueRegs arg1Regs = arg1.jsValueRegs();
401 JSValueRegs arg2Regs = arg2.jsValueRegs();
402
403 GPRTemporary result(this);
404 GPRReg resultGPR = result.gpr();
405
406 arg1.use();
407 arg2.use();
408
409 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
410 // see if we get lucky: if the arguments are cells and they reference the same
411 // cell, then they must be strictly equal.
412 // FIXME: this should flush registers instead of silent spill/fill.
413 JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr());
414
415 m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR);
416
417 JITCompiler::Jump done = m_jit.jump();
418
419 notEqualCase.link(&m_jit);
420
421 silentSpillAllRegisters(resultGPR);
422 callOperation(operationCompareStrictEqCell, resultGPR, arg1Regs, arg2Regs);
423 silentFillAllRegisters();
424 m_jit.exceptionCheck();
425
426 done.link(&m_jit);
427 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
428 return;
429 }
430
431 m_jit.or64(arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
432
433 JITCompiler::JumpList slowPathCases;
434
435 JITCompiler::Jump twoCellsCase = m_jit.branchIfCell(resultGPR);
436
437 JITCompiler::Jump leftOK = m_jit.branchIfInt32(arg1Regs);
438 slowPathCases.append(m_jit.branchIfNumber(arg1Regs, InvalidGPRReg));
439 leftOK.link(&m_jit);
440 JITCompiler::Jump rightOK = m_jit.branchIfInt32(arg2Regs);
441 slowPathCases.append(m_jit.branchIfNumber(arg2Regs, InvalidGPRReg));
442 rightOK.link(&m_jit);
443
444 m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1Regs.gpr(), arg2Regs.gpr(), resultGPR);
445
446 JITCompiler::Jump done = m_jit.jump();
447
448 twoCellsCase.link(&m_jit);
449 slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1Regs.gpr(), arg2Regs.gpr()));
450
451 m_jit.move(JITCompiler::TrustedImm64(!invert), resultGPR);
452
453 addSlowPathGenerator(slowPathCall(slowPathCases, this, operationCompareStrictEq, resultGPR, arg1Regs, arg2Regs));
454
455 done.link(&m_jit);
456
457 unblessedBooleanResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);
458}
459
460void SpeculativeJIT::emitCall(Node* node)
461{
462 CallLinkInfo::CallType callType;
463 bool isVarargs = false;
464 bool isForwardVarargs = false;
465 bool isTail = false;
466 bool isEmulatedTail = false;
467 bool isDirect = false;
468 switch (node->op()) {
469 case Call:
470 case CallEval:
471 callType = CallLinkInfo::Call;
472 break;
473 case TailCall:
474 callType = CallLinkInfo::TailCall;
475 isTail = true;
476 break;
477 case TailCallInlinedCaller:
478 callType = CallLinkInfo::Call;
479 isEmulatedTail = true;
480 break;
481 case Construct:
482 callType = CallLinkInfo::Construct;
483 break;
484 case CallVarargs:
485 callType = CallLinkInfo::CallVarargs;
486 isVarargs = true;
487 break;
488 case TailCallVarargs:
489 callType = CallLinkInfo::TailCallVarargs;
490 isVarargs = true;
491 isTail = true;
492 break;
493 case TailCallVarargsInlinedCaller:
494 callType = CallLinkInfo::CallVarargs;
495 isVarargs = true;
496 isEmulatedTail = true;
497 break;
498 case ConstructVarargs:
499 callType = CallLinkInfo::ConstructVarargs;
500 isVarargs = true;
501 break;
502 case CallForwardVarargs:
503 callType = CallLinkInfo::CallVarargs;
504 isForwardVarargs = true;
505 break;
506 case ConstructForwardVarargs:
507 callType = CallLinkInfo::ConstructVarargs;
508 isForwardVarargs = true;
509 break;
510 case TailCallForwardVarargs:
511 callType = CallLinkInfo::TailCallVarargs;
512 isTail = true;
513 isForwardVarargs = true;
514 break;
515 case TailCallForwardVarargsInlinedCaller:
516 callType = CallLinkInfo::CallVarargs;
517 isEmulatedTail = true;
518 isForwardVarargs = true;
519 break;
520 case DirectCall:
521 callType = CallLinkInfo::DirectCall;
522 isDirect = true;
523 break;
524 case DirectConstruct:
525 callType = CallLinkInfo::DirectConstruct;
526 isDirect = true;
527 break;
528 case DirectTailCall:
529 callType = CallLinkInfo::DirectTailCall;
530 isTail = true;
531 isDirect = true;
532 break;
533 case DirectTailCallInlinedCaller:
534 callType = CallLinkInfo::DirectCall;
535 isEmulatedTail = true;
536 isDirect = true;
537 break;
538 default:
539 DFG_CRASH(m_jit.graph(), node, "bad node type");
540 break;
541 }
542
543 GPRReg calleeGPR = InvalidGPRReg;
544 CallFrameShuffleData shuffleData;
545
546 ExecutableBase* executable = nullptr;
547 FunctionExecutable* functionExecutable = nullptr;
548 if (isDirect) {
549 executable = node->castOperand<ExecutableBase*>();
550 functionExecutable = jsDynamicCast<FunctionExecutable*>(*m_jit.vm(), executable);
551 }
552
553 unsigned numPassedArgs = 0;
554 unsigned numAllocatedArgs = 0;
555
556 // Gotta load the arguments somehow. Varargs is trickier.
557 if (isVarargs || isForwardVarargs) {
558 RELEASE_ASSERT(!isDirect);
559 CallVarargsData* data = node->callVarargsData();
560
561 int numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
562
563 if (isForwardVarargs) {
564 flushRegisters();
565 if (node->child3())
566 use(node->child3());
567
568 GPRReg scratchGPR1;
569 GPRReg scratchGPR2;
570 GPRReg scratchGPR3;
571
572 scratchGPR1 = JITCompiler::selectScratchGPR();
573 scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1);
574 scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2);
575
576 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
577 JITCompiler::JumpList slowCase;
578 InlineCallFrame* inlineCallFrame;
579 if (node->child3())
580 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame();
581 else
582 inlineCallFrame = node->origin.semantic.inlineCallFrame();
583 // emitSetupVarargsFrameFastCase modifies the stack pointer if it succeeds.
584 emitSetupVarargsFrameFastCase(*m_jit.vm(), m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
585 JITCompiler::Jump done = m_jit.jump();
586 slowCase.link(&m_jit);
587 callOperation(operationThrowStackOverflowForVarargs);
588 m_jit.exceptionCheck();
589 m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
590 done.link(&m_jit);
591 } else {
592 GPRReg argumentsGPR;
593 GPRReg scratchGPR1;
594 GPRReg scratchGPR2;
595 GPRReg scratchGPR3;
596
597 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) {
598 if (reservedGPR != InvalidGPRReg)
599 lock(reservedGPR);
600 JSValueOperand arguments(this, node->child3());
601 argumentsGPR = arguments.gpr();
602 if (reservedGPR != InvalidGPRReg)
603 unlock(reservedGPR);
604 flushRegisters();
605
606 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsGPR, reservedGPR);
607 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, reservedGPR);
608 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsGPR, scratchGPR1, scratchGPR2, reservedGPR);
609 };
610
611 loadArgumentsGPR(InvalidGPRReg);
612
613 DFG_ASSERT(m_jit.graph(), node, isFlushed());
614
615 // Right now, arguments is in argumentsGPR and the register file is flushed.
616 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, argumentsGPR, numUsedStackSlots, data->firstVarArgOffset);
617 m_jit.exceptionCheck();
618
619 // Now we have the argument count of the callee frame, but we've lost the arguments operand.
620 // Reconstruct the arguments operand while preserving the callee frame.
621 loadArgumentsGPR(GPRInfo::returnValueGPR);
622 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);
623 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);
624 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);
625
626 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, argumentsGPR, data->firstVarArgOffset, GPRInfo::returnValueGPR);
627 m_jit.exceptionCheck();
628 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::returnValueGPR, JITCompiler::stackPointerRegister);
629 }
630
631 DFG_ASSERT(m_jit.graph(), node, isFlushed());
632
633 // We don't need the arguments array anymore.
634 if (isVarargs)
635 use(node->child3());
636
637 // Now set up the "this" argument.
638 JSValueOperand thisArgument(this, node->child2());
639 GPRReg thisArgumentGPR = thisArgument.gpr();
640 thisArgument.use();
641
642 m_jit.store64(thisArgumentGPR, JITCompiler::calleeArgumentSlot(0));
643 } else {
644 // The call instruction's first child is the function; the subsequent children are the
645 // arguments.
646 numPassedArgs = node->numChildren() - 1;
647 numAllocatedArgs = numPassedArgs;
648
649 if (functionExecutable) {
650 // Allocate more args if this would let us avoid arity checks. This is throttled by
651 // CallLinkInfo's limit. It's probably good to throttle it - if the callee wants a
652 // ginormous amount of argument space then it's better for them to do it so that when we
653 // make calls to other things, we don't waste space.
654 unsigned desiredNumAllocatedArgs = static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
655 if (desiredNumAllocatedArgs <= Options::maximumDirectCallStackSize()) {
656 numAllocatedArgs = std::max(numAllocatedArgs, desiredNumAllocatedArgs);
657
658 // Whoever converts to DirectCall should do this adjustment. It's too late for us to
659 // do this adjustment now since we will have already emitted code that relied on the
660 // value of m_parameterSlots.
661 DFG_ASSERT(
662 m_jit.graph(), node,
663 Graph::parameterSlotsForArgCount(numAllocatedArgs)
664 <= m_jit.graph().m_parameterSlots);
665 }
666 }
667
668 if (isTail) {
669 Edge calleeEdge = m_jit.graph().child(node, 0);
670 JSValueOperand callee(this, calleeEdge);
671 calleeGPR = callee.gpr();
672 if (!isDirect)
673 callee.use();
674
675 shuffleData.tagTypeNumber = GPRInfo::tagTypeNumberRegister;
676 shuffleData.numLocals = m_jit.graph().frameRegisterCount();
677 shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatJS);
678 shuffleData.args.resize(numAllocatedArgs);
679 shuffleData.numPassedArgs = numPassedArgs;
680
681 for (unsigned i = 0; i < numPassedArgs; ++i) {
682 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
683 GenerationInfo& info = generationInfo(argEdge.node());
684 if (!isDirect)
685 use(argEdge);
686 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
687 }
688
689 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
690 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
691
692 shuffleData.setupCalleeSaveRegisters(m_jit.codeBlock());
693 } else {
694 m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCount));
695
696 for (unsigned i = 0; i < numPassedArgs; i++) {
697 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
698 JSValueOperand arg(this, argEdge);
699 GPRReg argGPR = arg.gpr();
700 use(argEdge);
701
702 m_jit.store64(argGPR, JITCompiler::calleeArgumentSlot(i));
703 }
704
705 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
706 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
707 }
708 }
709
710 if (!isTail || isVarargs || isForwardVarargs) {
711 Edge calleeEdge = m_jit.graph().child(node, 0);
712 JSValueOperand callee(this, calleeEdge);
713 calleeGPR = callee.gpr();
714 callee.use();
715 m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
716
717 flushRegisters();
718 }
719
720 CodeOrigin staticOrigin = node->origin.semantic;
721 InlineCallFrame* staticInlineCallFrame = staticOrigin.inlineCallFrame();
722 ASSERT(!isTail || !staticInlineCallFrame || !staticInlineCallFrame->getCallerSkippingTailCalls());
723 ASSERT(!isEmulatedTail || (staticInlineCallFrame && staticInlineCallFrame->getCallerSkippingTailCalls()));
724 CodeOrigin dynamicOrigin =
725 isEmulatedTail ? *staticInlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
726
727 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
728
729 auto setResultAndResetStack = [&] () {
730 GPRFlushedCallResult result(this);
731 GPRReg resultGPR = result.gpr();
732 m_jit.move(GPRInfo::returnValueGPR, resultGPR);
733
734 jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
735
736 // After the calls are done, we need to reestablish our stack
737 // pointer. We rely on this for varargs calls, calls with arity
738 // mismatch (the callframe is slided) and tail calls.
739 m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
740 };
741
742 CallLinkInfo* callLinkInfo = m_jit.codeBlock()->addCallLinkInfo();
743 callLinkInfo->setUpCall(callType, m_currentNode->origin.semantic, calleeGPR);
744
745 if (node->op() == CallEval) {
746 // We want to call operationCallEval but we don't want to overwrite the parameter area in
747 // which we have created a prototypical eval call frame. This means that we have to
748 // subtract stack to make room for the call. Lucky for us, at this point we have the whole
749 // register file to ourselves.
750
751 m_jit.emitStoreCallSiteIndex(callSite);
752 m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
753 m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
754
755 // Now we need to make room for:
756 // - The caller frame and PC of a call to operationCallEval.
757 // - Potentially two arguments on the stack.
758 unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
759 requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
760 m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
761 m_jit.setupArguments<decltype(operationCallEval)>(GPRInfo::regT0);
762 prepareForExternalCall();
763 m_jit.appendCall(operationCallEval);
764 m_jit.exceptionCheck();
765 JITCompiler::Jump done = m_jit.branchIfNotEmpty(GPRInfo::returnValueGPR);
766
767 // This is the part where we meant to make a normal call. Oops.
768 m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
769 m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
770 m_jit.emitDumbVirtualCall(*m_jit.vm(), callLinkInfo);
771
772 done.link(&m_jit);
773 setResultAndResetStack();
774 return;
775 }
776
777 if (isDirect) {
778 callLinkInfo->setExecutableDuringCompilation(executable);
779 callLinkInfo->setMaxNumArguments(numAllocatedArgs);
780
781 if (isTail) {
782 RELEASE_ASSERT(node->op() == DirectTailCall);
783
784 JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
785 JITCompiler::Label mainPath = m_jit.label();
786
787 m_jit.emitStoreCallSiteIndex(callSite);
788
789 callLinkInfo->setFrameShuffleData(shuffleData);
790 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
791
792 JITCompiler::Call call = m_jit.nearTailCall();
793
794 JITCompiler::Label slowPath = m_jit.label();
795 patchableJump.m_jump.linkTo(slowPath, &m_jit);
796
797 silentSpillAllRegisters(InvalidGPRReg);
798 callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
799 silentFillAllRegisters();
800 m_jit.exceptionCheck();
801 m_jit.jump().linkTo(mainPath, &m_jit);
802
803 useChildren(node);
804
805 m_jit.addJSDirectTailCall(patchableJump, call, slowPath, callLinkInfo);
806 return;
807 }
808
809 JITCompiler::Label mainPath = m_jit.label();
810
811 m_jit.emitStoreCallSiteIndex(callSite);
812
813 JITCompiler::Call call = m_jit.nearCall();
814 JITCompiler::Jump done = m_jit.jump();
815
816 JITCompiler::Label slowPath = m_jit.label();
817 if (isX86())
818 m_jit.pop(JITCompiler::selectScratchGPR(calleeGPR));
819
820 callOperation(operationLinkDirectCall, callLinkInfo, calleeGPR);
821 m_jit.exceptionCheck();
822 m_jit.jump().linkTo(mainPath, &m_jit);
823
824 done.link(&m_jit);
825
826 setResultAndResetStack();
827
828 m_jit.addJSDirectCall(call, slowPath, callLinkInfo);
829 return;
830 }
831
832 m_jit.emitStoreCallSiteIndex(callSite);
833
834 JITCompiler::DataLabelPtr targetToCheck;
835 JITCompiler::Jump slowPath = m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, TrustedImmPtr(nullptr));
836
837 if (isTail) {
838 if (node->op() == TailCall) {
839 callLinkInfo->setFrameShuffleData(shuffleData);
840 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
841 } else {
842 m_jit.emitRestoreCalleeSaves();
843 m_jit.prepareForTailCallSlow();
844 }
845 }
846
847 JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
848
849 JITCompiler::Jump done = m_jit.jump();
850
851 slowPath.link(&m_jit);
852
853 if (node->op() == TailCall) {
854 CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
855 callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(GPRInfo::regT0));
856 callFrameShuffler.prepareForSlowPath();
857 } else {
858 m_jit.move(calleeGPR, GPRInfo::regT0); // Callee needs to be in regT0
859
860 if (isTail)
861 m_jit.emitRestoreCalleeSaves(); // This needs to happen after we moved calleeGPR to regT0
862 }
863
864 m_jit.move(TrustedImmPtr(callLinkInfo), GPRInfo::regT2); // Link info needs to be in regT2
865 JITCompiler::Call slowCall = m_jit.nearCall();
866
867 done.link(&m_jit);
868
869 if (isTail)
870 m_jit.abortWithReason(JITDidReturnFromTailCall);
871 else
872 setResultAndResetStack();
873
874 m_jit.addJSCall(fastCall, slowCall, targetToCheck, callLinkInfo);
875}
876
877// Clang should allow unreachable [[clang::fallthrough]] in template functions if any template expansion uses it
878// http://llvm.org/bugs/show_bug.cgi?id=18619
879IGNORE_WARNINGS_BEGIN("implicit-fallthrough")
880template<bool strict>
881GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
882{
883 AbstractValue& value = m_state.forNode(edge);
884 SpeculatedType type = value.m_type;
885 ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
886
887 m_interpreter.filter(value, SpecInt32Only);
888 if (value.isClear()) {
889 if (mayHaveTypeCheck(edge.useKind()))
890 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
891 returnFormat = DataFormatInt32;
892 return allocate();
893 }
894
895 VirtualRegister virtualRegister = edge->virtualRegister();
896 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
897
898 switch (info.registerFormat()) {
899 case DataFormatNone: {
900 GPRReg gpr = allocate();
901
902 if (edge->hasConstant()) {
903 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
904 ASSERT(edge->isInt32Constant());
905 m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
906 info.fillInt32(*m_stream, gpr);
907 returnFormat = DataFormatInt32;
908 return gpr;
909 }
910
911 DataFormat spillFormat = info.spillFormat();
912
913 DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32, spillFormat);
914
915 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
916
917 if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
918 // If we know this was spilled as an integer we can fill without checking.
919 if (strict) {
920 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
921 info.fillInt32(*m_stream, gpr);
922 returnFormat = DataFormatInt32;
923 return gpr;
924 }
925 if (spillFormat == DataFormatInt32) {
926 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
927 info.fillInt32(*m_stream, gpr);
928 returnFormat = DataFormatInt32;
929 } else {
930 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
931 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
932 returnFormat = DataFormatJSInt32;
933 }
934 return gpr;
935 }
936 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
937
938 // Fill as JSValue, and fall through.
939 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
940 m_gprs.unlock(gpr);
941 FALLTHROUGH;
942 }
943
944 case DataFormatJS: {
945 DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Any));
946 // Check the value is an integer.
947 GPRReg gpr = info.gpr();
948 m_gprs.lock(gpr);
949 if (type & ~SpecInt32Only)
950 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotInt32(gpr));
951 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
952 // If !strict we're done, return.
953 if (!strict) {
954 returnFormat = DataFormatJSInt32;
955 return gpr;
956 }
957 // else fall through & handle as DataFormatJSInt32.
958 m_gprs.unlock(gpr);
959 FALLTHROUGH;
960 }
961
962 case DataFormatJSInt32: {
963 // In a strict fill we need to strip off the value tag.
964 if (strict) {
965 GPRReg gpr = info.gpr();
966 GPRReg result;
967 // If the register has already been locked we need to take a copy.
968 // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
969 if (m_gprs.isLocked(gpr))
970 result = allocate();
971 else {
972 m_gprs.lock(gpr);
973 info.fillInt32(*m_stream, gpr);
974 result = gpr;
975 }
976 m_jit.zeroExtend32ToPtr(gpr, result);
977 returnFormat = DataFormatInt32;
978 return result;
979 }
980
981 GPRReg gpr = info.gpr();
982 m_gprs.lock(gpr);
983 returnFormat = DataFormatJSInt32;
984 return gpr;
985 }
986
987 case DataFormatInt32: {
988 GPRReg gpr = info.gpr();
989 m_gprs.lock(gpr);
990 returnFormat = DataFormatInt32;
991 return gpr;
992 }
993
994 case DataFormatJSDouble:
995 case DataFormatCell:
996 case DataFormatBoolean:
997 case DataFormatJSCell:
998 case DataFormatJSBoolean:
999 case DataFormatDouble:
1000 case DataFormatStorage:
1001 case DataFormatInt52:
1002 case DataFormatStrictInt52:
1003 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1004
1005 default:
1006 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1007 return InvalidGPRReg;
1008 }
1009}
1010IGNORE_WARNINGS_END
1011
1012GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1013{
1014 return fillSpeculateInt32Internal<false>(edge, returnFormat);
1015}
1016
1017GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1018{
1019 DataFormat mustBeDataFormatInt32;
1020 GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1021 DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32, mustBeDataFormatInt32);
1022 return result;
1023}
1024
1025GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1026{
1027 ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1028 AbstractValue& value = m_state.forNode(edge);
1029
1030 m_interpreter.filter(value, SpecInt52Any);
1031 if (value.isClear()) {
1032 if (mayHaveTypeCheck(edge.useKind()))
1033 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1034 return allocate();
1035 }
1036
1037 VirtualRegister virtualRegister = edge->virtualRegister();
1038 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1039
1040 switch (info.registerFormat()) {
1041 case DataFormatNone: {
1042 GPRReg gpr = allocate();
1043
1044 if (edge->hasConstant()) {
1045 JSValue jsValue = edge->asJSValue();
1046 ASSERT(jsValue.isAnyInt());
1047 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1048 int64_t value = jsValue.asAnyInt();
1049 if (desiredFormat == DataFormatInt52)
1050 value = value << JSValue::int52ShiftAmount;
1051 m_jit.move(MacroAssembler::Imm64(value), gpr);
1052 info.fillGPR(*m_stream, gpr, desiredFormat);
1053 return gpr;
1054 }
1055
1056 DataFormat spillFormat = info.spillFormat();
1057
1058 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52, spillFormat);
1059
1060 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1061
1062 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1063 if (desiredFormat == DataFormatStrictInt52) {
1064 if (spillFormat == DataFormatInt52)
1065 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1066 info.fillStrictInt52(*m_stream, gpr);
1067 return gpr;
1068 }
1069 if (spillFormat == DataFormatStrictInt52)
1070 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1071 info.fillInt52(*m_stream, gpr);
1072 return gpr;
1073 }
1074
1075 case DataFormatStrictInt52: {
1076 GPRReg gpr = info.gpr();
1077 bool wasLocked = m_gprs.isLocked(gpr);
1078 lock(gpr);
1079 if (desiredFormat == DataFormatStrictInt52)
1080 return gpr;
1081 if (wasLocked) {
1082 GPRReg result = allocate();
1083 m_jit.move(gpr, result);
1084 unlock(gpr);
1085 gpr = result;
1086 } else
1087 info.fillInt52(*m_stream, gpr);
1088 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1089 return gpr;
1090 }
1091
1092 case DataFormatInt52: {
1093 GPRReg gpr = info.gpr();
1094 bool wasLocked = m_gprs.isLocked(gpr);
1095 lock(gpr);
1096 if (desiredFormat == DataFormatInt52)
1097 return gpr;
1098 if (wasLocked) {
1099 GPRReg result = allocate();
1100 m_jit.move(gpr, result);
1101 unlock(gpr);
1102 gpr = result;
1103 } else
1104 info.fillStrictInt52(*m_stream, gpr);
1105 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1106 return gpr;
1107 }
1108
1109 default:
1110 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1111 return InvalidGPRReg;
1112 }
1113}
1114
1115FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1116{
1117 ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1118 ASSERT(edge->hasDoubleResult());
1119 VirtualRegister virtualRegister = edge->virtualRegister();
1120 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1121
1122 if (info.registerFormat() == DataFormatNone) {
1123 if (edge->hasConstant()) {
1124 if (edge->isNumberConstant()) {
1125 FPRReg fpr = fprAllocate();
1126 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1127 if (!doubleAsInt)
1128 m_jit.moveZeroToDouble(fpr);
1129 else {
1130 GPRReg gpr = allocate();
1131 m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1132 m_jit.move64ToDouble(gpr, fpr);
1133 unlock(gpr);
1134 }
1135
1136 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1137 info.fillDouble(*m_stream, fpr);
1138 return fpr;
1139 }
1140 if (mayHaveTypeCheck(edge.useKind()))
1141 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1142 return fprAllocate();
1143 }
1144
1145 DataFormat spillFormat = info.spillFormat();
1146 if (spillFormat != DataFormatDouble) {
1147 DFG_CRASH(
1148 m_jit.graph(), m_currentNode, toCString(
1149 "Expected ", edge, " to have double format but instead it is spilled as ",
1150 dataFormatToString(spillFormat)).data());
1151 }
1152 DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble, spillFormat);
1153 FPRReg fpr = fprAllocate();
1154 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1155 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1156 info.fillDouble(*m_stream, fpr);
1157 return fpr;
1158 }
1159
1160 DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble, info.registerFormat());
1161 FPRReg fpr = info.fpr();
1162 m_fprs.lock(fpr);
1163 return fpr;
1164}
1165
1166GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1167{
1168 AbstractValue& value = m_state.forNode(edge);
1169 SpeculatedType type = value.m_type;
1170 ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCellCheck));
1171
1172 m_interpreter.filter(value, SpecCellCheck);
1173 if (value.isClear()) {
1174 if (mayHaveTypeCheck(edge.useKind()))
1175 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1176 return allocate();
1177 }
1178
1179 VirtualRegister virtualRegister = edge->virtualRegister();
1180 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1181
1182 switch (info.registerFormat()) {
1183 case DataFormatNone: {
1184 GPRReg gpr = allocate();
1185
1186 if (edge->hasConstant()) {
1187 JSValue jsValue = edge->asJSValue();
1188 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1189 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1190 info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1191 return gpr;
1192 }
1193
1194 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1195 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1196
1197 info.fillJSValue(*m_stream, gpr, DataFormatJS);
1198 if (type & ~SpecCellCheck)
1199 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1200 info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1201 return gpr;
1202 }
1203
1204 case DataFormatCell:
1205 case DataFormatJSCell: {
1206 GPRReg gpr = info.gpr();
1207 m_gprs.lock(gpr);
1208 if (!ASSERT_DISABLED) {
1209 MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1210 m_jit.abortWithReason(DFGIsNotCell);
1211 checkCell.link(&m_jit);
1212 }
1213 return gpr;
1214 }
1215
1216 case DataFormatJS: {
1217 GPRReg gpr = info.gpr();
1218 m_gprs.lock(gpr);
1219 if (type & ~SpecCellCheck)
1220 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1221 info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1222 return gpr;
1223 }
1224
1225 case DataFormatJSInt32:
1226 case DataFormatInt32:
1227 case DataFormatJSDouble:
1228 case DataFormatJSBoolean:
1229 case DataFormatBoolean:
1230 case DataFormatDouble:
1231 case DataFormatStorage:
1232 case DataFormatInt52:
1233 case DataFormatStrictInt52:
1234 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1235
1236 default:
1237 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1238 return InvalidGPRReg;
1239 }
1240}
1241
1242GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1243{
1244 AbstractValue& value = m_state.forNode(edge);
1245 SpeculatedType type = value.m_type;
1246 ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1247
1248 m_interpreter.filter(value, SpecBoolean);
1249 if (value.isClear()) {
1250 if (mayHaveTypeCheck(edge.useKind()))
1251 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1252 return allocate();
1253 }
1254
1255 VirtualRegister virtualRegister = edge->virtualRegister();
1256 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1257
1258 switch (info.registerFormat()) {
1259 case DataFormatNone: {
1260 GPRReg gpr = allocate();
1261
1262 if (edge->hasConstant()) {
1263 JSValue jsValue = edge->asJSValue();
1264 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1265 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1266 info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1267 return gpr;
1268 }
1269 DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS, info.spillFormat());
1270 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1271 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1272
1273 info.fillJSValue(*m_stream, gpr, DataFormatJS);
1274 if (type & ~SpecBoolean) {
1275 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1276 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1277 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1278 }
1279 info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1280 return gpr;
1281 }
1282
1283 case DataFormatBoolean:
1284 case DataFormatJSBoolean: {
1285 GPRReg gpr = info.gpr();
1286 m_gprs.lock(gpr);
1287 return gpr;
1288 }
1289
1290 case DataFormatJS: {
1291 GPRReg gpr = info.gpr();
1292 m_gprs.lock(gpr);
1293 if (type & ~SpecBoolean) {
1294 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1295 speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1296 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1297 }
1298 info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1299 return gpr;
1300 }
1301
1302 case DataFormatJSInt32:
1303 case DataFormatInt32:
1304 case DataFormatJSDouble:
1305 case DataFormatJSCell:
1306 case DataFormatCell:
1307 case DataFormatDouble:
1308 case DataFormatStorage:
1309 case DataFormatInt52:
1310 case DataFormatStrictInt52:
1311 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1312
1313 default:
1314 DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1315 return InvalidGPRReg;
1316 }
1317}
1318
1319void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1320{
1321 SpeculateCellOperand op1(this, objectChild);
1322 JSValueOperand op2(this, otherChild);
1323 GPRTemporary result(this);
1324
1325 GPRReg op1GPR = op1.gpr();
1326 GPRReg op2GPR = op2.gpr();
1327 GPRReg resultGPR = result.gpr();
1328
1329 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1330
1331 // At this point we know that we can perform a straight-forward equality comparison on pointer
1332 // values because we are doing strict equality.
1333 m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1334 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1335 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1336}
1337
1338void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1339{
1340 BasicBlock* taken = branchNode->branchData()->taken.block;
1341 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1342
1343 SpeculateCellOperand op1(this, objectChild);
1344 JSValueOperand op2(this, otherChild);
1345
1346 GPRReg op1GPR = op1.gpr();
1347 GPRReg op2GPR = op2.gpr();
1348
1349 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1350
1351 if (taken == nextBlock()) {
1352 branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1353 jump(taken);
1354 } else {
1355 branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1356 jump(notTaken);
1357 }
1358}
1359
1360void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1361{
1362 SpeculateCellOperand op1(this, leftChild);
1363 JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1364 GPRTemporary result(this);
1365
1366 GPRReg op1GPR = op1.gpr();
1367 GPRReg op2GPR = op2.gpr();
1368 GPRReg resultGPR = result.gpr();
1369
1370 bool masqueradesAsUndefinedWatchpointValid =
1371 masqueradesAsUndefinedWatchpointIsStillValid();
1372
1373 if (masqueradesAsUndefinedWatchpointValid) {
1374 DFG_TYPE_CHECK(
1375 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1376 } else {
1377 DFG_TYPE_CHECK(
1378 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1379 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1380 m_jit.branchTest8(
1381 MacroAssembler::NonZero,
1382 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1383 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1384 }
1385
1386 // It seems that most of the time when programs do a == b where b may be either null/undefined
1387 // or an object, b is usually an object. Balance the branches to make that case fast.
1388 MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1389
1390 // We know that within this branch, rightChild must be a cell.
1391 if (masqueradesAsUndefinedWatchpointValid) {
1392 DFG_TYPE_CHECK(
1393 JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1394 } else {
1395 DFG_TYPE_CHECK(
1396 JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1397 speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1398 m_jit.branchTest8(
1399 MacroAssembler::NonZero,
1400 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()),
1401 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1402 }
1403
1404 // At this point we know that we can perform a straight-forward equality comparison on pointer
1405 // values because both left and right are pointers to objects that have no special equality
1406 // protocols.
1407 m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1408 MacroAssembler::Jump done = m_jit.jump();
1409
1410 rightNotCell.link(&m_jit);
1411
1412 // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1413 // prove that it is either null or undefined.
1414 if (needsTypeCheck(rightChild, SpecCellCheck | SpecOther)) {
1415 m_jit.move(op2GPR, resultGPR);
1416 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1417
1418 typeCheck(
1419 JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther,
1420 m_jit.branch64(
1421 MacroAssembler::NotEqual, resultGPR,
1422 MacroAssembler::TrustedImm64(ValueNull)));
1423 }
1424 m_jit.move(TrustedImm32(0), result.gpr());
1425
1426 done.link(&m_jit);
1427 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1428 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1429}
1430
1431void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1432{
1433 BasicBlock* taken = branchNode->branchData()->taken.block;
1434 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1435
1436 SpeculateCellOperand op1(this, leftChild);
1437 JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1438 GPRTemporary result(this);
1439
1440 GPRReg op1GPR = op1.gpr();
1441 GPRReg op2GPR = op2.gpr();
1442 GPRReg resultGPR = result.gpr();
1443
1444 bool masqueradesAsUndefinedWatchpointValid =
1445 masqueradesAsUndefinedWatchpointIsStillValid();
1446
1447 if (masqueradesAsUndefinedWatchpointValid) {
1448 DFG_TYPE_CHECK(
1449 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1450 } else {
1451 DFG_TYPE_CHECK(
1452 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1453 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1454 m_jit.branchTest8(
1455 MacroAssembler::NonZero,
1456 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1457 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1458 }
1459
1460 // It seems that most of the time when programs do a == b where b may be either null/undefined
1461 // or an object, b is usually an object. Balance the branches to make that case fast.
1462 MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1463
1464 // We know that within this branch, rightChild must be a cell.
1465 if (masqueradesAsUndefinedWatchpointValid) {
1466 DFG_TYPE_CHECK(
1467 JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1468 } else {
1469 DFG_TYPE_CHECK(
1470 JSValueRegs(op2GPR), rightChild, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1471 speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1472 m_jit.branchTest8(
1473 MacroAssembler::NonZero,
1474 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()),
1475 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1476 }
1477
1478 // At this point we know that we can perform a straight-forward equality comparison on pointer
1479 // values because both left and right are pointers to objects that have no special equality
1480 // protocols.
1481 branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1482
1483 // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1484 // prove that it is either null or undefined.
1485 if (!needsTypeCheck(rightChild, SpecCellCheck | SpecOther))
1486 rightNotCell.link(&m_jit);
1487 else {
1488 jump(notTaken, ForceJump);
1489
1490 rightNotCell.link(&m_jit);
1491 m_jit.move(op2GPR, resultGPR);
1492 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1493
1494 typeCheck(
1495 JSValueRegs(op2GPR), rightChild, SpecCellCheck | SpecOther, m_jit.branch64(
1496 MacroAssembler::NotEqual, resultGPR,
1497 MacroAssembler::TrustedImm64(ValueNull)));
1498 }
1499
1500 jump(notTaken);
1501}
1502
1503void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1504{
1505 SpeculateCellOperand symbol(this, symbolEdge);
1506 JSValueOperand untyped(this, untypedEdge);
1507 GPRTemporary result(this, Reuse, symbol, untyped);
1508
1509 GPRReg symbolGPR = symbol.gpr();
1510 GPRReg untypedGPR = untyped.gpr();
1511 GPRReg resultGPR = result.gpr();
1512
1513 speculateSymbol(symbolEdge, symbolGPR);
1514
1515 // At this point we know that we can perform a straight-forward equality comparison on pointer
1516 // values because we are doing strict equality.
1517 m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
1518 unblessedBooleanResult(resultGPR, node);
1519}
1520
1521void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1522{
1523 SpeculateWhicheverInt52Operand op1(this, node->child1());
1524 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1525 GPRTemporary result(this, Reuse, op1, op2);
1526
1527 m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1528
1529 // If we add a DataFormatBool, we should use it here.
1530 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1531 jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1532}
1533
1534void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1535{
1536 BasicBlock* taken = branchNode->branchData()->taken.block;
1537 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1538
1539 // The branch instruction will branch to the taken block.
1540 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1541 if (taken == nextBlock()) {
1542 condition = JITCompiler::invert(condition);
1543 BasicBlock* tmp = taken;
1544 taken = notTaken;
1545 notTaken = tmp;
1546 }
1547
1548 SpeculateWhicheverInt52Operand op1(this, node->child1());
1549 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1550
1551 branch64(condition, op1.gpr(), op2.gpr(), taken);
1552 jump(notTaken);
1553}
1554
1555void SpeculativeJIT::compileCompareEqPtr(Node* node)
1556{
1557 JSValueOperand value(this, node->child1());
1558 GPRTemporary result(this);
1559 GPRReg valueGPR = value.gpr();
1560 GPRReg resultGPR = result.gpr();
1561
1562 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), node->cellOperand()->cell()), resultGPR);
1563 m_jit.compare64(MacroAssembler::Equal, valueGPR, resultGPR, resultGPR);
1564 unblessedBooleanResult(resultGPR, node);
1565}
1566
1567void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1568{
1569 JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1570 GPRTemporary result(this);
1571 GPRReg valueGPR = value.gpr();
1572 GPRReg resultGPR = result.gpr();
1573 GPRTemporary structure;
1574 GPRReg structureGPR = InvalidGPRReg;
1575 GPRTemporary scratch;
1576 GPRReg scratchGPR = InvalidGPRReg;
1577
1578 bool masqueradesAsUndefinedWatchpointValid =
1579 masqueradesAsUndefinedWatchpointIsStillValid();
1580
1581 if (!masqueradesAsUndefinedWatchpointValid) {
1582 // The masquerades as undefined case will use the structure register, so allocate it here.
1583 // Do this at the top of the function to avoid branching around a register allocation.
1584 GPRTemporary realStructure(this);
1585 GPRTemporary realScratch(this);
1586 structure.adopt(realStructure);
1587 scratch.adopt(realScratch);
1588 structureGPR = structure.gpr();
1589 scratchGPR = scratch.gpr();
1590 }
1591
1592 MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1593 if (masqueradesAsUndefinedWatchpointValid) {
1594 DFG_TYPE_CHECK(
1595 JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1596 } else {
1597 DFG_TYPE_CHECK(
1598 JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1599
1600 MacroAssembler::Jump isNotMasqueradesAsUndefined =
1601 m_jit.branchTest8(
1602 MacroAssembler::Zero,
1603 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()),
1604 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1605
1606 m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
1607 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1608 m_jit.branchPtr(
1609 MacroAssembler::Equal,
1610 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()),
1611 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1612
1613 isNotMasqueradesAsUndefined.link(&m_jit);
1614 }
1615 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1616 MacroAssembler::Jump done = m_jit.jump();
1617
1618 notCell.link(&m_jit);
1619
1620 if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
1621 m_jit.move(valueGPR, resultGPR);
1622 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1623 typeCheck(
1624 JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
1625 MacroAssembler::NotEqual,
1626 resultGPR,
1627 MacroAssembler::TrustedImm64(ValueNull)));
1628 }
1629 m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1630
1631 done.link(&m_jit);
1632
1633 jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1634}
1635
1636void SpeculativeJIT::compileLogicalNot(Node* node)
1637{
1638 switch (node->child1().useKind()) {
1639 case ObjectOrOtherUse: {
1640 compileObjectOrOtherLogicalNot(node->child1());
1641 return;
1642 }
1643
1644 case Int32Use: {
1645 SpeculateInt32Operand value(this, node->child1());
1646 GPRTemporary result(this, Reuse, value);
1647 m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1648 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1649 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1650 return;
1651 }
1652
1653 case DoubleRepUse: {
1654 SpeculateDoubleOperand value(this, node->child1());
1655 FPRTemporary scratch(this);
1656 GPRTemporary result(this);
1657 m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1658 MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1659 m_jit.xor32(TrustedImm32(true), result.gpr());
1660 nonZero.link(&m_jit);
1661 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1662 return;
1663 }
1664
1665 case BooleanUse:
1666 case KnownBooleanUse: {
1667 if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1668 SpeculateBooleanOperand value(this, node->child1());
1669 GPRTemporary result(this, Reuse, value);
1670
1671 m_jit.move(value.gpr(), result.gpr());
1672 m_jit.xor64(TrustedImm32(true), result.gpr());
1673
1674 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1675 return;
1676 }
1677
1678 JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1679 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1680
1681 m_jit.move(value.gpr(), result.gpr());
1682 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1683 typeCheck(
1684 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1685 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1686 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1687
1688 // If we add a DataFormatBool, we should use it here.
1689 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1690 return;
1691 }
1692
1693 case UntypedUse: {
1694 JSValueOperand arg1(this, node->child1());
1695 GPRTemporary result(this);
1696
1697 GPRReg arg1GPR = arg1.gpr();
1698 GPRReg resultGPR = result.gpr();
1699
1700 FPRTemporary valueFPR(this);
1701 FPRTemporary tempFPR(this);
1702
1703 bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1704 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1705 Optional<GPRTemporary> scratch;
1706 GPRReg scratchGPR = InvalidGPRReg;
1707 if (shouldCheckMasqueradesAsUndefined) {
1708 scratch.emplace(this);
1709 scratchGPR = scratch->gpr();
1710 }
1711 bool negateResult = true;
1712 m_jit.emitConvertValueToBoolean(*m_jit.vm(), JSValueRegs(arg1GPR), resultGPR, scratchGPR, valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1713 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1714 jsValueResult(resultGPR, node, DataFormatJSBoolean);
1715 return;
1716 }
1717 case StringUse:
1718 return compileStringZeroLength(node);
1719
1720 case StringOrOtherUse:
1721 return compileLogicalNotStringOrOther(node);
1722
1723 default:
1724 DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1725 break;
1726 }
1727}
1728
1729void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1730{
1731 JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1732 GPRTemporary scratch(this);
1733 GPRTemporary structure;
1734 GPRReg valueGPR = value.gpr();
1735 GPRReg scratchGPR = scratch.gpr();
1736 GPRReg structureGPR = InvalidGPRReg;
1737
1738 if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
1739 GPRTemporary realStructure(this);
1740 structure.adopt(realStructure);
1741 structureGPR = structure.gpr();
1742 }
1743
1744 MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1745 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1746 DFG_TYPE_CHECK(
1747 JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1748 } else {
1749 DFG_TYPE_CHECK(
1750 JSValueRegs(valueGPR), nodeUse, (~SpecCellCheck) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1751
1752 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1753 JITCompiler::Zero,
1754 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()),
1755 TrustedImm32(MasqueradesAsUndefined));
1756
1757 m_jit.emitLoadStructure(*m_jit.vm(), valueGPR, structureGPR, scratchGPR);
1758 speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1759 m_jit.branchPtr(
1760 MacroAssembler::Equal,
1761 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()),
1762 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1763
1764 isNotMasqueradesAsUndefined.link(&m_jit);
1765 }
1766 jump(taken, ForceJump);
1767
1768 notCell.link(&m_jit);
1769
1770 if (needsTypeCheck(nodeUse, SpecCellCheck | SpecOther)) {
1771 m_jit.move(valueGPR, scratchGPR);
1772 m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
1773 typeCheck(
1774 JSValueRegs(valueGPR), nodeUse, SpecCellCheck | SpecOther, m_jit.branch64(
1775 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
1776 }
1777 jump(notTaken);
1778
1779 noResult(m_currentNode);
1780}
1781
1782void SpeculativeJIT::emitBranch(Node* node)
1783{
1784 BasicBlock* taken = node->branchData()->taken.block;
1785 BasicBlock* notTaken = node->branchData()->notTaken.block;
1786
1787 switch (node->child1().useKind()) {
1788 case ObjectOrOtherUse: {
1789 emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1790 return;
1791 }
1792
1793 case Int32Use:
1794 case DoubleRepUse: {
1795 if (node->child1().useKind() == Int32Use) {
1796 bool invert = false;
1797
1798 if (taken == nextBlock()) {
1799 invert = true;
1800 BasicBlock* tmp = taken;
1801 taken = notTaken;
1802 notTaken = tmp;
1803 }
1804
1805 SpeculateInt32Operand value(this, node->child1());
1806 branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1807 } else {
1808 SpeculateDoubleOperand value(this, node->child1());
1809 FPRTemporary scratch(this);
1810 branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1811 }
1812
1813 jump(notTaken);
1814
1815 noResult(node);
1816 return;
1817 }
1818
1819 case StringUse: {
1820 emitStringBranch(node->child1(), taken, notTaken);
1821 return;
1822 }
1823
1824 case StringOrOtherUse: {
1825 emitStringOrOtherBranch(node->child1(), taken, notTaken);
1826 return;
1827 }
1828
1829 case UntypedUse:
1830 case BooleanUse:
1831 case KnownBooleanUse: {
1832 JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1833 GPRReg valueGPR = value.gpr();
1834
1835 if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
1836 if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1837 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1838
1839 if (taken == nextBlock()) {
1840 condition = MacroAssembler::Zero;
1841 BasicBlock* tmp = taken;
1842 taken = notTaken;
1843 notTaken = tmp;
1844 }
1845
1846 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
1847 jump(notTaken);
1848 } else {
1849 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1850 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1851
1852 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
1853 }
1854 value.use();
1855 } else {
1856 GPRTemporary result(this);
1857 FPRTemporary fprValue(this);
1858 FPRTemporary fprTemp(this);
1859 Optional<GPRTemporary> scratch;
1860
1861 GPRReg scratchGPR = InvalidGPRReg;
1862 bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1863 if (shouldCheckMasqueradesAsUndefined) {
1864 scratch.emplace(this);
1865 scratchGPR = scratch->gpr();
1866 }
1867
1868 GPRReg resultGPR = result.gpr();
1869 FPRReg valueFPR = fprValue.fpr();
1870 FPRReg tempFPR = fprTemp.fpr();
1871
1872 if (node->child1()->prediction() & SpecInt32Only) {
1873 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
1874 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
1875 }
1876
1877 if (node->child1()->prediction() & SpecBoolean) {
1878 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1879 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1880 }
1881
1882 value.use();
1883
1884 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1885 auto truthy = m_jit.branchIfTruthy(*m_jit.vm(), JSValueRegs(valueGPR), resultGPR, scratchGPR, valueFPR, tempFPR, shouldCheckMasqueradesAsUndefined, globalObject);
1886 addBranch(truthy, taken);
1887 jump(notTaken);
1888 }
1889
1890 noResult(node, UseChildrenCalledExplicitly);
1891 return;
1892 }
1893
1894 default:
1895 DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
1896 }
1897}
1898
1899void SpeculativeJIT::compile(Node* node)
1900{
1901 NodeType op = node->op();
1902
1903 if (validateDFGDoesGC) {
1904 bool expectDoesGC = doesGC(m_jit.graph(), node);
1905 m_jit.store8(TrustedImm32(expectDoesGC), m_jit.vm()->heap.addressOfExpectDoesGC());
1906 }
1907
1908#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1909 m_jit.clearRegisterAllocationOffsets();
1910#endif
1911
1912 switch (op) {
1913 case JSConstant:
1914 case DoubleConstant:
1915 case Int52Constant:
1916 case PhantomDirectArguments:
1917 case PhantomClonedArguments:
1918 initConstantInfo(node);
1919 break;
1920
1921 case LazyJSConstant:
1922 compileLazyJSConstant(node);
1923 break;
1924
1925 case Identity: {
1926 compileIdentity(node);
1927 break;
1928 }
1929
1930 case GetLocal: {
1931 AbstractValue& value = m_state.operand(node->local());
1932
1933 // If the CFA is tracking this variable and it found that the variable
1934 // cannot have been assigned, then don't attempt to proceed.
1935 if (value.isClear()) {
1936 m_compileOkay = false;
1937 break;
1938 }
1939
1940 switch (node->variableAccessData()->flushFormat()) {
1941 case FlushedDouble: {
1942 FPRTemporary result(this);
1943 m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
1944 VirtualRegister virtualRegister = node->virtualRegister();
1945 m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
1946 generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
1947 break;
1948 }
1949
1950 case FlushedInt32: {
1951 GPRTemporary result(this);
1952 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1953
1954 // Like int32Result, but don't useChildren - our children are phi nodes,
1955 // and don't represent values within this dataflow with virtual registers.
1956 VirtualRegister virtualRegister = node->virtualRegister();
1957 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
1958 generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
1959 break;
1960 }
1961
1962 case FlushedInt52: {
1963 GPRTemporary result(this);
1964 m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
1965
1966 VirtualRegister virtualRegister = node->virtualRegister();
1967 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1968 generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
1969 break;
1970 }
1971
1972 default:
1973 GPRTemporary result(this);
1974 m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
1975
1976 // Like jsValueResult, but don't useChildren - our children are phi nodes,
1977 // and don't represent values within this dataflow with virtual registers.
1978 VirtualRegister virtualRegister = node->virtualRegister();
1979 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1980
1981 DataFormat format;
1982 if (isCellSpeculation(value.m_type))
1983 format = DataFormatJSCell;
1984 else if (isBooleanSpeculation(value.m_type))
1985 format = DataFormatJSBoolean;
1986 else
1987 format = DataFormatJS;
1988
1989 generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
1990 break;
1991 }
1992 break;
1993 }
1994
1995 case MovHint: {
1996 compileMovHint(m_currentNode);
1997 noResult(node);
1998 break;
1999 }
2000
2001 case ZombieHint: {
2002 recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2003 noResult(node);
2004 break;
2005 }
2006
2007 case ExitOK: {
2008 noResult(node);
2009 break;
2010 }
2011
2012 case SetLocal: {
2013 switch (node->variableAccessData()->flushFormat()) {
2014 case FlushedDouble: {
2015 SpeculateDoubleOperand value(this, node->child1());
2016 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2017 noResult(node);
2018 // Indicate that it's no longer necessary to retrieve the value of
2019 // this bytecode variable from registers or other locations in the stack,
2020 // but that it is stored as a double.
2021 recordSetLocal(DataFormatDouble);
2022 break;
2023 }
2024
2025 case FlushedInt32: {
2026 SpeculateInt32Operand value(this, node->child1());
2027 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2028 noResult(node);
2029 recordSetLocal(DataFormatInt32);
2030 break;
2031 }
2032
2033 case FlushedInt52: {
2034 SpeculateInt52Operand value(this, node->child1());
2035 m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2036 noResult(node);
2037 recordSetLocal(DataFormatInt52);
2038 break;
2039 }
2040
2041 case FlushedCell: {
2042 SpeculateCellOperand cell(this, node->child1());
2043 GPRReg cellGPR = cell.gpr();
2044 m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2045 noResult(node);
2046 recordSetLocal(DataFormatCell);
2047 break;
2048 }
2049
2050 case FlushedBoolean: {
2051 SpeculateBooleanOperand boolean(this, node->child1());
2052 m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2053 noResult(node);
2054 recordSetLocal(DataFormatBoolean);
2055 break;
2056 }
2057
2058 case FlushedJSValue: {
2059 JSValueOperand value(this, node->child1());
2060 m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2061 noResult(node);
2062 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2063 break;
2064 }
2065
2066 default:
2067 DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2068 break;
2069 }
2070
2071 break;
2072 }
2073
2074 case SetArgumentDefinitely:
2075 case SetArgumentMaybe:
2076 // This is a no-op; it just marks the fact that the argument is being used.
2077 // But it may be profitable to use this as a hook to run speculation checks
2078 // on arguments, thereby allowing us to trivially eliminate such checks if
2079 // the argument is not used.
2080 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2081 break;
2082
2083 case ValueBitNot:
2084 compileValueBitNot(node);
2085 break;
2086
2087 case ArithBitNot:
2088 compileBitwiseNot(node);
2089 break;
2090
2091 case ValueBitAnd:
2092 case ValueBitXor:
2093 case ValueBitOr:
2094 compileValueBitwiseOp(node);
2095 break;
2096
2097 case ArithBitAnd:
2098 case ArithBitOr:
2099 case ArithBitXor:
2100 compileBitwiseOp(node);
2101 break;
2102
2103 case BitRShift:
2104 case BitLShift:
2105 case BitURShift:
2106 compileShiftOp(node);
2107 break;
2108
2109 case UInt32ToNumber: {
2110 compileUInt32ToNumber(node);
2111 break;
2112 }
2113
2114 case DoubleAsInt32: {
2115 compileDoubleAsInt32(node);
2116 break;
2117 }
2118
2119 case ValueToInt32: {
2120 compileValueToInt32(node);
2121 break;
2122 }
2123
2124 case DoubleRep: {
2125 compileDoubleRep(node);
2126 break;
2127 }
2128
2129 case ValueRep: {
2130 compileValueRep(node);
2131 break;
2132 }
2133
2134 case Int52Rep: {
2135 switch (node->child1().useKind()) {
2136 case Int32Use: {
2137 SpeculateInt32Operand operand(this, node->child1());
2138 GPRTemporary result(this, Reuse, operand);
2139
2140 m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2141
2142 strictInt52Result(result.gpr(), node);
2143 break;
2144 }
2145
2146 case AnyIntUse: {
2147 GPRTemporary result(this);
2148 GPRReg resultGPR = result.gpr();
2149
2150 convertAnyInt(node->child1(), resultGPR);
2151
2152 strictInt52Result(resultGPR, node);
2153 break;
2154 }
2155
2156 case DoubleRepAnyIntUse: {
2157 SpeculateDoubleOperand value(this, node->child1());
2158 FPRReg valueFPR = value.fpr();
2159
2160 flushRegisters();
2161 GPRFlushedCallResult result(this);
2162 GPRReg resultGPR = result.gpr();
2163 callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2164
2165 DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2166 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2167 m_jit.branch64(
2168 JITCompiler::Equal, resultGPR,
2169 JITCompiler::TrustedImm64(JSValue::notInt52)));
2170
2171 strictInt52Result(resultGPR, node);
2172 break;
2173 }
2174
2175 default:
2176 DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2177 }
2178 break;
2179 }
2180
2181 case ValueNegate:
2182 compileValueNegate(node);
2183 break;
2184
2185 case ValueAdd:
2186 compileValueAdd(node);
2187 break;
2188
2189 case ValueSub:
2190 compileValueSub(node);
2191 break;
2192
2193 case StrCat: {
2194 compileStrCat(node);
2195 break;
2196 }
2197
2198 case ArithAdd:
2199 compileArithAdd(node);
2200 break;
2201
2202 case ArithClz32:
2203 compileArithClz32(node);
2204 break;
2205
2206 case MakeRope:
2207 compileMakeRope(node);
2208 break;
2209
2210 case ArithSub:
2211 compileArithSub(node);
2212 break;
2213
2214 case ArithNegate:
2215 compileArithNegate(node);
2216 break;
2217
2218 case ArithMul:
2219 compileArithMul(node);
2220 break;
2221
2222 case ValueMul:
2223 compileValueMul(node);
2224 break;
2225
2226 case ValueDiv: {
2227 compileValueDiv(node);
2228 break;
2229 }
2230
2231 case ArithDiv: {
2232 compileArithDiv(node);
2233 break;
2234 }
2235
2236 case ValueMod: {
2237 compileValueMod(node);
2238 break;
2239 }
2240
2241 case ArithMod: {
2242 compileArithMod(node);
2243 break;
2244 }
2245
2246 case ArithAbs:
2247 compileArithAbs(node);
2248 break;
2249
2250 case ArithMin:
2251 case ArithMax: {
2252 compileArithMinMax(node);
2253 break;
2254 }
2255
2256 case ArithPow:
2257 compileArithPow(node);
2258 break;
2259
2260 case ArithSqrt:
2261 compileArithSqrt(node);
2262 break;
2263
2264 case ArithFRound:
2265 compileArithFRound(node);
2266 break;
2267
2268 case ArithRandom:
2269 compileArithRandom(node);
2270 break;
2271
2272 case ArithRound:
2273 case ArithFloor:
2274 case ArithCeil:
2275 case ArithTrunc:
2276 compileArithRounding(node);
2277 break;
2278
2279 case ArithUnary:
2280 compileArithUnary(node);
2281 break;
2282
2283 case LogicalNot:
2284 compileLogicalNot(node);
2285 break;
2286
2287 case CompareLess:
2288 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2289 return;
2290 break;
2291
2292 case CompareLessEq:
2293 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2294 return;
2295 break;
2296
2297 case CompareGreater:
2298 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2299 return;
2300 break;
2301
2302 case CompareGreaterEq:
2303 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2304 return;
2305 break;
2306
2307 case CompareBelow:
2308 compileCompareUnsigned(node, JITCompiler::Below);
2309 break;
2310
2311 case CompareBelowEq:
2312 compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2313 break;
2314
2315 case CompareEq:
2316 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2317 return;
2318 break;
2319
2320 case CompareStrictEq:
2321 if (compileStrictEq(node))
2322 return;
2323 break;
2324
2325 case CompareEqPtr:
2326 compileCompareEqPtr(node);
2327 break;
2328
2329 case SameValue:
2330 compileSameValue(node);
2331 break;
2332
2333 case StringCharCodeAt: {
2334 compileGetCharCodeAt(node);
2335 break;
2336 }
2337
2338 case StringCharAt: {
2339 // Relies on StringCharAt node having same basic layout as GetByVal
2340 compileGetByValOnString(node);
2341 break;
2342 }
2343
2344 case StringFromCharCode: {
2345 compileFromCharCode(node);
2346 break;
2347 }
2348
2349 case CheckArray: {
2350 checkArray(node);
2351 break;
2352 }
2353
2354 case Arrayify:
2355 case ArrayifyToStructure: {
2356 arrayify(node);
2357 break;
2358 }
2359
2360 case GetByVal: {
2361 switch (node->arrayMode().type()) {
2362 case Array::AnyTypedArray:
2363 case Array::ForceExit:
2364 case Array::SelectUsingArguments:
2365 case Array::SelectUsingPredictions:
2366 case Array::Unprofiled:
2367 DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2368 break;
2369 case Array::Undecided: {
2370 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2371 GPRTemporary result(this, Reuse, index);
2372 GPRReg indexGPR = index.gpr();
2373 GPRReg resultGPR = result.gpr();
2374
2375 speculationCheck(OutOfBounds, JSValueRegs(), node,
2376 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2377
2378 use(m_graph.varArgChild(node, 0));
2379 index.use();
2380
2381 m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2382 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2383 break;
2384 }
2385 case Array::Generic: {
2386 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2387 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2388 compileGetByValForObjectWithString(node);
2389 break;
2390 }
2391
2392 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2393 compileGetByValForObjectWithSymbol(node);
2394 break;
2395 }
2396 }
2397 JSValueOperand base(this, m_graph.varArgChild(node, 0));
2398 JSValueOperand property(this, m_graph.varArgChild(node, 1));
2399 GPRReg baseGPR = base.gpr();
2400 GPRReg propertyGPR = property.gpr();
2401
2402 flushRegisters();
2403 GPRFlushedCallResult result(this);
2404 callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2405 m_jit.exceptionCheck();
2406
2407 jsValueResult(result.gpr(), node);
2408 break;
2409 }
2410 case Array::Int32:
2411 case Array::Contiguous: {
2412 if (node->arrayMode().isInBounds()) {
2413 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2414 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2415
2416 GPRReg propertyReg = property.gpr();
2417 GPRReg storageReg = storage.gpr();
2418
2419 if (!m_compileOkay)
2420 return;
2421
2422 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2423
2424 GPRTemporary result(this);
2425
2426 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2427 if (node->arrayMode().isSaneChain()) {
2428 ASSERT(node->arrayMode().type() == Array::Contiguous);
2429 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result.gpr());
2430 m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2431 notHole.link(&m_jit);
2432 } else {
2433 speculationCheck(
2434 LoadFromHole, JSValueRegs(), 0,
2435 m_jit.branchIfEmpty(result.gpr()));
2436 }
2437 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2438 break;
2439 }
2440
2441 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2442 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2443 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2444
2445 GPRReg baseReg = base.gpr();
2446 GPRReg propertyReg = property.gpr();
2447 GPRReg storageReg = storage.gpr();
2448
2449 if (!m_compileOkay)
2450 return;
2451
2452 GPRTemporary result(this);
2453 GPRReg resultReg = result.gpr();
2454
2455 MacroAssembler::JumpList slowCases;
2456
2457 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2458
2459 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2460 slowCases.append(m_jit.branchIfEmpty(resultReg));
2461
2462 addSlowPathGenerator(
2463 slowPathCall(
2464 slowCases, this, operationGetByValObjectInt,
2465 result.gpr(), baseReg, propertyReg));
2466
2467 jsValueResult(resultReg, node);
2468 break;
2469 }
2470
2471 case Array::Double: {
2472 if (node->arrayMode().isInBounds()) {
2473 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2474 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2475
2476 GPRReg propertyReg = property.gpr();
2477 GPRReg storageReg = storage.gpr();
2478
2479 if (!m_compileOkay)
2480 return;
2481
2482 FPRTemporary result(this);
2483 FPRReg resultReg = result.fpr();
2484
2485 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2486
2487 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2488 if (!node->arrayMode().isSaneChain())
2489 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(resultReg));
2490 doubleResult(resultReg, node);
2491 break;
2492 }
2493
2494 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2495 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2496 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2497
2498 GPRReg baseReg = base.gpr();
2499 GPRReg propertyReg = property.gpr();
2500 GPRReg storageReg = storage.gpr();
2501
2502 if (!m_compileOkay)
2503 return;
2504
2505 GPRTemporary result(this);
2506 FPRTemporary temp(this);
2507 GPRReg resultReg = result.gpr();
2508 FPRReg tempReg = temp.fpr();
2509
2510 MacroAssembler::JumpList slowCases;
2511
2512 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2513
2514 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2515 slowCases.append(m_jit.branchIfNaN(tempReg));
2516 boxDouble(tempReg, resultReg);
2517
2518 addSlowPathGenerator(
2519 slowPathCall(
2520 slowCases, this, operationGetByValObjectInt,
2521 result.gpr(), baseReg, propertyReg));
2522
2523 jsValueResult(resultReg, node);
2524 break;
2525 }
2526
2527 case Array::ArrayStorage:
2528 case Array::SlowPutArrayStorage: {
2529 if (node->arrayMode().isInBounds()) {
2530 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2531 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2532
2533 GPRReg propertyReg = property.gpr();
2534 GPRReg storageReg = storage.gpr();
2535
2536 if (!m_compileOkay)
2537 return;
2538
2539 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2540
2541 GPRTemporary result(this);
2542 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2543 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(result.gpr()));
2544
2545 jsValueResult(result.gpr(), node);
2546 break;
2547 }
2548
2549 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2550 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2551 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2552
2553 GPRReg baseReg = base.gpr();
2554 GPRReg propertyReg = property.gpr();
2555 GPRReg storageReg = storage.gpr();
2556
2557 if (!m_compileOkay)
2558 return;
2559
2560 GPRTemporary result(this);
2561 GPRReg resultReg = result.gpr();
2562
2563 MacroAssembler::JumpList slowCases;
2564
2565 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2566
2567 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2568 slowCases.append(m_jit.branchIfEmpty(resultReg));
2569
2570 addSlowPathGenerator(
2571 slowPathCall(
2572 slowCases, this, operationGetByValObjectInt,
2573 result.gpr(), baseReg, propertyReg));
2574
2575 jsValueResult(resultReg, node);
2576 break;
2577 }
2578 case Array::String:
2579 compileGetByValOnString(node);
2580 break;
2581 case Array::DirectArguments:
2582 compileGetByValOnDirectArguments(node);
2583 break;
2584 case Array::ScopedArguments:
2585 compileGetByValOnScopedArguments(node);
2586 break;
2587 case Array::Int8Array:
2588 case Array::Int16Array:
2589 case Array::Int32Array:
2590 case Array::Uint8Array:
2591 case Array::Uint8ClampedArray:
2592 case Array::Uint16Array:
2593 case Array::Uint32Array:
2594 case Array::Float32Array:
2595 case Array::Float64Array: {
2596 TypedArrayType type = node->arrayMode().typedArrayType();
2597 if (isInt(type))
2598 compileGetByValOnIntTypedArray(node, type);
2599 else
2600 compileGetByValOnFloatTypedArray(node, type);
2601 } }
2602 break;
2603 }
2604
2605 case GetByValWithThis: {
2606 compileGetByValWithThis(node);
2607 break;
2608 }
2609
2610 case PutByValDirect:
2611 case PutByVal:
2612 case PutByValAlias: {
2613 Edge child1 = m_jit.graph().varArgChild(node, 0);
2614 Edge child2 = m_jit.graph().varArgChild(node, 1);
2615 Edge child3 = m_jit.graph().varArgChild(node, 2);
2616 Edge child4 = m_jit.graph().varArgChild(node, 3);
2617
2618 ArrayMode arrayMode = node->arrayMode().modeForPut();
2619 bool alreadyHandled = false;
2620
2621 switch (arrayMode.type()) {
2622 case Array::SelectUsingPredictions:
2623 case Array::ForceExit:
2624 DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2625 break;
2626 case Array::Generic: {
2627 DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
2628
2629 if (child1.useKind() == CellUse) {
2630 if (child2.useKind() == StringUse) {
2631 compilePutByValForCellWithString(node, child1, child2, child3);
2632 alreadyHandled = true;
2633 break;
2634 }
2635
2636 if (child2.useKind() == SymbolUse) {
2637 compilePutByValForCellWithSymbol(node, child1, child2, child3);
2638 alreadyHandled = true;
2639 break;
2640 }
2641 }
2642
2643 JSValueOperand arg1(this, child1);
2644 JSValueOperand arg2(this, child2);
2645 JSValueOperand arg3(this, child3);
2646 GPRReg arg1GPR = arg1.gpr();
2647 GPRReg arg2GPR = arg2.gpr();
2648 GPRReg arg3GPR = arg3.gpr();
2649 flushRegisters();
2650 if (node->op() == PutByValDirect)
2651 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2652 else
2653 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2654 m_jit.exceptionCheck();
2655
2656 noResult(node);
2657 alreadyHandled = true;
2658 break;
2659 }
2660 default:
2661 break;
2662 }
2663
2664 if (alreadyHandled)
2665 break;
2666
2667 SpeculateCellOperand base(this, child1);
2668 SpeculateStrictInt32Operand property(this, child2);
2669
2670 GPRReg baseReg = base.gpr();
2671 GPRReg propertyReg = property.gpr();
2672
2673 switch (arrayMode.type()) {
2674 case Array::Int32:
2675 case Array::Contiguous: {
2676 JSValueOperand value(this, child3, ManualOperandSpeculation);
2677
2678 GPRReg valueReg = value.gpr();
2679
2680 if (!m_compileOkay)
2681 return;
2682
2683 if (arrayMode.type() == Array::Int32) {
2684 DFG_TYPE_CHECK(
2685 JSValueRegs(valueReg), child3, SpecInt32Only,
2686 m_jit.branchIfNotInt32(valueReg));
2687 }
2688
2689 StorageOperand storage(this, child4);
2690 GPRReg storageReg = storage.gpr();
2691
2692 if (node->op() == PutByValAlias) {
2693 // Store the value to the array.
2694 GPRReg propertyReg = property.gpr();
2695 GPRReg valueReg = value.gpr();
2696 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2697
2698 noResult(node);
2699 break;
2700 }
2701
2702 GPRTemporary temporary;
2703 GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2704
2705 MacroAssembler::Jump slowCase;
2706
2707 if (arrayMode.isInBounds()) {
2708 speculationCheck(
2709 OutOfBounds, JSValueRegs(), 0,
2710 m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2711 } else {
2712 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2713
2714 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2715
2716 if (!arrayMode.isOutOfBounds())
2717 speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2718
2719 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2720 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2721
2722 inBounds.link(&m_jit);
2723 }
2724
2725 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2726
2727 base.use();
2728 property.use();
2729 value.use();
2730 storage.use();
2731
2732 if (arrayMode.isOutOfBounds()) {
2733 addSlowPathGenerator(slowPathCall(
2734 slowCase, this,
2735 m_jit.isStrictModeFor(node->origin.semantic)
2736 ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2737 : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2738 NoResult, baseReg, propertyReg, valueReg));
2739 }
2740
2741 noResult(node, UseChildrenCalledExplicitly);
2742 break;
2743 }
2744
2745 case Array::Double: {
2746 compileDoublePutByVal(node, base, property);
2747 break;
2748 }
2749
2750 case Array::ArrayStorage:
2751 case Array::SlowPutArrayStorage: {
2752 JSValueOperand value(this, child3);
2753
2754 GPRReg valueReg = value.gpr();
2755
2756 if (!m_compileOkay)
2757 return;
2758
2759 StorageOperand storage(this, child4);
2760 GPRReg storageReg = storage.gpr();
2761
2762 if (node->op() == PutByValAlias) {
2763 // Store the value to the array.
2764 GPRReg propertyReg = property.gpr();
2765 GPRReg valueReg = value.gpr();
2766 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2767
2768 noResult(node);
2769 break;
2770 }
2771
2772 GPRTemporary temporary;
2773 GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2774
2775 MacroAssembler::JumpList slowCases;
2776
2777 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2778 if (!arrayMode.isOutOfBounds())
2779 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2780 else
2781 slowCases.append(beyondArrayBounds);
2782
2783 // Check if we're writing to a hole; if so increment m_numValuesInVector.
2784 if (arrayMode.isInBounds()) {
2785 speculationCheck(
2786 StoreToHole, JSValueRegs(), 0,
2787 m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
2788 } else {
2789 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2790 if (arrayMode.isSlowPut()) {
2791 // This is sort of strange. If we wanted to optimize this code path, we would invert
2792 // the above branch. But it's simply not worth it since this only happens if we're
2793 // already having a bad time.
2794 slowCases.append(m_jit.jump());
2795 } else {
2796 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2797
2798 // If we're writing to a hole we might be growing the array;
2799 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2800 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2801 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2802
2803 lengthDoesNotNeedUpdate.link(&m_jit);
2804 }
2805 notHoleValue.link(&m_jit);
2806 }
2807
2808 // Store the value to the array.
2809 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2810
2811 base.use();
2812 property.use();
2813 value.use();
2814 storage.use();
2815
2816 if (!slowCases.empty()) {
2817 addSlowPathGenerator(slowPathCall(
2818 slowCases, this,
2819 m_jit.isStrictModeFor(node->origin.semantic)
2820 ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2821 : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2822 NoResult, baseReg, propertyReg, valueReg));
2823 }
2824
2825 noResult(node, UseChildrenCalledExplicitly);
2826 break;
2827 }
2828
2829 case Array::Int8Array:
2830 case Array::Int16Array:
2831 case Array::Int32Array:
2832 case Array::Uint8Array:
2833 case Array::Uint8ClampedArray:
2834 case Array::Uint16Array:
2835 case Array::Uint32Array:
2836 case Array::Float32Array:
2837 case Array::Float64Array: {
2838 TypedArrayType type = arrayMode.typedArrayType();
2839 if (isInt(type))
2840 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2841 else
2842 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2843 break;
2844 }
2845
2846 case Array::AnyTypedArray:
2847 case Array::String:
2848 case Array::DirectArguments:
2849 case Array::ForceExit:
2850 case Array::Generic:
2851 case Array::ScopedArguments:
2852 case Array::SelectUsingArguments:
2853 case Array::SelectUsingPredictions:
2854 case Array::Undecided:
2855 case Array::Unprofiled:
2856 RELEASE_ASSERT_NOT_REACHED();
2857 }
2858 break;
2859 }
2860
2861 case AtomicsAdd:
2862 case AtomicsAnd:
2863 case AtomicsCompareExchange:
2864 case AtomicsExchange:
2865 case AtomicsLoad:
2866 case AtomicsOr:
2867 case AtomicsStore:
2868 case AtomicsSub:
2869 case AtomicsXor: {
2870 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
2871 Edge baseEdge = m_jit.graph().child(node, 0);
2872 Edge indexEdge = m_jit.graph().child(node, 1);
2873 Edge argEdges[maxNumExtraAtomicsArgs];
2874 for (unsigned i = numExtraArgs; i--;)
2875 argEdges[i] = m_jit.graph().child(node, 2 + i);
2876 Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
2877
2878 GPRReg baseGPR;
2879 GPRReg indexGPR;
2880 GPRReg argGPRs[2];
2881 GPRReg resultGPR;
2882
2883 auto callSlowPath = [&] () {
2884 switch (node->op()) {
2885 case AtomicsAdd:
2886 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2887 break;
2888 case AtomicsAnd:
2889 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2890 break;
2891 case AtomicsCompareExchange:
2892 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
2893 break;
2894 case AtomicsExchange:
2895 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2896 break;
2897 case AtomicsLoad:
2898 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
2899 break;
2900 case AtomicsOr:
2901 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2902 break;
2903 case AtomicsStore:
2904 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2905 break;
2906 case AtomicsSub:
2907 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2908 break;
2909 case AtomicsXor:
2910 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2911 break;
2912 default:
2913 RELEASE_ASSERT_NOT_REACHED();
2914 break;
2915 }
2916 };
2917
2918 if (!storageEdge) {
2919 // We are in generic mode!
2920 JSValueOperand base(this, baseEdge);
2921 JSValueOperand index(this, indexEdge);
2922 Optional<JSValueOperand> args[2];
2923 baseGPR = base.gpr();
2924 indexGPR = index.gpr();
2925 for (unsigned i = numExtraArgs; i--;) {
2926 args[i].emplace(this, argEdges[i]);
2927 argGPRs[i] = args[i]->gpr();
2928 }
2929
2930 flushRegisters();
2931 GPRFlushedCallResult result(this);
2932 resultGPR = result.gpr();
2933 callSlowPath();
2934 m_jit.exceptionCheck();
2935
2936 jsValueResult(resultGPR, node);
2937 break;
2938 }
2939
2940 TypedArrayType type = node->arrayMode().typedArrayType();
2941
2942 SpeculateCellOperand base(this, baseEdge);
2943 SpeculateStrictInt32Operand index(this, indexEdge);
2944
2945 baseGPR = base.gpr();
2946 indexGPR = index.gpr();
2947
2948 emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
2949
2950 GPRTemporary args[2];
2951
2952 JITCompiler::JumpList slowPathCases;
2953
2954 bool ok = true;
2955 for (unsigned i = numExtraArgs; i--;) {
2956 if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
2957 noResult(node);
2958 ok = false;
2959 }
2960 argGPRs[i] = args[i].gpr();
2961 }
2962 if (!ok)
2963 break;
2964
2965 StorageOperand storage(this, storageEdge);
2966 GPRTemporary oldValue(this);
2967 GPRTemporary result(this);
2968 GPRTemporary newValue(this);
2969 GPRReg storageGPR = storage.gpr();
2970 GPRReg oldValueGPR = oldValue.gpr();
2971 resultGPR = result.gpr();
2972 GPRReg newValueGPR = newValue.gpr();
2973
2974 // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
2975 // https://bugs.webkit.org/show_bug.cgi?id=170974
2976 m_jit.nop();
2977
2978 JITCompiler::Label loop = m_jit.label();
2979
2980 loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
2981 m_jit.move(oldValueGPR, newValueGPR);
2982 m_jit.move(oldValueGPR, resultGPR);
2983
2984 switch (node->op()) {
2985 case AtomicsAdd:
2986 m_jit.add32(argGPRs[0], newValueGPR);
2987 break;
2988 case AtomicsAnd:
2989 m_jit.and32(argGPRs[0], newValueGPR);
2990 break;
2991 case AtomicsCompareExchange: {
2992 switch (elementSize(type)) {
2993 case 1:
2994 if (isSigned(type))
2995 m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
2996 else
2997 m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
2998 break;
2999 case 2:
3000 if (isSigned(type))
3001 m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3002 else
3003 m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3004 break;
3005 case 4:
3006 break;
3007 default:
3008 RELEASE_ASSERT_NOT_REACHED();
3009 break;
3010 }
3011 JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3012 m_jit.move(argGPRs[1], newValueGPR);
3013 fail.link(&m_jit);
3014 break;
3015 }
3016 case AtomicsExchange:
3017 m_jit.move(argGPRs[0], newValueGPR);
3018 break;
3019 case AtomicsLoad:
3020 break;
3021 case AtomicsOr:
3022 m_jit.or32(argGPRs[0], newValueGPR);
3023 break;
3024 case AtomicsStore:
3025 m_jit.move(argGPRs[0], newValueGPR);
3026 m_jit.move(argGPRs[0], resultGPR);
3027 break;
3028 case AtomicsSub:
3029 m_jit.sub32(argGPRs[0], newValueGPR);
3030 break;
3031 case AtomicsXor:
3032 m_jit.xor32(argGPRs[0], newValueGPR);
3033 break;
3034 default:
3035 RELEASE_ASSERT_NOT_REACHED();
3036 break;
3037 }
3038
3039 JITCompiler::JumpList success;
3040 switch (elementSize(type)) {
3041 case 1:
3042 success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3043 break;
3044 case 2:
3045 success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3046 break;
3047 case 4:
3048 success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3049 break;
3050 default:
3051 RELEASE_ASSERT_NOT_REACHED();
3052 break;
3053 }
3054 m_jit.jump().linkTo(loop, &m_jit);
3055
3056 if (!slowPathCases.empty()) {
3057 slowPathCases.link(&m_jit);
3058 silentSpillAllRegisters(resultGPR);
3059 // Since we spilled, we can do things to registers.
3060 m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3061 m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3062 for (unsigned i = numExtraArgs; i--;)
3063 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3064 callSlowPath();
3065 silentFillAllRegisters();
3066 m_jit.exceptionCheck();
3067 }
3068
3069 success.link(&m_jit);
3070 setIntTypedArrayLoadResult(node, resultGPR, type);
3071 break;
3072 }
3073
3074 case AtomicsIsLockFree: {
3075 if (node->child1().useKind() != Int32Use) {
3076 JSValueOperand operand(this, node->child1());
3077 GPRReg operandGPR = operand.gpr();
3078 flushRegisters();
3079 GPRFlushedCallResult result(this);
3080 GPRReg resultGPR = result.gpr();
3081 callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3082 m_jit.exceptionCheck();
3083 jsValueResult(resultGPR, node);
3084 break;
3085 }
3086
3087 SpeculateInt32Operand operand(this, node->child1());
3088 GPRTemporary result(this);
3089 GPRReg operandGPR = operand.gpr();
3090 GPRReg resultGPR = result.gpr();
3091 m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3092 JITCompiler::JumpList done;
3093 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3094 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3095 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3096 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3097 done.link(&m_jit);
3098 jsValueResult(resultGPR, node);
3099 break;
3100 }
3101
3102 case RegExpExec: {
3103 compileRegExpExec(node);
3104 break;
3105 }
3106
3107 case RegExpExecNonGlobalOrSticky: {
3108 compileRegExpExecNonGlobalOrSticky(node);
3109 break;
3110 }
3111
3112 case RegExpMatchFastGlobal: {
3113 compileRegExpMatchFastGlobal(node);
3114 break;
3115 }
3116
3117 case RegExpTest: {
3118 compileRegExpTest(node);
3119 break;
3120 }
3121
3122 case RegExpMatchFast: {
3123 compileRegExpMatchFast(node);
3124 break;
3125 }
3126
3127 case StringReplace:
3128 case StringReplaceRegExp: {
3129 compileStringReplace(node);
3130 break;
3131 }
3132
3133 case GetRegExpObjectLastIndex: {
3134 compileGetRegExpObjectLastIndex(node);
3135 break;
3136 }
3137
3138 case SetRegExpObjectLastIndex: {
3139 compileSetRegExpObjectLastIndex(node);
3140 break;
3141 }
3142
3143 case RecordRegExpCachedResult: {
3144 compileRecordRegExpCachedResult(node);
3145 break;
3146 }
3147
3148 case ArrayPush: {
3149 compileArrayPush(node);
3150 break;
3151 }
3152
3153 case ArraySlice: {
3154 compileArraySlice(node);
3155 break;
3156 }
3157
3158 case ArrayIndexOf: {
3159 compileArrayIndexOf(node);
3160 break;
3161 }
3162
3163 case ArrayPop: {
3164 ASSERT(node->arrayMode().isJSArray());
3165
3166 SpeculateCellOperand base(this, node->child1());
3167 StorageOperand storage(this, node->child2());
3168 GPRTemporary value(this);
3169 GPRTemporary storageLength(this);
3170 FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop().
3171
3172 GPRReg baseGPR = base.gpr();
3173 GPRReg storageGPR = storage.gpr();
3174 GPRReg valueGPR = value.gpr();
3175 GPRReg storageLengthGPR = storageLength.gpr();
3176 FPRReg tempFPR = temp.fpr();
3177
3178 switch (node->arrayMode().type()) {
3179 case Array::Int32:
3180 case Array::Double:
3181 case Array::Contiguous: {
3182 m_jit.load32(
3183 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3184 MacroAssembler::Jump undefinedCase =
3185 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3186 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3187 m_jit.store32(
3188 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3189 MacroAssembler::Jump slowCase;
3190 if (node->arrayMode().type() == Array::Double) {
3191 m_jit.loadDouble(
3192 MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3193 tempFPR);
3194 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3195 // length and the new length.
3196 m_jit.store64(
3197 MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3198 slowCase = m_jit.branchIfNaN(tempFPR);
3199 boxDouble(tempFPR, valueGPR);
3200 } else {
3201 m_jit.load64(
3202 MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3203 valueGPR);
3204 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3205 // length and the new length.
3206 m_jit.store64(
3207 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3208 slowCase = m_jit.branchIfEmpty(valueGPR);
3209 }
3210
3211 addSlowPathGenerator(
3212 slowPathMove(
3213 undefinedCase, this,
3214 MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3215 addSlowPathGenerator(
3216 slowPathCall(
3217 slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3218
3219 // We can't know for sure that the result is an int because of the slow paths. :-/
3220 jsValueResult(valueGPR, node);
3221 break;
3222 }
3223
3224 case Array::ArrayStorage: {
3225 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3226
3227 JITCompiler::Jump undefinedCase =
3228 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3229
3230 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3231
3232 JITCompiler::JumpList slowCases;
3233 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3234
3235 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3236 slowCases.append(m_jit.branchIfEmpty(valueGPR));
3237
3238 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3239
3240 m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3241 m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3242
3243 addSlowPathGenerator(
3244 slowPathMove(
3245 undefinedCase, this,
3246 MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3247
3248 addSlowPathGenerator(
3249 slowPathCall(
3250 slowCases, this, operationArrayPop, valueGPR, baseGPR));
3251
3252 jsValueResult(valueGPR, node);
3253 break;
3254 }
3255
3256 default:
3257 CRASH();
3258 break;
3259 }
3260 break;
3261 }
3262
3263 case DFG::Jump: {
3264 jump(node->targetBlock());
3265 noResult(node);
3266 break;
3267 }
3268
3269 case Branch:
3270 emitBranch(node);
3271 break;
3272
3273 case Switch:
3274 emitSwitch(node);
3275 break;
3276
3277 case Return: {
3278 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3279 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3280 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3281
3282 // Return the result in returnValueGPR.
3283 JSValueOperand op1(this, node->child1());
3284 m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3285
3286 m_jit.emitRestoreCalleeSaves();
3287 m_jit.emitFunctionEpilogue();
3288 m_jit.ret();
3289
3290 noResult(node);
3291 break;
3292 }
3293
3294 case Throw: {
3295 compileThrow(node);
3296 break;
3297 }
3298
3299 case ThrowStaticError: {
3300 compileThrowStaticError(node);
3301 break;
3302 }
3303
3304 case BooleanToNumber: {
3305 switch (node->child1().useKind()) {
3306 case BooleanUse: {
3307 JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3308 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3309
3310 m_jit.move(value.gpr(), result.gpr());
3311 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3312 DFG_TYPE_CHECK(
3313 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3314 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3315
3316 int32Result(result.gpr(), node);
3317 break;
3318 }
3319
3320 case UntypedUse: {
3321 JSValueOperand value(this, node->child1());
3322 GPRTemporary result(this);
3323
3324 if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3325 m_jit.move(value.gpr(), result.gpr());
3326 m_jit.and32(TrustedImm32(1), result.gpr());
3327 int32Result(result.gpr(), node);
3328 break;
3329 }
3330
3331 m_jit.move(value.gpr(), result.gpr());
3332 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3333 JITCompiler::Jump isBoolean = m_jit.branchTest64(
3334 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3335 m_jit.move(value.gpr(), result.gpr());
3336 JITCompiler::Jump done = m_jit.jump();
3337 isBoolean.link(&m_jit);
3338 m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3339 done.link(&m_jit);
3340
3341 jsValueResult(result.gpr(), node);
3342 break;
3343 }
3344
3345 default:
3346 DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3347 break;
3348 }
3349 break;
3350 }
3351
3352 case ToPrimitive: {
3353 compileToPrimitive(node);
3354 break;
3355 }
3356
3357 case ToNumber: {
3358 JSValueOperand argument(this, node->child1());
3359 GPRTemporary result(this, Reuse, argument);
3360
3361 GPRReg argumentGPR = argument.gpr();
3362 GPRReg resultGPR = result.gpr();
3363
3364 argument.use();
3365
3366 // We have several attempts to remove ToNumber. But ToNumber still exists.
3367 // It means that converting non-numbers to numbers by this ToNumber is not rare.
3368 // Instead of the slow path generator, we emit callOperation here.
3369 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3370 flushRegisters();
3371 callOperation(operationToNumber, resultGPR, argumentGPR);
3372 m_jit.exceptionCheck();
3373 } else {
3374 MacroAssembler::Jump notNumber = m_jit.branchIfNotNumber(argumentGPR);
3375 m_jit.move(argumentGPR, resultGPR);
3376 MacroAssembler::Jump done = m_jit.jump();
3377
3378 notNumber.link(&m_jit);
3379 silentSpillAllRegisters(resultGPR);
3380 callOperation(operationToNumber, resultGPR, argumentGPR);
3381 silentFillAllRegisters();
3382 m_jit.exceptionCheck();
3383
3384 done.link(&m_jit);
3385 }
3386
3387 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3388 break;
3389 }
3390
3391 case ToString:
3392 case CallStringConstructor:
3393 case StringValueOf: {
3394 compileToStringOrCallStringConstructorOrStringValueOf(node);
3395 break;
3396 }
3397
3398 case NewStringObject: {
3399 compileNewStringObject(node);
3400 break;
3401 }
3402
3403 case NewSymbol: {
3404 compileNewSymbol(node);
3405 break;
3406 }
3407
3408 case NewArray: {
3409 compileNewArray(node);
3410 break;
3411 }
3412
3413 case NewArrayWithSpread: {
3414 compileNewArrayWithSpread(node);
3415 break;
3416 }
3417
3418 case Spread: {
3419 compileSpread(node);
3420 break;
3421 }
3422
3423 case NewArrayWithSize: {
3424 compileNewArrayWithSize(node);
3425 break;
3426 }
3427
3428 case NewArrayBuffer: {
3429 compileNewArrayBuffer(node);
3430 break;
3431 }
3432
3433 case NewTypedArray: {
3434 compileNewTypedArray(node);
3435 break;
3436 }
3437
3438 case NewRegexp: {
3439 compileNewRegexp(node);
3440 break;
3441 }
3442
3443 case ToObject:
3444 case CallObjectConstructor: {
3445 compileToObjectOrCallObjectConstructor(node);
3446 break;
3447 }
3448
3449 case ToThis: {
3450 compileToThis(node);
3451 break;
3452 }
3453
3454 case ObjectCreate: {
3455 compileObjectCreate(node);
3456 break;
3457 }
3458
3459 case ObjectKeys: {
3460 compileObjectKeys(node);
3461 break;
3462 }
3463
3464 case CreateThis: {
3465 compileCreateThis(node);
3466 break;
3467 }
3468
3469 case NewObject: {
3470 compileNewObject(node);
3471 break;
3472 }
3473
3474 case GetCallee: {
3475 compileGetCallee(node);
3476 break;
3477 }
3478
3479 case SetCallee: {
3480 compileSetCallee(node);
3481 break;
3482 }
3483
3484 case GetArgumentCountIncludingThis: {
3485 compileGetArgumentCountIncludingThis(node);
3486 break;
3487 }
3488
3489 case SetArgumentCountIncludingThis:
3490 compileSetArgumentCountIncludingThis(node);
3491 break;
3492
3493 case GetRestLength: {
3494 compileGetRestLength(node);
3495 break;
3496 }
3497
3498 case GetScope:
3499 compileGetScope(node);
3500 break;
3501
3502 case SkipScope:
3503 compileSkipScope(node);
3504 break;
3505
3506 case GetGlobalObject:
3507 compileGetGlobalObject(node);
3508 break;
3509
3510 case GetGlobalThis:
3511 compileGetGlobalThis(node);
3512 break;
3513
3514 case GetClosureVar: {
3515 compileGetClosureVar(node);
3516 break;
3517 }
3518 case PutClosureVar: {
3519 compilePutClosureVar(node);
3520 break;
3521 }
3522
3523 case TryGetById: {
3524 compileGetById(node, AccessType::TryGet);
3525 break;
3526 }
3527
3528 case GetByIdDirect: {
3529 compileGetById(node, AccessType::GetDirect);
3530 break;
3531 }
3532
3533 case GetByIdDirectFlush: {
3534 compileGetByIdFlush(node, AccessType::GetDirect);
3535 break;
3536 }
3537
3538 case GetById: {
3539 compileGetById(node, AccessType::Get);
3540 break;
3541 }
3542
3543 case GetByIdFlush: {
3544 compileGetByIdFlush(node, AccessType::Get);
3545 break;
3546 }
3547
3548 case GetByIdWithThis: {
3549 if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3550 SpeculateCellOperand base(this, node->child1());
3551 GPRReg baseGPR = base.gpr();
3552 SpeculateCellOperand thisValue(this, node->child2());
3553 GPRReg thisValueGPR = thisValue.gpr();
3554
3555 GPRFlushedCallResult result(this);
3556 GPRReg resultGPR = result.gpr();
3557
3558 flushRegisters();
3559
3560 cachedGetByIdWithThis(node->origin.semantic, baseGPR, thisValueGPR, resultGPR, node->identifierNumber(), JITCompiler::JumpList());
3561
3562 jsValueResult(resultGPR, node);
3563
3564 } else {
3565 JSValueOperand base(this, node->child1());
3566 GPRReg baseGPR = base.gpr();
3567 JSValueOperand thisValue(this, node->child2());
3568 GPRReg thisValueGPR = thisValue.gpr();
3569
3570 GPRFlushedCallResult result(this);
3571 GPRReg resultGPR = result.gpr();
3572
3573 flushRegisters();
3574
3575 JITCompiler::JumpList notCellList;
3576 notCellList.append(m_jit.branchIfNotCell(JSValueRegs(baseGPR)));
3577 notCellList.append(m_jit.branchIfNotCell(JSValueRegs(thisValueGPR)));
3578
3579 cachedGetByIdWithThis(node->origin.semantic, baseGPR, thisValueGPR, resultGPR, node->identifierNumber(), notCellList);
3580
3581 jsValueResult(resultGPR, node);
3582 }
3583
3584 break;
3585 }
3586
3587 case GetArrayLength:
3588 compileGetArrayLength(node);
3589 break;
3590
3591 case DeleteById: {
3592 compileDeleteById(node);
3593 break;
3594 }
3595
3596 case DeleteByVal: {
3597 compileDeleteByVal(node);
3598 break;
3599 }
3600
3601 case CheckCell: {
3602 compileCheckCell(node);
3603 break;
3604 }
3605
3606 case CheckNotEmpty: {
3607 compileCheckNotEmpty(node);
3608 break;
3609 }
3610
3611 case AssertNotEmpty: {
3612 if (validationEnabled()) {
3613 JSValueOperand operand(this, node->child1());
3614 GPRReg input = operand.gpr();
3615 auto done = m_jit.branchIfNotEmpty(input);
3616 m_jit.breakpoint();
3617 done.link(&m_jit);
3618 }
3619 noResult(node);
3620 break;
3621 }
3622
3623 case CheckStringIdent:
3624 compileCheckStringIdent(node);
3625 break;
3626
3627 case GetExecutable: {
3628 compileGetExecutable(node);
3629 break;
3630 }
3631
3632 case CheckStructureOrEmpty: {
3633 SpeculateCellOperand cell(this, node->child1());
3634 GPRReg cellGPR = cell.gpr();
3635
3636 GPRReg tempGPR = InvalidGPRReg;
3637 Optional<GPRTemporary> temp;
3638 if (node->structureSet().size() > 1) {
3639 temp.emplace(this);
3640 tempGPR = temp->gpr();
3641 }
3642
3643 MacroAssembler::Jump isEmpty;
3644 if (m_interpreter.forNode(node->child1()).m_type & SpecEmpty)
3645 isEmpty = m_jit.branchIfEmpty(cellGPR);
3646
3647 emitStructureCheck(node, cellGPR, tempGPR);
3648
3649 if (isEmpty.isSet())
3650 isEmpty.link(&m_jit);
3651
3652 noResult(node);
3653 break;
3654 }
3655
3656 case CheckStructure: {
3657 compileCheckStructure(node);
3658 break;
3659 }
3660
3661 case PutStructure: {
3662 RegisteredStructure oldStructure = node->transition()->previous;
3663 RegisteredStructure newStructure = node->transition()->next;
3664
3665 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3666
3667 SpeculateCellOperand base(this, node->child1());
3668 GPRReg baseGPR = base.gpr();
3669
3670 ASSERT_UNUSED(oldStructure, oldStructure->indexingMode() == newStructure->indexingMode());
3671 ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3672 ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3673 m_jit.store32(MacroAssembler::TrustedImm32(newStructure->id()), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3674
3675 noResult(node);
3676 break;
3677 }
3678
3679 case AllocatePropertyStorage:
3680 compileAllocatePropertyStorage(node);
3681 break;
3682
3683 case ReallocatePropertyStorage:
3684 compileReallocatePropertyStorage(node);
3685 break;
3686
3687 case NukeStructureAndSetButterfly:
3688 compileNukeStructureAndSetButterfly(node);
3689 break;
3690
3691 case GetButterfly:
3692 compileGetButterfly(node);
3693 break;
3694
3695 case GetIndexedPropertyStorage: {
3696 compileGetIndexedPropertyStorage(node);
3697 break;
3698 }
3699
3700 case ConstantStoragePointer: {
3701 compileConstantStoragePointer(node);
3702 break;
3703 }
3704
3705 case GetTypedArrayByteOffset: {
3706 compileGetTypedArrayByteOffset(node);
3707 break;
3708 }
3709
3710 case GetPrototypeOf: {
3711 compileGetPrototypeOf(node);
3712 break;
3713 }
3714
3715 case GetByOffset:
3716 case GetGetterSetterByOffset: {
3717 compileGetByOffset(node);
3718 break;
3719 }
3720
3721 case MatchStructure: {
3722 compileMatchStructure(node);
3723 break;
3724 }
3725
3726 case GetGetter: {
3727 compileGetGetter(node);
3728 break;
3729 }
3730
3731 case GetSetter: {
3732 compileGetSetter(node);
3733 break;
3734 }
3735
3736 case PutByOffset: {
3737 compilePutByOffset(node);
3738 break;
3739 }
3740
3741 case PutByIdFlush: {
3742 compilePutByIdFlush(node);
3743 break;
3744 }
3745
3746 case PutById: {
3747 compilePutById(node);
3748 break;
3749 }
3750
3751 case PutByIdWithThis: {
3752 compilePutByIdWithThis(node);
3753 break;
3754 }
3755
3756 case PutByValWithThis: {
3757 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
3758 GPRReg baseGPR = base.gpr();
3759 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
3760 GPRReg thisValueGPR = thisValue.gpr();
3761 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
3762 GPRReg propertyGPR = property.gpr();
3763 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
3764 GPRReg valueGPR = value.gpr();
3765
3766 flushRegisters();
3767 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis, NoResult, baseGPR, thisValueGPR, propertyGPR, valueGPR);
3768 m_jit.exceptionCheck();
3769
3770 noResult(node);
3771 break;
3772 }
3773
3774 case PutByIdDirect: {
3775 compilePutByIdDirect(node);
3776 break;
3777 }
3778
3779 case PutGetterById:
3780 case PutSetterById: {
3781 compilePutAccessorById(node);
3782 break;
3783 }
3784
3785 case PutGetterSetterById: {
3786 compilePutGetterSetterById(node);
3787 break;
3788 }
3789
3790 case PutGetterByVal:
3791 case PutSetterByVal: {
3792 compilePutAccessorByVal(node);
3793 break;
3794 }
3795
3796 case DefineDataProperty: {
3797 compileDefineDataProperty(node);
3798 break;
3799 }
3800
3801 case DefineAccessorProperty: {
3802 compileDefineAccessorProperty(node);
3803 break;
3804 }
3805
3806 case GetGlobalLexicalVariable:
3807 case GetGlobalVar: {
3808 compileGetGlobalVariable(node);
3809 break;
3810 }
3811
3812 case PutGlobalVariable: {
3813 compilePutGlobalVariable(node);
3814 break;
3815 }
3816
3817 case PutDynamicVar: {
3818 compilePutDynamicVar(node);
3819 break;
3820 }
3821
3822 case GetDynamicVar: {
3823 compileGetDynamicVar(node);
3824 break;
3825 }
3826
3827 case ResolveScopeForHoistingFuncDeclInEval: {
3828 compileResolveScopeForHoistingFuncDeclInEval(node);
3829 break;
3830 }
3831
3832 case ResolveScope: {
3833 compileResolveScope(node);
3834 break;
3835 }
3836
3837 case NotifyWrite: {
3838 compileNotifyWrite(node);
3839 break;
3840 }
3841
3842 case CheckTypeInfoFlags: {
3843 compileCheckTypeInfoFlags(node);
3844 break;
3845 }
3846
3847 case ParseInt: {
3848 compileParseInt(node);
3849 break;
3850 }
3851
3852 case OverridesHasInstance: {
3853 compileOverridesHasInstance(node);
3854 break;
3855 }
3856
3857 case InstanceOf: {
3858 compileInstanceOf(node);
3859 break;
3860 }
3861
3862 case InstanceOfCustom: {
3863 compileInstanceOfCustom(node);
3864 break;
3865 }
3866
3867 case IsEmpty: {
3868 JSValueOperand value(this, node->child1());
3869 GPRTemporary result(this, Reuse, value);
3870
3871 m_jit.comparePtr(JITCompiler::Equal, value.gpr(), TrustedImm32(JSValue::encode(JSValue())), result.gpr());
3872 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3873
3874 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3875 break;
3876 }
3877
3878 case IsUndefined: {
3879 JSValueOperand value(this, node->child1());
3880 GPRTemporary result(this);
3881 GPRTemporary localGlobalObject(this);
3882 GPRTemporary remoteGlobalObject(this);
3883 GPRTemporary scratch(this);
3884
3885 JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3886
3887 m_jit.compare64(JITCompiler::Equal, value.gpr(), TrustedImm32(ValueUndefined), result.gpr());
3888 JITCompiler::Jump done = m_jit.jump();
3889
3890 isCell.link(&m_jit);
3891 JITCompiler::Jump notMasqueradesAsUndefined;
3892 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3893 m_jit.move(TrustedImm32(0), result.gpr());
3894 notMasqueradesAsUndefined = m_jit.jump();
3895 } else {
3896 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3897 JITCompiler::NonZero,
3898 JITCompiler::Address(value.gpr(), JSCell::typeInfoFlagsOffset()),
3899 TrustedImm32(MasqueradesAsUndefined));
3900 m_jit.move(TrustedImm32(0), result.gpr());
3901 notMasqueradesAsUndefined = m_jit.jump();
3902
3903 isMasqueradesAsUndefined.link(&m_jit);
3904 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3905 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3906 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3907 m_jit.emitLoadStructure(*m_jit.vm(), value.gpr(), result.gpr(), scratch.gpr());
3908 m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR);
3909 m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3910 }
3911
3912 notMasqueradesAsUndefined.link(&m_jit);
3913 done.link(&m_jit);
3914 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3915 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3916 break;
3917 }
3918
3919 case IsUndefinedOrNull: {
3920 JSValueOperand value(this, node->child1());
3921 GPRTemporary result(this, Reuse, value);
3922
3923 GPRReg valueGPR = value.gpr();
3924 GPRReg resultGPR = result.gpr();
3925
3926 m_jit.move(valueGPR, resultGPR);
3927 m_jit.and64(CCallHelpers::TrustedImm32(~TagBitUndefined), resultGPR);
3928 m_jit.compare64(CCallHelpers::Equal, resultGPR, CCallHelpers::TrustedImm32(ValueNull), resultGPR);
3929
3930 unblessedBooleanResult(resultGPR, node);
3931 break;
3932 }
3933
3934 case IsBoolean: {
3935 JSValueOperand value(this, node->child1());
3936 GPRTemporary result(this, Reuse, value);
3937
3938 m_jit.move(value.gpr(), result.gpr());
3939 m_jit.xor64(JITCompiler::TrustedImm32(ValueFalse), result.gpr());
3940 m_jit.test64(JITCompiler::Zero, result.gpr(), JITCompiler::TrustedImm32(static_cast<int32_t>(~1)), result.gpr());
3941 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3942 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3943 break;
3944 }
3945
3946 case IsNumber: {
3947 JSValueOperand value(this, node->child1());
3948 GPRTemporary result(this, Reuse, value);
3949
3950 m_jit.test64(JITCompiler::NonZero, value.gpr(), GPRInfo::tagTypeNumberRegister, result.gpr());
3951 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3952 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3953 break;
3954 }
3955
3956 case NumberIsInteger: {
3957 JSValueOperand value(this, node->child1());
3958 GPRTemporary result(this, Reuse, value);
3959
3960 FPRTemporary temp1(this);
3961 FPRTemporary temp2(this);
3962
3963 JSValueRegs valueRegs = JSValueRegs(value.gpr());
3964 GPRReg resultGPR = result.gpr();
3965
3966 FPRReg tempFPR1 = temp1.fpr();
3967 FPRReg tempFPR2 = temp2.fpr();
3968
3969 MacroAssembler::JumpList done;
3970
3971 auto isInt32 = m_jit.branchIfInt32(valueRegs);
3972 auto notNumber = m_jit.branchIfNotDoubleKnownNotInt32(valueRegs);
3973
3974 // We're a double here.
3975 m_jit.unboxDouble(valueRegs.gpr(), resultGPR, tempFPR1);
3976 m_jit.urshift64(TrustedImm32(52), resultGPR);
3977 m_jit.and32(TrustedImm32(0x7ff), resultGPR);
3978 auto notNanNorInfinity = m_jit.branch32(JITCompiler::NotEqual, TrustedImm32(0x7ff), resultGPR);
3979 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3980 done.append(m_jit.jump());
3981
3982 notNanNorInfinity.link(&m_jit);
3983 m_jit.roundTowardZeroDouble(tempFPR1, tempFPR2);
3984 m_jit.compareDouble(JITCompiler::DoubleEqual, tempFPR1, tempFPR2, resultGPR);
3985 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
3986 done.append(m_jit.jump());
3987
3988 isInt32.link(&m_jit);
3989 m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3990 done.append(m_jit.jump());
3991
3992 notNumber.link(&m_jit);
3993 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3994
3995 done.link(&m_jit);
3996 jsValueResult(resultGPR, node, DataFormatJSBoolean);
3997 break;
3998 }
3999
4000 case MapHash: {
4001 switch (node->child1().useKind()) {
4002 case BooleanUse:
4003 case Int32Use:
4004 case SymbolUse:
4005 case ObjectUse: {
4006 JSValueOperand input(this, node->child1(), ManualOperandSpeculation);
4007 GPRTemporary result(this, Reuse, input);
4008 GPRTemporary temp(this);
4009
4010 GPRReg inputGPR = input.gpr();
4011 GPRReg resultGPR = result.gpr();
4012 GPRReg tempGPR = temp.gpr();
4013
4014 speculate(node, node->child1());
4015
4016 m_jit.move(inputGPR, resultGPR);
4017 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4018 int32Result(resultGPR, node);
4019 break;
4020 }
4021 case CellUse:
4022 case StringUse: {
4023 SpeculateCellOperand input(this, node->child1());
4024 GPRTemporary result(this);
4025 Optional<GPRTemporary> temp;
4026
4027 GPRReg tempGPR = InvalidGPRReg;
4028 if (node->child1().useKind() == CellUse) {
4029 temp.emplace(this);
4030 tempGPR = temp->gpr();
4031 }
4032
4033 GPRReg inputGPR = input.gpr();
4034 GPRReg resultGPR = result.gpr();
4035
4036 MacroAssembler::JumpList slowPath;
4037 MacroAssembler::JumpList done;
4038
4039 if (node->child1().useKind() == StringUse)
4040 speculateString(node->child1(), inputGPR);
4041 else {
4042 auto isString = m_jit.branchIfString(inputGPR);
4043 m_jit.move(inputGPR, resultGPR);
4044 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4045 done.append(m_jit.jump());
4046 isString.link(&m_jit);
4047 }
4048
4049 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
4050 slowPath.append(m_jit.branchIfRopeStringImpl(resultGPR));
4051 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR);
4052 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);
4053 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
4054 done.append(m_jit.jump());
4055
4056 slowPath.link(&m_jit);
4057 silentSpillAllRegisters(resultGPR);
4058 callOperation(operationMapHash, resultGPR, JSValueRegs(inputGPR));
4059 silentFillAllRegisters();
4060 m_jit.exceptionCheck();
4061
4062 done.link(&m_jit);
4063 int32Result(resultGPR, node);
4064 break;
4065 }
4066 default:
4067 RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
4068 break;
4069 }
4070
4071 if (node->child1().useKind() != UntypedUse)
4072 break;
4073
4074 JSValueOperand input(this, node->child1());
4075 GPRTemporary temp(this);
4076 GPRTemporary result(this);
4077
4078 GPRReg inputGPR = input.gpr();
4079 GPRReg resultGPR = result.gpr();
4080 GPRReg tempGPR = temp.gpr();
4081
4082 MacroAssembler::JumpList straightHash;
4083 MacroAssembler::JumpList done;
4084 straightHash.append(m_jit.branchIfNotCell(inputGPR));
4085 MacroAssembler::JumpList slowPath;
4086 straightHash.append(m_jit.branchIfNotString(inputGPR));
4087 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
4088 slowPath.append(m_jit.branchIfRopeStringImpl(resultGPR));
4089 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR);
4090 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);
4091 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
4092 done.append(m_jit.jump());
4093
4094 straightHash.link(&m_jit);
4095 m_jit.move(inputGPR, resultGPR);
4096 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4097 done.append(m_jit.jump());
4098
4099 slowPath.link(&m_jit);
4100 silentSpillAllRegisters(resultGPR);
4101 callOperation(operationMapHash, resultGPR, JSValueRegs(inputGPR));
4102 silentFillAllRegisters();
4103 m_jit.exceptionCheck();
4104
4105 done.link(&m_jit);
4106 int32Result(resultGPR, node);
4107 break;
4108 }
4109
4110 case NormalizeMapKey: {
4111 compileNormalizeMapKey(node);
4112 break;
4113 }
4114
4115 case GetMapBucket: {
4116 SpeculateCellOperand map(this, node->child1());
4117 JSValueOperand key(this, node->child2(), ManualOperandSpeculation);
4118 SpeculateInt32Operand hash(this, node->child3());
4119 GPRTemporary mask(this);
4120 GPRTemporary index(this);
4121 GPRTemporary buffer(this);
4122 GPRTemporary bucket(this);
4123 GPRTemporary result(this);
4124
4125 GPRReg hashGPR = hash.gpr();
4126 GPRReg mapGPR = map.gpr();
4127 GPRReg maskGPR = mask.gpr();
4128 GPRReg indexGPR = index.gpr();
4129 GPRReg bufferGPR = buffer.gpr();
4130 GPRReg bucketGPR = bucket.gpr();
4131 GPRReg keyGPR = key.gpr();
4132 GPRReg resultGPR = result.gpr();
4133
4134 if (node->child1().useKind() == MapObjectUse)
4135 speculateMapObject(node->child1(), mapGPR);
4136 else if (node->child1().useKind() == SetObjectUse)
4137 speculateSetObject(node->child1(), mapGPR);
4138 else
4139 RELEASE_ASSERT_NOT_REACHED();
4140
4141 if (node->child2().useKind() != UntypedUse)
4142 speculate(node, node->child2());
4143
4144 m_jit.load32(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()), maskGPR);
4145 m_jit.loadPtr(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()), bufferGPR);
4146 m_jit.sub32(TrustedImm32(1), maskGPR);
4147 m_jit.move(hashGPR, indexGPR);
4148
4149 MacroAssembler::Label loop = m_jit.label();
4150 MacroAssembler::JumpList done;
4151 MacroAssembler::JumpList slowPathCases;
4152 MacroAssembler::JumpList loopAround;
4153
4154 m_jit.and32(maskGPR, indexGPR);
4155 m_jit.loadPtr(MacroAssembler::BaseIndex(bufferGPR, indexGPR, MacroAssembler::TimesEight), bucketGPR);
4156 m_jit.move(bucketGPR, resultGPR);
4157 auto notPresentInTable = m_jit.branchPtr(MacroAssembler::Equal,
4158 bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())));
4159 loopAround.append(m_jit.branchPtr(MacroAssembler::Equal,
4160 bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))));
4161
4162 m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKey>::offsetOfKey()), bucketGPR);
4163
4164 // Perform Object.is()
4165 switch (node->child2().useKind()) {
4166 case BooleanUse:
4167 case Int32Use:
4168 case SymbolUse:
4169 case ObjectUse: {
4170 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4171 // Otherwise, loop around.
4172 break;
4173 }
4174 case CellUse: {
4175 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR));
4176 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4177 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4178 loopAround.append(m_jit.branchIfNotString(keyGPR));
4179 // They're both strings.
4180 slowPathCases.append(m_jit.jump());
4181 break;
4182 }
4183 case StringUse: {
4184 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4185 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4186 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4187 slowPathCases.append(m_jit.jump());
4188 break;
4189 }
4190 case UntypedUse: {
4191 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4192 // The input key and bucket's key are already normalized. So if 64-bit compare fails and one is not a cell, they're definitely not equal.
4193 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4194 // first is a cell here.
4195 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
4196 // Both are cells here.
4197 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4198 // The first is a string here.
4199 slowPathCases.append(m_jit.branchIfString(keyGPR));
4200 // The first is a string, but the second is not, we continue to loop around.
4201 loopAround.append(m_jit.jump());
4202 break;
4203 }
4204 default:
4205 RELEASE_ASSERT_NOT_REACHED();
4206 }
4207
4208
4209 if (!loopAround.empty())
4210 loopAround.link(&m_jit);
4211
4212 m_jit.add32(TrustedImm32(1), indexGPR);
4213 m_jit.jump().linkTo(loop, &m_jit);
4214
4215 if (!slowPathCases.empty()) {
4216 slowPathCases.link(&m_jit);
4217 silentSpillAllRegisters(indexGPR);
4218 if (node->child1().useKind() == MapObjectUse)
4219 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
4220 else
4221 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
4222 silentFillAllRegisters();
4223 m_jit.exceptionCheck();
4224 done.append(m_jit.jump());
4225 }
4226
4227 notPresentInTable.link(&m_jit);
4228 if (node->child1().useKind() == MapObjectUse)
4229 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket()), resultGPR);
4230 else
4231 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket()), resultGPR);
4232 done.link(&m_jit);
4233 cellResult(resultGPR, node);
4234 break;
4235 }
4236
4237 case GetMapBucketHead:
4238 compileGetMapBucketHead(node);
4239 break;
4240
4241 case GetMapBucketNext:
4242 compileGetMapBucketNext(node);
4243 break;
4244
4245 case LoadKeyFromMapBucket:
4246 compileLoadKeyFromMapBucket(node);
4247 break;
4248
4249 case LoadValueFromMapBucket:
4250 compileLoadValueFromMapBucket(node);
4251 break;
4252
4253 case ExtractValueFromWeakMapGet:
4254 compileExtractValueFromWeakMapGet(node);
4255 break;
4256
4257 case SetAdd:
4258 compileSetAdd(node);
4259 break;
4260
4261 case MapSet:
4262 compileMapSet(node);
4263 break;
4264
4265 case WeakMapGet:
4266 compileWeakMapGet(node);
4267 break;
4268
4269 case WeakSetAdd:
4270 compileWeakSetAdd(node);
4271 break;
4272
4273 case WeakMapSet:
4274 compileWeakMapSet(node);
4275 break;
4276
4277 case StringSlice: {
4278 compileStringSlice(node);
4279 break;
4280 }
4281
4282 case ToLowerCase: {
4283 compileToLowerCase(node);
4284 break;
4285 }
4286
4287 case NumberToStringWithRadix: {
4288 compileNumberToStringWithRadix(node);
4289 break;
4290 }
4291
4292 case NumberToStringWithValidRadixConstant: {
4293 compileNumberToStringWithValidRadixConstant(node);
4294 break;
4295 }
4296
4297 case IsObject: {
4298 compileIsObject(node);
4299 break;
4300 }
4301
4302 case IsObjectOrNull: {
4303 compileIsObjectOrNull(node);
4304 break;
4305 }
4306
4307 case IsFunction: {
4308 compileIsFunction(node);
4309 break;
4310 }
4311
4312 case IsCellWithType: {
4313 compileIsCellWithType(node);
4314 break;
4315 }
4316
4317 case IsTypedArrayView: {
4318 compileIsTypedArrayView(node);
4319 break;
4320 }
4321
4322 case TypeOf: {
4323 compileTypeOf(node);
4324 break;
4325 }
4326
4327 case Flush:
4328 break;
4329
4330 case Call:
4331 case TailCall:
4332 case TailCallInlinedCaller:
4333 case Construct:
4334 case CallVarargs:
4335 case TailCallVarargs:
4336 case TailCallVarargsInlinedCaller:
4337 case CallForwardVarargs:
4338 case ConstructVarargs:
4339 case ConstructForwardVarargs:
4340 case TailCallForwardVarargs:
4341 case TailCallForwardVarargsInlinedCaller:
4342 case CallEval:
4343 case DirectCall:
4344 case DirectConstruct:
4345 case DirectTailCall:
4346 case DirectTailCallInlinedCaller:
4347 emitCall(node);
4348 break;
4349
4350 case LoadVarargs: {
4351 compileLoadVarargs(node);
4352 break;
4353 }
4354
4355 case ForwardVarargs: {
4356 compileForwardVarargs(node);
4357 break;
4358 }
4359
4360 case CreateActivation: {
4361 compileCreateActivation(node);
4362 break;
4363 }
4364
4365 case PushWithScope: {
4366 compilePushWithScope(node);
4367 break;
4368 }
4369
4370 case CreateDirectArguments: {
4371 compileCreateDirectArguments(node);
4372 break;
4373 }
4374
4375 case GetFromArguments: {
4376 compileGetFromArguments(node);
4377 break;
4378 }
4379
4380 case PutToArguments: {
4381 compilePutToArguments(node);
4382 break;
4383 }
4384
4385 case GetArgument: {
4386 compileGetArgument(node);
4387 break;
4388 }
4389
4390 case CreateScopedArguments: {
4391 compileCreateScopedArguments(node);
4392 break;
4393 }
4394
4395 case CreateClonedArguments: {
4396 compileCreateClonedArguments(node);
4397 break;
4398 }
4399 case CreateRest: {
4400 compileCreateRest(node);
4401 break;
4402 }
4403
4404 case NewFunction:
4405 case NewGeneratorFunction:
4406 case NewAsyncGeneratorFunction:
4407 case NewAsyncFunction:
4408 compileNewFunction(node);
4409 break;
4410
4411 case SetFunctionName:
4412 compileSetFunctionName(node);
4413 break;
4414
4415 case InById:
4416 compileInById(node);
4417 break;
4418
4419 case InByVal:
4420 compileInByVal(node);
4421 break;
4422
4423 case HasOwnProperty: {
4424 SpeculateCellOperand object(this, node->child1());
4425 GPRTemporary uniquedStringImpl(this);
4426 GPRTemporary temp(this);
4427 GPRTemporary hash(this);
4428 GPRTemporary structureID(this);
4429 GPRTemporary result(this);
4430
4431 Optional<SpeculateCellOperand> keyAsCell;
4432 Optional<JSValueOperand> keyAsValue;
4433 GPRReg keyGPR;
4434 if (node->child2().useKind() == UntypedUse) {
4435 keyAsValue.emplace(this, node->child2());
4436 keyGPR = keyAsValue->gpr();
4437 } else {
4438 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse);
4439 keyAsCell.emplace(this, node->child2());
4440 keyGPR = keyAsCell->gpr();
4441 }
4442
4443 GPRReg objectGPR = object.gpr();
4444 GPRReg implGPR = uniquedStringImpl.gpr();
4445 GPRReg tempGPR = temp.gpr();
4446 GPRReg hashGPR = hash.gpr();
4447 GPRReg structureIDGPR = structureID.gpr();
4448 GPRReg resultGPR = result.gpr();
4449
4450 speculateObject(node->child1());
4451
4452 MacroAssembler::JumpList slowPath;
4453 switch (node->child2().useKind()) {
4454 case SymbolUse: {
4455 speculateSymbol(node->child2(), keyGPR);
4456 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR);
4457 break;
4458 }
4459 case StringUse: {
4460 speculateString(node->child2(), keyGPR);
4461 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR);
4462 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
4463 slowPath.append(m_jit.branchTest32(
4464 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
4465 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
4466 break;
4467 }
4468 case UntypedUse: {
4469 slowPath.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
4470 auto isNotString = m_jit.branchIfNotString(keyGPR);
4471 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR);
4472 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
4473 slowPath.append(m_jit.branchTest32(
4474 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
4475 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
4476 auto hasUniquedImpl = m_jit.jump();
4477
4478 isNotString.link(&m_jit);
4479 slowPath.append(m_jit.branchIfNotSymbol(keyGPR));
4480 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR);
4481
4482 hasUniquedImpl.link(&m_jit);
4483 break;
4484 }
4485 default:
4486 RELEASE_ASSERT_NOT_REACHED();
4487 }
4488
4489 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero
4490 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only
4491 // ever load the result from the cache if the cache entry matches what we are querying for.
4492 // So we either get super lucky and use zero for the hash and somehow collide with the entity
4493 // we're looking for, or we realize we're comparing against another entity, and go to the
4494 // slow path anyways.
4495 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR);
4496 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR);
4497 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR);
4498 m_jit.add32(structureIDGPR, hashGPR);
4499 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR);
4500 if (hasOneBitSet(sizeof(HasOwnPropertyCache::Entry))) // is a power of 2
4501 m_jit.lshift32(TrustedImm32(getLSBSet(sizeof(HasOwnPropertyCache::Entry))), hashGPR);
4502 else
4503 m_jit.mul32(TrustedImm32(sizeof(HasOwnPropertyCache::Entry)), hashGPR, hashGPR);
4504 ASSERT(m_jit.vm()->hasOwnPropertyCache());
4505 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR);
4506 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual,
4507 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR));
4508 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR);
4509 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR);
4510 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR));
4511 auto done = m_jit.jump();
4512
4513 slowPath.link(&m_jit);
4514 silentSpillAllRegisters(resultGPR);
4515 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyGPR);
4516 silentFillAllRegisters();
4517 m_jit.exceptionCheck();
4518
4519 done.link(&m_jit);
4520 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
4521 jsValueResult(resultGPR, node, DataFormatJSBoolean);
4522 break;
4523 }
4524
4525 case CountExecution:
4526 m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
4527 break;
4528
4529 case SuperSamplerBegin:
4530 m_jit.add32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4531 break;
4532
4533 case SuperSamplerEnd:
4534 m_jit.sub32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4535 break;
4536
4537 case ForceOSRExit: {
4538 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
4539 break;
4540 }
4541
4542 case InvalidationPoint:
4543 emitInvalidationPoint(node);
4544 break;
4545
4546 case CheckTraps:
4547 compileCheckTraps(node);
4548 break;
4549
4550 case Phantom:
4551 case Check:
4552 case CheckVarargs:
4553 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
4554 noResult(node);
4555 break;
4556
4557 case PhantomLocal:
4558 case LoopHint:
4559 // This is a no-op.
4560 noResult(node);
4561 break;
4562
4563 case Unreachable:
4564 unreachable(node);
4565 break;
4566
4567 case StoreBarrier:
4568 case FencedStoreBarrier: {
4569 compileStoreBarrier(node);
4570 break;
4571 }
4572
4573 case GetEnumerableLength: {
4574 compileGetEnumerableLength(node);
4575 break;
4576 }
4577 case HasGenericProperty: {
4578 compileHasGenericProperty(node);
4579 break;
4580 }
4581 case HasStructureProperty: {
4582 compileHasStructureProperty(node);
4583 break;
4584 }
4585 case HasIndexedProperty: {
4586 compileHasIndexedProperty(node);
4587 break;
4588 }
4589 case GetDirectPname: {
4590 compileGetDirectPname(node);
4591 break;
4592 }
4593 case GetPropertyEnumerator: {
4594 compileGetPropertyEnumerator(node);
4595 break;
4596 }
4597 case GetEnumeratorStructurePname:
4598 case GetEnumeratorGenericPname: {
4599 compileGetEnumeratorPname(node);
4600 break;
4601 }
4602 case ToIndexString: {
4603 compileToIndexString(node);
4604 break;
4605 }
4606 case ProfileType: {
4607 compileProfileType(node);
4608 break;
4609 }
4610 case ProfileControlFlow: {
4611 BasicBlockLocation* basicBlockLocation = node->basicBlockLocation();
4612 basicBlockLocation->emitExecuteCode(m_jit);
4613 noResult(node);
4614 break;
4615 }
4616
4617 case LogShadowChickenPrologue: {
4618 compileLogShadowChickenPrologue(node);
4619 break;
4620 }
4621
4622 case LogShadowChickenTail: {
4623 compileLogShadowChickenTail(node);
4624 break;
4625 }
4626
4627 case MaterializeNewObject:
4628 compileMaterializeNewObject(node);
4629 break;
4630
4631 case CallDOM:
4632 compileCallDOM(node);
4633 break;
4634
4635 case CallDOMGetter:
4636 compileCallDOMGetter(node);
4637 break;
4638
4639 case CheckSubClass:
4640 compileCheckSubClass(node);
4641 break;
4642
4643 case ExtractCatchLocal: {
4644 compileExtractCatchLocal(node);
4645 break;
4646 }
4647
4648 case ClearCatchLocals:
4649 compileClearCatchLocals(node);
4650 break;
4651
4652 case DataViewGetFloat:
4653 case DataViewGetInt: {
4654 SpeculateCellOperand dataView(this, node->child1());
4655 GPRReg dataViewGPR = dataView.gpr();
4656 speculateDataViewObject(node->child1(), dataViewGPR);
4657
4658 SpeculateInt32Operand index(this, node->child2());
4659 GPRReg indexGPR = index.gpr();
4660
4661 GPRTemporary temp1(this);
4662 GPRReg t1 = temp1.gpr();
4663 GPRTemporary temp2(this);
4664 GPRReg t2 = temp2.gpr();
4665
4666 Optional<SpeculateBooleanOperand> isLittleEndianOperand;
4667 if (node->child3())
4668 isLittleEndianOperand.emplace(this, node->child3());
4669 GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg;
4670
4671 DataViewData data = node->dataViewData();
4672
4673 m_jit.zeroExtend32ToPtr(indexGPR, t2);
4674 if (data.byteSize > 1)
4675 m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
4676 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
4677 speculationCheck(OutOfBounds, JSValueRegs(), node,
4678 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
4679
4680 m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2);
4681 cageTypedArrayStorage(dataViewGPR, t2);
4682
4683 m_jit.zeroExtend32ToPtr(indexGPR, t1);
4684 auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne);
4685
4686 if (node->op() == DataViewGetInt) {
4687 switch (data.byteSize) {
4688 case 1:
4689 if (data.isSigned)
4690 m_jit.load8SignedExtendTo32(baseIndex, t2);
4691 else
4692 m_jit.load8(baseIndex, t2);
4693 int32Result(t2, node);
4694 break;
4695 case 2: {
4696 auto emitLittleEndianLoad = [&] {
4697 if (data.isSigned)
4698 m_jit.load16SignedExtendTo32(baseIndex, t2);
4699 else
4700 m_jit.load16(baseIndex, t2);
4701 };
4702 auto emitBigEndianLoad = [&] {
4703 m_jit.load16(baseIndex, t2);
4704 m_jit.byteSwap16(t2);
4705 if (data.isSigned)
4706 m_jit.signExtend16To32(t2, t2);
4707 };
4708
4709 if (data.isLittleEndian == FalseTriState)
4710 emitBigEndianLoad();
4711 else if (data.isLittleEndian == TrueTriState)
4712 emitLittleEndianLoad();
4713 else {
4714 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4715 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4716 emitLittleEndianLoad();
4717 auto done = m_jit.jump();
4718 isBigEndian.link(&m_jit);
4719 emitBigEndianLoad();
4720 done.link(&m_jit);
4721 }
4722 int32Result(t2, node);
4723 break;
4724 }
4725 case 4: {
4726 m_jit.load32(baseIndex, t2);
4727
4728 if (data.isLittleEndian == FalseTriState)
4729 m_jit.byteSwap32(t2);
4730 else if (data.isLittleEndian == MixedTriState) {
4731 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4732 auto isLittleEndian = m_jit.branchTest32(MacroAssembler::NonZero, isLittleEndianGPR, TrustedImm32(1));
4733 m_jit.byteSwap32(t2);
4734 isLittleEndian.link(&m_jit);
4735 }
4736
4737 if (data.isSigned)
4738 int32Result(t2, node);
4739 else
4740 strictInt52Result(t2, node);
4741 break;
4742 }
4743 default:
4744 RELEASE_ASSERT_NOT_REACHED();
4745 }
4746 } else {
4747 FPRTemporary result(this);
4748 FPRReg resultFPR = result.fpr();
4749
4750 switch (data.byteSize) {
4751 case 4: {
4752 auto emitLittleEndianCode = [&] {
4753 m_jit.loadFloat(baseIndex, resultFPR);
4754 m_jit.convertFloatToDouble(resultFPR, resultFPR);
4755 };
4756
4757 auto emitBigEndianCode = [&] {
4758 m_jit.load32(baseIndex, t2);
4759 m_jit.byteSwap32(t2);
4760 m_jit.move32ToFloat(t2, resultFPR);
4761 m_jit.convertFloatToDouble(resultFPR, resultFPR);
4762 };
4763
4764 if (data.isLittleEndian == TrueTriState)
4765 emitLittleEndianCode();
4766 else if (data.isLittleEndian == FalseTriState)
4767 emitBigEndianCode();
4768 else {
4769 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4770 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4771 emitLittleEndianCode();
4772 auto done = m_jit.jump();
4773 isBigEndian.link(&m_jit);
4774 emitBigEndianCode();
4775 done.link(&m_jit);
4776 }
4777
4778 break;
4779 }
4780 case 8: {
4781 auto emitLittleEndianCode = [&] {
4782 m_jit.loadDouble(baseIndex, resultFPR);
4783 };
4784
4785 auto emitBigEndianCode = [&] {
4786 m_jit.load64(baseIndex, t2);
4787 m_jit.byteSwap64(t2);
4788 m_jit.move64ToDouble(t2, resultFPR);
4789 };
4790
4791 if (data.isLittleEndian == TrueTriState)
4792 emitLittleEndianCode();
4793 else if (data.isLittleEndian == FalseTriState)
4794 emitBigEndianCode();
4795 else {
4796 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4797 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4798 emitLittleEndianCode();
4799 auto done = m_jit.jump();
4800 isBigEndian.link(&m_jit);
4801 emitBigEndianCode();
4802 done.link(&m_jit);
4803 }
4804
4805 break;
4806 }
4807 default:
4808 RELEASE_ASSERT_NOT_REACHED();
4809 }
4810
4811 doubleResult(resultFPR, node);
4812 }
4813
4814 break;
4815 }
4816
4817 case DataViewSet: {
4818 SpeculateCellOperand dataView(this, m_graph.varArgChild(node, 0));
4819 GPRReg dataViewGPR = dataView.gpr();
4820 speculateDataViewObject(m_graph.varArgChild(node, 0), dataViewGPR);
4821
4822 SpeculateInt32Operand index(this, m_graph.varArgChild(node, 1));
4823 GPRReg indexGPR = index.gpr();
4824
4825 Optional<SpeculateStrictInt52Operand> int52Value;
4826 Optional<SpeculateDoubleOperand> doubleValue;
4827 Optional<SpeculateInt32Operand> int32Value;
4828 Optional<FPRTemporary> fprTemporary;
4829 GPRReg valueGPR = InvalidGPRReg;
4830 FPRReg valueFPR = InvalidFPRReg;
4831 FPRReg tempFPR = InvalidFPRReg;
4832
4833 DataViewData data = node->dataViewData();
4834
4835 Edge& valueEdge = m_graph.varArgChild(node, 2);
4836 switch (valueEdge.useKind()) {
4837 case Int32Use:
4838 int32Value.emplace(this, valueEdge);
4839 valueGPR = int32Value->gpr();
4840 break;
4841 case DoubleRepUse:
4842 doubleValue.emplace(this, valueEdge);
4843 valueFPR = doubleValue->fpr();
4844 if (data.byteSize == 4) {
4845 fprTemporary.emplace(this);
4846 tempFPR = fprTemporary->fpr();
4847 }
4848 break;
4849 case Int52RepUse:
4850 int52Value.emplace(this, valueEdge);
4851 valueGPR = int52Value->gpr();
4852 break;
4853 default:
4854 RELEASE_ASSERT_NOT_REACHED();
4855 }
4856
4857 GPRTemporary temp1(this);
4858 GPRReg t1 = temp1.gpr();
4859 GPRTemporary temp2(this);
4860 GPRReg t2 = temp2.gpr();
4861 GPRTemporary temp3(this);
4862 GPRReg t3 = temp3.gpr();
4863
4864 Optional<SpeculateBooleanOperand> isLittleEndianOperand;
4865 if (m_graph.varArgChild(node, 3))
4866 isLittleEndianOperand.emplace(this, m_graph.varArgChild(node, 3));
4867 GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg;
4868
4869 m_jit.zeroExtend32ToPtr(indexGPR, t2);
4870 if (data.byteSize > 1)
4871 m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
4872 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
4873 speculationCheck(OutOfBounds, JSValueRegs(), node,
4874 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
4875
4876 m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2);
4877 cageTypedArrayStorage(dataViewGPR, t2);
4878
4879 m_jit.zeroExtend32ToPtr(indexGPR, t1);
4880 auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne);
4881
4882 if (data.isFloatingPoint) {
4883 RELEASE_ASSERT(valueFPR != InvalidFPRReg);
4884 if (data.byteSize == 4) {
4885 RELEASE_ASSERT(tempFPR != InvalidFPRReg);
4886 m_jit.convertDoubleToFloat(valueFPR, tempFPR);
4887
4888 auto emitLittleEndianCode = [&] {
4889 m_jit.storeFloat(tempFPR, baseIndex);
4890 };
4891
4892 auto emitBigEndianCode = [&] {
4893 m_jit.moveFloatTo32(tempFPR, t3);
4894 m_jit.byteSwap32(t3);
4895 m_jit.store32(t3, baseIndex);
4896 };
4897
4898 if (data.isLittleEndian == FalseTriState)
4899 emitBigEndianCode();
4900 else if (data.isLittleEndian == TrueTriState)
4901 emitLittleEndianCode();
4902 else {
4903 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4904 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4905 emitLittleEndianCode();
4906 auto done = m_jit.jump();
4907 isBigEndian.link(&m_jit);
4908 emitBigEndianCode();
4909 done.link(&m_jit);
4910 }
4911 } else {
4912 RELEASE_ASSERT(data.byteSize == 8);
4913 RELEASE_ASSERT(valueFPR != InvalidFPRReg);
4914
4915 auto emitLittleEndianCode = [&] {
4916 m_jit.storeDouble(valueFPR, baseIndex);
4917 };
4918 auto emitBigEndianCode = [&] {
4919 m_jit.moveDoubleTo64(valueFPR, t3);
4920 m_jit.byteSwap64(t3);
4921 m_jit.store64(t3, baseIndex);
4922 };
4923
4924 if (data.isLittleEndian == FalseTriState)
4925 emitBigEndianCode();
4926 else if (data.isLittleEndian == TrueTriState)
4927 emitLittleEndianCode();
4928 else {
4929 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4930 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4931 emitLittleEndianCode();
4932 auto done = m_jit.jump();
4933 isBigEndian.link(&m_jit);
4934 emitBigEndianCode();
4935 done.link(&m_jit);
4936 }
4937 }
4938 } else {
4939 switch (data.byteSize) {
4940 case 1:
4941 RELEASE_ASSERT(valueEdge.useKind() == Int32Use);
4942 RELEASE_ASSERT(valueGPR != InvalidGPRReg);
4943 m_jit.store8(valueGPR, baseIndex);
4944 break;
4945 case 2: {
4946 RELEASE_ASSERT(valueEdge.useKind() == Int32Use);
4947 RELEASE_ASSERT(valueGPR != InvalidGPRReg);
4948
4949 auto emitLittleEndianCode = [&] {
4950 m_jit.store16(valueGPR, baseIndex);
4951 };
4952 auto emitBigEndianCode = [&] {
4953 m_jit.move(valueGPR, t3);
4954 m_jit.byteSwap16(t3);
4955 m_jit.store16(t3, baseIndex);
4956 };
4957
4958 if (data.isLittleEndian == FalseTriState)
4959 emitBigEndianCode();
4960 else if (data.isLittleEndian == TrueTriState)
4961 emitLittleEndianCode();
4962 else {
4963 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4964 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4965 emitLittleEndianCode();
4966 auto done = m_jit.jump();
4967 isBigEndian.link(&m_jit);
4968 emitBigEndianCode();
4969 done.link(&m_jit);
4970 }
4971 break;
4972 }
4973 case 4: {
4974 RELEASE_ASSERT(valueEdge.useKind() == Int32Use || valueEdge.useKind() == Int52RepUse);
4975
4976 auto emitLittleEndianCode = [&] {
4977 m_jit.store32(valueGPR, baseIndex);
4978 };
4979
4980 auto emitBigEndianCode = [&] {
4981 m_jit.zeroExtend32ToPtr(valueGPR, t3);
4982 m_jit.byteSwap32(t3);
4983 m_jit.store32(t3, baseIndex);
4984 };
4985
4986 if (data.isLittleEndian == FalseTriState)
4987 emitBigEndianCode();
4988 else if (data.isLittleEndian == TrueTriState)
4989 emitLittleEndianCode();
4990 else {
4991 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4992 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4993 emitLittleEndianCode();
4994 auto done = m_jit.jump();
4995 isBigEndian.link(&m_jit);
4996 emitBigEndianCode();
4997 done.link(&m_jit);
4998 }
4999
5000 break;
5001 }
5002 default:
5003 RELEASE_ASSERT_NOT_REACHED();
5004 }
5005 }
5006
5007 noResult(node);
5008 break;
5009 }
5010
5011#if ENABLE(FTL_JIT)
5012 case CheckTierUpInLoop: {
5013 MacroAssembler::Jump callTierUp = m_jit.branchAdd32(
5014 MacroAssembler::PositiveOrZero,
5015 TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
5016 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5017
5018 MacroAssembler::Label toNextOperation = m_jit.label();
5019
5020 Vector<SilentRegisterSavePlan> savePlans;
5021 silentSpillAllRegistersImpl(false, savePlans, InvalidGPRReg);
5022 unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex();
5023
5024 addSlowPathGeneratorLambda([=]() {
5025 callTierUp.link(&m_jit);
5026
5027 silentSpill(savePlans);
5028 callOperation(triggerTierUpNowInLoop, TrustedImm32(bytecodeIndex));
5029 silentFill(savePlans);
5030
5031 m_jit.jump().linkTo(toNextOperation, &m_jit);
5032 });
5033 break;
5034 }
5035
5036 case CheckTierUpAtReturn: {
5037 MacroAssembler::Jump done = m_jit.branchAdd32(
5038 MacroAssembler::Signed,
5039 TrustedImm32(Options::ftlTierUpCounterIncrementForReturn()),
5040 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5041
5042 silentSpillAllRegisters(InvalidGPRReg);
5043 callOperation(triggerTierUpNow);
5044 silentFillAllRegisters();
5045
5046 done.link(&m_jit);
5047 break;
5048 }
5049
5050 case CheckTierUpAndOSREnter: {
5051 ASSERT(!node->origin.semantic.inlineCallFrame());
5052
5053 GPRTemporary temp(this);
5054 GPRReg tempGPR = temp.gpr();
5055
5056 unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex();
5057 auto triggerIterator = m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex);
5058 DFG_ASSERT(m_jit.graph(), node, triggerIterator != m_jit.jitCode()->tierUpEntryTriggers.end());
5059 JITCode::TriggerReason* forceEntryTrigger = &(m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex)->value);
5060 static_assert(!static_cast<uint8_t>(JITCode::TriggerReason::DontTrigger), "the JIT code assumes non-zero means 'enter'");
5061 static_assert(sizeof(JITCode::TriggerReason) == 1, "branchTest8 assumes this size");
5062
5063 MacroAssembler::Jump forceOSREntry = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(forceEntryTrigger));
5064 MacroAssembler::Jump overflowedCounter = m_jit.branchAdd32(
5065 MacroAssembler::PositiveOrZero,
5066 TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
5067 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5068 MacroAssembler::Label toNextOperation = m_jit.label();
5069
5070 Vector<SilentRegisterSavePlan> savePlans;
5071 silentSpillAllRegistersImpl(false, savePlans, tempGPR);
5072
5073 unsigned streamIndex = m_stream->size();
5074 m_jit.jitCode()->bytecodeIndexToStreamIndex.add(bytecodeIndex, streamIndex);
5075
5076 addSlowPathGeneratorLambda([=]() {
5077 forceOSREntry.link(&m_jit);
5078 overflowedCounter.link(&m_jit);
5079
5080 silentSpill(savePlans);
5081 callOperation(triggerOSREntryNow, tempGPR, TrustedImm32(bytecodeIndex));
5082
5083 if (savePlans.isEmpty())
5084 m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR).linkTo(toNextOperation, &m_jit);
5085 else {
5086 MacroAssembler::Jump osrEnter = m_jit.branchTestPtr(MacroAssembler::NonZero, tempGPR);
5087 silentFill(savePlans);
5088 m_jit.jump().linkTo(toNextOperation, &m_jit);
5089 osrEnter.link(&m_jit);
5090 }
5091 m_jit.emitRestoreCalleeSaves();
5092 m_jit.jump(tempGPR, GPRInfo::callFrameRegister);
5093 });
5094 break;
5095 }
5096
5097#else // ENABLE(FTL_JIT)
5098 case CheckTierUpInLoop:
5099 case CheckTierUpAtReturn:
5100 case CheckTierUpAndOSREnter:
5101 DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
5102 break;
5103#endif // ENABLE(FTL_JIT)
5104
5105 case FilterCallLinkStatus:
5106 case FilterGetByIdStatus:
5107 case FilterPutByIdStatus:
5108 case FilterInByIdStatus:
5109 m_interpreter.filterICStatus(node);
5110 noResult(node);
5111 break;
5112
5113 case LastNodeType:
5114 case EntrySwitch:
5115 case InitializeEntrypointArguments:
5116 case Phi:
5117 case Upsilon:
5118 case ExtractOSREntryLocal:
5119 case CheckInBounds:
5120 case ArithIMul:
5121 case MultiGetByOffset:
5122 case MultiPutByOffset:
5123 case FiatInt52:
5124 case CheckBadCell:
5125 case BottomValue:
5126 case PhantomNewObject:
5127 case PhantomNewFunction:
5128 case PhantomNewGeneratorFunction:
5129 case PhantomNewAsyncFunction:
5130 case PhantomNewAsyncGeneratorFunction:
5131 case PhantomCreateActivation:
5132 case PhantomNewRegexp:
5133 case GetMyArgumentByVal:
5134 case GetMyArgumentByValOutOfBounds:
5135 case GetVectorLength:
5136 case PutHint:
5137 case CheckStructureImmediate:
5138 case MaterializeCreateActivation:
5139 case PutStack:
5140 case KillStack:
5141 case GetStack:
5142 case PhantomCreateRest:
5143 case PhantomSpread:
5144 case PhantomNewArrayWithSpread:
5145 case PhantomNewArrayBuffer:
5146 case IdentityWithProfile:
5147 case CPUIntrinsic:
5148 DFG_CRASH(m_jit.graph(), node, "Unexpected node");
5149 break;
5150 }
5151
5152 if (!m_compileOkay)
5153 return;
5154
5155 if (node->hasResult() && node->mustGenerate())
5156 use(node);
5157}
5158
5159void SpeculativeJIT::moveTrueTo(GPRReg gpr)
5160{
5161 m_jit.move(TrustedImm32(ValueTrue), gpr);
5162}
5163
5164void SpeculativeJIT::moveFalseTo(GPRReg gpr)
5165{
5166 m_jit.move(TrustedImm32(ValueFalse), gpr);
5167}
5168
5169void SpeculativeJIT::blessBoolean(GPRReg gpr)
5170{
5171 m_jit.or32(TrustedImm32(ValueFalse), gpr);
5172}
5173
5174void SpeculativeJIT::convertAnyInt(Edge valueEdge, GPRReg resultGPR)
5175{
5176 JSValueOperand value(this, valueEdge, ManualOperandSpeculation);
5177 GPRReg valueGPR = value.gpr();
5178
5179 JITCompiler::Jump notInt32 = m_jit.branchIfNotInt32(valueGPR);
5180
5181 m_jit.signExtend32ToPtr(valueGPR, resultGPR);
5182 JITCompiler::Jump done = m_jit.jump();
5183
5184 notInt32.link(&m_jit);
5185 silentSpillAllRegisters(resultGPR);
5186 callOperation(operationConvertBoxedDoubleToInt52, resultGPR, valueGPR);
5187 silentFillAllRegisters();
5188
5189 DFG_TYPE_CHECK(
5190 JSValueRegs(valueGPR), valueEdge, SpecInt32Only | SpecAnyIntAsDouble,
5191 m_jit.branch64(
5192 JITCompiler::Equal, resultGPR,
5193 JITCompiler::TrustedImm64(JSValue::notInt52)));
5194 done.link(&m_jit);
5195}
5196
5197void SpeculativeJIT::speculateAnyInt(Edge edge)
5198{
5199 if (!needsTypeCheck(edge, SpecInt32Only | SpecAnyIntAsDouble))
5200 return;
5201
5202 GPRTemporary temp(this);
5203 convertAnyInt(edge, temp.gpr());
5204}
5205
5206void SpeculativeJIT::speculateInt32(Edge edge, JSValueRegs regs)
5207{
5208 DFG_TYPE_CHECK(regs, edge, SpecInt32Only, m_jit.branchIfNotInt32(regs));
5209}
5210
5211void SpeculativeJIT::speculateDoubleRepAnyInt(Edge edge)
5212{
5213 if (!needsTypeCheck(edge, SpecAnyIntAsDouble))
5214 return;
5215
5216 SpeculateDoubleOperand value(this, edge);
5217 FPRReg valueFPR = value.fpr();
5218
5219 flushRegisters();
5220 GPRFlushedCallResult result(this);
5221 GPRReg resultGPR = result.gpr();
5222 callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
5223
5224 DFG_TYPE_CHECK(
5225 JSValueRegs(), edge, SpecAnyIntAsDouble,
5226 m_jit.branch64(
5227 JITCompiler::Equal, resultGPR,
5228 JITCompiler::TrustedImm64(JSValue::notInt52)));
5229}
5230
5231void SpeculativeJIT::compileArithRandom(Node* node)
5232{
5233 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
5234 GPRTemporary temp1(this);
5235 GPRTemporary temp2(this);
5236 GPRTemporary temp3(this);
5237 FPRTemporary result(this);
5238 m_jit.emitRandomThunk(globalObject, temp1.gpr(), temp2.gpr(), temp3.gpr(), result.fpr());
5239 doubleResult(result.fpr(), node);
5240}
5241
5242#endif
5243
5244} } // namespace JSC::DFG
5245
5246#endif
5247