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 ValuePow:
2257 compileValuePow(node);
2258 break;
2259
2260 case ArithPow:
2261 compileArithPow(node);
2262 break;
2263
2264 case ArithSqrt:
2265 compileArithSqrt(node);
2266 break;
2267
2268 case ArithFRound:
2269 compileArithFRound(node);
2270 break;
2271
2272 case ArithRandom:
2273 compileArithRandom(node);
2274 break;
2275
2276 case ArithRound:
2277 case ArithFloor:
2278 case ArithCeil:
2279 case ArithTrunc:
2280 compileArithRounding(node);
2281 break;
2282
2283 case ArithUnary:
2284 compileArithUnary(node);
2285 break;
2286
2287 case LogicalNot:
2288 compileLogicalNot(node);
2289 break;
2290
2291 case CompareLess:
2292 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2293 return;
2294 break;
2295
2296 case CompareLessEq:
2297 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2298 return;
2299 break;
2300
2301 case CompareGreater:
2302 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2303 return;
2304 break;
2305
2306 case CompareGreaterEq:
2307 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2308 return;
2309 break;
2310
2311 case CompareBelow:
2312 compileCompareUnsigned(node, JITCompiler::Below);
2313 break;
2314
2315 case CompareBelowEq:
2316 compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2317 break;
2318
2319 case CompareEq:
2320 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2321 return;
2322 break;
2323
2324 case CompareStrictEq:
2325 if (compileStrictEq(node))
2326 return;
2327 break;
2328
2329 case CompareEqPtr:
2330 compileCompareEqPtr(node);
2331 break;
2332
2333 case SameValue:
2334 compileSameValue(node);
2335 break;
2336
2337 case StringCharCodeAt: {
2338 compileGetCharCodeAt(node);
2339 break;
2340 }
2341
2342 case StringCharAt: {
2343 // Relies on StringCharAt node having same basic layout as GetByVal
2344 compileGetByValOnString(node);
2345 break;
2346 }
2347
2348 case StringFromCharCode: {
2349 compileFromCharCode(node);
2350 break;
2351 }
2352
2353 case CheckArray: {
2354 checkArray(node);
2355 break;
2356 }
2357
2358 case Arrayify:
2359 case ArrayifyToStructure: {
2360 arrayify(node);
2361 break;
2362 }
2363
2364 case GetByVal: {
2365 switch (node->arrayMode().type()) {
2366 case Array::AnyTypedArray:
2367 case Array::ForceExit:
2368 case Array::SelectUsingArguments:
2369 case Array::SelectUsingPredictions:
2370 case Array::Unprofiled:
2371 DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2372 break;
2373 case Array::Undecided: {
2374 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2375 GPRTemporary result(this, Reuse, index);
2376 GPRReg indexGPR = index.gpr();
2377 GPRReg resultGPR = result.gpr();
2378
2379 speculationCheck(OutOfBounds, JSValueRegs(), node,
2380 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2381
2382 use(m_graph.varArgChild(node, 0));
2383 index.use();
2384
2385 m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2386 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2387 break;
2388 }
2389 case Array::Generic: {
2390 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2391 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2392 compileGetByValForObjectWithString(node);
2393 break;
2394 }
2395
2396 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2397 compileGetByValForObjectWithSymbol(node);
2398 break;
2399 }
2400 }
2401 JSValueOperand base(this, m_graph.varArgChild(node, 0));
2402 JSValueOperand property(this, m_graph.varArgChild(node, 1));
2403 GPRReg baseGPR = base.gpr();
2404 GPRReg propertyGPR = property.gpr();
2405
2406 flushRegisters();
2407 GPRFlushedCallResult result(this);
2408 callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2409 m_jit.exceptionCheck();
2410
2411 jsValueResult(result.gpr(), node);
2412 break;
2413 }
2414 case Array::Int32:
2415 case Array::Contiguous: {
2416 if (node->arrayMode().isInBounds()) {
2417 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2418 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2419
2420 GPRReg propertyReg = property.gpr();
2421 GPRReg storageReg = storage.gpr();
2422
2423 if (!m_compileOkay)
2424 return;
2425
2426 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2427
2428 GPRTemporary result(this);
2429
2430 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2431 if (node->arrayMode().isSaneChain()) {
2432 ASSERT(node->arrayMode().type() == Array::Contiguous);
2433 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(result.gpr());
2434 m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2435 notHole.link(&m_jit);
2436 } else {
2437 speculationCheck(
2438 LoadFromHole, JSValueRegs(), 0,
2439 m_jit.branchIfEmpty(result.gpr()));
2440 }
2441 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2442 break;
2443 }
2444
2445 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2446 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2447 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2448
2449 GPRReg baseReg = base.gpr();
2450 GPRReg propertyReg = property.gpr();
2451 GPRReg storageReg = storage.gpr();
2452
2453 if (!m_compileOkay)
2454 return;
2455
2456 GPRTemporary result(this);
2457 GPRReg resultReg = result.gpr();
2458
2459 MacroAssembler::JumpList slowCases;
2460
2461 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2462
2463 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2464 slowCases.append(m_jit.branchIfEmpty(resultReg));
2465
2466 addSlowPathGenerator(
2467 slowPathCall(
2468 slowCases, this, operationGetByValObjectInt,
2469 result.gpr(), baseReg, propertyReg));
2470
2471 jsValueResult(resultReg, node);
2472 break;
2473 }
2474
2475 case Array::Double: {
2476 if (node->arrayMode().isInBounds()) {
2477 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2478 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2479
2480 GPRReg propertyReg = property.gpr();
2481 GPRReg storageReg = storage.gpr();
2482
2483 if (!m_compileOkay)
2484 return;
2485
2486 FPRTemporary result(this);
2487 FPRReg resultReg = result.fpr();
2488
2489 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2490
2491 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2492 if (!node->arrayMode().isSaneChain())
2493 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(resultReg));
2494 doubleResult(resultReg, node);
2495 break;
2496 }
2497
2498 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2499 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2500 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2501
2502 GPRReg baseReg = base.gpr();
2503 GPRReg propertyReg = property.gpr();
2504 GPRReg storageReg = storage.gpr();
2505
2506 if (!m_compileOkay)
2507 return;
2508
2509 GPRTemporary result(this);
2510 FPRTemporary temp(this);
2511 GPRReg resultReg = result.gpr();
2512 FPRReg tempReg = temp.fpr();
2513
2514 MacroAssembler::JumpList slowCases;
2515
2516 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2517
2518 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2519 slowCases.append(m_jit.branchIfNaN(tempReg));
2520 boxDouble(tempReg, resultReg);
2521
2522 addSlowPathGenerator(
2523 slowPathCall(
2524 slowCases, this, operationGetByValObjectInt,
2525 result.gpr(), baseReg, propertyReg));
2526
2527 jsValueResult(resultReg, node);
2528 break;
2529 }
2530
2531 case Array::ArrayStorage:
2532 case Array::SlowPutArrayStorage: {
2533 if (node->arrayMode().isInBounds()) {
2534 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2535 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2536
2537 GPRReg propertyReg = property.gpr();
2538 GPRReg storageReg = storage.gpr();
2539
2540 if (!m_compileOkay)
2541 return;
2542
2543 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2544
2545 GPRTemporary result(this);
2546 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), result.gpr());
2547 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(result.gpr()));
2548
2549 jsValueResult(result.gpr(), node);
2550 break;
2551 }
2552
2553 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2554 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2555 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2556
2557 GPRReg baseReg = base.gpr();
2558 GPRReg propertyReg = property.gpr();
2559 GPRReg storageReg = storage.gpr();
2560
2561 if (!m_compileOkay)
2562 return;
2563
2564 GPRTemporary result(this);
2565 GPRReg resultReg = result.gpr();
2566
2567 MacroAssembler::JumpList slowCases;
2568
2569 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2570
2571 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), resultReg);
2572 slowCases.append(m_jit.branchIfEmpty(resultReg));
2573
2574 addSlowPathGenerator(
2575 slowPathCall(
2576 slowCases, this, operationGetByValObjectInt,
2577 result.gpr(), baseReg, propertyReg));
2578
2579 jsValueResult(resultReg, node);
2580 break;
2581 }
2582 case Array::String:
2583 compileGetByValOnString(node);
2584 break;
2585 case Array::DirectArguments:
2586 compileGetByValOnDirectArguments(node);
2587 break;
2588 case Array::ScopedArguments:
2589 compileGetByValOnScopedArguments(node);
2590 break;
2591 case Array::Int8Array:
2592 case Array::Int16Array:
2593 case Array::Int32Array:
2594 case Array::Uint8Array:
2595 case Array::Uint8ClampedArray:
2596 case Array::Uint16Array:
2597 case Array::Uint32Array:
2598 case Array::Float32Array:
2599 case Array::Float64Array: {
2600 TypedArrayType type = node->arrayMode().typedArrayType();
2601 if (isInt(type))
2602 compileGetByValOnIntTypedArray(node, type);
2603 else
2604 compileGetByValOnFloatTypedArray(node, type);
2605 } }
2606 break;
2607 }
2608
2609 case GetByValWithThis: {
2610 compileGetByValWithThis(node);
2611 break;
2612 }
2613
2614 case PutByValDirect:
2615 case PutByVal:
2616 case PutByValAlias: {
2617 Edge child1 = m_jit.graph().varArgChild(node, 0);
2618 Edge child2 = m_jit.graph().varArgChild(node, 1);
2619 Edge child3 = m_jit.graph().varArgChild(node, 2);
2620 Edge child4 = m_jit.graph().varArgChild(node, 3);
2621
2622 ArrayMode arrayMode = node->arrayMode().modeForPut();
2623 bool alreadyHandled = false;
2624
2625 switch (arrayMode.type()) {
2626 case Array::SelectUsingPredictions:
2627 case Array::ForceExit:
2628 DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2629 break;
2630 case Array::Generic: {
2631 DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
2632
2633 if (child1.useKind() == CellUse) {
2634 if (child2.useKind() == StringUse) {
2635 compilePutByValForCellWithString(node, child1, child2, child3);
2636 alreadyHandled = true;
2637 break;
2638 }
2639
2640 if (child2.useKind() == SymbolUse) {
2641 compilePutByValForCellWithSymbol(node, child1, child2, child3);
2642 alreadyHandled = true;
2643 break;
2644 }
2645 }
2646
2647 JSValueOperand arg1(this, child1);
2648 JSValueOperand arg2(this, child2);
2649 JSValueOperand arg3(this, child3);
2650 GPRReg arg1GPR = arg1.gpr();
2651 GPRReg arg2GPR = arg2.gpr();
2652 GPRReg arg3GPR = arg3.gpr();
2653 flushRegisters();
2654 if (node->op() == PutByValDirect)
2655 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2656 else
2657 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2658 m_jit.exceptionCheck();
2659
2660 noResult(node);
2661 alreadyHandled = true;
2662 break;
2663 }
2664 default:
2665 break;
2666 }
2667
2668 if (alreadyHandled)
2669 break;
2670
2671 SpeculateCellOperand base(this, child1);
2672 SpeculateStrictInt32Operand property(this, child2);
2673
2674 GPRReg baseReg = base.gpr();
2675 GPRReg propertyReg = property.gpr();
2676
2677 switch (arrayMode.type()) {
2678 case Array::Int32:
2679 case Array::Contiguous: {
2680 JSValueOperand value(this, child3, ManualOperandSpeculation);
2681
2682 GPRReg valueReg = value.gpr();
2683
2684 if (!m_compileOkay)
2685 return;
2686
2687 if (arrayMode.type() == Array::Int32) {
2688 DFG_TYPE_CHECK(
2689 JSValueRegs(valueReg), child3, SpecInt32Only,
2690 m_jit.branchIfNotInt32(valueReg));
2691 }
2692
2693 StorageOperand storage(this, child4);
2694 GPRReg storageReg = storage.gpr();
2695
2696 if (node->op() == PutByValAlias) {
2697 // Store the value to the array.
2698 GPRReg propertyReg = property.gpr();
2699 GPRReg valueReg = value.gpr();
2700 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2701
2702 noResult(node);
2703 break;
2704 }
2705
2706 GPRTemporary temporary;
2707 GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2708
2709 MacroAssembler::Jump slowCase;
2710
2711 if (arrayMode.isInBounds()) {
2712 speculationCheck(
2713 OutOfBounds, JSValueRegs(), 0,
2714 m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2715 } else {
2716 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2717
2718 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2719
2720 if (!arrayMode.isOutOfBounds())
2721 speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2722
2723 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2724 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2725
2726 inBounds.link(&m_jit);
2727 }
2728
2729 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2730
2731 base.use();
2732 property.use();
2733 value.use();
2734 storage.use();
2735
2736 if (arrayMode.isOutOfBounds()) {
2737 addSlowPathGenerator(slowPathCall(
2738 slowCase, this,
2739 m_jit.isStrictModeFor(node->origin.semantic)
2740 ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2741 : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2742 NoResult, baseReg, propertyReg, valueReg));
2743 }
2744
2745 noResult(node, UseChildrenCalledExplicitly);
2746 break;
2747 }
2748
2749 case Array::Double: {
2750 compileDoublePutByVal(node, base, property);
2751 break;
2752 }
2753
2754 case Array::ArrayStorage:
2755 case Array::SlowPutArrayStorage: {
2756 JSValueOperand value(this, child3);
2757
2758 GPRReg valueReg = value.gpr();
2759
2760 if (!m_compileOkay)
2761 return;
2762
2763 StorageOperand storage(this, child4);
2764 GPRReg storageReg = storage.gpr();
2765
2766 if (node->op() == PutByValAlias) {
2767 // Store the value to the array.
2768 GPRReg propertyReg = property.gpr();
2769 GPRReg valueReg = value.gpr();
2770 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2771
2772 noResult(node);
2773 break;
2774 }
2775
2776 GPRTemporary temporary;
2777 GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2778
2779 MacroAssembler::JumpList slowCases;
2780
2781 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2782 if (!arrayMode.isOutOfBounds())
2783 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2784 else
2785 slowCases.append(beyondArrayBounds);
2786
2787 // Check if we're writing to a hole; if so increment m_numValuesInVector.
2788 if (arrayMode.isInBounds()) {
2789 speculationCheck(
2790 StoreToHole, JSValueRegs(), 0,
2791 m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset())));
2792 } else {
2793 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2794 if (arrayMode.isSlowPut()) {
2795 // This is sort of strange. If we wanted to optimize this code path, we would invert
2796 // the above branch. But it's simply not worth it since this only happens if we're
2797 // already having a bad time.
2798 slowCases.append(m_jit.jump());
2799 } else {
2800 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2801
2802 // If we're writing to a hole we might be growing the array;
2803 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2804 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2805 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2806
2807 lengthDoesNotNeedUpdate.link(&m_jit);
2808 }
2809 notHoleValue.link(&m_jit);
2810 }
2811
2812 // Store the value to the array.
2813 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
2814
2815 base.use();
2816 property.use();
2817 value.use();
2818 storage.use();
2819
2820 if (!slowCases.empty()) {
2821 addSlowPathGenerator(slowPathCall(
2822 slowCases, this,
2823 m_jit.isStrictModeFor(node->origin.semantic)
2824 ? (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsStrict)
2825 : (node->op() == PutByValDirect ? operationPutByValDirectBeyondArrayBoundsNonStrict : operationPutByValBeyondArrayBoundsNonStrict),
2826 NoResult, baseReg, propertyReg, valueReg));
2827 }
2828
2829 noResult(node, UseChildrenCalledExplicitly);
2830 break;
2831 }
2832
2833 case Array::Int8Array:
2834 case Array::Int16Array:
2835 case Array::Int32Array:
2836 case Array::Uint8Array:
2837 case Array::Uint8ClampedArray:
2838 case Array::Uint16Array:
2839 case Array::Uint32Array:
2840 case Array::Float32Array:
2841 case Array::Float64Array: {
2842 TypedArrayType type = arrayMode.typedArrayType();
2843 if (isInt(type))
2844 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2845 else
2846 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2847 break;
2848 }
2849
2850 case Array::AnyTypedArray:
2851 case Array::String:
2852 case Array::DirectArguments:
2853 case Array::ForceExit:
2854 case Array::Generic:
2855 case Array::ScopedArguments:
2856 case Array::SelectUsingArguments:
2857 case Array::SelectUsingPredictions:
2858 case Array::Undecided:
2859 case Array::Unprofiled:
2860 RELEASE_ASSERT_NOT_REACHED();
2861 }
2862 break;
2863 }
2864
2865 case AtomicsAdd:
2866 case AtomicsAnd:
2867 case AtomicsCompareExchange:
2868 case AtomicsExchange:
2869 case AtomicsLoad:
2870 case AtomicsOr:
2871 case AtomicsStore:
2872 case AtomicsSub:
2873 case AtomicsXor: {
2874 unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
2875 Edge baseEdge = m_jit.graph().child(node, 0);
2876 Edge indexEdge = m_jit.graph().child(node, 1);
2877 Edge argEdges[maxNumExtraAtomicsArgs];
2878 for (unsigned i = numExtraArgs; i--;)
2879 argEdges[i] = m_jit.graph().child(node, 2 + i);
2880 Edge storageEdge = m_jit.graph().child(node, 2 + numExtraArgs);
2881
2882 GPRReg baseGPR;
2883 GPRReg indexGPR;
2884 GPRReg argGPRs[2];
2885 GPRReg resultGPR;
2886
2887 auto callSlowPath = [&] () {
2888 switch (node->op()) {
2889 case AtomicsAdd:
2890 callOperation(operationAtomicsAdd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2891 break;
2892 case AtomicsAnd:
2893 callOperation(operationAtomicsAnd, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2894 break;
2895 case AtomicsCompareExchange:
2896 callOperation(operationAtomicsCompareExchange, resultGPR, baseGPR, indexGPR, argGPRs[0], argGPRs[1]);
2897 break;
2898 case AtomicsExchange:
2899 callOperation(operationAtomicsExchange, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2900 break;
2901 case AtomicsLoad:
2902 callOperation(operationAtomicsLoad, resultGPR, baseGPR, indexGPR);
2903 break;
2904 case AtomicsOr:
2905 callOperation(operationAtomicsOr, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2906 break;
2907 case AtomicsStore:
2908 callOperation(operationAtomicsStore, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2909 break;
2910 case AtomicsSub:
2911 callOperation(operationAtomicsSub, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2912 break;
2913 case AtomicsXor:
2914 callOperation(operationAtomicsXor, resultGPR, baseGPR, indexGPR, argGPRs[0]);
2915 break;
2916 default:
2917 RELEASE_ASSERT_NOT_REACHED();
2918 break;
2919 }
2920 };
2921
2922 if (!storageEdge) {
2923 // We are in generic mode!
2924 JSValueOperand base(this, baseEdge);
2925 JSValueOperand index(this, indexEdge);
2926 Optional<JSValueOperand> args[2];
2927 baseGPR = base.gpr();
2928 indexGPR = index.gpr();
2929 for (unsigned i = numExtraArgs; i--;) {
2930 args[i].emplace(this, argEdges[i]);
2931 argGPRs[i] = args[i]->gpr();
2932 }
2933
2934 flushRegisters();
2935 GPRFlushedCallResult result(this);
2936 resultGPR = result.gpr();
2937 callSlowPath();
2938 m_jit.exceptionCheck();
2939
2940 jsValueResult(resultGPR, node);
2941 break;
2942 }
2943
2944 TypedArrayType type = node->arrayMode().typedArrayType();
2945
2946 SpeculateCellOperand base(this, baseEdge);
2947 SpeculateStrictInt32Operand index(this, indexEdge);
2948
2949 baseGPR = base.gpr();
2950 indexGPR = index.gpr();
2951
2952 emitTypedArrayBoundsCheck(node, baseGPR, indexGPR);
2953
2954 GPRTemporary args[2];
2955
2956 JITCompiler::JumpList slowPathCases;
2957
2958 bool ok = true;
2959 for (unsigned i = numExtraArgs; i--;) {
2960 if (!getIntTypedArrayStoreOperand(args[i], indexGPR, argEdges[i], slowPathCases)) {
2961 noResult(node);
2962 ok = false;
2963 }
2964 argGPRs[i] = args[i].gpr();
2965 }
2966 if (!ok)
2967 break;
2968
2969 StorageOperand storage(this, storageEdge);
2970 GPRTemporary oldValue(this);
2971 GPRTemporary result(this);
2972 GPRTemporary newValue(this);
2973 GPRReg storageGPR = storage.gpr();
2974 GPRReg oldValueGPR = oldValue.gpr();
2975 resultGPR = result.gpr();
2976 GPRReg newValueGPR = newValue.gpr();
2977
2978 // FIXME: It shouldn't be necessary to nop-pad between register allocation and a jump label.
2979 // https://bugs.webkit.org/show_bug.cgi?id=170974
2980 m_jit.nop();
2981
2982 JITCompiler::Label loop = m_jit.label();
2983
2984 loadFromIntTypedArray(storageGPR, indexGPR, oldValueGPR, type);
2985 m_jit.move(oldValueGPR, newValueGPR);
2986 m_jit.move(oldValueGPR, resultGPR);
2987
2988 switch (node->op()) {
2989 case AtomicsAdd:
2990 m_jit.add32(argGPRs[0], newValueGPR);
2991 break;
2992 case AtomicsAnd:
2993 m_jit.and32(argGPRs[0], newValueGPR);
2994 break;
2995 case AtomicsCompareExchange: {
2996 switch (elementSize(type)) {
2997 case 1:
2998 if (isSigned(type))
2999 m_jit.signExtend8To32(argGPRs[0], argGPRs[0]);
3000 else
3001 m_jit.and32(TrustedImm32(0xff), argGPRs[0]);
3002 break;
3003 case 2:
3004 if (isSigned(type))
3005 m_jit.signExtend16To32(argGPRs[0], argGPRs[0]);
3006 else
3007 m_jit.and32(TrustedImm32(0xffff), argGPRs[0]);
3008 break;
3009 case 4:
3010 break;
3011 default:
3012 RELEASE_ASSERT_NOT_REACHED();
3013 break;
3014 }
3015 JITCompiler::Jump fail = m_jit.branch32(JITCompiler::NotEqual, oldValueGPR, argGPRs[0]);
3016 m_jit.move(argGPRs[1], newValueGPR);
3017 fail.link(&m_jit);
3018 break;
3019 }
3020 case AtomicsExchange:
3021 m_jit.move(argGPRs[0], newValueGPR);
3022 break;
3023 case AtomicsLoad:
3024 break;
3025 case AtomicsOr:
3026 m_jit.or32(argGPRs[0], newValueGPR);
3027 break;
3028 case AtomicsStore:
3029 m_jit.move(argGPRs[0], newValueGPR);
3030 m_jit.move(argGPRs[0], resultGPR);
3031 break;
3032 case AtomicsSub:
3033 m_jit.sub32(argGPRs[0], newValueGPR);
3034 break;
3035 case AtomicsXor:
3036 m_jit.xor32(argGPRs[0], newValueGPR);
3037 break;
3038 default:
3039 RELEASE_ASSERT_NOT_REACHED();
3040 break;
3041 }
3042
3043 JITCompiler::JumpList success;
3044 switch (elementSize(type)) {
3045 case 1:
3046 success = m_jit.branchAtomicWeakCAS8(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesOne));
3047 break;
3048 case 2:
3049 success = m_jit.branchAtomicWeakCAS16(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesTwo));
3050 break;
3051 case 4:
3052 success = m_jit.branchAtomicWeakCAS32(JITCompiler::Success, oldValueGPR, newValueGPR, JITCompiler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesFour));
3053 break;
3054 default:
3055 RELEASE_ASSERT_NOT_REACHED();
3056 break;
3057 }
3058 m_jit.jump().linkTo(loop, &m_jit);
3059
3060 if (!slowPathCases.empty()) {
3061 slowPathCases.link(&m_jit);
3062 silentSpillAllRegisters(resultGPR);
3063 // Since we spilled, we can do things to registers.
3064 m_jit.boxCell(baseGPR, JSValueRegs(baseGPR));
3065 m_jit.boxInt32(indexGPR, JSValueRegs(indexGPR));
3066 for (unsigned i = numExtraArgs; i--;)
3067 m_jit.boxInt32(argGPRs[i], JSValueRegs(argGPRs[i]));
3068 callSlowPath();
3069 silentFillAllRegisters();
3070 m_jit.exceptionCheck();
3071 }
3072
3073 success.link(&m_jit);
3074 setIntTypedArrayLoadResult(node, resultGPR, type);
3075 break;
3076 }
3077
3078 case AtomicsIsLockFree: {
3079 if (node->child1().useKind() != Int32Use) {
3080 JSValueOperand operand(this, node->child1());
3081 GPRReg operandGPR = operand.gpr();
3082 flushRegisters();
3083 GPRFlushedCallResult result(this);
3084 GPRReg resultGPR = result.gpr();
3085 callOperation(operationAtomicsIsLockFree, resultGPR, operandGPR);
3086 m_jit.exceptionCheck();
3087 jsValueResult(resultGPR, node);
3088 break;
3089 }
3090
3091 SpeculateInt32Operand operand(this, node->child1());
3092 GPRTemporary result(this);
3093 GPRReg operandGPR = operand.gpr();
3094 GPRReg resultGPR = result.gpr();
3095 m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3096 JITCompiler::JumpList done;
3097 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(4)));
3098 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(1)));
3099 done.append(m_jit.branch32(JITCompiler::Equal, operandGPR, TrustedImm32(2)));
3100 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3101 done.link(&m_jit);
3102 jsValueResult(resultGPR, node);
3103 break;
3104 }
3105
3106 case RegExpExec: {
3107 compileRegExpExec(node);
3108 break;
3109 }
3110
3111 case RegExpExecNonGlobalOrSticky: {
3112 compileRegExpExecNonGlobalOrSticky(node);
3113 break;
3114 }
3115
3116 case RegExpMatchFastGlobal: {
3117 compileRegExpMatchFastGlobal(node);
3118 break;
3119 }
3120
3121 case RegExpTest: {
3122 compileRegExpTest(node);
3123 break;
3124 }
3125
3126 case RegExpMatchFast: {
3127 compileRegExpMatchFast(node);
3128 break;
3129 }
3130
3131 case StringReplace:
3132 case StringReplaceRegExp: {
3133 compileStringReplace(node);
3134 break;
3135 }
3136
3137 case GetRegExpObjectLastIndex: {
3138 compileGetRegExpObjectLastIndex(node);
3139 break;
3140 }
3141
3142 case SetRegExpObjectLastIndex: {
3143 compileSetRegExpObjectLastIndex(node);
3144 break;
3145 }
3146
3147 case RecordRegExpCachedResult: {
3148 compileRecordRegExpCachedResult(node);
3149 break;
3150 }
3151
3152 case ArrayPush: {
3153 compileArrayPush(node);
3154 break;
3155 }
3156
3157 case ArraySlice: {
3158 compileArraySlice(node);
3159 break;
3160 }
3161
3162 case ArrayIndexOf: {
3163 compileArrayIndexOf(node);
3164 break;
3165 }
3166
3167 case ArrayPop: {
3168 ASSERT(node->arrayMode().isJSArray());
3169
3170 SpeculateCellOperand base(this, node->child1());
3171 StorageOperand storage(this, node->child2());
3172 GPRTemporary value(this);
3173 GPRTemporary storageLength(this);
3174 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().
3175
3176 GPRReg baseGPR = base.gpr();
3177 GPRReg storageGPR = storage.gpr();
3178 GPRReg valueGPR = value.gpr();
3179 GPRReg storageLengthGPR = storageLength.gpr();
3180 FPRReg tempFPR = temp.fpr();
3181
3182 switch (node->arrayMode().type()) {
3183 case Array::Int32:
3184 case Array::Double:
3185 case Array::Contiguous: {
3186 m_jit.load32(
3187 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3188 MacroAssembler::Jump undefinedCase =
3189 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3190 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3191 m_jit.store32(
3192 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3193 MacroAssembler::Jump slowCase;
3194 if (node->arrayMode().type() == Array::Double) {
3195 m_jit.loadDouble(
3196 MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3197 tempFPR);
3198 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3199 // length and the new length.
3200 m_jit.store64(
3201 MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3202 slowCase = m_jit.branchIfNaN(tempFPR);
3203 boxDouble(tempFPR, valueGPR);
3204 } else {
3205 m_jit.load64(
3206 MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3207 valueGPR);
3208 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3209 // length and the new length.
3210 m_jit.store64(
3211 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3212 slowCase = m_jit.branchIfEmpty(valueGPR);
3213 }
3214
3215 addSlowPathGenerator(
3216 slowPathMove(
3217 undefinedCase, this,
3218 MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3219 addSlowPathGenerator(
3220 slowPathCall(
3221 slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3222
3223 // We can't know for sure that the result is an int because of the slow paths. :-/
3224 jsValueResult(valueGPR, node);
3225 break;
3226 }
3227
3228 case Array::ArrayStorage: {
3229 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3230
3231 JITCompiler::Jump undefinedCase =
3232 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3233
3234 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3235
3236 JITCompiler::JumpList slowCases;
3237 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3238
3239 m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), valueGPR);
3240 slowCases.append(m_jit.branchIfEmpty(valueGPR));
3241
3242 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3243
3244 m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()));
3245 m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3246
3247 addSlowPathGenerator(
3248 slowPathMove(
3249 undefinedCase, this,
3250 MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3251
3252 addSlowPathGenerator(
3253 slowPathCall(
3254 slowCases, this, operationArrayPop, valueGPR, baseGPR));
3255
3256 jsValueResult(valueGPR, node);
3257 break;
3258 }
3259
3260 default:
3261 CRASH();
3262 break;
3263 }
3264 break;
3265 }
3266
3267 case DFG::Jump: {
3268 jump(node->targetBlock());
3269 noResult(node);
3270 break;
3271 }
3272
3273 case Branch:
3274 emitBranch(node);
3275 break;
3276
3277 case Switch:
3278 emitSwitch(node);
3279 break;
3280
3281 case Return: {
3282 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3283 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3284 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3285
3286 // Return the result in returnValueGPR.
3287 JSValueOperand op1(this, node->child1());
3288 m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3289
3290 m_jit.emitRestoreCalleeSaves();
3291 m_jit.emitFunctionEpilogue();
3292 m_jit.ret();
3293
3294 noResult(node);
3295 break;
3296 }
3297
3298 case Throw: {
3299 compileThrow(node);
3300 break;
3301 }
3302
3303 case ThrowStaticError: {
3304 compileThrowStaticError(node);
3305 break;
3306 }
3307
3308 case BooleanToNumber: {
3309 switch (node->child1().useKind()) {
3310 case BooleanUse: {
3311 JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3312 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3313
3314 m_jit.move(value.gpr(), result.gpr());
3315 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3316 DFG_TYPE_CHECK(
3317 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3318 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3319
3320 int32Result(result.gpr(), node);
3321 break;
3322 }
3323
3324 case UntypedUse: {
3325 JSValueOperand value(this, node->child1());
3326 GPRTemporary result(this);
3327
3328 if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3329 m_jit.move(value.gpr(), result.gpr());
3330 m_jit.and32(TrustedImm32(1), result.gpr());
3331 int32Result(result.gpr(), node);
3332 break;
3333 }
3334
3335 m_jit.move(value.gpr(), result.gpr());
3336 m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3337 JITCompiler::Jump isBoolean = m_jit.branchTest64(
3338 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3339 m_jit.move(value.gpr(), result.gpr());
3340 JITCompiler::Jump done = m_jit.jump();
3341 isBoolean.link(&m_jit);
3342 m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3343 done.link(&m_jit);
3344
3345 jsValueResult(result.gpr(), node);
3346 break;
3347 }
3348
3349 default:
3350 DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3351 break;
3352 }
3353 break;
3354 }
3355
3356 case ToPrimitive: {
3357 compileToPrimitive(node);
3358 break;
3359 }
3360
3361 case ToNumber: {
3362 JSValueOperand argument(this, node->child1());
3363 GPRTemporary result(this, Reuse, argument);
3364
3365 GPRReg argumentGPR = argument.gpr();
3366 GPRReg resultGPR = result.gpr();
3367
3368 argument.use();
3369
3370 // We have several attempts to remove ToNumber. But ToNumber still exists.
3371 // It means that converting non-numbers to numbers by this ToNumber is not rare.
3372 // Instead of the slow path generator, we emit callOperation here.
3373 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3374 flushRegisters();
3375 callOperation(operationToNumber, resultGPR, argumentGPR);
3376 m_jit.exceptionCheck();
3377 } else {
3378 MacroAssembler::Jump notNumber = m_jit.branchIfNotNumber(argumentGPR);
3379 m_jit.move(argumentGPR, resultGPR);
3380 MacroAssembler::Jump done = m_jit.jump();
3381
3382 notNumber.link(&m_jit);
3383 silentSpillAllRegisters(resultGPR);
3384 callOperation(operationToNumber, resultGPR, argumentGPR);
3385 silentFillAllRegisters();
3386 m_jit.exceptionCheck();
3387
3388 done.link(&m_jit);
3389 }
3390
3391 jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3392 break;
3393 }
3394
3395 case ToString:
3396 case CallStringConstructor:
3397 case StringValueOf: {
3398 compileToStringOrCallStringConstructorOrStringValueOf(node);
3399 break;
3400 }
3401
3402 case NewStringObject: {
3403 compileNewStringObject(node);
3404 break;
3405 }
3406
3407 case NewSymbol: {
3408 compileNewSymbol(node);
3409 break;
3410 }
3411
3412 case NewArray: {
3413 compileNewArray(node);
3414 break;
3415 }
3416
3417 case NewArrayWithSpread: {
3418 compileNewArrayWithSpread(node);
3419 break;
3420 }
3421
3422 case Spread: {
3423 compileSpread(node);
3424 break;
3425 }
3426
3427 case NewArrayWithSize: {
3428 compileNewArrayWithSize(node);
3429 break;
3430 }
3431
3432 case NewArrayBuffer: {
3433 compileNewArrayBuffer(node);
3434 break;
3435 }
3436
3437 case NewTypedArray: {
3438 compileNewTypedArray(node);
3439 break;
3440 }
3441
3442 case NewRegexp: {
3443 compileNewRegexp(node);
3444 break;
3445 }
3446
3447 case ToObject:
3448 case CallObjectConstructor: {
3449 compileToObjectOrCallObjectConstructor(node);
3450 break;
3451 }
3452
3453 case ToThis: {
3454 compileToThis(node);
3455 break;
3456 }
3457
3458 case ObjectCreate: {
3459 compileObjectCreate(node);
3460 break;
3461 }
3462
3463 case ObjectKeys: {
3464 compileObjectKeys(node);
3465 break;
3466 }
3467
3468 case CreateThis: {
3469 compileCreateThis(node);
3470 break;
3471 }
3472
3473 case NewObject: {
3474 compileNewObject(node);
3475 break;
3476 }
3477
3478 case GetCallee: {
3479 compileGetCallee(node);
3480 break;
3481 }
3482
3483 case SetCallee: {
3484 compileSetCallee(node);
3485 break;
3486 }
3487
3488 case GetArgumentCountIncludingThis: {
3489 compileGetArgumentCountIncludingThis(node);
3490 break;
3491 }
3492
3493 case SetArgumentCountIncludingThis:
3494 compileSetArgumentCountIncludingThis(node);
3495 break;
3496
3497 case GetRestLength: {
3498 compileGetRestLength(node);
3499 break;
3500 }
3501
3502 case GetScope:
3503 compileGetScope(node);
3504 break;
3505
3506 case SkipScope:
3507 compileSkipScope(node);
3508 break;
3509
3510 case GetGlobalObject:
3511 compileGetGlobalObject(node);
3512 break;
3513
3514 case GetGlobalThis:
3515 compileGetGlobalThis(node);
3516 break;
3517
3518 case GetClosureVar: {
3519 compileGetClosureVar(node);
3520 break;
3521 }
3522 case PutClosureVar: {
3523 compilePutClosureVar(node);
3524 break;
3525 }
3526
3527 case TryGetById: {
3528 compileGetById(node, AccessType::TryGet);
3529 break;
3530 }
3531
3532 case GetByIdDirect: {
3533 compileGetById(node, AccessType::GetDirect);
3534 break;
3535 }
3536
3537 case GetByIdDirectFlush: {
3538 compileGetByIdFlush(node, AccessType::GetDirect);
3539 break;
3540 }
3541
3542 case GetById: {
3543 compileGetById(node, AccessType::Get);
3544 break;
3545 }
3546
3547 case GetByIdFlush: {
3548 compileGetByIdFlush(node, AccessType::Get);
3549 break;
3550 }
3551
3552 case GetByIdWithThis: {
3553 if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3554 SpeculateCellOperand base(this, node->child1());
3555 GPRReg baseGPR = base.gpr();
3556 SpeculateCellOperand thisValue(this, node->child2());
3557 GPRReg thisValueGPR = thisValue.gpr();
3558
3559 GPRFlushedCallResult result(this);
3560 GPRReg resultGPR = result.gpr();
3561
3562 flushRegisters();
3563
3564 cachedGetByIdWithThis(node->origin.semantic, baseGPR, thisValueGPR, resultGPR, node->identifierNumber(), JITCompiler::JumpList());
3565
3566 jsValueResult(resultGPR, node);
3567
3568 } else {
3569 JSValueOperand base(this, node->child1());
3570 GPRReg baseGPR = base.gpr();
3571 JSValueOperand thisValue(this, node->child2());
3572 GPRReg thisValueGPR = thisValue.gpr();
3573
3574 GPRFlushedCallResult result(this);
3575 GPRReg resultGPR = result.gpr();
3576
3577 flushRegisters();
3578
3579 JITCompiler::JumpList notCellList;
3580 notCellList.append(m_jit.branchIfNotCell(JSValueRegs(baseGPR)));
3581 notCellList.append(m_jit.branchIfNotCell(JSValueRegs(thisValueGPR)));
3582
3583 cachedGetByIdWithThis(node->origin.semantic, baseGPR, thisValueGPR, resultGPR, node->identifierNumber(), notCellList);
3584
3585 jsValueResult(resultGPR, node);
3586 }
3587
3588 break;
3589 }
3590
3591 case GetArrayLength:
3592 compileGetArrayLength(node);
3593 break;
3594
3595 case DeleteById: {
3596 compileDeleteById(node);
3597 break;
3598 }
3599
3600 case DeleteByVal: {
3601 compileDeleteByVal(node);
3602 break;
3603 }
3604
3605 case CheckCell: {
3606 compileCheckCell(node);
3607 break;
3608 }
3609
3610 case CheckNotEmpty: {
3611 compileCheckNotEmpty(node);
3612 break;
3613 }
3614
3615 case AssertNotEmpty: {
3616 if (validationEnabled()) {
3617 JSValueOperand operand(this, node->child1());
3618 GPRReg input = operand.gpr();
3619 auto done = m_jit.branchIfNotEmpty(input);
3620 m_jit.breakpoint();
3621 done.link(&m_jit);
3622 }
3623 noResult(node);
3624 break;
3625 }
3626
3627 case CheckStringIdent:
3628 compileCheckStringIdent(node);
3629 break;
3630
3631 case GetExecutable: {
3632 compileGetExecutable(node);
3633 break;
3634 }
3635
3636 case CheckStructureOrEmpty: {
3637 SpeculateCellOperand cell(this, node->child1());
3638 GPRReg cellGPR = cell.gpr();
3639
3640 GPRReg tempGPR = InvalidGPRReg;
3641 Optional<GPRTemporary> temp;
3642 if (node->structureSet().size() > 1) {
3643 temp.emplace(this);
3644 tempGPR = temp->gpr();
3645 }
3646
3647 MacroAssembler::Jump isEmpty;
3648 if (m_interpreter.forNode(node->child1()).m_type & SpecEmpty)
3649 isEmpty = m_jit.branchIfEmpty(cellGPR);
3650
3651 emitStructureCheck(node, cellGPR, tempGPR);
3652
3653 if (isEmpty.isSet())
3654 isEmpty.link(&m_jit);
3655
3656 noResult(node);
3657 break;
3658 }
3659
3660 case CheckStructure: {
3661 compileCheckStructure(node);
3662 break;
3663 }
3664
3665 case PutStructure: {
3666 RegisteredStructure oldStructure = node->transition()->previous;
3667 RegisteredStructure newStructure = node->transition()->next;
3668
3669 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3670
3671 SpeculateCellOperand base(this, node->child1());
3672 GPRReg baseGPR = base.gpr();
3673
3674 ASSERT_UNUSED(oldStructure, oldStructure->indexingMode() == newStructure->indexingMode());
3675 ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3676 ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3677 m_jit.store32(MacroAssembler::TrustedImm32(newStructure->id()), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3678
3679 noResult(node);
3680 break;
3681 }
3682
3683 case AllocatePropertyStorage:
3684 compileAllocatePropertyStorage(node);
3685 break;
3686
3687 case ReallocatePropertyStorage:
3688 compileReallocatePropertyStorage(node);
3689 break;
3690
3691 case NukeStructureAndSetButterfly:
3692 compileNukeStructureAndSetButterfly(node);
3693 break;
3694
3695 case GetButterfly:
3696 compileGetButterfly(node);
3697 break;
3698
3699 case GetIndexedPropertyStorage: {
3700 compileGetIndexedPropertyStorage(node);
3701 break;
3702 }
3703
3704 case ConstantStoragePointer: {
3705 compileConstantStoragePointer(node);
3706 break;
3707 }
3708
3709 case GetTypedArrayByteOffset: {
3710 compileGetTypedArrayByteOffset(node);
3711 break;
3712 }
3713
3714 case GetPrototypeOf: {
3715 compileGetPrototypeOf(node);
3716 break;
3717 }
3718
3719 case GetByOffset:
3720 case GetGetterSetterByOffset: {
3721 compileGetByOffset(node);
3722 break;
3723 }
3724
3725 case MatchStructure: {
3726 compileMatchStructure(node);
3727 break;
3728 }
3729
3730 case GetGetter: {
3731 compileGetGetter(node);
3732 break;
3733 }
3734
3735 case GetSetter: {
3736 compileGetSetter(node);
3737 break;
3738 }
3739
3740 case PutByOffset: {
3741 compilePutByOffset(node);
3742 break;
3743 }
3744
3745 case PutByIdFlush: {
3746 compilePutByIdFlush(node);
3747 break;
3748 }
3749
3750 case PutById: {
3751 compilePutById(node);
3752 break;
3753 }
3754
3755 case PutByIdWithThis: {
3756 compilePutByIdWithThis(node);
3757 break;
3758 }
3759
3760 case PutByValWithThis: {
3761 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
3762 GPRReg baseGPR = base.gpr();
3763 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
3764 GPRReg thisValueGPR = thisValue.gpr();
3765 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
3766 GPRReg propertyGPR = property.gpr();
3767 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
3768 GPRReg valueGPR = value.gpr();
3769
3770 flushRegisters();
3771 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis, NoResult, baseGPR, thisValueGPR, propertyGPR, valueGPR);
3772 m_jit.exceptionCheck();
3773
3774 noResult(node);
3775 break;
3776 }
3777
3778 case PutByIdDirect: {
3779 compilePutByIdDirect(node);
3780 break;
3781 }
3782
3783 case PutGetterById:
3784 case PutSetterById: {
3785 compilePutAccessorById(node);
3786 break;
3787 }
3788
3789 case PutGetterSetterById: {
3790 compilePutGetterSetterById(node);
3791 break;
3792 }
3793
3794 case PutGetterByVal:
3795 case PutSetterByVal: {
3796 compilePutAccessorByVal(node);
3797 break;
3798 }
3799
3800 case DefineDataProperty: {
3801 compileDefineDataProperty(node);
3802 break;
3803 }
3804
3805 case DefineAccessorProperty: {
3806 compileDefineAccessorProperty(node);
3807 break;
3808 }
3809
3810 case GetGlobalLexicalVariable:
3811 case GetGlobalVar: {
3812 compileGetGlobalVariable(node);
3813 break;
3814 }
3815
3816 case PutGlobalVariable: {
3817 compilePutGlobalVariable(node);
3818 break;
3819 }
3820
3821 case PutDynamicVar: {
3822 compilePutDynamicVar(node);
3823 break;
3824 }
3825
3826 case GetDynamicVar: {
3827 compileGetDynamicVar(node);
3828 break;
3829 }
3830
3831 case ResolveScopeForHoistingFuncDeclInEval: {
3832 compileResolveScopeForHoistingFuncDeclInEval(node);
3833 break;
3834 }
3835
3836 case ResolveScope: {
3837 compileResolveScope(node);
3838 break;
3839 }
3840
3841 case NotifyWrite: {
3842 compileNotifyWrite(node);
3843 break;
3844 }
3845
3846 case CheckTypeInfoFlags: {
3847 compileCheckTypeInfoFlags(node);
3848 break;
3849 }
3850
3851 case ParseInt: {
3852 compileParseInt(node);
3853 break;
3854 }
3855
3856 case OverridesHasInstance: {
3857 compileOverridesHasInstance(node);
3858 break;
3859 }
3860
3861 case InstanceOf: {
3862 compileInstanceOf(node);
3863 break;
3864 }
3865
3866 case InstanceOfCustom: {
3867 compileInstanceOfCustom(node);
3868 break;
3869 }
3870
3871 case IsEmpty: {
3872 JSValueOperand value(this, node->child1());
3873 GPRTemporary result(this, Reuse, value);
3874
3875 m_jit.comparePtr(JITCompiler::Equal, value.gpr(), TrustedImm32(JSValue::encode(JSValue())), result.gpr());
3876 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3877
3878 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3879 break;
3880 }
3881
3882 case IsUndefined: {
3883 JSValueOperand value(this, node->child1());
3884 GPRTemporary result(this);
3885 GPRTemporary localGlobalObject(this);
3886 GPRTemporary remoteGlobalObject(this);
3887 GPRTemporary scratch(this);
3888
3889 JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3890
3891 m_jit.compare64(JITCompiler::Equal, value.gpr(), TrustedImm32(ValueUndefined), result.gpr());
3892 JITCompiler::Jump done = m_jit.jump();
3893
3894 isCell.link(&m_jit);
3895 JITCompiler::Jump notMasqueradesAsUndefined;
3896 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3897 m_jit.move(TrustedImm32(0), result.gpr());
3898 notMasqueradesAsUndefined = m_jit.jump();
3899 } else {
3900 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3901 JITCompiler::NonZero,
3902 JITCompiler::Address(value.gpr(), JSCell::typeInfoFlagsOffset()),
3903 TrustedImm32(MasqueradesAsUndefined));
3904 m_jit.move(TrustedImm32(0), result.gpr());
3905 notMasqueradesAsUndefined = m_jit.jump();
3906
3907 isMasqueradesAsUndefined.link(&m_jit);
3908 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3909 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3910 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3911 m_jit.emitLoadStructure(*m_jit.vm(), value.gpr(), result.gpr(), scratch.gpr());
3912 m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR);
3913 m_jit.comparePtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3914 }
3915
3916 notMasqueradesAsUndefined.link(&m_jit);
3917 done.link(&m_jit);
3918 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3919 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3920 break;
3921 }
3922
3923 case IsUndefinedOrNull: {
3924 JSValueOperand value(this, node->child1());
3925 GPRTemporary result(this, Reuse, value);
3926
3927 GPRReg valueGPR = value.gpr();
3928 GPRReg resultGPR = result.gpr();
3929
3930 m_jit.move(valueGPR, resultGPR);
3931 m_jit.and64(CCallHelpers::TrustedImm32(~TagBitUndefined), resultGPR);
3932 m_jit.compare64(CCallHelpers::Equal, resultGPR, CCallHelpers::TrustedImm32(ValueNull), resultGPR);
3933
3934 unblessedBooleanResult(resultGPR, node);
3935 break;
3936 }
3937
3938 case IsBoolean: {
3939 JSValueOperand value(this, node->child1());
3940 GPRTemporary result(this, Reuse, value);
3941
3942 m_jit.move(value.gpr(), result.gpr());
3943 m_jit.xor64(JITCompiler::TrustedImm32(ValueFalse), result.gpr());
3944 m_jit.test64(JITCompiler::Zero, result.gpr(), JITCompiler::TrustedImm32(static_cast<int32_t>(~1)), result.gpr());
3945 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3946 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3947 break;
3948 }
3949
3950 case IsNumber: {
3951 JSValueOperand value(this, node->child1());
3952 GPRTemporary result(this, Reuse, value);
3953
3954 m_jit.test64(JITCompiler::NonZero, value.gpr(), GPRInfo::tagTypeNumberRegister, result.gpr());
3955 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3956 jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3957 break;
3958 }
3959
3960 case NumberIsInteger: {
3961 JSValueOperand value(this, node->child1());
3962 GPRTemporary result(this, Reuse, value);
3963
3964 FPRTemporary temp1(this);
3965 FPRTemporary temp2(this);
3966
3967 JSValueRegs valueRegs = JSValueRegs(value.gpr());
3968 GPRReg resultGPR = result.gpr();
3969
3970 FPRReg tempFPR1 = temp1.fpr();
3971 FPRReg tempFPR2 = temp2.fpr();
3972
3973 MacroAssembler::JumpList done;
3974
3975 auto isInt32 = m_jit.branchIfInt32(valueRegs);
3976 auto notNumber = m_jit.branchIfNotDoubleKnownNotInt32(valueRegs);
3977
3978 // We're a double here.
3979 m_jit.unboxDouble(valueRegs.gpr(), resultGPR, tempFPR1);
3980 m_jit.urshift64(TrustedImm32(52), resultGPR);
3981 m_jit.and32(TrustedImm32(0x7ff), resultGPR);
3982 auto notNanNorInfinity = m_jit.branch32(JITCompiler::NotEqual, TrustedImm32(0x7ff), resultGPR);
3983 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3984 done.append(m_jit.jump());
3985
3986 notNanNorInfinity.link(&m_jit);
3987 m_jit.roundTowardZeroDouble(tempFPR1, tempFPR2);
3988 m_jit.compareDouble(JITCompiler::DoubleEqual, tempFPR1, tempFPR2, resultGPR);
3989 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
3990 done.append(m_jit.jump());
3991
3992 isInt32.link(&m_jit);
3993 m_jit.move(TrustedImm32(ValueTrue), resultGPR);
3994 done.append(m_jit.jump());
3995
3996 notNumber.link(&m_jit);
3997 m_jit.move(TrustedImm32(ValueFalse), resultGPR);
3998
3999 done.link(&m_jit);
4000 jsValueResult(resultGPR, node, DataFormatJSBoolean);
4001 break;
4002 }
4003
4004 case MapHash: {
4005 switch (node->child1().useKind()) {
4006 case BooleanUse:
4007 case Int32Use:
4008 case SymbolUse:
4009 case ObjectUse: {
4010 JSValueOperand input(this, node->child1(), ManualOperandSpeculation);
4011 GPRTemporary result(this, Reuse, input);
4012 GPRTemporary temp(this);
4013
4014 GPRReg inputGPR = input.gpr();
4015 GPRReg resultGPR = result.gpr();
4016 GPRReg tempGPR = temp.gpr();
4017
4018 speculate(node, node->child1());
4019
4020 m_jit.move(inputGPR, resultGPR);
4021 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4022 int32Result(resultGPR, node);
4023 break;
4024 }
4025 case CellUse:
4026 case StringUse: {
4027 SpeculateCellOperand input(this, node->child1());
4028 GPRTemporary result(this);
4029 Optional<GPRTemporary> temp;
4030
4031 GPRReg tempGPR = InvalidGPRReg;
4032 if (node->child1().useKind() == CellUse) {
4033 temp.emplace(this);
4034 tempGPR = temp->gpr();
4035 }
4036
4037 GPRReg inputGPR = input.gpr();
4038 GPRReg resultGPR = result.gpr();
4039
4040 MacroAssembler::JumpList slowPath;
4041 MacroAssembler::JumpList done;
4042
4043 if (node->child1().useKind() == StringUse)
4044 speculateString(node->child1(), inputGPR);
4045 else {
4046 auto isString = m_jit.branchIfString(inputGPR);
4047 m_jit.move(inputGPR, resultGPR);
4048 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4049 done.append(m_jit.jump());
4050 isString.link(&m_jit);
4051 }
4052
4053 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
4054 slowPath.append(m_jit.branchIfRopeStringImpl(resultGPR));
4055 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR);
4056 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);
4057 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
4058 done.append(m_jit.jump());
4059
4060 slowPath.link(&m_jit);
4061 silentSpillAllRegisters(resultGPR);
4062 callOperation(operationMapHash, resultGPR, JSValueRegs(inputGPR));
4063 silentFillAllRegisters();
4064 m_jit.exceptionCheck();
4065
4066 done.link(&m_jit);
4067 int32Result(resultGPR, node);
4068 break;
4069 }
4070 default:
4071 RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
4072 break;
4073 }
4074
4075 if (node->child1().useKind() != UntypedUse)
4076 break;
4077
4078 JSValueOperand input(this, node->child1());
4079 GPRTemporary temp(this);
4080 GPRTemporary result(this);
4081
4082 GPRReg inputGPR = input.gpr();
4083 GPRReg resultGPR = result.gpr();
4084 GPRReg tempGPR = temp.gpr();
4085
4086 MacroAssembler::JumpList straightHash;
4087 MacroAssembler::JumpList done;
4088 straightHash.append(m_jit.branchIfNotCell(inputGPR));
4089 MacroAssembler::JumpList slowPath;
4090 straightHash.append(m_jit.branchIfNotString(inputGPR));
4091 m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
4092 slowPath.append(m_jit.branchIfRopeStringImpl(resultGPR));
4093 m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR);
4094 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);
4095 slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
4096 done.append(m_jit.jump());
4097
4098 straightHash.link(&m_jit);
4099 m_jit.move(inputGPR, resultGPR);
4100 m_jit.wangsInt64Hash(resultGPR, tempGPR);
4101 done.append(m_jit.jump());
4102
4103 slowPath.link(&m_jit);
4104 silentSpillAllRegisters(resultGPR);
4105 callOperation(operationMapHash, resultGPR, JSValueRegs(inputGPR));
4106 silentFillAllRegisters();
4107 m_jit.exceptionCheck();
4108
4109 done.link(&m_jit);
4110 int32Result(resultGPR, node);
4111 break;
4112 }
4113
4114 case NormalizeMapKey: {
4115 compileNormalizeMapKey(node);
4116 break;
4117 }
4118
4119 case GetMapBucket: {
4120 SpeculateCellOperand map(this, node->child1());
4121 JSValueOperand key(this, node->child2(), ManualOperandSpeculation);
4122 SpeculateInt32Operand hash(this, node->child3());
4123 GPRTemporary mask(this);
4124 GPRTemporary index(this);
4125 GPRTemporary buffer(this);
4126 GPRTemporary bucket(this);
4127 GPRTemporary result(this);
4128
4129 GPRReg hashGPR = hash.gpr();
4130 GPRReg mapGPR = map.gpr();
4131 GPRReg maskGPR = mask.gpr();
4132 GPRReg indexGPR = index.gpr();
4133 GPRReg bufferGPR = buffer.gpr();
4134 GPRReg bucketGPR = bucket.gpr();
4135 GPRReg keyGPR = key.gpr();
4136 GPRReg resultGPR = result.gpr();
4137
4138 if (node->child1().useKind() == MapObjectUse)
4139 speculateMapObject(node->child1(), mapGPR);
4140 else if (node->child1().useKind() == SetObjectUse)
4141 speculateSetObject(node->child1(), mapGPR);
4142 else
4143 RELEASE_ASSERT_NOT_REACHED();
4144
4145 if (node->child2().useKind() != UntypedUse)
4146 speculate(node, node->child2());
4147
4148 m_jit.load32(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()), maskGPR);
4149 m_jit.loadPtr(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()), bufferGPR);
4150 m_jit.sub32(TrustedImm32(1), maskGPR);
4151 m_jit.move(hashGPR, indexGPR);
4152
4153 MacroAssembler::Label loop = m_jit.label();
4154 MacroAssembler::JumpList done;
4155 MacroAssembler::JumpList slowPathCases;
4156 MacroAssembler::JumpList loopAround;
4157
4158 m_jit.and32(maskGPR, indexGPR);
4159 m_jit.loadPtr(MacroAssembler::BaseIndex(bufferGPR, indexGPR, MacroAssembler::TimesEight), bucketGPR);
4160 m_jit.move(bucketGPR, resultGPR);
4161 auto notPresentInTable = m_jit.branchPtr(MacroAssembler::Equal,
4162 bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())));
4163 loopAround.append(m_jit.branchPtr(MacroAssembler::Equal,
4164 bucketGPR, TrustedImmPtr(bitwise_cast<size_t>(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue()))));
4165
4166 m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKey>::offsetOfKey()), bucketGPR);
4167
4168 // Perform Object.is()
4169 switch (node->child2().useKind()) {
4170 case BooleanUse:
4171 case Int32Use:
4172 case SymbolUse:
4173 case ObjectUse: {
4174 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4175 // Otherwise, loop around.
4176 break;
4177 }
4178 case CellUse: {
4179 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR));
4180 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4181 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4182 loopAround.append(m_jit.branchIfNotString(keyGPR));
4183 // They're both strings.
4184 slowPathCases.append(m_jit.jump());
4185 break;
4186 }
4187 case StringUse: {
4188 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4189 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4190 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4191 slowPathCases.append(m_jit.jump());
4192 break;
4193 }
4194 case UntypedUse: {
4195 done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
4196 // 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.
4197 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(bucketGPR)));
4198 // first is a cell here.
4199 loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
4200 // Both are cells here.
4201 loopAround.append(m_jit.branchIfNotString(bucketGPR));
4202 // The first is a string here.
4203 slowPathCases.append(m_jit.branchIfString(keyGPR));
4204 // The first is a string, but the second is not, we continue to loop around.
4205 loopAround.append(m_jit.jump());
4206 break;
4207 }
4208 default:
4209 RELEASE_ASSERT_NOT_REACHED();
4210 }
4211
4212
4213 if (!loopAround.empty())
4214 loopAround.link(&m_jit);
4215
4216 m_jit.add32(TrustedImm32(1), indexGPR);
4217 m_jit.jump().linkTo(loop, &m_jit);
4218
4219 if (!slowPathCases.empty()) {
4220 slowPathCases.link(&m_jit);
4221 silentSpillAllRegisters(indexGPR);
4222 if (node->child1().useKind() == MapObjectUse)
4223 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
4224 else
4225 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
4226 silentFillAllRegisters();
4227 m_jit.exceptionCheck();
4228 done.append(m_jit.jump());
4229 }
4230
4231 notPresentInTable.link(&m_jit);
4232 if (node->child1().useKind() == MapObjectUse)
4233 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket()), resultGPR);
4234 else
4235 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket()), resultGPR);
4236 done.link(&m_jit);
4237 cellResult(resultGPR, node);
4238 break;
4239 }
4240
4241 case GetMapBucketHead:
4242 compileGetMapBucketHead(node);
4243 break;
4244
4245 case GetMapBucketNext:
4246 compileGetMapBucketNext(node);
4247 break;
4248
4249 case LoadKeyFromMapBucket:
4250 compileLoadKeyFromMapBucket(node);
4251 break;
4252
4253 case LoadValueFromMapBucket:
4254 compileLoadValueFromMapBucket(node);
4255 break;
4256
4257 case ExtractValueFromWeakMapGet:
4258 compileExtractValueFromWeakMapGet(node);
4259 break;
4260
4261 case SetAdd:
4262 compileSetAdd(node);
4263 break;
4264
4265 case MapSet:
4266 compileMapSet(node);
4267 break;
4268
4269 case WeakMapGet:
4270 compileWeakMapGet(node);
4271 break;
4272
4273 case WeakSetAdd:
4274 compileWeakSetAdd(node);
4275 break;
4276
4277 case WeakMapSet:
4278 compileWeakMapSet(node);
4279 break;
4280
4281 case StringSlice: {
4282 compileStringSlice(node);
4283 break;
4284 }
4285
4286 case ToLowerCase: {
4287 compileToLowerCase(node);
4288 break;
4289 }
4290
4291 case NumberToStringWithRadix: {
4292 compileNumberToStringWithRadix(node);
4293 break;
4294 }
4295
4296 case NumberToStringWithValidRadixConstant: {
4297 compileNumberToStringWithValidRadixConstant(node);
4298 break;
4299 }
4300
4301 case IsObject: {
4302 compileIsObject(node);
4303 break;
4304 }
4305
4306 case IsObjectOrNull: {
4307 compileIsObjectOrNull(node);
4308 break;
4309 }
4310
4311 case IsFunction: {
4312 compileIsFunction(node);
4313 break;
4314 }
4315
4316 case IsCellWithType: {
4317 compileIsCellWithType(node);
4318 break;
4319 }
4320
4321 case IsTypedArrayView: {
4322 compileIsTypedArrayView(node);
4323 break;
4324 }
4325
4326 case TypeOf: {
4327 compileTypeOf(node);
4328 break;
4329 }
4330
4331 case Flush:
4332 break;
4333
4334 case Call:
4335 case TailCall:
4336 case TailCallInlinedCaller:
4337 case Construct:
4338 case CallVarargs:
4339 case TailCallVarargs:
4340 case TailCallVarargsInlinedCaller:
4341 case CallForwardVarargs:
4342 case ConstructVarargs:
4343 case ConstructForwardVarargs:
4344 case TailCallForwardVarargs:
4345 case TailCallForwardVarargsInlinedCaller:
4346 case CallEval:
4347 case DirectCall:
4348 case DirectConstruct:
4349 case DirectTailCall:
4350 case DirectTailCallInlinedCaller:
4351 emitCall(node);
4352 break;
4353
4354 case LoadVarargs: {
4355 compileLoadVarargs(node);
4356 break;
4357 }
4358
4359 case ForwardVarargs: {
4360 compileForwardVarargs(node);
4361 break;
4362 }
4363
4364 case CreateActivation: {
4365 compileCreateActivation(node);
4366 break;
4367 }
4368
4369 case PushWithScope: {
4370 compilePushWithScope(node);
4371 break;
4372 }
4373
4374 case CreateDirectArguments: {
4375 compileCreateDirectArguments(node);
4376 break;
4377 }
4378
4379 case GetFromArguments: {
4380 compileGetFromArguments(node);
4381 break;
4382 }
4383
4384 case PutToArguments: {
4385 compilePutToArguments(node);
4386 break;
4387 }
4388
4389 case GetArgument: {
4390 compileGetArgument(node);
4391 break;
4392 }
4393
4394 case CreateScopedArguments: {
4395 compileCreateScopedArguments(node);
4396 break;
4397 }
4398
4399 case CreateClonedArguments: {
4400 compileCreateClonedArguments(node);
4401 break;
4402 }
4403 case CreateRest: {
4404 compileCreateRest(node);
4405 break;
4406 }
4407
4408 case NewFunction:
4409 case NewGeneratorFunction:
4410 case NewAsyncGeneratorFunction:
4411 case NewAsyncFunction:
4412 compileNewFunction(node);
4413 break;
4414
4415 case SetFunctionName:
4416 compileSetFunctionName(node);
4417 break;
4418
4419 case InById:
4420 compileInById(node);
4421 break;
4422
4423 case InByVal:
4424 compileInByVal(node);
4425 break;
4426
4427 case HasOwnProperty: {
4428 SpeculateCellOperand object(this, node->child1());
4429 GPRTemporary uniquedStringImpl(this);
4430 GPRTemporary temp(this);
4431 GPRTemporary hash(this);
4432 GPRTemporary structureID(this);
4433 GPRTemporary result(this);
4434
4435 Optional<SpeculateCellOperand> keyAsCell;
4436 Optional<JSValueOperand> keyAsValue;
4437 GPRReg keyGPR;
4438 if (node->child2().useKind() == UntypedUse) {
4439 keyAsValue.emplace(this, node->child2());
4440 keyGPR = keyAsValue->gpr();
4441 } else {
4442 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse);
4443 keyAsCell.emplace(this, node->child2());
4444 keyGPR = keyAsCell->gpr();
4445 }
4446
4447 GPRReg objectGPR = object.gpr();
4448 GPRReg implGPR = uniquedStringImpl.gpr();
4449 GPRReg tempGPR = temp.gpr();
4450 GPRReg hashGPR = hash.gpr();
4451 GPRReg structureIDGPR = structureID.gpr();
4452 GPRReg resultGPR = result.gpr();
4453
4454 speculateObject(node->child1());
4455
4456 MacroAssembler::JumpList slowPath;
4457 switch (node->child2().useKind()) {
4458 case SymbolUse: {
4459 speculateSymbol(node->child2(), keyGPR);
4460 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR);
4461 break;
4462 }
4463 case StringUse: {
4464 speculateString(node->child2(), keyGPR);
4465 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR);
4466 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
4467 slowPath.append(m_jit.branchTest32(
4468 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
4469 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
4470 break;
4471 }
4472 case UntypedUse: {
4473 slowPath.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
4474 auto isNotString = m_jit.branchIfNotString(keyGPR);
4475 m_jit.loadPtr(MacroAssembler::Address(keyGPR, JSString::offsetOfValue()), implGPR);
4476 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
4477 slowPath.append(m_jit.branchTest32(
4478 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
4479 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
4480 auto hasUniquedImpl = m_jit.jump();
4481
4482 isNotString.link(&m_jit);
4483 slowPath.append(m_jit.branchIfNotSymbol(keyGPR));
4484 m_jit.loadPtr(MacroAssembler::Address(keyGPR, Symbol::offsetOfSymbolImpl()), implGPR);
4485
4486 hasUniquedImpl.link(&m_jit);
4487 break;
4488 }
4489 default:
4490 RELEASE_ASSERT_NOT_REACHED();
4491 }
4492
4493 // Note that we don't test if the hash is zero here. AtomStringImpl's can't have a zero
4494 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only
4495 // ever load the result from the cache if the cache entry matches what we are querying for.
4496 // So we either get super lucky and use zero for the hash and somehow collide with the entity
4497 // we're looking for, or we realize we're comparing against another entity, and go to the
4498 // slow path anyways.
4499 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR);
4500 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR);
4501 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR);
4502 m_jit.add32(structureIDGPR, hashGPR);
4503 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR);
4504 if (hasOneBitSet(sizeof(HasOwnPropertyCache::Entry))) // is a power of 2
4505 m_jit.lshift32(TrustedImm32(getLSBSet(sizeof(HasOwnPropertyCache::Entry))), hashGPR);
4506 else
4507 m_jit.mul32(TrustedImm32(sizeof(HasOwnPropertyCache::Entry)), hashGPR, hashGPR);
4508 ASSERT(m_jit.vm()->hasOwnPropertyCache());
4509 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR);
4510 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual,
4511 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR));
4512 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR);
4513 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR);
4514 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR));
4515 auto done = m_jit.jump();
4516
4517 slowPath.link(&m_jit);
4518 silentSpillAllRegisters(resultGPR);
4519 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyGPR);
4520 silentFillAllRegisters();
4521 m_jit.exceptionCheck();
4522
4523 done.link(&m_jit);
4524 m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
4525 jsValueResult(resultGPR, node, DataFormatJSBoolean);
4526 break;
4527 }
4528
4529 case CountExecution:
4530 m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
4531 break;
4532
4533 case SuperSamplerBegin:
4534 m_jit.add32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4535 break;
4536
4537 case SuperSamplerEnd:
4538 m_jit.sub32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4539 break;
4540
4541 case ForceOSRExit: {
4542 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
4543 break;
4544 }
4545
4546 case InvalidationPoint:
4547 emitInvalidationPoint(node);
4548 break;
4549
4550 case CheckTraps:
4551 compileCheckTraps(node);
4552 break;
4553
4554 case Phantom:
4555 case Check:
4556 case CheckVarargs:
4557 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
4558 noResult(node);
4559 break;
4560
4561 case PhantomLocal:
4562 case LoopHint:
4563 // This is a no-op.
4564 noResult(node);
4565 break;
4566
4567 case Unreachable:
4568 unreachable(node);
4569 break;
4570
4571 case StoreBarrier:
4572 case FencedStoreBarrier: {
4573 compileStoreBarrier(node);
4574 break;
4575 }
4576
4577 case GetEnumerableLength: {
4578 compileGetEnumerableLength(node);
4579 break;
4580 }
4581 case HasGenericProperty: {
4582 compileHasGenericProperty(node);
4583 break;
4584 }
4585 case HasStructureProperty: {
4586 compileHasStructureProperty(node);
4587 break;
4588 }
4589 case HasIndexedProperty: {
4590 compileHasIndexedProperty(node);
4591 break;
4592 }
4593 case GetDirectPname: {
4594 compileGetDirectPname(node);
4595 break;
4596 }
4597 case GetPropertyEnumerator: {
4598 compileGetPropertyEnumerator(node);
4599 break;
4600 }
4601 case GetEnumeratorStructurePname:
4602 case GetEnumeratorGenericPname: {
4603 compileGetEnumeratorPname(node);
4604 break;
4605 }
4606 case ToIndexString: {
4607 compileToIndexString(node);
4608 break;
4609 }
4610 case ProfileType: {
4611 compileProfileType(node);
4612 break;
4613 }
4614 case ProfileControlFlow: {
4615 BasicBlockLocation* basicBlockLocation = node->basicBlockLocation();
4616 basicBlockLocation->emitExecuteCode(m_jit);
4617 noResult(node);
4618 break;
4619 }
4620
4621 case LogShadowChickenPrologue: {
4622 compileLogShadowChickenPrologue(node);
4623 break;
4624 }
4625
4626 case LogShadowChickenTail: {
4627 compileLogShadowChickenTail(node);
4628 break;
4629 }
4630
4631 case MaterializeNewObject:
4632 compileMaterializeNewObject(node);
4633 break;
4634
4635 case CallDOM:
4636 compileCallDOM(node);
4637 break;
4638
4639 case CallDOMGetter:
4640 compileCallDOMGetter(node);
4641 break;
4642
4643 case CheckSubClass:
4644 compileCheckSubClass(node);
4645 break;
4646
4647 case ExtractCatchLocal: {
4648 compileExtractCatchLocal(node);
4649 break;
4650 }
4651
4652 case ClearCatchLocals:
4653 compileClearCatchLocals(node);
4654 break;
4655
4656 case DataViewGetFloat:
4657 case DataViewGetInt: {
4658 SpeculateCellOperand dataView(this, node->child1());
4659 GPRReg dataViewGPR = dataView.gpr();
4660 speculateDataViewObject(node->child1(), dataViewGPR);
4661
4662 SpeculateInt32Operand index(this, node->child2());
4663 GPRReg indexGPR = index.gpr();
4664
4665 GPRTemporary temp1(this);
4666 GPRReg t1 = temp1.gpr();
4667 GPRTemporary temp2(this);
4668 GPRReg t2 = temp2.gpr();
4669
4670 Optional<SpeculateBooleanOperand> isLittleEndianOperand;
4671 if (node->child3())
4672 isLittleEndianOperand.emplace(this, node->child3());
4673 GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg;
4674
4675 DataViewData data = node->dataViewData();
4676
4677 m_jit.zeroExtend32ToPtr(indexGPR, t2);
4678 if (data.byteSize > 1)
4679 m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
4680 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
4681 speculationCheck(OutOfBounds, JSValueRegs(), node,
4682 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
4683
4684 m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2);
4685 cageTypedArrayStorage(dataViewGPR, t2);
4686
4687 m_jit.zeroExtend32ToPtr(indexGPR, t1);
4688 auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne);
4689
4690 if (node->op() == DataViewGetInt) {
4691 switch (data.byteSize) {
4692 case 1:
4693 if (data.isSigned)
4694 m_jit.load8SignedExtendTo32(baseIndex, t2);
4695 else
4696 m_jit.load8(baseIndex, t2);
4697 int32Result(t2, node);
4698 break;
4699 case 2: {
4700 auto emitLittleEndianLoad = [&] {
4701 if (data.isSigned)
4702 m_jit.load16SignedExtendTo32(baseIndex, t2);
4703 else
4704 m_jit.load16(baseIndex, t2);
4705 };
4706 auto emitBigEndianLoad = [&] {
4707 m_jit.load16(baseIndex, t2);
4708 m_jit.byteSwap16(t2);
4709 if (data.isSigned)
4710 m_jit.signExtend16To32(t2, t2);
4711 };
4712
4713 if (data.isLittleEndian == FalseTriState)
4714 emitBigEndianLoad();
4715 else if (data.isLittleEndian == TrueTriState)
4716 emitLittleEndianLoad();
4717 else {
4718 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4719 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4720 emitLittleEndianLoad();
4721 auto done = m_jit.jump();
4722 isBigEndian.link(&m_jit);
4723 emitBigEndianLoad();
4724 done.link(&m_jit);
4725 }
4726 int32Result(t2, node);
4727 break;
4728 }
4729 case 4: {
4730 m_jit.load32(baseIndex, t2);
4731
4732 if (data.isLittleEndian == FalseTriState)
4733 m_jit.byteSwap32(t2);
4734 else if (data.isLittleEndian == MixedTriState) {
4735 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4736 auto isLittleEndian = m_jit.branchTest32(MacroAssembler::NonZero, isLittleEndianGPR, TrustedImm32(1));
4737 m_jit.byteSwap32(t2);
4738 isLittleEndian.link(&m_jit);
4739 }
4740
4741 if (data.isSigned)
4742 int32Result(t2, node);
4743 else
4744 strictInt52Result(t2, node);
4745 break;
4746 }
4747 default:
4748 RELEASE_ASSERT_NOT_REACHED();
4749 }
4750 } else {
4751 FPRTemporary result(this);
4752 FPRReg resultFPR = result.fpr();
4753
4754 switch (data.byteSize) {
4755 case 4: {
4756 auto emitLittleEndianCode = [&] {
4757 m_jit.loadFloat(baseIndex, resultFPR);
4758 m_jit.convertFloatToDouble(resultFPR, resultFPR);
4759 };
4760
4761 auto emitBigEndianCode = [&] {
4762 m_jit.load32(baseIndex, t2);
4763 m_jit.byteSwap32(t2);
4764 m_jit.move32ToFloat(t2, resultFPR);
4765 m_jit.convertFloatToDouble(resultFPR, resultFPR);
4766 };
4767
4768 if (data.isLittleEndian == TrueTriState)
4769 emitLittleEndianCode();
4770 else if (data.isLittleEndian == FalseTriState)
4771 emitBigEndianCode();
4772 else {
4773 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4774 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4775 emitLittleEndianCode();
4776 auto done = m_jit.jump();
4777 isBigEndian.link(&m_jit);
4778 emitBigEndianCode();
4779 done.link(&m_jit);
4780 }
4781
4782 break;
4783 }
4784 case 8: {
4785 auto emitLittleEndianCode = [&] {
4786 m_jit.loadDouble(baseIndex, resultFPR);
4787 };
4788
4789 auto emitBigEndianCode = [&] {
4790 m_jit.load64(baseIndex, t2);
4791 m_jit.byteSwap64(t2);
4792 m_jit.move64ToDouble(t2, resultFPR);
4793 };
4794
4795 if (data.isLittleEndian == TrueTriState)
4796 emitLittleEndianCode();
4797 else if (data.isLittleEndian == FalseTriState)
4798 emitBigEndianCode();
4799 else {
4800 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4801 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4802 emitLittleEndianCode();
4803 auto done = m_jit.jump();
4804 isBigEndian.link(&m_jit);
4805 emitBigEndianCode();
4806 done.link(&m_jit);
4807 }
4808
4809 break;
4810 }
4811 default:
4812 RELEASE_ASSERT_NOT_REACHED();
4813 }
4814
4815 doubleResult(resultFPR, node);
4816 }
4817
4818 break;
4819 }
4820
4821 case DataViewSet: {
4822 SpeculateCellOperand dataView(this, m_graph.varArgChild(node, 0));
4823 GPRReg dataViewGPR = dataView.gpr();
4824 speculateDataViewObject(m_graph.varArgChild(node, 0), dataViewGPR);
4825
4826 SpeculateInt32Operand index(this, m_graph.varArgChild(node, 1));
4827 GPRReg indexGPR = index.gpr();
4828
4829 Optional<SpeculateStrictInt52Operand> int52Value;
4830 Optional<SpeculateDoubleOperand> doubleValue;
4831 Optional<SpeculateInt32Operand> int32Value;
4832 Optional<FPRTemporary> fprTemporary;
4833 GPRReg valueGPR = InvalidGPRReg;
4834 FPRReg valueFPR = InvalidFPRReg;
4835 FPRReg tempFPR = InvalidFPRReg;
4836
4837 DataViewData data = node->dataViewData();
4838
4839 Edge& valueEdge = m_graph.varArgChild(node, 2);
4840 switch (valueEdge.useKind()) {
4841 case Int32Use:
4842 int32Value.emplace(this, valueEdge);
4843 valueGPR = int32Value->gpr();
4844 break;
4845 case DoubleRepUse:
4846 doubleValue.emplace(this, valueEdge);
4847 valueFPR = doubleValue->fpr();
4848 if (data.byteSize == 4) {
4849 fprTemporary.emplace(this);
4850 tempFPR = fprTemporary->fpr();
4851 }
4852 break;
4853 case Int52RepUse:
4854 int52Value.emplace(this, valueEdge);
4855 valueGPR = int52Value->gpr();
4856 break;
4857 default:
4858 RELEASE_ASSERT_NOT_REACHED();
4859 }
4860
4861 GPRTemporary temp1(this);
4862 GPRReg t1 = temp1.gpr();
4863 GPRTemporary temp2(this);
4864 GPRReg t2 = temp2.gpr();
4865 GPRTemporary temp3(this);
4866 GPRReg t3 = temp3.gpr();
4867
4868 Optional<SpeculateBooleanOperand> isLittleEndianOperand;
4869 if (m_graph.varArgChild(node, 3))
4870 isLittleEndianOperand.emplace(this, m_graph.varArgChild(node, 3));
4871 GPRReg isLittleEndianGPR = isLittleEndianOperand ? isLittleEndianOperand->gpr() : InvalidGPRReg;
4872
4873 m_jit.zeroExtend32ToPtr(indexGPR, t2);
4874 if (data.byteSize > 1)
4875 m_jit.add64(TrustedImm32(data.byteSize - 1), t2);
4876 m_jit.load32(MacroAssembler::Address(dataViewGPR, JSArrayBufferView::offsetOfLength()), t1);
4877 speculationCheck(OutOfBounds, JSValueRegs(), node,
4878 m_jit.branch64(MacroAssembler::AboveOrEqual, t2, t1));
4879
4880 m_jit.loadPtr(JITCompiler::Address(dataViewGPR, JSArrayBufferView::offsetOfVector()), t2);
4881 cageTypedArrayStorage(dataViewGPR, t2);
4882
4883 m_jit.zeroExtend32ToPtr(indexGPR, t1);
4884 auto baseIndex = JITCompiler::BaseIndex(t2, t1, MacroAssembler::TimesOne);
4885
4886 if (data.isFloatingPoint) {
4887 RELEASE_ASSERT(valueFPR != InvalidFPRReg);
4888 if (data.byteSize == 4) {
4889 RELEASE_ASSERT(tempFPR != InvalidFPRReg);
4890 m_jit.convertDoubleToFloat(valueFPR, tempFPR);
4891
4892 auto emitLittleEndianCode = [&] {
4893 m_jit.storeFloat(tempFPR, baseIndex);
4894 };
4895
4896 auto emitBigEndianCode = [&] {
4897 m_jit.moveFloatTo32(tempFPR, t3);
4898 m_jit.byteSwap32(t3);
4899 m_jit.store32(t3, baseIndex);
4900 };
4901
4902 if (data.isLittleEndian == FalseTriState)
4903 emitBigEndianCode();
4904 else if (data.isLittleEndian == TrueTriState)
4905 emitLittleEndianCode();
4906 else {
4907 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4908 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4909 emitLittleEndianCode();
4910 auto done = m_jit.jump();
4911 isBigEndian.link(&m_jit);
4912 emitBigEndianCode();
4913 done.link(&m_jit);
4914 }
4915 } else {
4916 RELEASE_ASSERT(data.byteSize == 8);
4917 RELEASE_ASSERT(valueFPR != InvalidFPRReg);
4918
4919 auto emitLittleEndianCode = [&] {
4920 m_jit.storeDouble(valueFPR, baseIndex);
4921 };
4922 auto emitBigEndianCode = [&] {
4923 m_jit.moveDoubleTo64(valueFPR, t3);
4924 m_jit.byteSwap64(t3);
4925 m_jit.store64(t3, baseIndex);
4926 };
4927
4928 if (data.isLittleEndian == FalseTriState)
4929 emitBigEndianCode();
4930 else if (data.isLittleEndian == TrueTriState)
4931 emitLittleEndianCode();
4932 else {
4933 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4934 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4935 emitLittleEndianCode();
4936 auto done = m_jit.jump();
4937 isBigEndian.link(&m_jit);
4938 emitBigEndianCode();
4939 done.link(&m_jit);
4940 }
4941 }
4942 } else {
4943 switch (data.byteSize) {
4944 case 1:
4945 RELEASE_ASSERT(valueEdge.useKind() == Int32Use);
4946 RELEASE_ASSERT(valueGPR != InvalidGPRReg);
4947 m_jit.store8(valueGPR, baseIndex);
4948 break;
4949 case 2: {
4950 RELEASE_ASSERT(valueEdge.useKind() == Int32Use);
4951 RELEASE_ASSERT(valueGPR != InvalidGPRReg);
4952
4953 auto emitLittleEndianCode = [&] {
4954 m_jit.store16(valueGPR, baseIndex);
4955 };
4956 auto emitBigEndianCode = [&] {
4957 m_jit.move(valueGPR, t3);
4958 m_jit.byteSwap16(t3);
4959 m_jit.store16(t3, baseIndex);
4960 };
4961
4962 if (data.isLittleEndian == FalseTriState)
4963 emitBigEndianCode();
4964 else if (data.isLittleEndian == TrueTriState)
4965 emitLittleEndianCode();
4966 else {
4967 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4968 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4969 emitLittleEndianCode();
4970 auto done = m_jit.jump();
4971 isBigEndian.link(&m_jit);
4972 emitBigEndianCode();
4973 done.link(&m_jit);
4974 }
4975 break;
4976 }
4977 case 4: {
4978 RELEASE_ASSERT(valueEdge.useKind() == Int32Use || valueEdge.useKind() == Int52RepUse);
4979
4980 auto emitLittleEndianCode = [&] {
4981 m_jit.store32(valueGPR, baseIndex);
4982 };
4983
4984 auto emitBigEndianCode = [&] {
4985 m_jit.zeroExtend32ToPtr(valueGPR, t3);
4986 m_jit.byteSwap32(t3);
4987 m_jit.store32(t3, baseIndex);
4988 };
4989
4990 if (data.isLittleEndian == FalseTriState)
4991 emitBigEndianCode();
4992 else if (data.isLittleEndian == TrueTriState)
4993 emitLittleEndianCode();
4994 else {
4995 RELEASE_ASSERT(isLittleEndianGPR != InvalidGPRReg);
4996 auto isBigEndian = m_jit.branchTest32(MacroAssembler::Zero, isLittleEndianGPR, TrustedImm32(1));
4997 emitLittleEndianCode();
4998 auto done = m_jit.jump();
4999 isBigEndian.link(&m_jit);
5000 emitBigEndianCode();
5001 done.link(&m_jit);
5002 }
5003
5004 break;
5005 }
5006 default:
5007 RELEASE_ASSERT_NOT_REACHED();
5008 }
5009 }
5010
5011 noResult(node);
5012 break;
5013 }
5014
5015#if ENABLE(FTL_JIT)
5016 case CheckTierUpInLoop: {
5017 MacroAssembler::Jump callTierUp = m_jit.branchAdd32(
5018 MacroAssembler::PositiveOrZero,
5019 TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
5020 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5021
5022 MacroAssembler::Label toNextOperation = m_jit.label();
5023
5024 Vector<SilentRegisterSavePlan> savePlans;
5025 silentSpillAllRegistersImpl(false, savePlans, InvalidGPRReg);
5026 unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex();
5027
5028 addSlowPathGeneratorLambda([=]() {
5029 callTierUp.link(&m_jit);
5030
5031 silentSpill(savePlans);
5032 callOperation(triggerTierUpNowInLoop, TrustedImm32(bytecodeIndex));
5033 silentFill(savePlans);
5034
5035 m_jit.jump().linkTo(toNextOperation, &m_jit);
5036 });
5037 break;
5038 }
5039
5040 case CheckTierUpAtReturn: {
5041 MacroAssembler::Jump done = m_jit.branchAdd32(
5042 MacroAssembler::Signed,
5043 TrustedImm32(Options::ftlTierUpCounterIncrementForReturn()),
5044 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5045
5046 silentSpillAllRegisters(InvalidGPRReg);
5047 callOperation(triggerTierUpNow);
5048 silentFillAllRegisters();
5049
5050 done.link(&m_jit);
5051 break;
5052 }
5053
5054 case CheckTierUpAndOSREnter: {
5055 ASSERT(!node->origin.semantic.inlineCallFrame());
5056
5057 GPRTemporary temp(this);
5058 GPRReg tempGPR = temp.gpr();
5059
5060 unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex();
5061 auto triggerIterator = m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex);
5062 DFG_ASSERT(m_jit.graph(), node, triggerIterator != m_jit.jitCode()->tierUpEntryTriggers.end());
5063 JITCode::TriggerReason* forceEntryTrigger = &(m_jit.jitCode()->tierUpEntryTriggers.find(bytecodeIndex)->value);
5064 static_assert(!static_cast<uint8_t>(JITCode::TriggerReason::DontTrigger), "the JIT code assumes non-zero means 'enter'");
5065 static_assert(sizeof(JITCode::TriggerReason) == 1, "branchTest8 assumes this size");
5066
5067 MacroAssembler::Jump forceOSREntry = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(forceEntryTrigger));
5068 MacroAssembler::Jump overflowedCounter = m_jit.branchAdd32(
5069 MacroAssembler::PositiveOrZero,
5070 TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
5071 MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
5072 MacroAssembler::Label toNextOperation = m_jit.label();
5073
5074 Vector<SilentRegisterSavePlan> savePlans;
5075 silentSpillAllRegistersImpl(false, savePlans, tempGPR);
5076
5077 unsigned streamIndex = m_stream->size();
5078 m_jit.jitCode()->bytecodeIndexToStreamIndex.add(bytecodeIndex, streamIndex);
5079
5080 addSlowPathGeneratorLambda([=]() {
5081 forceOSREntry.link(&m_jit);
5082 overflowedCounter.link(&m_jit);
5083
5084 silentSpill(savePlans);
5085 callOperation(triggerOSREntryNow, tempGPR, TrustedImm32(bytecodeIndex));
5086
5087 if (savePlans.isEmpty())
5088 m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR).linkTo(toNextOperation, &m_jit);
5089 else {
5090 MacroAssembler::Jump osrEnter = m_jit.branchTestPtr(MacroAssembler::NonZero, tempGPR);
5091 silentFill(savePlans);
5092 m_jit.jump().linkTo(toNextOperation, &m_jit);
5093 osrEnter.link(&m_jit);
5094 }
5095 m_jit.emitRestoreCalleeSaves();
5096 m_jit.jump(tempGPR, GPRInfo::callFrameRegister);
5097 });
5098 break;
5099 }
5100
5101#else // ENABLE(FTL_JIT)
5102 case CheckTierUpInLoop:
5103 case CheckTierUpAtReturn:
5104 case CheckTierUpAndOSREnter:
5105 DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
5106 break;
5107#endif // ENABLE(FTL_JIT)
5108
5109 case FilterCallLinkStatus:
5110 case FilterGetByIdStatus:
5111 case FilterPutByIdStatus:
5112 case FilterInByIdStatus:
5113 m_interpreter.filterICStatus(node);
5114 noResult(node);
5115 break;
5116
5117 case LastNodeType:
5118 case EntrySwitch:
5119 case InitializeEntrypointArguments:
5120 case Phi:
5121 case Upsilon:
5122 case ExtractOSREntryLocal:
5123 case CheckInBounds:
5124 case ArithIMul:
5125 case MultiGetByOffset:
5126 case MultiPutByOffset:
5127 case FiatInt52:
5128 case CheckBadCell:
5129 case BottomValue:
5130 case PhantomNewObject:
5131 case PhantomNewFunction:
5132 case PhantomNewGeneratorFunction:
5133 case PhantomNewAsyncFunction:
5134 case PhantomNewAsyncGeneratorFunction:
5135 case PhantomCreateActivation:
5136 case PhantomNewRegexp:
5137 case GetMyArgumentByVal:
5138 case GetMyArgumentByValOutOfBounds:
5139 case GetVectorLength:
5140 case PutHint:
5141 case CheckStructureImmediate:
5142 case MaterializeCreateActivation:
5143 case PutStack:
5144 case KillStack:
5145 case GetStack:
5146 case PhantomCreateRest:
5147 case PhantomSpread:
5148 case PhantomNewArrayWithSpread:
5149 case PhantomNewArrayBuffer:
5150 case IdentityWithProfile:
5151 case CPUIntrinsic:
5152 DFG_CRASH(m_jit.graph(), node, "Unexpected node");
5153 break;
5154 }
5155
5156 if (!m_compileOkay)
5157 return;
5158
5159 if (node->hasResult() && node->mustGenerate())
5160 use(node);
5161}
5162
5163void SpeculativeJIT::moveTrueTo(GPRReg gpr)
5164{
5165 m_jit.move(TrustedImm32(ValueTrue), gpr);
5166}
5167
5168void SpeculativeJIT::moveFalseTo(GPRReg gpr)
5169{
5170 m_jit.move(TrustedImm32(ValueFalse), gpr);
5171}
5172
5173void SpeculativeJIT::blessBoolean(GPRReg gpr)
5174{
5175 m_jit.or32(TrustedImm32(ValueFalse), gpr);
5176}
5177
5178void SpeculativeJIT::convertAnyInt(Edge valueEdge, GPRReg resultGPR)
5179{
5180 JSValueOperand value(this, valueEdge, ManualOperandSpeculation);
5181 GPRReg valueGPR = value.gpr();
5182
5183 JITCompiler::Jump notInt32 = m_jit.branchIfNotInt32(valueGPR);
5184
5185 m_jit.signExtend32ToPtr(valueGPR, resultGPR);
5186 JITCompiler::Jump done = m_jit.jump();
5187
5188 notInt32.link(&m_jit);
5189 silentSpillAllRegisters(resultGPR);
5190 callOperation(operationConvertBoxedDoubleToInt52, resultGPR, valueGPR);
5191 silentFillAllRegisters();
5192
5193 DFG_TYPE_CHECK(
5194 JSValueRegs(valueGPR), valueEdge, SpecInt32Only | SpecAnyIntAsDouble,
5195 m_jit.branch64(
5196 JITCompiler::Equal, resultGPR,
5197 JITCompiler::TrustedImm64(JSValue::notInt52)));
5198 done.link(&m_jit);
5199}
5200
5201void SpeculativeJIT::speculateAnyInt(Edge edge)
5202{
5203 if (!needsTypeCheck(edge, SpecInt32Only | SpecAnyIntAsDouble))
5204 return;
5205
5206 GPRTemporary temp(this);
5207 convertAnyInt(edge, temp.gpr());
5208}
5209
5210void SpeculativeJIT::speculateInt32(Edge edge, JSValueRegs regs)
5211{
5212 DFG_TYPE_CHECK(regs, edge, SpecInt32Only, m_jit.branchIfNotInt32(regs));
5213}
5214
5215void SpeculativeJIT::speculateDoubleRepAnyInt(Edge edge)
5216{
5217 if (!needsTypeCheck(edge, SpecAnyIntAsDouble))
5218 return;
5219
5220 SpeculateDoubleOperand value(this, edge);
5221 FPRReg valueFPR = value.fpr();
5222
5223 flushRegisters();
5224 GPRFlushedCallResult result(this);
5225 GPRReg resultGPR = result.gpr();
5226 callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
5227
5228 DFG_TYPE_CHECK(
5229 JSValueRegs(), edge, SpecAnyIntAsDouble,
5230 m_jit.branch64(
5231 JITCompiler::Equal, resultGPR,
5232 JITCompiler::TrustedImm64(JSValue::notInt52)));
5233}
5234
5235void SpeculativeJIT::compileArithRandom(Node* node)
5236{
5237 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
5238 GPRTemporary temp1(this);
5239 GPRTemporary temp2(this);
5240 GPRTemporary temp3(this);
5241 FPRTemporary result(this);
5242 m_jit.emitRandomThunk(globalObject, temp1.gpr(), temp2.gpr(), temp3.gpr(), result.fpr());
5243 doubleResult(result.fpr(), node);
5244}
5245
5246#endif
5247
5248} } // namespace JSC::DFG
5249
5250#endif
5251