1/*
2 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Intel Corporation. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "DFGSpeculativeJIT.h"
29
30#if ENABLE(DFG_JIT)
31
32#include "ArrayPrototype.h"
33#include "CallFrameShuffler.h"
34#include "DFGAbstractInterpreterInlines.h"
35#include "DFGCallArrayAllocatorSlowPathGenerator.h"
36#include "DFGOperations.h"
37#include "DFGSlowPathGenerator.h"
38#include "DirectArguments.h"
39#include "GetterSetter.h"
40#include "HasOwnPropertyCache.h"
41#include "HashMapImpl.h"
42#include "JSLexicalEnvironment.h"
43#include "JSPropertyNameEnumerator.h"
44#include "ObjectPrototype.h"
45#include "JSCInlines.h"
46#include "SetupVarargsFrame.h"
47#include "SuperSampler.h"
48#include "Watchdog.h"
49
50namespace JSC { namespace DFG {
51
52#if USE(JSVALUE32_64)
53
54static_assert(SpecCellCheck == SpecCell, "This is strongly assumed in the 32-bit DFG backend.");
55
56bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr)
57{
58 // FIXME: For double we could fill with a FPR.
59 UNUSED_PARAM(fpr);
60
61 VirtualRegister virtualRegister = edge->virtualRegister();
62 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
63
64 switch (info.registerFormat()) {
65 case DataFormatNone: {
66
67 if (edge->hasConstant()) {
68 tagGPR = allocate();
69 payloadGPR = allocate();
70 JSValue value = edge->asJSValue();
71 m_jit.move(Imm32(value.tag()), tagGPR);
72 m_jit.move(Imm32(value.payload()), payloadGPR);
73 m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant);
74 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant);
75 info.fillJSValue(*m_stream, tagGPR, payloadGPR, DataFormatJS);
76 } else {
77 DataFormat spillFormat = info.spillFormat();
78 ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage);
79 tagGPR = allocate();
80 payloadGPR = allocate();
81 switch (spillFormat) {
82 case DataFormatInt32:
83 m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR);
84 spillFormat = DataFormatJSInt32; // This will be used as the new register format.
85 break;
86 case DataFormatCell:
87 m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR);
88 spillFormat = DataFormatJSCell; // This will be used as the new register format.
89 break;
90 case DataFormatBoolean:
91 m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR);
92 spillFormat = DataFormatJSBoolean; // This will be used as the new register format.
93 break;
94 default:
95 m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
96 break;
97 }
98 m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR);
99 m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
100 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
101 info.fillJSValue(*m_stream, tagGPR, payloadGPR, spillFormat == DataFormatJSDouble ? DataFormatJS : spillFormat);
102 }
103
104 return true;
105 }
106
107 case DataFormatInt32:
108 case DataFormatCell:
109 case DataFormatBoolean: {
110 GPRReg gpr = info.gpr();
111 // If the register has already been locked we need to take a copy.
112 if (m_gprs.isLocked(gpr)) {
113 payloadGPR = allocate();
114 m_jit.move(gpr, payloadGPR);
115 } else {
116 payloadGPR = gpr;
117 m_gprs.lock(gpr);
118 }
119 tagGPR = allocate();
120 int32_t tag = JSValue::EmptyValueTag;
121 DataFormat fillFormat = DataFormatJS;
122 switch (info.registerFormat()) {
123 case DataFormatInt32:
124 tag = JSValue::Int32Tag;
125 fillFormat = DataFormatJSInt32;
126 break;
127 case DataFormatCell:
128 tag = JSValue::CellTag;
129 fillFormat = DataFormatJSCell;
130 break;
131 case DataFormatBoolean:
132 tag = JSValue::BooleanTag;
133 fillFormat = DataFormatJSBoolean;
134 break;
135 default:
136 RELEASE_ASSERT_NOT_REACHED();
137 break;
138 }
139 m_jit.move(TrustedImm32(tag), tagGPR);
140 m_gprs.release(gpr);
141 m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
142 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
143 info.fillJSValue(*m_stream, tagGPR, payloadGPR, fillFormat);
144 return true;
145 }
146
147 case DataFormatJSDouble:
148 case DataFormatJS:
149 case DataFormatJSInt32:
150 case DataFormatJSCell:
151 case DataFormatJSBoolean: {
152 tagGPR = info.tagGPR();
153 payloadGPR = info.payloadGPR();
154 m_gprs.lock(tagGPR);
155 m_gprs.lock(payloadGPR);
156 return true;
157 }
158
159 case DataFormatStorage:
160 case DataFormatDouble:
161 // this type currently never occurs
162 RELEASE_ASSERT_NOT_REACHED();
163
164 default:
165 RELEASE_ASSERT_NOT_REACHED();
166 return true;
167 }
168}
169
170void SpeculativeJIT::cachedGetById(CodeOrigin origin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget , SpillRegistersMode mode, AccessType type)
171{
172 cachedGetById(origin, base.tagGPR(), base.payloadGPR(), result.tagGPR(), result.payloadGPR(), identifierNumber, slowPathTarget, mode, type);
173}
174
175void SpeculativeJIT::cachedGetById(
176 CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
177 unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode, AccessType type)
178{
179 // This is a hacky fix for when the register allocator decides to alias the base payload with the result tag. This only happens
180 // in the case of GetByIdFlush/GetByIdDirectFlush, which has a relatively expensive register allocation story already so we probably don't need to
181 // trip over one move instruction.
182 if (basePayloadGPR == resultTagGPR) {
183 RELEASE_ASSERT(basePayloadGPR != resultPayloadGPR);
184
185 if (baseTagGPROrNone == resultPayloadGPR) {
186 m_jit.swap(basePayloadGPR, baseTagGPROrNone);
187 baseTagGPROrNone = resultTagGPR;
188 } else
189 m_jit.move(basePayloadGPR, resultPayloadGPR);
190 basePayloadGPR = resultPayloadGPR;
191 }
192
193 RegisterSet usedRegisters = this->usedRegisters();
194 if (spillMode == DontSpill) {
195 // We've already flushed registers to the stack, we don't need to spill these.
196 usedRegisters.set(JSValueRegs(baseTagGPROrNone, basePayloadGPR), false);
197 usedRegisters.set(JSValueRegs(resultTagGPR, resultPayloadGPR), false);
198 }
199
200 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
201 JITGetByIdGenerator gen(
202 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
203 JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(resultTagGPR, resultPayloadGPR), type);
204
205 gen.generateFastPath(m_jit);
206
207 JITCompiler::JumpList slowCases;
208 if (slowPathTarget.isSet())
209 slowCases.append(slowPathTarget);
210 slowCases.append(gen.slowPathJump());
211
212 std::unique_ptr<SlowPathGenerator> slowPath;
213 if (baseTagGPROrNone == InvalidGPRReg) {
214 slowPath = slowPathCall(
215 slowCases, this, appropriateOptimizingGetByIdFunction(type),
216 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
217 CCallHelpers::CellValue(basePayloadGPR),
218 identifierUID(identifierNumber));
219 } else {
220 slowPath = slowPathCall(
221 slowCases, this, appropriateOptimizingGetByIdFunction(type),
222 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), JSValueRegs(baseTagGPROrNone, basePayloadGPR), identifierUID(identifierNumber));
223 }
224
225 m_jit.addGetById(gen, slowPath.get());
226 addSlowPathGenerator(WTFMove(slowPath));
227}
228
229void SpeculativeJIT::cachedGetByIdWithThis(
230 CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPR, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
231 unsigned identifierNumber, const JITCompiler::JumpList& slowPathTarget)
232{
233 RegisterSet usedRegisters = this->usedRegisters();
234
235 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
236 JITGetByIdWithThisGenerator gen(
237 m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
238 JSValueRegs(resultTagGPR, resultPayloadGPR), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), AccessType::GetWithThis);
239
240 gen.generateFastPath(m_jit);
241
242 JITCompiler::JumpList slowCases;
243 if (!slowPathTarget.empty())
244 slowCases.append(slowPathTarget);
245 slowCases.append(gen.slowPathJump());
246
247 std::unique_ptr<SlowPathGenerator> slowPath;
248 if (baseTagGPROrNone == InvalidGPRReg && thisTagGPR == InvalidGPRReg) {
249 slowPath = slowPathCall(
250 slowCases, this, operationGetByIdWithThisOptimize,
251 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
252 CCallHelpers::CellValue(basePayloadGPR),
253 CCallHelpers::CellValue(thisPayloadGPR),
254 identifierUID(identifierNumber));
255 } else {
256 ASSERT(baseTagGPROrNone != InvalidGPRReg);
257 ASSERT(thisTagGPR != InvalidGPRReg);
258
259 slowPath = slowPathCall(
260 slowCases, this, operationGetByIdWithThisOptimize,
261 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), identifierUID(identifierNumber));
262 }
263
264 m_jit.addGetByIdWithThis(gen, slowPath.get());
265 addSlowPathGenerator(WTFMove(slowPath));
266}
267
268void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
269{
270 JSValueOperand arg(this, operand, ManualOperandSpeculation);
271 GPRReg argTagGPR = arg.tagGPR();
272 GPRReg argPayloadGPR = arg.payloadGPR();
273
274 GPRTemporary resultPayload(this, Reuse, arg, PayloadWord);
275 GPRReg resultPayloadGPR = resultPayload.gpr();
276
277 JITCompiler::Jump notCell;
278 JITCompiler::Jump notMasqueradesAsUndefined;
279 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
280 if (!isKnownCell(operand.node()))
281 notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
282
283 m_jit.move(TrustedImm32(0), resultPayloadGPR);
284 notMasqueradesAsUndefined = m_jit.jump();
285 } else {
286 GPRTemporary localGlobalObject(this);
287 GPRTemporary remoteGlobalObject(this);
288
289 if (!isKnownCell(operand.node()))
290 notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
291
292 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
293 JITCompiler::NonZero,
294 JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()),
295 JITCompiler::TrustedImm32(MasqueradesAsUndefined));
296
297 m_jit.move(TrustedImm32(0), resultPayloadGPR);
298 notMasqueradesAsUndefined = m_jit.jump();
299
300 isMasqueradesAsUndefined.link(&m_jit);
301 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
302 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
303 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
304 m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultPayloadGPR);
305 m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
306 m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR);
307 }
308
309 if (!isKnownCell(operand.node())) {
310 JITCompiler::Jump done = m_jit.jump();
311
312 notCell.link(&m_jit);
313 // null or undefined?
314 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
315 m_jit.or32(TrustedImm32(1), argTagGPR, resultPayloadGPR);
316 m_jit.compare32(JITCompiler::Equal, resultPayloadGPR, TrustedImm32(JSValue::NullTag), resultPayloadGPR);
317
318 done.link(&m_jit);
319 }
320
321 notMasqueradesAsUndefined.link(&m_jit);
322
323 booleanResult(resultPayloadGPR, m_currentNode);
324}
325
326void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode)
327{
328 BasicBlock* taken = branchNode->branchData()->taken.block;
329 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
330
331 bool invert = false;
332 if (taken == nextBlock()) {
333 invert = !invert;
334 BasicBlock* tmp = taken;
335 taken = notTaken;
336 notTaken = tmp;
337 }
338
339 JSValueOperand arg(this, operand, ManualOperandSpeculation);
340 GPRReg argTagGPR = arg.tagGPR();
341 GPRReg argPayloadGPR = arg.payloadGPR();
342
343 GPRTemporary result(this, Reuse, arg, TagWord);
344 GPRReg resultGPR = result.gpr();
345
346 JITCompiler::Jump notCell;
347
348 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
349 if (!isKnownCell(operand.node()))
350 notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
351
352 jump(invert ? taken : notTaken, ForceJump);
353 } else {
354 GPRTemporary localGlobalObject(this);
355 GPRTemporary remoteGlobalObject(this);
356
357 if (!isKnownCell(operand.node()))
358 notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
359
360 branchTest8(JITCompiler::Zero,
361 JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()),
362 JITCompiler::TrustedImm32(MasqueradesAsUndefined),
363 invert ? taken : notTaken);
364
365 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
366 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
367 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
368 m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultGPR);
369 m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
370 branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
371 }
372
373 if (!isKnownCell(operand.node())) {
374 jump(notTaken, ForceJump);
375
376 notCell.link(&m_jit);
377 // null or undefined?
378 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
379 m_jit.or32(TrustedImm32(1), argTagGPR, resultGPR);
380 branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(JSValue::NullTag), taken);
381 }
382
383 jump(notTaken);
384}
385
386void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
387{
388 BasicBlock* taken = branchNode->branchData()->taken.block;
389 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
390
391 // The branch instruction will branch to the taken block.
392 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
393 if (taken == nextBlock()) {
394 invert = !invert;
395 BasicBlock* tmp = taken;
396 taken = notTaken;
397 notTaken = tmp;
398 }
399
400 JSValueOperand arg1(this, node->child1());
401 JSValueOperand arg2(this, node->child2());
402 GPRReg arg1PayloadGPR = arg1.payloadGPR();
403 GPRReg arg2PayloadGPR = arg2.payloadGPR();
404 JSValueRegs arg1Regs = arg1.jsValueRegs();
405 JSValueRegs arg2Regs = arg2.jsValueRegs();
406
407 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
408 GPRReg resultPayloadGPR = resultPayload.gpr();
409
410 arg1.use();
411 arg2.use();
412
413 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
414 // see if we get lucky: if the arguments are cells and they reference the same
415 // cell, then they must be strictly equal.
416 branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR, invert ? notTaken : taken);
417
418 silentSpillAllRegisters(resultPayloadGPR);
419 callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1PayloadGPR, arg2PayloadGPR);
420 m_jit.exceptionCheck();
421 silentFillAllRegisters();
422
423 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
424 } else {
425 // FIXME: Add fast paths for twoCells, number etc.
426
427 silentSpillAllRegisters(resultPayloadGPR);
428 callOperation(operationCompareStrictEq, resultPayloadGPR, arg1Regs, arg2Regs);
429 m_jit.exceptionCheck();
430 silentFillAllRegisters();
431
432 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
433 }
434
435 jump(notTaken);
436}
437
438void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
439{
440 JSValueOperand arg1(this, node->child1());
441 JSValueOperand arg2(this, node->child2());
442 GPRReg arg1PayloadGPR = arg1.payloadGPR();
443 GPRReg arg2PayloadGPR = arg2.payloadGPR();
444 JSValueRegs arg1Regs = arg1.jsValueRegs();
445 JSValueRegs arg2Regs = arg2.jsValueRegs();
446
447 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
448 GPRReg resultPayloadGPR = resultPayload.gpr();
449
450 arg1.use();
451 arg2.use();
452
453 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
454 // see if we get lucky: if the arguments are cells and they reference the same
455 // cell, then they must be strictly equal.
456 // FIXME: this should flush registers instead of silent spill/fill.
457 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR);
458
459 m_jit.move(JITCompiler::TrustedImm32(!invert), resultPayloadGPR);
460 JITCompiler::Jump done = m_jit.jump();
461
462 notEqualCase.link(&m_jit);
463
464 silentSpillAllRegisters(resultPayloadGPR);
465 callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1PayloadGPR, arg2PayloadGPR);
466 m_jit.exceptionCheck();
467 silentFillAllRegisters();
468
469 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
470
471 done.link(&m_jit);
472 } else {
473 // FIXME: Add fast paths.
474
475 silentSpillAllRegisters(resultPayloadGPR);
476 callOperation(operationCompareStrictEq, resultPayloadGPR, arg1Regs, arg2Regs);
477 silentFillAllRegisters();
478 m_jit.exceptionCheck();
479
480 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
481 }
482
483 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
484}
485
486void SpeculativeJIT::compileCompareEqPtr(Node* node)
487{
488 JSValueOperand operand(this, node->child1());
489 GPRTemporary result(this);
490 JSValueRegs regs = operand.jsValueRegs();
491 GPRReg resultGPR = result.gpr();
492 m_jit.boxBooleanPayload(false, resultGPR);
493 JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value());
494 m_jit.boxBooleanPayload(true, resultGPR);
495 notEqual.link(&m_jit);
496 blessedBooleanResult(resultGPR, node);
497}
498
499void SpeculativeJIT::emitCall(Node* node)
500{
501 CallLinkInfo::CallType callType;
502 bool isVarargs = false;
503 bool isForwardVarargs = false;
504 bool isTail = false;
505 bool isDirect = false;
506 bool isEmulatedTail = false;
507 switch (node->op()) {
508 case Call:
509 case CallEval:
510 callType = CallLinkInfo::Call;
511 break;
512 case TailCall:
513 callType = CallLinkInfo::TailCall;
514 isTail = true;
515 break;
516 case TailCallInlinedCaller:
517 callType = CallLinkInfo::Call;
518 isEmulatedTail = true;
519 break;
520 case Construct:
521 callType = CallLinkInfo::Construct;
522 break;
523 case CallVarargs:
524 callType = CallLinkInfo::CallVarargs;
525 isVarargs = true;
526 break;
527 case TailCallVarargs:
528 callType = CallLinkInfo::TailCallVarargs;
529 isVarargs = true;
530 isTail = true;
531 break;
532 case TailCallVarargsInlinedCaller:
533 callType = CallLinkInfo::CallVarargs;
534 isVarargs = true;
535 isEmulatedTail = true;
536 break;
537 case ConstructVarargs:
538 callType = CallLinkInfo::ConstructVarargs;
539 isVarargs = true;
540 break;
541 case CallForwardVarargs:
542 callType = CallLinkInfo::CallVarargs;
543 isForwardVarargs = true;
544 break;
545 case TailCallForwardVarargs:
546 callType = CallLinkInfo::TailCallVarargs;
547 isTail = true;
548 isForwardVarargs = true;
549 break;
550 case TailCallForwardVarargsInlinedCaller:
551 callType = CallLinkInfo::CallVarargs;
552 isEmulatedTail = true;
553 isForwardVarargs = true;
554 break;
555 case ConstructForwardVarargs:
556 callType = CallLinkInfo::ConstructVarargs;
557 isForwardVarargs = true;
558 break;
559 case DirectCall:
560 callType = CallLinkInfo::DirectCall;
561 isDirect = true;
562 break;
563 case DirectConstruct:
564 callType = CallLinkInfo::DirectConstruct;
565 isDirect = true;
566 break;
567 case DirectTailCall:
568 callType = CallLinkInfo::DirectTailCall;
569 isTail = true;
570 isDirect = true;
571 break;
572 case DirectTailCallInlinedCaller:
573 callType = CallLinkInfo::DirectCall;
574 isEmulatedTail = true;
575 isDirect = true;
576 break;
577 default:
578 DFG_CRASH(m_jit.graph(), node, "bad node type");
579 break;
580 }
581
582 Edge calleeEdge = m_jit.graph().child(node, 0);
583 GPRReg calleeTagGPR = InvalidGPRReg;
584 GPRReg calleePayloadGPR = InvalidGPRReg;
585 CallFrameShuffleData shuffleData;
586
587 ExecutableBase* executable = nullptr;
588 FunctionExecutable* functionExecutable = nullptr;
589 if (isDirect) {
590 executable = node->castOperand<ExecutableBase*>();
591 functionExecutable = jsDynamicCast<FunctionExecutable*>(*m_jit.vm(), executable);
592 }
593
594 unsigned numPassedArgs = 0;
595 unsigned numAllocatedArgs = 0;
596
597 // Gotta load the arguments somehow. Varargs is trickier.
598 if (isVarargs || isForwardVarargs) {
599 RELEASE_ASSERT(!isDirect);
600 CallVarargsData* data = node->callVarargsData();
601
602 int numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
603
604 if (isForwardVarargs) {
605 flushRegisters();
606 if (node->child3())
607 use(node->child3());
608
609 GPRReg scratchGPR1;
610 GPRReg scratchGPR2;
611 GPRReg scratchGPR3;
612
613 scratchGPR1 = JITCompiler::selectScratchGPR();
614 scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1);
615 scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2);
616
617 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
618 JITCompiler::JumpList slowCase;
619 InlineCallFrame* inlineCallFrame;
620 if (node->child3())
621 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame();
622 else
623 inlineCallFrame = node->origin.semantic.inlineCallFrame();
624 // emitSetupVarargsFrameFastCase modifies the stack pointer if it succeeds.
625 emitSetupVarargsFrameFastCase(*m_jit.vm(), m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
626 JITCompiler::Jump done = m_jit.jump();
627 slowCase.link(&m_jit);
628 callOperation(operationThrowStackOverflowForVarargs);
629 m_jit.exceptionCheck();
630 m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
631 done.link(&m_jit);
632 } else {
633 GPRReg argumentsPayloadGPR;
634 GPRReg argumentsTagGPR;
635 GPRReg scratchGPR1;
636 GPRReg scratchGPR2;
637 GPRReg scratchGPR3;
638
639 auto loadArgumentsGPR = [&] (GPRReg reservedGPR) {
640 if (reservedGPR != InvalidGPRReg)
641 lock(reservedGPR);
642 JSValueOperand arguments(this, node->child3());
643 argumentsTagGPR = arguments.tagGPR();
644 argumentsPayloadGPR = arguments.payloadGPR();
645 if (reservedGPR != InvalidGPRReg)
646 unlock(reservedGPR);
647 flushRegisters();
648
649 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, reservedGPR);
650 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, reservedGPR);
651 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, scratchGPR2, reservedGPR);
652 };
653
654 loadArgumentsGPR(InvalidGPRReg);
655
656 DFG_ASSERT(m_jit.graph(), node, isFlushed());
657
658 // Right now, arguments is in argumentsTagGPR/argumentsPayloadGPR and the register file is
659 // flushed.
660 callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, JSValueRegs(argumentsTagGPR, argumentsPayloadGPR), numUsedStackSlots, data->firstVarArgOffset);
661 m_jit.exceptionCheck();
662
663 // Now we have the argument count of the callee frame, but we've lost the arguments operand.
664 // Reconstruct the arguments operand while preserving the callee frame.
665 loadArgumentsGPR(GPRInfo::returnValueGPR);
666 m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);
667 emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);
668 m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);
669
670 callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, JSValueRegs(argumentsTagGPR, argumentsPayloadGPR), data->firstVarArgOffset, GPRInfo::returnValueGPR);
671 m_jit.exceptionCheck();
672 m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::returnValueGPR, JITCompiler::stackPointerRegister);
673 }
674
675 DFG_ASSERT(m_jit.graph(), node, isFlushed());
676
677 // We don't need the arguments array anymore.
678 if (isVarargs)
679 use(node->child3());
680
681 // Now set up the "this" argument.
682 JSValueOperand thisArgument(this, node->child2());
683 GPRReg thisArgumentTagGPR = thisArgument.tagGPR();
684 GPRReg thisArgumentPayloadGPR = thisArgument.payloadGPR();
685 thisArgument.use();
686
687 m_jit.store32(thisArgumentTagGPR, JITCompiler::calleeArgumentTagSlot(0));
688 m_jit.store32(thisArgumentPayloadGPR, JITCompiler::calleeArgumentPayloadSlot(0));
689 } else {
690 // The call instruction's first child is either the function (normal call) or the
691 // receiver (method call). subsequent children are the arguments.
692 numPassedArgs = node->numChildren() - 1;
693 numAllocatedArgs = numPassedArgs;
694
695 if (functionExecutable) {
696 // Allocate more args if this would let us avoid arity checks. This is throttled by
697 // CallLinkInfo's limit. It's probably good to throttle it - if the callee wants a
698 // ginormous amount of argument space then it's better for them to do it so that when we
699 // make calls to other things, we don't waste space.
700 unsigned desiredNumAllocatedArgs = static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
701 if (desiredNumAllocatedArgs <= Options::maximumDirectCallStackSize()) {
702 numAllocatedArgs = std::max(numAllocatedArgs, desiredNumAllocatedArgs);
703
704 // Whoever converts to DirectCall should do this adjustment. It's too late for us to
705 // do this adjustment now since we will have already emitted code that relied on the
706 // value of m_parameterSlots.
707 DFG_ASSERT(
708 m_jit.graph(), node,
709 Graph::parameterSlotsForArgCount(numAllocatedArgs)
710 <= m_jit.graph().m_parameterSlots);
711 }
712 }
713
714 if (isTail) {
715 JSValueOperand callee(this, calleeEdge);
716 calleeTagGPR = callee.tagGPR();
717 calleePayloadGPR = callee.payloadGPR();
718 if (!isDirect)
719 use(calleeEdge);
720
721 shuffleData.numLocals = m_jit.graph().frameRegisterCount();
722 shuffleData.callee = ValueRecovery::inPair(calleeTagGPR, calleePayloadGPR);
723 shuffleData.args.resize(numAllocatedArgs);
724 shuffleData.numPassedArgs = numPassedArgs;
725
726 for (unsigned i = 0; i < numPassedArgs; ++i) {
727 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
728 GenerationInfo& info = generationInfo(argEdge.node());
729 if (!isDirect)
730 use(argEdge);
731 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
732 }
733
734 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
735 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
736 } else {
737 m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), m_jit.calleeFramePayloadSlot(CallFrameSlot::argumentCount));
738
739 for (unsigned i = 0; i < numPassedArgs; i++) {
740 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
741 JSValueOperand arg(this, argEdge);
742 GPRReg argTagGPR = arg.tagGPR();
743 GPRReg argPayloadGPR = arg.payloadGPR();
744 use(argEdge);
745
746 m_jit.store32(argTagGPR, m_jit.calleeArgumentTagSlot(i));
747 m_jit.store32(argPayloadGPR, m_jit.calleeArgumentPayloadSlot(i));
748 }
749
750 for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
751 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
752 }
753 }
754
755 if (!isTail || isVarargs || isForwardVarargs) {
756 JSValueOperand callee(this, calleeEdge);
757 calleeTagGPR = callee.tagGPR();
758 calleePayloadGPR = callee.payloadGPR();
759 use(calleeEdge);
760 m_jit.store32(calleePayloadGPR, m_jit.calleeFramePayloadSlot(CallFrameSlot::callee));
761 m_jit.store32(calleeTagGPR, m_jit.calleeFrameTagSlot(CallFrameSlot::callee));
762
763 if (!isTail)
764 flushRegisters();
765 }
766
767 JITCompiler::DataLabelPtr targetToCheck;
768 JITCompiler::JumpList slowPath;
769
770 CodeOrigin staticOrigin = node->origin.semantic;
771 InlineCallFrame* staticInlineCallFrame = staticOrigin.inlineCallFrame();
772 ASSERT(!isTail || !staticInlineCallFrame || !staticInlineCallFrame->getCallerSkippingTailCalls());
773 ASSERT(!isEmulatedTail || (staticInlineCallFrame && staticInlineCallFrame->getCallerSkippingTailCalls()));
774 CodeOrigin dynamicOrigin =
775 isEmulatedTail ? *staticInlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
776 CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
777
778 CallLinkInfo* info = m_jit.codeBlock()->addCallLinkInfo();
779 info->setUpCall(callType, node->origin.semantic, calleePayloadGPR);
780
781 auto setResultAndResetStack = [&] () {
782 JSValueRegsFlushedCallResult result(this);
783 JSValueRegs resultRegs = result.regs();
784
785 m_jit.setupResults(resultRegs);
786
787 jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
788 // After the calls are done, we need to reestablish our stack
789 // pointer. We rely on this for varargs calls, calls with arity
790 // mismatch (the callframe is slided) and tail calls.
791 m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
792 };
793
794 if (node->op() == CallEval) {
795 // We want to call operationCallEval but we don't want to overwrite the parameter area in
796 // which we have created a prototypical eval call frame. This means that we have to
797 // subtract stack to make room for the call. Lucky for us, at this point we have the whole
798 // register file to ourselves.
799
800 m_jit.emitStoreCallSiteIndex(callSite);
801 m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
802 m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
803
804 // Now we need to make room for:
805 // - The caller frame and PC of a call to operationCallEval.
806 // - Potentially two arguments on the stack.
807 unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
808 requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
809 m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
810 m_jit.setupArguments<decltype(operationCallEval)>(GPRInfo::regT0);
811 prepareForExternalCall();
812 m_jit.appendCall(operationCallEval);
813 m_jit.exceptionCheck();
814 JITCompiler::Jump done = m_jit.branchIfNotEmpty(GPRInfo::returnValueGPR2);
815
816 // This is the part where we meant to make a normal call. Oops.
817 m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
818 m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(PayloadOffset), GPRInfo::regT0);
819 m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(TagOffset), GPRInfo::regT1);
820 m_jit.emitDumbVirtualCall(*m_jit.vm(), info);
821
822 done.link(&m_jit);
823 setResultAndResetStack();
824 return;
825 }
826
827 if (isDirect) {
828 info->setExecutableDuringCompilation(executable);
829 info->setMaxNumArguments(numAllocatedArgs);
830
831 if (isTail) {
832 RELEASE_ASSERT(node->op() == DirectTailCall);
833
834 JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
835 JITCompiler::Label mainPath = m_jit.label();
836
837 m_jit.emitStoreCallSiteIndex(callSite);
838
839 info->setFrameShuffleData(shuffleData);
840 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
841
842 JITCompiler::Call call = m_jit.nearTailCall();
843
844 JITCompiler::Label slowPath = m_jit.label();
845 patchableJump.m_jump.linkTo(slowPath, &m_jit);
846
847 silentSpillAllRegisters(InvalidGPRReg);
848 callOperation(operationLinkDirectCall, info, calleePayloadGPR);
849 silentFillAllRegisters();
850 m_jit.exceptionCheck();
851 m_jit.jump().linkTo(mainPath, &m_jit);
852
853 useChildren(node);
854
855 m_jit.addJSDirectTailCall(patchableJump, call, slowPath, info);
856 return;
857 }
858
859 JITCompiler::Label mainPath = m_jit.label();
860
861 m_jit.emitStoreCallSiteIndex(callSite);
862
863 JITCompiler::Call call = m_jit.nearCall();
864 JITCompiler::Jump done = m_jit.jump();
865
866 JITCompiler::Label slowPath = m_jit.label();
867 if (isX86())
868 m_jit.pop(JITCompiler::selectScratchGPR(calleePayloadGPR));
869
870 callOperation(operationLinkDirectCall, info, calleePayloadGPR);
871 m_jit.exceptionCheck();
872 m_jit.jump().linkTo(mainPath, &m_jit);
873
874 done.link(&m_jit);
875
876 setResultAndResetStack();
877
878 m_jit.addJSDirectCall(call, slowPath, info);
879 return;
880 }
881
882 m_jit.emitStoreCallSiteIndex(callSite);
883
884 slowPath.append(m_jit.branchIfNotCell(JSValueRegs(calleeTagGPR, calleePayloadGPR)));
885 slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
886
887 if (isTail) {
888 if (node->op() == TailCall) {
889 info->setFrameShuffleData(shuffleData);
890 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
891 } else {
892 m_jit.emitRestoreCalleeSaves();
893 m_jit.prepareForTailCallSlow();
894 }
895 }
896
897 JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
898
899 JITCompiler::Jump done = m_jit.jump();
900
901 slowPath.link(&m_jit);
902
903 if (node->op() == TailCall) {
904 CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
905 callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(
906 GPRInfo::regT1, GPRInfo::regT0));
907 callFrameShuffler.prepareForSlowPath();
908 } else {
909 // Callee payload needs to be in regT0, tag in regT1
910 if (calleeTagGPR == GPRInfo::regT0) {
911 if (calleePayloadGPR == GPRInfo::regT1)
912 m_jit.swap(GPRInfo::regT1, GPRInfo::regT0);
913 else {
914 m_jit.move(calleeTagGPR, GPRInfo::regT1);
915 m_jit.move(calleePayloadGPR, GPRInfo::regT0);
916 }
917 } else {
918 m_jit.move(calleePayloadGPR, GPRInfo::regT0);
919 m_jit.move(calleeTagGPR, GPRInfo::regT1);
920 }
921
922 if (isTail)
923 m_jit.emitRestoreCalleeSaves();
924 }
925
926 m_jit.move(TrustedImmPtr(info), GPRInfo::regT2);
927 JITCompiler::Call slowCall = m_jit.nearCall();
928
929 done.link(&m_jit);
930
931 if (isTail)
932 m_jit.abortWithReason(JITDidReturnFromTailCall);
933 else
934 setResultAndResetStack();
935
936 m_jit.addJSCall(fastCall, slowCall, targetToCheck, info);
937}
938
939template<bool strict>
940GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
941{
942 AbstractValue& value = m_state.forNode(edge);
943 SpeculatedType type = value.m_type;
944 ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
945
946 m_interpreter.filter(value, SpecInt32Only);
947 if (value.isClear()) {
948 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
949 returnFormat = DataFormatInt32;
950 return allocate();
951 }
952
953 VirtualRegister virtualRegister = edge->virtualRegister();
954 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
955
956 switch (info.registerFormat()) {
957 case DataFormatNone: {
958 if (edge->hasConstant()) {
959 ASSERT(edge->isInt32Constant());
960 GPRReg gpr = allocate();
961 m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
962 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
963 info.fillInt32(*m_stream, gpr);
964 returnFormat = DataFormatInt32;
965 return gpr;
966 }
967
968 DataFormat spillFormat = info.spillFormat();
969
970 ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
971
972 // If we know this was spilled as an integer we can fill without checking.
973 if (type & ~SpecInt32Only)
974 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
975
976 GPRReg gpr = allocate();
977 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
978 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
979 info.fillInt32(*m_stream, gpr);
980 returnFormat = DataFormatInt32;
981 return gpr;
982 }
983
984 case DataFormatJSInt32:
985 case DataFormatJS: {
986 // Check the value is an integer.
987 GPRReg tagGPR = info.tagGPR();
988 GPRReg payloadGPR = info.payloadGPR();
989 m_gprs.lock(tagGPR);
990 m_gprs.lock(payloadGPR);
991 if (type & ~SpecInt32Only)
992 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branchIfNotInt32(tagGPR));
993 m_gprs.unlock(tagGPR);
994 m_gprs.release(tagGPR);
995 m_gprs.release(payloadGPR);
996 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger);
997 info.fillInt32(*m_stream, payloadGPR);
998 // If !strict we're done, return.
999 returnFormat = DataFormatInt32;
1000 return payloadGPR;
1001 }
1002
1003 case DataFormatInt32: {
1004 GPRReg gpr = info.gpr();
1005 m_gprs.lock(gpr);
1006 returnFormat = DataFormatInt32;
1007 return gpr;
1008 }
1009
1010 case DataFormatCell:
1011 case DataFormatBoolean:
1012 case DataFormatJSDouble:
1013 case DataFormatJSCell:
1014 case DataFormatJSBoolean:
1015 case DataFormatDouble:
1016 case DataFormatStorage:
1017 default:
1018 RELEASE_ASSERT_NOT_REACHED();
1019 return InvalidGPRReg;
1020 }
1021}
1022
1023GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1024{
1025 return fillSpeculateInt32Internal<false>(edge, returnFormat);
1026}
1027
1028GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1029{
1030 DataFormat mustBeDataFormatInt32;
1031 GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1032 ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
1033 return result;
1034}
1035
1036FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1037{
1038 ASSERT(isDouble(edge.useKind()));
1039 ASSERT(edge->hasDoubleResult());
1040 VirtualRegister virtualRegister = edge->virtualRegister();
1041 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1042
1043 if (info.registerFormat() == DataFormatNone) {
1044
1045 if (edge->hasConstant()) {
1046 RELEASE_ASSERT(edge->isNumberConstant());
1047 FPRReg fpr = fprAllocate();
1048 m_jit.loadDouble(TrustedImmPtr(m_jit.addressOfDoubleConstant(edge.node())), fpr);
1049 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
1050 info.fillDouble(*m_stream, fpr);
1051 return fpr;
1052 }
1053
1054 RELEASE_ASSERT(info.spillFormat() == DataFormatDouble);
1055 FPRReg fpr = fprAllocate();
1056 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1057 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
1058 info.fillDouble(*m_stream, fpr);
1059 return fpr;
1060 }
1061
1062 RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
1063 FPRReg fpr = info.fpr();
1064 m_fprs.lock(fpr);
1065 return fpr;
1066}
1067
1068GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1069{
1070 AbstractValue& value = m_state.forNode(edge);
1071 SpeculatedType type = value.m_type;
1072 ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1073
1074 m_interpreter.filter(value, SpecCell);
1075 if (value.isClear()) {
1076 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1077 return allocate();
1078 }
1079
1080 VirtualRegister virtualRegister = edge->virtualRegister();
1081 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1082
1083 switch (info.registerFormat()) {
1084 case DataFormatNone: {
1085 if (edge->hasConstant()) {
1086 GPRReg gpr = allocate();
1087 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1088 m_jit.move(TrustedImmPtr(edge->constant()), gpr);
1089 info.fillCell(*m_stream, gpr);
1090 return gpr;
1091 }
1092
1093 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
1094 if (type & ~SpecCell) {
1095 speculationCheck(
1096 BadType,
1097 JSValueSource(JITCompiler::addressFor(virtualRegister)),
1098 edge,
1099 m_jit.branch32(
1100 MacroAssembler::NotEqual,
1101 JITCompiler::tagFor(virtualRegister),
1102 TrustedImm32(JSValue::CellTag)));
1103 }
1104 GPRReg gpr = allocate();
1105 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1106 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1107 info.fillCell(*m_stream, gpr);
1108 return gpr;
1109 }
1110
1111 case DataFormatCell: {
1112 GPRReg gpr = info.gpr();
1113 m_gprs.lock(gpr);
1114 return gpr;
1115 }
1116
1117 case DataFormatJSCell:
1118 case DataFormatJS: {
1119 GPRReg tagGPR = info.tagGPR();
1120 GPRReg payloadGPR = info.payloadGPR();
1121 m_gprs.lock(tagGPR);
1122 m_gprs.lock(payloadGPR);
1123 if (type & ~SpecCell) {
1124 speculationCheck(
1125 BadType, JSValueRegs(tagGPR, payloadGPR), edge,
1126 m_jit.branchIfNotCell(info.jsValueRegs()));
1127 }
1128 m_gprs.unlock(tagGPR);
1129 m_gprs.release(tagGPR);
1130 m_gprs.release(payloadGPR);
1131 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell);
1132 info.fillCell(*m_stream, payloadGPR);
1133 return payloadGPR;
1134 }
1135
1136 case DataFormatJSInt32:
1137 case DataFormatInt32:
1138 case DataFormatJSDouble:
1139 case DataFormatJSBoolean:
1140 case DataFormatBoolean:
1141 case DataFormatDouble:
1142 case DataFormatStorage:
1143 RELEASE_ASSERT_NOT_REACHED();
1144
1145 default:
1146 RELEASE_ASSERT_NOT_REACHED();
1147 return InvalidGPRReg;
1148 }
1149}
1150
1151GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1152{
1153 AbstractValue& value = m_state.forNode(edge);
1154 SpeculatedType type = value.m_type;
1155 ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1156
1157 m_interpreter.filter(value, SpecBoolean);
1158 if (value.isClear()) {
1159 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1160 return allocate();
1161 }
1162
1163 VirtualRegister virtualRegister = edge->virtualRegister();
1164 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1165
1166 switch (info.registerFormat()) {
1167 case DataFormatNone: {
1168 if (edge->hasConstant()) {
1169 JSValue jsValue = edge->asJSValue();
1170 GPRReg gpr = allocate();
1171 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1172 m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
1173 info.fillBoolean(*m_stream, gpr);
1174 return gpr;
1175 }
1176
1177 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
1178
1179 if (type & ~SpecBoolean)
1180 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1181
1182 GPRReg gpr = allocate();
1183 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1184 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1185 info.fillBoolean(*m_stream, gpr);
1186 return gpr;
1187 }
1188
1189 case DataFormatBoolean: {
1190 GPRReg gpr = info.gpr();
1191 m_gprs.lock(gpr);
1192 return gpr;
1193 }
1194
1195 case DataFormatJSBoolean:
1196 case DataFormatJS: {
1197 GPRReg tagGPR = info.tagGPR();
1198 GPRReg payloadGPR = info.payloadGPR();
1199 m_gprs.lock(tagGPR);
1200 m_gprs.lock(payloadGPR);
1201 if (type & ~SpecBoolean)
1202 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branchIfNotBoolean(tagGPR, InvalidGPRReg));
1203
1204 m_gprs.unlock(tagGPR);
1205 m_gprs.release(tagGPR);
1206 m_gprs.release(payloadGPR);
1207 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean);
1208 info.fillBoolean(*m_stream, payloadGPR);
1209 return payloadGPR;
1210 }
1211
1212 case DataFormatJSInt32:
1213 case DataFormatInt32:
1214 case DataFormatJSDouble:
1215 case DataFormatJSCell:
1216 case DataFormatCell:
1217 case DataFormatDouble:
1218 case DataFormatStorage:
1219 RELEASE_ASSERT_NOT_REACHED();
1220
1221 default:
1222 RELEASE_ASSERT_NOT_REACHED();
1223 return InvalidGPRReg;
1224 }
1225}
1226
1227void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1228{
1229 SpeculateCellOperand op1(this, objectChild);
1230 JSValueOperand op2(this, otherChild);
1231
1232 GPRReg op1GPR = op1.gpr();
1233 GPRReg op2GPR = op2.payloadGPR();
1234
1235 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1236
1237 GPRTemporary resultPayload(this, Reuse, op1);
1238 GPRReg resultPayloadGPR = resultPayload.gpr();
1239
1240 MacroAssembler::Jump op2CellJump = m_jit.branchIfCell(op2.jsValueRegs());
1241
1242 m_jit.move(TrustedImm32(0), resultPayloadGPR);
1243 MacroAssembler::Jump op2NotCellJump = m_jit.jump();
1244
1245 // At this point we know that we can perform a straight-forward equality comparison on pointer
1246 // values because we are doing strict equality.
1247 op2CellJump.link(&m_jit);
1248 m_jit.compare32(MacroAssembler::Equal, op1GPR, op2GPR, resultPayloadGPR);
1249
1250 op2NotCellJump.link(&m_jit);
1251 booleanResult(resultPayloadGPR, m_currentNode);
1252}
1253
1254void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1255{
1256 BasicBlock* taken = branchNode->branchData()->taken.block;
1257 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1258
1259 SpeculateCellOperand op1(this, objectChild);
1260 JSValueOperand op2(this, otherChild);
1261
1262 GPRReg op1GPR = op1.gpr();
1263 GPRReg op2GPR = op2.payloadGPR();
1264
1265 DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1266
1267 branch32(MacroAssembler::NotEqual, op2.tagGPR(), TrustedImm32(JSValue::CellTag), notTaken);
1268
1269 if (taken == nextBlock()) {
1270 branch32(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1271 jump(taken);
1272 } else {
1273 branch32(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1274 jump(notTaken);
1275 }
1276}
1277
1278void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1279{
1280 SpeculateCellOperand op1(this, leftChild);
1281 JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1282 GPRTemporary result(this);
1283
1284 GPRReg op1GPR = op1.gpr();
1285 GPRReg op2TagGPR = op2.tagGPR();
1286 GPRReg op2PayloadGPR = op2.payloadGPR();
1287 GPRReg resultGPR = result.gpr();
1288
1289 bool masqueradesAsUndefinedWatchpointValid =
1290 masqueradesAsUndefinedWatchpointIsStillValid();
1291
1292 if (masqueradesAsUndefinedWatchpointValid) {
1293 DFG_TYPE_CHECK(
1294 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1295 } else {
1296 DFG_TYPE_CHECK(
1297 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1298 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1299 m_jit.branchTest8(
1300 MacroAssembler::NonZero,
1301 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1302 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1303 }
1304
1305
1306 // It seems that most of the time when programs do a == b where b may be either null/undefined
1307 // or an object, b is usually an object. Balance the branches to make that case fast.
1308 MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(op2.jsValueRegs());
1309
1310 // We know that within this branch, rightChild must be a cell.
1311 if (masqueradesAsUndefinedWatchpointValid) {
1312 DFG_TYPE_CHECK(
1313 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2PayloadGPR));
1314 } else {
1315 DFG_TYPE_CHECK(
1316 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2PayloadGPR));
1317 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1318 m_jit.branchTest8(
1319 MacroAssembler::NonZero,
1320 MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()),
1321 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1322 }
1323
1324 // At this point we know that we can perform a straight-forward equality comparison on pointer
1325 // values because both left and right are pointers to objects that have no special equality
1326 // protocols.
1327 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR);
1328 MacroAssembler::Jump trueCase = m_jit.jump();
1329
1330 rightNotCell.link(&m_jit);
1331
1332 // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1333 // prove that it is either null or undefined.
1334 if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1335 m_jit.or32(TrustedImm32(1), op2TagGPR, resultGPR);
1336
1337 typeCheck(
1338 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1339 m_jit.branch32(
1340 MacroAssembler::NotEqual, resultGPR,
1341 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1342 }
1343
1344 falseCase.link(&m_jit);
1345 m_jit.move(TrustedImm32(0), resultGPR);
1346 MacroAssembler::Jump done = m_jit.jump();
1347 trueCase.link(&m_jit);
1348 m_jit.move(TrustedImm32(1), resultGPR);
1349 done.link(&m_jit);
1350
1351 booleanResult(resultGPR, m_currentNode);
1352}
1353
1354void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1355{
1356 BasicBlock* taken = branchNode->branchData()->taken.block;
1357 BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1358
1359 SpeculateCellOperand op1(this, leftChild);
1360 JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1361 GPRTemporary result(this);
1362
1363 GPRReg op1GPR = op1.gpr();
1364 GPRReg op2TagGPR = op2.tagGPR();
1365 GPRReg op2PayloadGPR = op2.payloadGPR();
1366 GPRReg resultGPR = result.gpr();
1367
1368 bool masqueradesAsUndefinedWatchpointValid =
1369 masqueradesAsUndefinedWatchpointIsStillValid();
1370
1371 if (masqueradesAsUndefinedWatchpointValid) {
1372 DFG_TYPE_CHECK(
1373 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1374 } else {
1375 DFG_TYPE_CHECK(
1376 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1377 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1378 m_jit.branchTest8(
1379 MacroAssembler::NonZero,
1380 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()),
1381 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1382 }
1383
1384 // It seems that most of the time when programs do a == b where b may be either null/undefined
1385 // or an object, b is usually an object. Balance the branches to make that case fast.
1386 MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(op2.jsValueRegs());
1387
1388 // We know that within this branch, rightChild must be a cell.
1389 if (masqueradesAsUndefinedWatchpointValid) {
1390 DFG_TYPE_CHECK(
1391 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1392 m_jit.branchIfNotObject(op2PayloadGPR));
1393 } else {
1394 DFG_TYPE_CHECK(
1395 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1396 m_jit.branchIfNotObject(op2PayloadGPR));
1397 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1398 m_jit.branchTest8(
1399 MacroAssembler::NonZero,
1400 MacroAssembler::Address(op2PayloadGPR, 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 branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken);
1408
1409 // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1410 // prove that it is either null or undefined.
1411 if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1412 rightNotCell.link(&m_jit);
1413 else {
1414 jump(notTaken, ForceJump);
1415
1416 rightNotCell.link(&m_jit);
1417 m_jit.or32(TrustedImm32(1), op2TagGPR, resultGPR);
1418
1419 typeCheck(
1420 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1421 m_jit.branch32(
1422 MacroAssembler::NotEqual, resultGPR,
1423 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1424 }
1425
1426 jump(notTaken);
1427}
1428
1429void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1430{
1431 SpeculateCellOperand symbol(this, symbolEdge);
1432 JSValueOperand untyped(this, untypedEdge);
1433
1434 GPRReg symbolGPR = symbol.gpr();
1435 GPRReg untypedGPR = untyped.payloadGPR();
1436
1437 speculateSymbol(symbolEdge, symbolGPR);
1438
1439 GPRTemporary resultPayload(this, Reuse, symbol);
1440 GPRReg resultPayloadGPR = resultPayload.gpr();
1441
1442 MacroAssembler::Jump untypedCellJump = m_jit.branchIfCell(untyped.jsValueRegs());
1443
1444 m_jit.move(TrustedImm32(0), resultPayloadGPR);
1445 MacroAssembler::Jump untypedNotCellJump = m_jit.jump();
1446
1447 // At this point we know that we can perform a straight-forward equality comparison on pointer
1448 // values because we are doing strict equality.
1449 untypedCellJump.link(&m_jit);
1450 m_jit.compare32(MacroAssembler::Equal, symbolGPR, untypedGPR, resultPayloadGPR);
1451
1452 untypedNotCellJump.link(&m_jit);
1453 booleanResult(resultPayloadGPR, node);
1454}
1455
1456void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1457{
1458 JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1459 GPRTemporary resultPayload(this);
1460 GPRReg valueTagGPR = value.tagGPR();
1461 GPRReg valuePayloadGPR = value.payloadGPR();
1462 GPRReg resultPayloadGPR = resultPayload.gpr();
1463 GPRTemporary structure;
1464 GPRReg structureGPR = InvalidGPRReg;
1465
1466 bool masqueradesAsUndefinedWatchpointValid =
1467 masqueradesAsUndefinedWatchpointIsStillValid();
1468
1469 if (!masqueradesAsUndefinedWatchpointValid) {
1470 // The masquerades as undefined case will use the structure register, so allocate it here.
1471 // Do this at the top of the function to avoid branching around a register allocation.
1472 GPRTemporary realStructure(this);
1473 structure.adopt(realStructure);
1474 structureGPR = structure.gpr();
1475 }
1476
1477 MacroAssembler::Jump notCell = m_jit.branchIfNotCell(value.jsValueRegs());
1478 if (masqueradesAsUndefinedWatchpointValid) {
1479 DFG_TYPE_CHECK(
1480 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1481 m_jit.branchIfNotObject(valuePayloadGPR));
1482 } else {
1483 DFG_TYPE_CHECK(
1484 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1485 m_jit.branchIfNotObject(valuePayloadGPR));
1486
1487 MacroAssembler::Jump isNotMasqueradesAsUndefined =
1488 m_jit.branchTest8(
1489 MacroAssembler::Zero,
1490 MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()),
1491 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1492
1493 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), structureGPR);
1494 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1495 m_jit.branchPtr(
1496 MacroAssembler::Equal,
1497 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()),
1498 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1499
1500 isNotMasqueradesAsUndefined.link(&m_jit);
1501 }
1502 m_jit.move(TrustedImm32(0), resultPayloadGPR);
1503 MacroAssembler::Jump done = m_jit.jump();
1504
1505 notCell.link(&m_jit);
1506
1507 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1508 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1509 m_jit.or32(TrustedImm32(1), valueTagGPR, resultPayloadGPR);
1510 typeCheck(
1511 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1512 m_jit.branch32(
1513 MacroAssembler::NotEqual,
1514 resultPayloadGPR,
1515 TrustedImm32(JSValue::NullTag)));
1516 }
1517 m_jit.move(TrustedImm32(1), resultPayloadGPR);
1518
1519 done.link(&m_jit);
1520
1521 booleanResult(resultPayloadGPR, m_currentNode);
1522}
1523
1524void SpeculativeJIT::compileLogicalNot(Node* node)
1525{
1526 switch (node->child1().useKind()) {
1527 case BooleanUse:
1528 case KnownBooleanUse: {
1529 SpeculateBooleanOperand value(this, node->child1());
1530 GPRTemporary result(this, Reuse, value);
1531 m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
1532 booleanResult(result.gpr(), node);
1533 return;
1534 }
1535
1536 case ObjectOrOtherUse: {
1537 compileObjectOrOtherLogicalNot(node->child1());
1538 return;
1539 }
1540
1541 case Int32Use: {
1542 SpeculateInt32Operand value(this, node->child1());
1543 GPRTemporary resultPayload(this, Reuse, value);
1544 m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr());
1545 booleanResult(resultPayload.gpr(), node);
1546 return;
1547 }
1548
1549 case DoubleRepUse: {
1550 SpeculateDoubleOperand value(this, node->child1());
1551 FPRTemporary scratch(this);
1552 GPRTemporary resultPayload(this);
1553 m_jit.move(TrustedImm32(0), resultPayload.gpr());
1554 MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1555 m_jit.move(TrustedImm32(1), resultPayload.gpr());
1556 nonZero.link(&m_jit);
1557 booleanResult(resultPayload.gpr(), node);
1558 return;
1559 }
1560
1561 case UntypedUse: {
1562 JSValueOperand arg1(this, node->child1());
1563 GPRTemporary result(this);
1564 GPRTemporary temp(this);
1565 FPRTemporary valueFPR(this);
1566 FPRTemporary tempFPR(this);
1567
1568 GPRReg resultGPR = result.gpr();
1569
1570 bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1571 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1572 bool negateResult = true;
1573 m_jit.emitConvertValueToBoolean(*m_jit.vm(), arg1.jsValueRegs(), resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1574 booleanResult(resultGPR, node);
1575 return;
1576 }
1577 case StringUse:
1578 return compileStringZeroLength(node);
1579
1580 case StringOrOtherUse:
1581 return compileLogicalNotStringOrOther(node);
1582
1583 default:
1584 RELEASE_ASSERT_NOT_REACHED();
1585 break;
1586 }
1587}
1588
1589void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1590{
1591 JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1592 GPRTemporary scratch(this);
1593 GPRReg valueTagGPR = value.tagGPR();
1594 GPRReg valuePayloadGPR = value.payloadGPR();
1595 GPRReg scratchGPR = scratch.gpr();
1596
1597 MacroAssembler::Jump notCell = m_jit.branchIfNotCell(value.jsValueRegs());
1598 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1599 DFG_TYPE_CHECK(
1600 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1601 m_jit.branchIfNotObject(valuePayloadGPR));
1602 } else {
1603 DFG_TYPE_CHECK(
1604 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1605 m_jit.branchIfNotObject(valuePayloadGPR));
1606
1607 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1608 JITCompiler::Zero,
1609 MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()),
1610 TrustedImm32(MasqueradesAsUndefined));
1611
1612 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), scratchGPR);
1613 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1614 m_jit.branchPtr(
1615 MacroAssembler::Equal,
1616 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()),
1617 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1618
1619 isNotMasqueradesAsUndefined.link(&m_jit);
1620 }
1621 jump(taken, ForceJump);
1622
1623 notCell.link(&m_jit);
1624
1625 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1626 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1627 m_jit.or32(TrustedImm32(1), valueTagGPR, scratchGPR);
1628 typeCheck(
1629 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1630 m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
1631 }
1632
1633 jump(notTaken);
1634
1635 noResult(m_currentNode);
1636}
1637
1638void SpeculativeJIT::emitBranch(Node* node)
1639{
1640 BasicBlock* taken = node->branchData()->taken.block;
1641 BasicBlock* notTaken = node->branchData()->notTaken.block;
1642
1643 switch (node->child1().useKind()) {
1644 case BooleanUse:
1645 case KnownBooleanUse: {
1646 SpeculateBooleanOperand value(this, node->child1());
1647 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1648
1649 if (taken == nextBlock()) {
1650 condition = MacroAssembler::Zero;
1651 BasicBlock* tmp = taken;
1652 taken = notTaken;
1653 notTaken = tmp;
1654 }
1655
1656 branchTest32(condition, value.gpr(), TrustedImm32(1), taken);
1657 jump(notTaken);
1658
1659 noResult(node);
1660 return;
1661 }
1662
1663 case ObjectOrOtherUse: {
1664 emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1665 return;
1666 }
1667
1668 case StringUse: {
1669 emitStringBranch(node->child1(), taken, notTaken);
1670 return;
1671 }
1672
1673 case StringOrOtherUse: {
1674 emitStringOrOtherBranch(node->child1(), taken, notTaken);
1675 return;
1676 }
1677
1678 case DoubleRepUse:
1679 case Int32Use: {
1680 if (node->child1().useKind() == Int32Use) {
1681 bool invert = false;
1682
1683 if (taken == nextBlock()) {
1684 invert = true;
1685 BasicBlock* tmp = taken;
1686 taken = notTaken;
1687 notTaken = tmp;
1688 }
1689
1690 SpeculateInt32Operand value(this, node->child1());
1691 branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1692 } else {
1693 SpeculateDoubleOperand value(this, node->child1());
1694 FPRTemporary scratch(this);
1695 branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1696 }
1697
1698 jump(notTaken);
1699
1700 noResult(node);
1701 return;
1702 }
1703
1704 case UntypedUse: {
1705 JSValueOperand value(this, node->child1());
1706 FPRTemporary valueFPR(this);
1707 FPRTemporary tempFPR(this);
1708 GPRTemporary result(this);
1709 GPRTemporary temp(this);
1710
1711 JSValueRegs valueRegs = value.jsValueRegs();
1712 GPRReg resultGPR = result.gpr();
1713
1714 use(node->child1());
1715
1716 bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1717 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1718 auto falsey = m_jit.branchIfFalsey(*m_jit.vm(), valueRegs, resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject);
1719 addBranch(falsey, notTaken);
1720 jump(taken, ForceJump);
1721
1722 noResult(node, UseChildrenCalledExplicitly);
1723 return;
1724 }
1725
1726 default:
1727 RELEASE_ASSERT_NOT_REACHED();
1728 break;
1729 }
1730}
1731
1732template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1733void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag)
1734{
1735 Edge child4 = m_jit.graph().varArgChild(node, 3);
1736
1737 ArrayMode arrayMode = node->arrayMode();
1738
1739 GPRReg baseReg = base.gpr();
1740 GPRReg propertyReg = property.gpr();
1741
1742 StorageOperand storage(this, child4);
1743 GPRReg storageReg = storage.gpr();
1744
1745 if (node->op() == PutByValAlias) {
1746 // Store the value to the array.
1747 GPRReg propertyReg = property.gpr();
1748 m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1749 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1750
1751 noResult(node);
1752 return;
1753 }
1754
1755 MacroAssembler::Jump slowCase;
1756
1757 if (arrayMode.isInBounds()) {
1758 speculationCheck(
1759 OutOfBounds, JSValueRegs(), 0,
1760 m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1761 } else {
1762 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1763
1764 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1765
1766 if (!arrayMode.isOutOfBounds())
1767 speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1768
1769 m_jit.add32(TrustedImm32(1), propertyReg);
1770 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1771 m_jit.sub32(TrustedImm32(1), propertyReg);
1772
1773 inBounds.link(&m_jit);
1774 }
1775
1776 m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1777 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1778
1779 base.use();
1780 property.use();
1781 value.use();
1782 storage.use();
1783
1784 if (arrayMode.isOutOfBounds()) {
1785 if (node->op() == PutByValDirect) {
1786 addSlowPathGenerator(slowPathCall(
1787 slowCase, this,
1788 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
1789 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
1790 } else {
1791 addSlowPathGenerator(slowPathCall(
1792 slowCase, this,
1793 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
1794 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
1795 }
1796 }
1797
1798 noResult(node, UseChildrenCalledExplicitly);
1799}
1800
1801void SpeculativeJIT::compile(Node* node)
1802{
1803 NodeType op = node->op();
1804
1805#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1806 m_jit.clearRegisterAllocationOffsets();
1807#endif
1808
1809 switch (op) {
1810 case JSConstant:
1811 case DoubleConstant:
1812 case PhantomDirectArguments:
1813 case PhantomClonedArguments:
1814 initConstantInfo(node);
1815 break;
1816
1817 case LazyJSConstant:
1818 compileLazyJSConstant(node);
1819 break;
1820
1821 case Identity: {
1822 compileIdentity(node);
1823 break;
1824 }
1825
1826 case GetLocal: {
1827 AbstractValue& value = m_state.operand(node->local());
1828
1829 // If the CFA is tracking this variable and it found that the variable
1830 // cannot have been assigned, then don't attempt to proceed.
1831 if (value.isClear()) {
1832 m_compileOkay = false;
1833 break;
1834 }
1835
1836 switch (node->variableAccessData()->flushFormat()) {
1837 case FlushedDouble: {
1838 FPRTemporary result(this);
1839 m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
1840 VirtualRegister virtualRegister = node->virtualRegister();
1841 m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
1842 generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
1843 break;
1844 }
1845
1846 case FlushedInt32: {
1847 GPRTemporary result(this);
1848 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1849
1850 // Like int32Result, but don't useChildren - our children are phi nodes,
1851 // and don't represent values within this dataflow with virtual registers.
1852 VirtualRegister virtualRegister = node->virtualRegister();
1853 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
1854 generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
1855 break;
1856 }
1857
1858 case FlushedCell: {
1859 GPRTemporary result(this);
1860 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1861
1862 // Like cellResult, but don't useChildren - our children are phi nodes,
1863 // and don't represent values within this dataflow with virtual registers.
1864 VirtualRegister virtualRegister = node->virtualRegister();
1865 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
1866 generationInfoFromVirtualRegister(virtualRegister).initCell(node, node->refCount(), result.gpr());
1867 break;
1868 }
1869
1870 case FlushedBoolean: {
1871 GPRTemporary result(this);
1872 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1873
1874 // Like booleanResult, but don't useChildren - our children are phi nodes,
1875 // and don't represent values within this dataflow with virtual registers.
1876 VirtualRegister virtualRegister = node->virtualRegister();
1877 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
1878 generationInfoFromVirtualRegister(virtualRegister).initBoolean(node, node->refCount(), result.gpr());
1879 break;
1880 }
1881
1882 case FlushedJSValue: {
1883 GPRTemporary result(this);
1884 GPRTemporary tag(this);
1885 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1886 m_jit.load32(JITCompiler::tagFor(node->machineLocal()), tag.gpr());
1887
1888 // Like jsValueResult, but don't useChildren - our children are phi nodes,
1889 // and don't represent values within this dataflow with virtual registers.
1890 VirtualRegister virtualRegister = node->virtualRegister();
1891 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1892 m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
1893
1894 generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS);
1895 break;
1896 }
1897
1898 default:
1899 RELEASE_ASSERT_NOT_REACHED();
1900 }
1901 break;
1902 }
1903
1904 case MovHint: {
1905 compileMovHint(m_currentNode);
1906 noResult(node);
1907 break;
1908 }
1909
1910 case ZombieHint: {
1911 recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
1912 noResult(node);
1913 break;
1914 }
1915
1916 case ExitOK: {
1917 noResult(node);
1918 break;
1919 }
1920
1921 case SetLocal: {
1922 switch (node->variableAccessData()->flushFormat()) {
1923 case FlushedDouble: {
1924 SpeculateDoubleOperand value(this, node->child1());
1925 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
1926 noResult(node);
1927 // Indicate that it's no longer necessary to retrieve the value of
1928 // this bytecode variable from registers or other locations in the stack,
1929 // but that it is stored as a double.
1930 recordSetLocal(DataFormatDouble);
1931 break;
1932 }
1933
1934 case FlushedInt32: {
1935 SpeculateInt32Operand value(this, node->child1());
1936 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1937 noResult(node);
1938 recordSetLocal(DataFormatInt32);
1939 break;
1940 }
1941
1942 case FlushedCell: {
1943 SpeculateCellOperand cell(this, node->child1());
1944 GPRReg cellGPR = cell.gpr();
1945 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->machineLocal()));
1946 noResult(node);
1947 recordSetLocal(DataFormatCell);
1948 break;
1949 }
1950
1951 case FlushedBoolean: {
1952 SpeculateBooleanOperand value(this, node->child1());
1953 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1954 noResult(node);
1955 recordSetLocal(DataFormatBoolean);
1956 break;
1957 }
1958
1959 case FlushedJSValue: {
1960 JSValueOperand value(this, node->child1());
1961 m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal()));
1962 m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal()));
1963 noResult(node);
1964 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1965 break;
1966 }
1967
1968 default:
1969 RELEASE_ASSERT_NOT_REACHED();
1970 break;
1971 }
1972 break;
1973 }
1974
1975 case SetArgument:
1976 // This is a no-op; it just marks the fact that the argument is being used.
1977 // But it may be profitable to use this as a hook to run speculation checks
1978 // on arguments, thereby allowing us to trivially eliminate such checks if
1979 // the argument is not used.
1980 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1981 break;
1982
1983 case ValueBitOr:
1984 case ValueBitAnd:
1985 case ValueBitXor:
1986 compileValueBitwiseOp(node);
1987 break;
1988
1989 case ArithBitAnd:
1990 case ArithBitOr:
1991 case ArithBitXor:
1992 compileBitwiseOp(node);
1993 break;
1994
1995 case ValueBitNot:
1996 compileValueBitNot(node);
1997 break;
1998
1999 case ArithBitNot:
2000 compileBitwiseNot(node);
2001 break;
2002
2003 case BitRShift:
2004 case BitLShift:
2005 case BitURShift:
2006 compileShiftOp(node);
2007 break;
2008
2009 case UInt32ToNumber: {
2010 compileUInt32ToNumber(node);
2011 break;
2012 }
2013
2014 case DoubleAsInt32: {
2015 compileDoubleAsInt32(node);
2016 break;
2017 }
2018
2019 case ValueToInt32: {
2020 compileValueToInt32(node);
2021 break;
2022 }
2023
2024 case DoubleRep: {
2025 compileDoubleRep(node);
2026 break;
2027 }
2028
2029 case ValueRep: {
2030 compileValueRep(node);
2031 break;
2032 }
2033
2034 case ValueNegate:
2035 compileValueNegate(node);
2036 break;
2037
2038 case ValueAdd:
2039 compileValueAdd(node);
2040 break;
2041
2042 case ValueSub:
2043 compileValueSub(node);
2044 break;
2045
2046 case StrCat: {
2047 compileStrCat(node);
2048 break;
2049 }
2050
2051 case ArithAdd:
2052 compileArithAdd(node);
2053 break;
2054
2055 case ArithClz32:
2056 compileArithClz32(node);
2057 break;
2058
2059 case MakeRope:
2060 compileMakeRope(node);
2061 break;
2062
2063 case ArithSub:
2064 compileArithSub(node);
2065 break;
2066
2067 case ArithNegate:
2068 compileArithNegate(node);
2069 break;
2070
2071 case ArithMul:
2072 compileArithMul(node);
2073 break;
2074
2075 case ValueMul:
2076 compileValueMul(node);
2077 break;
2078
2079 case ValueDiv: {
2080 compileValueDiv(node);
2081 break;
2082 }
2083
2084 case ArithDiv: {
2085 compileArithDiv(node);
2086 break;
2087 }
2088
2089 case ArithMod: {
2090 compileArithMod(node);
2091 break;
2092 }
2093
2094 case ArithPow: {
2095 compileArithPow(node);
2096 break;
2097 }
2098
2099 case ArithAbs:
2100 compileArithAbs(node);
2101 break;
2102
2103 case ArithMin:
2104 case ArithMax: {
2105 compileArithMinMax(node);
2106 break;
2107 }
2108
2109 case ArithSqrt:
2110 compileArithSqrt(node);
2111 break;
2112
2113 case ArithFRound:
2114 compileArithFRound(node);
2115 break;
2116
2117 case ArithRandom:
2118 compileArithRandom(node);
2119 break;
2120
2121 case ArithRound:
2122 case ArithFloor:
2123 case ArithCeil:
2124 case ArithTrunc:
2125 compileArithRounding(node);
2126 break;
2127
2128 case ArithUnary:
2129 compileArithUnary(node);
2130 break;
2131
2132 case LogicalNot:
2133 compileLogicalNot(node);
2134 break;
2135
2136 case CompareLess:
2137 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2138 return;
2139 break;
2140
2141 case CompareLessEq:
2142 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2143 return;
2144 break;
2145
2146 case CompareGreater:
2147 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2148 return;
2149 break;
2150
2151 case CompareGreaterEq:
2152 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2153 return;
2154 break;
2155
2156 case CompareBelow:
2157 compileCompareUnsigned(node, JITCompiler::Below);
2158 break;
2159
2160 case CompareBelowEq:
2161 compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2162 break;
2163
2164 case CompareEq:
2165 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2166 return;
2167 break;
2168
2169 case CompareStrictEq:
2170 if (compileStrictEq(node))
2171 return;
2172 break;
2173
2174 case CompareEqPtr:
2175 compileCompareEqPtr(node);
2176 break;
2177
2178 case SameValue:
2179 compileSameValue(node);
2180 break;
2181
2182 case StringCharCodeAt: {
2183 compileGetCharCodeAt(node);
2184 break;
2185 }
2186
2187 case StringCharAt: {
2188 // Relies on StringCharAt node having same basic layout as GetByVal
2189 compileGetByValOnString(node);
2190 break;
2191 }
2192
2193 case StringFromCharCode: {
2194 compileFromCharCode(node);
2195 break;
2196 }
2197
2198 case CheckArray: {
2199 checkArray(node);
2200 break;
2201 }
2202
2203 case Arrayify:
2204 case ArrayifyToStructure: {
2205 arrayify(node);
2206 break;
2207 }
2208
2209 case GetByVal: {
2210 switch (node->arrayMode().type()) {
2211 case Array::SelectUsingPredictions:
2212 case Array::ForceExit:
2213 RELEASE_ASSERT_NOT_REACHED();
2214#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2215 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2216#endif
2217 break;
2218 case Array::Undecided: {
2219 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2220 GPRTemporary resultTag(this, Reuse, index);
2221 GPRTemporary resultPayload(this);
2222
2223 GPRReg indexGPR = index.gpr();
2224 GPRReg resultTagGPR = resultTag.gpr();
2225 GPRReg resultPayloadGPR = resultPayload.gpr();
2226
2227 speculationCheck(OutOfBounds, JSValueRegs(), node,
2228 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2229
2230 use(m_graph.varArgChild(node, 0));
2231 index.use();
2232
2233 m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
2234 m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
2235 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
2236 break;
2237 }
2238 case Array::Generic: {
2239 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2240 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2241 compileGetByValForObjectWithString(node);
2242 break;
2243 }
2244
2245 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2246 compileGetByValForObjectWithSymbol(node);
2247 break;
2248 }
2249 }
2250
2251 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
2252 JSValueOperand property(this, m_graph.varArgChild(node, 1));
2253 GPRReg baseGPR = base.gpr();
2254 JSValueRegs propertyRegs = property.jsValueRegs();
2255
2256 flushRegisters();
2257 JSValueRegsFlushedCallResult result(this);
2258 JSValueRegs resultRegs = result.regs();
2259 callOperation(operationGetByValCell, resultRegs, baseGPR, propertyRegs);
2260 m_jit.exceptionCheck();
2261
2262 jsValueResult(resultRegs, node);
2263 break;
2264 }
2265 case Array::Int32:
2266 case Array::Contiguous: {
2267 if (node->arrayMode().isInBounds()) {
2268 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2269 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2270
2271 GPRReg propertyReg = property.gpr();
2272 GPRReg storageReg = storage.gpr();
2273
2274 if (!m_compileOkay)
2275 return;
2276
2277 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2278
2279 GPRTemporary resultPayload(this);
2280 if (node->arrayMode().type() == Array::Int32) {
2281 ASSERT(!node->arrayMode().isSaneChain());
2282
2283 speculationCheck(
2284 OutOfBounds, JSValueRegs(), 0,
2285 m_jit.branch32(
2286 MacroAssembler::Equal,
2287 MacroAssembler::BaseIndex(
2288 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2289 TrustedImm32(JSValue::EmptyValueTag)));
2290 m_jit.load32(
2291 MacroAssembler::BaseIndex(
2292 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2293 resultPayload.gpr());
2294 int32Result(resultPayload.gpr(), node);
2295 break;
2296 }
2297
2298 GPRTemporary resultTag(this);
2299 m_jit.load32(
2300 MacroAssembler::BaseIndex(
2301 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2302 resultTag.gpr());
2303 m_jit.load32(
2304 MacroAssembler::BaseIndex(
2305 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2306 resultPayload.gpr());
2307 if (node->arrayMode().isSaneChain()) {
2308 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr());
2309 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
2310 m_jit.move(TrustedImm32(0), resultPayload.gpr());
2311 notHole.link(&m_jit);
2312 } else {
2313 speculationCheck(
2314 LoadFromHole, JSValueRegs(), 0,
2315 m_jit.branchIfEmpty(resultTag.gpr()));
2316 }
2317 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2318 break;
2319 }
2320
2321 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2322 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2323 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2324
2325 GPRReg baseReg = base.gpr();
2326 GPRReg propertyReg = property.gpr();
2327 GPRReg storageReg = storage.gpr();
2328
2329 if (!m_compileOkay)
2330 return;
2331
2332 GPRTemporary resultTag(this);
2333 GPRTemporary resultPayload(this);
2334 GPRReg resultTagReg = resultTag.gpr();
2335 GPRReg resultPayloadReg = resultPayload.gpr();
2336
2337 MacroAssembler::JumpList slowCases;
2338
2339 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2340
2341 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2342 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2343 slowCases.append(m_jit.branchIfEmpty(resultTagReg));
2344
2345 addSlowPathGenerator(
2346 slowPathCall(
2347 slowCases, this, operationGetByValObjectInt,
2348 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2349
2350 jsValueResult(resultTagReg, resultPayloadReg, node);
2351 break;
2352 }
2353 case Array::Double: {
2354 if (node->arrayMode().isInBounds()) {
2355 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2356 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2357
2358 GPRReg propertyReg = property.gpr();
2359 GPRReg storageReg = storage.gpr();
2360
2361 if (!m_compileOkay)
2362 return;
2363
2364 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2365
2366 FPRTemporary result(this);
2367 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2368 if (!node->arrayMode().isSaneChain())
2369 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
2370 doubleResult(result.fpr(), node);
2371 break;
2372 }
2373
2374 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2375 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2376 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2377
2378 GPRReg baseReg = base.gpr();
2379 GPRReg propertyReg = property.gpr();
2380 GPRReg storageReg = storage.gpr();
2381
2382 if (!m_compileOkay)
2383 return;
2384
2385 GPRTemporary resultTag(this);
2386 GPRTemporary resultPayload(this);
2387 FPRTemporary temp(this);
2388 GPRReg resultTagReg = resultTag.gpr();
2389 GPRReg resultPayloadReg = resultPayload.gpr();
2390 FPRReg tempReg = temp.fpr();
2391
2392 MacroAssembler::JumpList slowCases;
2393
2394 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2395
2396 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2397 slowCases.append(m_jit.branchIfNaN(tempReg));
2398 boxDouble(tempReg, resultTagReg, resultPayloadReg);
2399
2400 addSlowPathGenerator(
2401 slowPathCall(
2402 slowCases, this, operationGetByValObjectInt,
2403 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2404
2405 jsValueResult(resultTagReg, resultPayloadReg, node);
2406 break;
2407 }
2408 case Array::ArrayStorage:
2409 case Array::SlowPutArrayStorage: {
2410 if (node->arrayMode().isInBounds()) {
2411 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2412 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2413 GPRReg propertyReg = property.gpr();
2414 GPRReg storageReg = storage.gpr();
2415
2416 if (!m_compileOkay)
2417 return;
2418
2419 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2420
2421 GPRTemporary resultTag(this);
2422 GPRTemporary resultPayload(this);
2423
2424 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2425 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr()));
2426 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2427
2428 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2429 break;
2430 }
2431
2432 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2433 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2434 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2435 GPRReg propertyReg = property.gpr();
2436 GPRReg storageReg = storage.gpr();
2437 GPRReg baseReg = base.gpr();
2438
2439 if (!m_compileOkay)
2440 return;
2441
2442 GPRTemporary resultTag(this);
2443 GPRTemporary resultPayload(this);
2444 GPRReg resultTagReg = resultTag.gpr();
2445 GPRReg resultPayloadReg = resultPayload.gpr();
2446
2447 JITCompiler::Jump outOfBounds = m_jit.branch32(
2448 MacroAssembler::AboveOrEqual, propertyReg,
2449 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2450
2451 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2452 JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr());
2453 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2454
2455 JITCompiler::JumpList slowCases;
2456 slowCases.append(outOfBounds);
2457 slowCases.append(hole);
2458 addSlowPathGenerator(
2459 slowPathCall(
2460 slowCases, this, operationGetByValObjectInt,
2461 JSValueRegs(resultTagReg, resultPayloadReg),
2462 baseReg, propertyReg));
2463
2464 jsValueResult(resultTagReg, resultPayloadReg, node);
2465 break;
2466 }
2467 case Array::String:
2468 compileGetByValOnString(node);
2469 break;
2470 case Array::DirectArguments:
2471 compileGetByValOnDirectArguments(node);
2472 break;
2473 case Array::ScopedArguments:
2474 compileGetByValOnScopedArguments(node);
2475 break;
2476 default: {
2477 TypedArrayType type = node->arrayMode().typedArrayType();
2478 if (isInt(type))
2479 compileGetByValOnIntTypedArray(node, type);
2480 else
2481 compileGetByValOnFloatTypedArray(node, type);
2482 } }
2483 break;
2484 }
2485
2486 case StringSlice: {
2487 compileStringSlice(node);
2488 break;
2489 }
2490
2491 case ToLowerCase: {
2492 compileToLowerCase(node);
2493 break;
2494 }
2495
2496 case NumberToStringWithRadix: {
2497 compileNumberToStringWithRadix(node);
2498 break;
2499 }
2500
2501 case NumberToStringWithValidRadixConstant: {
2502 compileNumberToStringWithValidRadixConstant(node);
2503 break;
2504 }
2505
2506 case GetByValWithThis: {
2507 compileGetByValWithThis(node);
2508 break;
2509 }
2510
2511 case PutByValDirect:
2512 case PutByVal:
2513 case PutByValAlias: {
2514 Edge child1 = m_jit.graph().varArgChild(node, 0);
2515 Edge child2 = m_jit.graph().varArgChild(node, 1);
2516 Edge child3 = m_jit.graph().varArgChild(node, 2);
2517 Edge child4 = m_jit.graph().varArgChild(node, 3);
2518
2519 ArrayMode arrayMode = node->arrayMode().modeForPut();
2520 bool alreadyHandled = false;
2521
2522 switch (arrayMode.type()) {
2523 case Array::SelectUsingPredictions:
2524 case Array::ForceExit:
2525 RELEASE_ASSERT_NOT_REACHED();
2526#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2527 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2528 alreadyHandled = true;
2529#endif
2530 break;
2531 case Array::Generic: {
2532 ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
2533
2534 if (child1.useKind() == CellUse) {
2535 if (child2.useKind() == StringUse) {
2536 compilePutByValForCellWithString(node, child1, child2, child3);
2537 alreadyHandled = true;
2538 break;
2539 }
2540
2541 if (child2.useKind() == SymbolUse) {
2542 compilePutByValForCellWithSymbol(node, child1, child2, child3);
2543 alreadyHandled = true;
2544 break;
2545 }
2546 }
2547
2548 SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2549 JSValueOperand property(this, child2);
2550 JSValueOperand value(this, child3);
2551 GPRReg baseGPR = base.gpr();
2552 JSValueRegs propertyRegs = property.jsValueRegs();
2553 JSValueRegs valueRegs = value.jsValueRegs();
2554
2555 flushRegisters();
2556 if (node->op() == PutByValDirect)
2557 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
2558 else
2559 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
2560 m_jit.exceptionCheck();
2561
2562 noResult(node);
2563 alreadyHandled = true;
2564 break;
2565 }
2566 default:
2567 break;
2568 }
2569
2570 if (alreadyHandled)
2571 break;
2572
2573 SpeculateCellOperand base(this, child1);
2574 SpeculateStrictInt32Operand property(this, child2);
2575
2576 GPRReg baseReg = base.gpr();
2577 GPRReg propertyReg = property.gpr();
2578
2579 switch (arrayMode.type()) {
2580 case Array::Int32: {
2581 speculateInt32(child3);
2582 FALLTHROUGH;
2583 }
2584 case Array::Contiguous: {
2585 JSValueOperand value(this, child3, ManualOperandSpeculation);
2586
2587 GPRReg valueTagReg = value.tagGPR();
2588 GPRReg valuePayloadReg = value.payloadGPR();
2589
2590 if (!m_compileOkay)
2591 return;
2592
2593 compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2594 break;
2595 }
2596 case Array::Double: {
2597 compileDoublePutByVal(node, base, property);
2598 break;
2599 }
2600 case Array::ArrayStorage:
2601 case Array::SlowPutArrayStorage: {
2602 JSValueOperand value(this, child3);
2603
2604 GPRReg valueTagReg = value.tagGPR();
2605 GPRReg valuePayloadReg = value.payloadGPR();
2606
2607 if (!m_compileOkay)
2608 return;
2609
2610 StorageOperand storage(this, child4);
2611 GPRReg storageReg = storage.gpr();
2612
2613 if (node->op() == PutByValAlias) {
2614 // Store the value to the array.
2615 GPRReg propertyReg = property.gpr();
2616 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2617 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2618
2619 noResult(node);
2620 break;
2621 }
2622
2623 MacroAssembler::JumpList slowCases;
2624
2625 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2626 if (!arrayMode.isOutOfBounds())
2627 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2628 else
2629 slowCases.append(beyondArrayBounds);
2630
2631 // Check if we're writing to a hole; if so increment m_numValuesInVector.
2632 if (arrayMode.isInBounds()) {
2633 speculationCheck(
2634 StoreToHole, JSValueRegs(), 0,
2635 m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
2636 } else {
2637 MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
2638 if (arrayMode.isSlowPut()) {
2639 // This is sort of strange. If we wanted to optimize this code path, we would invert
2640 // the above branch. But it's simply not worth it since this only happens if we're
2641 // already having a bad time.
2642 slowCases.append(m_jit.jump());
2643 } else {
2644 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2645
2646 // If we're writing to a hole we might be growing the array;
2647 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2648 m_jit.add32(TrustedImm32(1), propertyReg);
2649 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2650 m_jit.sub32(TrustedImm32(1), propertyReg);
2651
2652 lengthDoesNotNeedUpdate.link(&m_jit);
2653 }
2654 notHoleValue.link(&m_jit);
2655 }
2656
2657 // Store the value to the array.
2658 m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2659 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2660
2661 base.use();
2662 property.use();
2663 value.use();
2664 storage.use();
2665
2666 if (!slowCases.empty()) {
2667 if (node->op() == PutByValDirect) {
2668 addSlowPathGenerator(slowPathCall(
2669 slowCases, this,
2670 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2671 NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2672 } else {
2673 addSlowPathGenerator(slowPathCall(
2674 slowCases, this,
2675 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2676 NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2677 }
2678 }
2679
2680 noResult(node, UseChildrenCalledExplicitly);
2681 break;
2682 }
2683
2684 default: {
2685 TypedArrayType type = arrayMode.typedArrayType();
2686 if (isInt(type))
2687 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2688 else
2689 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2690 } }
2691 break;
2692 }
2693
2694 case PutByValWithThis: {
2695#if CPU(X86)
2696 // We don't have enough registers on X86 to do this
2697 // without setting up the call frame incrementally.
2698 unsigned index = 0;
2699 m_jit.poke(GPRInfo::callFrameRegister, index++);
2700
2701 {
2702 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2703 GPRReg baseTag = base.tagGPR();
2704 GPRReg basePayload = base.payloadGPR();
2705
2706 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2707 GPRReg thisValueTag = thisValue.tagGPR();
2708 GPRReg thisValuePayload = thisValue.payloadGPR();
2709
2710 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2711 GPRReg propertyTag = property.tagGPR();
2712 GPRReg propertyPayload = property.payloadGPR();
2713
2714 m_jit.poke(basePayload, index++);
2715 m_jit.poke(baseTag, index++);
2716
2717 m_jit.poke(thisValuePayload, index++);
2718 m_jit.poke(thisValueTag, index++);
2719
2720 m_jit.poke(propertyPayload, index++);
2721 m_jit.poke(propertyTag, index++);
2722
2723 flushRegisters();
2724 }
2725
2726 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2727 GPRReg valueTag = value.tagGPR();
2728 GPRReg valuePayload = value.payloadGPR();
2729 m_jit.poke(valuePayload, index++);
2730 m_jit.poke(valueTag, index++);
2731
2732 flushRegisters();
2733 appendCall(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis);
2734 m_jit.exceptionCheck();
2735#else
2736 static_assert(GPRInfo::numberOfRegisters >= 8, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
2737
2738 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2739 JSValueRegs baseRegs = base.jsValueRegs();
2740
2741 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2742 JSValueRegs thisRegs = thisValue.jsValueRegs();
2743
2744 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2745 JSValueRegs propertyRegs = property.jsValueRegs();
2746
2747 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2748 JSValueRegs valueRegs = value.jsValueRegs();
2749
2750 flushRegisters();
2751 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis,
2752 NoResult, baseRegs, thisRegs, propertyRegs, valueRegs);
2753 m_jit.exceptionCheck();
2754#endif // CPU(X86)
2755
2756 noResult(node);
2757 break;
2758 }
2759
2760 case RegExpExec: {
2761 compileRegExpExec(node);
2762 break;
2763 }
2764
2765 case RegExpExecNonGlobalOrSticky: {
2766 compileRegExpExecNonGlobalOrSticky(node);
2767 break;
2768 }
2769
2770 case RegExpMatchFastGlobal: {
2771 compileRegExpMatchFastGlobal(node);
2772 break;
2773 }
2774
2775 case RegExpTest: {
2776 compileRegExpTest(node);
2777 break;
2778 }
2779
2780 case RegExpMatchFast: {
2781 compileRegExpMatchFast(node);
2782 break;
2783 }
2784
2785 case StringReplace:
2786 case StringReplaceRegExp: {
2787 compileStringReplace(node);
2788 break;
2789 }
2790
2791 case GetRegExpObjectLastIndex: {
2792 compileGetRegExpObjectLastIndex(node);
2793 break;
2794 }
2795
2796 case SetRegExpObjectLastIndex: {
2797 compileSetRegExpObjectLastIndex(node);
2798 break;
2799 }
2800
2801 case RecordRegExpCachedResult: {
2802 compileRecordRegExpCachedResult(node);
2803 break;
2804 }
2805
2806 case ArrayPush: {
2807 compileArrayPush(node);
2808 break;
2809 }
2810
2811 case ArrayPop: {
2812 ASSERT(node->arrayMode().isJSArray());
2813
2814 SpeculateCellOperand base(this, node->child1());
2815 StorageOperand storage(this, node->child2());
2816 GPRTemporary valueTag(this);
2817 GPRTemporary valuePayload(this);
2818
2819 GPRReg baseGPR = base.gpr();
2820 GPRReg valueTagGPR = valueTag.gpr();
2821 GPRReg valuePayloadGPR = valuePayload.gpr();
2822 GPRReg storageGPR = storage.gpr();
2823
2824 switch (node->arrayMode().type()) {
2825 case Array::Int32:
2826 case Array::Contiguous: {
2827 m_jit.load32(
2828 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2829 MacroAssembler::Jump undefinedCase =
2830 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2831 m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2832 m_jit.store32(
2833 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2834 m_jit.load32(
2835 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2836 valueTagGPR);
2837 MacroAssembler::Jump slowCase = m_jit.branchIfEmpty(valueTagGPR);
2838 m_jit.store32(
2839 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
2840 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2841 m_jit.load32(
2842 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
2843 valuePayloadGPR);
2844
2845 addSlowPathGenerator(
2846 slowPathMove(
2847 undefinedCase, this,
2848 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2849 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2850 addSlowPathGenerator(
2851 slowPathCall(
2852 slowCase, this, operationArrayPopAndRecoverLength,
2853 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2854
2855 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2856 break;
2857 }
2858
2859 case Array::Double: {
2860 FPRTemporary temp(this);
2861 FPRReg tempFPR = temp.fpr();
2862
2863 m_jit.load32(
2864 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2865 MacroAssembler::Jump undefinedCase =
2866 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2867 m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2868 m_jit.store32(
2869 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2870 m_jit.loadDouble(
2871 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
2872 tempFPR);
2873 MacroAssembler::Jump slowCase = m_jit.branchIfNaN(tempFPR);
2874 JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
2875 m_jit.store32(
2876 MacroAssembler::TrustedImm32(nan.u.asBits.tag),
2877 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2878 m_jit.store32(
2879 MacroAssembler::TrustedImm32(nan.u.asBits.payload),
2880 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2881 boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
2882
2883 addSlowPathGenerator(
2884 slowPathMove(
2885 undefinedCase, this,
2886 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2887 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2888 addSlowPathGenerator(
2889 slowPathCall(
2890 slowCase, this, operationArrayPopAndRecoverLength,
2891 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2892
2893 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2894 break;
2895 }
2896
2897 case Array::ArrayStorage: {
2898 GPRTemporary storageLength(this);
2899 GPRReg storageLengthGPR = storageLength.gpr();
2900
2901 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2902
2903 JITCompiler::JumpList setUndefinedCases;
2904 setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
2905
2906 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2907
2908 MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2909
2910 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
2911 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
2912
2913 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2914
2915 setUndefinedCases.append(m_jit.branchIfEmpty(valueTagGPR));
2916
2917 m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2918
2919 m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2920
2921 addSlowPathGenerator(
2922 slowPathMove(
2923 setUndefinedCases, this,
2924 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2925 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2926
2927 addSlowPathGenerator(
2928 slowPathCall(
2929 slowCase, this, operationArrayPop,
2930 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2931
2932 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2933 break;
2934 }
2935
2936 default:
2937 CRASH();
2938 break;
2939 }
2940 break;
2941 }
2942
2943 case ArraySlice: {
2944 compileArraySlice(node);
2945 break;
2946 }
2947
2948 case ArrayIndexOf: {
2949 compileArrayIndexOf(node);
2950 break;
2951 }
2952
2953 case DFG::Jump: {
2954 jump(node->targetBlock());
2955 noResult(node);
2956 break;
2957 }
2958
2959 case Branch:
2960 emitBranch(node);
2961 break;
2962
2963 case Switch:
2964 emitSwitch(node);
2965 break;
2966
2967 case Return: {
2968 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
2969 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2970 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2971
2972 // Return the result in returnValueGPR.
2973 JSValueOperand op1(this, node->child1());
2974 op1.fill();
2975 if (op1.isDouble())
2976 boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
2977 else {
2978 if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
2979 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
2980 else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
2981 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2982 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2983 } else {
2984 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2985 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2986 }
2987 }
2988
2989 m_jit.emitRestoreCalleeSaves();
2990 m_jit.emitFunctionEpilogue();
2991 m_jit.ret();
2992
2993 noResult(node);
2994 break;
2995 }
2996
2997 case Throw: {
2998 compileThrow(node);
2999 break;
3000 }
3001
3002 case ThrowStaticError: {
3003 compileThrowStaticError(node);
3004 break;
3005 }
3006
3007 case BooleanToNumber: {
3008 switch (node->child1().useKind()) {
3009 case BooleanUse: {
3010 SpeculateBooleanOperand value(this, node->child1());
3011 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3012
3013 m_jit.move(value.gpr(), result.gpr());
3014
3015 int32Result(result.gpr(), node);
3016 break;
3017 }
3018
3019 case UntypedUse: {
3020 JSValueOperand value(this, node->child1());
3021
3022 if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3023 GPRTemporary result(this);
3024
3025 GPRReg valueGPR = value.payloadGPR();
3026 GPRReg resultGPR = result.gpr();
3027
3028 m_jit.move(valueGPR, resultGPR);
3029 int32Result(result.gpr(), node);
3030 break;
3031 }
3032
3033 GPRTemporary resultTag(this);
3034 GPRTemporary resultPayload(this);
3035
3036 GPRReg valueTagGPR = value.tagGPR();
3037 GPRReg valuePayloadGPR = value.payloadGPR();
3038 GPRReg resultTagGPR = resultTag.gpr();
3039 GPRReg resultPayloadGPR = resultPayload.gpr();
3040
3041 m_jit.move(valuePayloadGPR, resultPayloadGPR);
3042 JITCompiler::Jump isBoolean = m_jit.branchIfBoolean(valueTagGPR, InvalidGPRReg);
3043 m_jit.move(valueTagGPR, resultTagGPR);
3044 JITCompiler::Jump done = m_jit.jump();
3045 isBoolean.link(&m_jit);
3046 m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
3047 done.link(&m_jit);
3048
3049 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3050 break;
3051 }
3052
3053 default:
3054 RELEASE_ASSERT_NOT_REACHED();
3055 break;
3056 }
3057 break;
3058 }
3059
3060 case ToPrimitive: {
3061 compileToPrimitive(node);
3062 break;
3063 }
3064
3065 case ToNumber: {
3066 JSValueOperand argument(this, node->child1());
3067 GPRTemporary resultTag(this, Reuse, argument, TagWord);
3068 GPRTemporary resultPayload(this, Reuse, argument, PayloadWord);
3069
3070 GPRReg argumentPayloadGPR = argument.payloadGPR();
3071 GPRReg argumentTagGPR = argument.tagGPR();
3072 JSValueRegs argumentRegs = argument.jsValueRegs();
3073 JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr());
3074
3075 argument.use();
3076
3077 // We have several attempts to remove ToNumber. But ToNumber still exists.
3078 // It means that converting non-numbers to numbers by this ToNumber is not rare.
3079 // Instead of the slow path generator, we emit callOperation here.
3080 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3081 flushRegisters();
3082 callOperation(operationToNumber, resultRegs, argumentRegs);
3083 m_jit.exceptionCheck();
3084 } else {
3085 MacroAssembler::Jump notNumber;
3086 {
3087 GPRTemporary scratch(this);
3088 notNumber = m_jit.branchIfNotNumber(argument.jsValueRegs(), scratch.gpr());
3089 }
3090 m_jit.move(argumentTagGPR, resultRegs.tagGPR());
3091 m_jit.move(argumentPayloadGPR, resultRegs.payloadGPR());
3092 MacroAssembler::Jump done = m_jit.jump();
3093
3094 notNumber.link(&m_jit);
3095 silentSpillAllRegisters(resultRegs);
3096 callOperation(operationToNumber, resultRegs, argumentRegs);
3097 silentFillAllRegisters();
3098 m_jit.exceptionCheck();
3099
3100 done.link(&m_jit);
3101 }
3102
3103 jsValueResult(resultRegs.tagGPR(), resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
3104 break;
3105 }
3106
3107 case ToString:
3108 case CallStringConstructor:
3109 case StringValueOf: {
3110 compileToStringOrCallStringConstructorOrStringValueOf(node);
3111 break;
3112 }
3113
3114 case NewStringObject: {
3115 compileNewStringObject(node);
3116 break;
3117 }
3118
3119 case NewSymbol: {
3120 compileNewSymbol(node);
3121 break;
3122 }
3123
3124 case NewArray: {
3125 compileNewArray(node);
3126 break;
3127 }
3128
3129 case NewArrayWithSpread: {
3130 compileNewArrayWithSpread(node);
3131 break;
3132 }
3133
3134 case Spread: {
3135 compileSpread(node);
3136 break;
3137 }
3138
3139 case NewArrayWithSize: {
3140 compileNewArrayWithSize(node);
3141 break;
3142 }
3143
3144 case NewArrayBuffer: {
3145 compileNewArrayBuffer(node);
3146 break;
3147 }
3148
3149 case NewTypedArray: {
3150 compileNewTypedArray(node);
3151 break;
3152 }
3153
3154 case NewRegexp: {
3155 compileNewRegexp(node);
3156 break;
3157 }
3158
3159 case ToObject:
3160 case CallObjectConstructor: {
3161 compileToObjectOrCallObjectConstructor(node);
3162 break;
3163 }
3164
3165 case ToThis: {
3166 compileToThis(node);
3167 break;
3168 }
3169
3170 case ObjectCreate: {
3171 compileObjectCreate(node);
3172 break;
3173 }
3174
3175 case ObjectKeys: {
3176 compileObjectKeys(node);
3177 break;
3178 }
3179
3180 case CreateThis: {
3181 compileCreateThis(node);
3182 break;
3183 }
3184
3185 case NewObject: {
3186 compileNewObject(node);
3187 break;
3188 }
3189
3190 case GetCallee: {
3191 compileGetCallee(node);
3192 break;
3193 }
3194
3195 case SetCallee: {
3196 compileSetCallee(node);
3197 break;
3198 }
3199
3200 case GetArgumentCountIncludingThis: {
3201 compileGetArgumentCountIncludingThis(node);
3202 break;
3203 }
3204
3205 case SetArgumentCountIncludingThis:
3206 compileSetArgumentCountIncludingThis(node);
3207 break;
3208
3209 case GetScope:
3210 compileGetScope(node);
3211 break;
3212
3213 case SkipScope:
3214 compileSkipScope(node);
3215 break;
3216
3217 case GetGlobalObject:
3218 compileGetGlobalObject(node);
3219 break;
3220
3221 case GetGlobalThis:
3222 compileGetGlobalThis(node);
3223 break;
3224
3225 case GetClosureVar: {
3226 compileGetClosureVar(node);
3227 break;
3228 }
3229
3230 case PutClosureVar: {
3231 compilePutClosureVar(node);
3232 break;
3233 }
3234
3235 case TryGetById: {
3236 compileGetById(node, AccessType::TryGet);
3237 break;
3238 }
3239
3240 case GetByIdDirect: {
3241 compileGetById(node, AccessType::GetDirect);
3242 break;
3243 }
3244
3245 case GetByIdDirectFlush: {
3246 compileGetByIdFlush(node, AccessType::GetDirect);
3247 break;
3248 }
3249
3250 case GetById: {
3251 compileGetById(node, AccessType::Get);
3252 break;
3253 }
3254
3255 case GetByIdFlush: {
3256 compileGetByIdFlush(node, AccessType::Get);
3257 break;
3258 }
3259
3260 case GetByIdWithThis: {
3261 if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3262 SpeculateCellOperand base(this, node->child1());
3263 SpeculateCellOperand thisValue(this, node->child2());
3264 GPRTemporary resultTag(this);
3265 GPRTemporary resultPayload(this);
3266
3267 GPRReg baseGPR = base.gpr();
3268 GPRReg thisGPR = thisValue.gpr();
3269 GPRReg resultTagGPR = resultTag.gpr();
3270 GPRReg resultPayloadGPR = resultPayload.gpr();
3271
3272 cachedGetByIdWithThis(node->origin.semantic, InvalidGPRReg, baseGPR, InvalidGPRReg, thisGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber());
3273
3274 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3275 } else {
3276 JSValueOperand base(this, node->child1());
3277 JSValueOperand thisValue(this, node->child2());
3278 GPRTemporary resultTag(this);
3279 GPRTemporary resultPayload(this);
3280
3281 GPRReg baseTagGPR = base.tagGPR();
3282 GPRReg basePayloadGPR = base.payloadGPR();
3283 GPRReg thisTagGPR = thisValue.tagGPR();
3284 GPRReg thisPayloadGPR = thisValue.payloadGPR();
3285 GPRReg resultTagGPR = resultTag.gpr();
3286 GPRReg resultPayloadGPR = resultPayload.gpr();
3287
3288 JITCompiler::JumpList notCellList;
3289 notCellList.append(m_jit.branchIfNotCell(base.jsValueRegs()));
3290 notCellList.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
3291
3292 cachedGetByIdWithThis(node->origin.semantic, baseTagGPR, basePayloadGPR, thisTagGPR, thisPayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCellList);
3293
3294 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3295 }
3296
3297 break;
3298 }
3299
3300 case GetArrayLength:
3301 compileGetArrayLength(node);
3302 break;
3303
3304 case DeleteById: {
3305 compileDeleteById(node);
3306 break;
3307 }
3308
3309 case DeleteByVal: {
3310 compileDeleteByVal(node);
3311 break;
3312 }
3313
3314 case CheckCell: {
3315 compileCheckCell(node);
3316 break;
3317 }
3318
3319 case CheckNotEmpty: {
3320 compileCheckNotEmpty(node);
3321 break;
3322 }
3323
3324 case CheckStringIdent:
3325 compileCheckStringIdent(node);
3326 break;
3327
3328 case GetExecutable: {
3329 compileGetExecutable(node);
3330 break;
3331 }
3332
3333 case CheckStructure: {
3334 compileCheckStructure(node);
3335 break;
3336 }
3337
3338 case PutStructure: {
3339 RegisteredStructure oldStructure = node->transition()->previous;
3340 RegisteredStructure newStructure = node->transition()->next;
3341
3342 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3343
3344 SpeculateCellOperand base(this, node->child1());
3345 GPRReg baseGPR = base.gpr();
3346
3347 ASSERT_UNUSED(oldStructure, oldStructure->indexingMode() == newStructure->indexingMode());
3348 ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3349 ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3350 m_jit.storePtr(TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3351
3352 noResult(node);
3353 break;
3354 }
3355
3356 case AllocatePropertyStorage:
3357 compileAllocatePropertyStorage(node);
3358 break;
3359
3360 case ReallocatePropertyStorage:
3361 compileReallocatePropertyStorage(node);
3362 break;
3363
3364 case NukeStructureAndSetButterfly:
3365 compileNukeStructureAndSetButterfly(node);
3366 break;
3367
3368 case GetButterfly:
3369 compileGetButterfly(node);
3370 break;
3371
3372 case GetIndexedPropertyStorage: {
3373 compileGetIndexedPropertyStorage(node);
3374 break;
3375 }
3376
3377 case ConstantStoragePointer: {
3378 compileConstantStoragePointer(node);
3379 break;
3380 }
3381
3382 case GetTypedArrayByteOffset: {
3383 compileGetTypedArrayByteOffset(node);
3384 break;
3385 }
3386
3387 case GetPrototypeOf: {
3388 compileGetPrototypeOf(node);
3389 break;
3390 }
3391
3392 case GetByOffset: {
3393 compileGetByOffset(node);
3394 break;
3395 }
3396
3397 case GetGetterSetterByOffset: {
3398 StorageOperand storage(this, node->child1());
3399 GPRTemporary resultPayload(this);
3400
3401 GPRReg storageGPR = storage.gpr();
3402 GPRReg resultPayloadGPR = resultPayload.gpr();
3403
3404 StorageAccessData& storageAccessData = node->storageAccessData();
3405
3406 m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3407
3408 cellResult(resultPayloadGPR, node);
3409 break;
3410 }
3411
3412 case MatchStructure: {
3413 compileMatchStructure(node);
3414 break;
3415 }
3416
3417 case GetGetter: {
3418 compileGetGetter(node);
3419 break;
3420 }
3421
3422 case GetSetter: {
3423 compileGetSetter(node);
3424 break;
3425 }
3426
3427 case PutByOffset: {
3428 compilePutByOffset(node);
3429 break;
3430 }
3431
3432 case PutByIdFlush: {
3433 compilePutByIdFlush(node);
3434 break;
3435 }
3436
3437 case PutById: {
3438 compilePutById(node);
3439 break;
3440 }
3441
3442 case PutByIdDirect: {
3443 compilePutByIdDirect(node);
3444 break;
3445 }
3446
3447 case PutByIdWithThis: {
3448 compilePutByIdWithThis(node);
3449 break;
3450 }
3451
3452 case PutGetterById:
3453 case PutSetterById: {
3454 compilePutAccessorById(node);
3455 break;
3456 }
3457
3458 case PutGetterSetterById: {
3459 compilePutGetterSetterById(node);
3460 break;
3461 }
3462
3463 case PutGetterByVal:
3464 case PutSetterByVal: {
3465 compilePutAccessorByVal(node);
3466 break;
3467 }
3468
3469 case DefineDataProperty: {
3470 compileDefineDataProperty(node);
3471 break;
3472 }
3473
3474 case DefineAccessorProperty: {
3475 compileDefineAccessorProperty(node);
3476 break;
3477 }
3478
3479 case GetGlobalLexicalVariable:
3480 case GetGlobalVar: {
3481 compileGetGlobalVariable(node);
3482 break;
3483 }
3484
3485 case PutGlobalVariable: {
3486 compilePutGlobalVariable(node);
3487 break;
3488 }
3489
3490 case NotifyWrite: {
3491 compileNotifyWrite(node);
3492 break;
3493 }
3494
3495 case ParseInt: {
3496 compileParseInt(node);
3497 break;
3498 }
3499
3500 case CheckTypeInfoFlags: {
3501 compileCheckTypeInfoFlags(node);
3502 break;
3503 }
3504
3505 case OverridesHasInstance: {
3506 compileOverridesHasInstance(node);
3507 break;
3508 }
3509
3510 case InstanceOf: {
3511 compileInstanceOf(node);
3512 break;
3513 }
3514
3515 case InstanceOfCustom: {
3516 compileInstanceOfCustom(node);
3517 break;
3518 }
3519
3520 case IsEmpty: {
3521 JSValueOperand value(this, node->child1());
3522 GPRTemporary result(this, Reuse, value, TagWord);
3523 m_jit.comparePtr(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag), result.gpr());
3524 booleanResult(result.gpr(), node);
3525 break;
3526 }
3527
3528 case IsUndefined: {
3529 JSValueOperand value(this, node->child1());
3530 GPRTemporary result(this);
3531 GPRTemporary localGlobalObject(this);
3532 GPRTemporary remoteGlobalObject(this);
3533
3534 JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3535
3536 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
3537 JITCompiler::Jump done = m_jit.jump();
3538
3539 isCell.link(&m_jit);
3540 JITCompiler::Jump notMasqueradesAsUndefined;
3541 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3542 m_jit.move(TrustedImm32(0), result.gpr());
3543 notMasqueradesAsUndefined = m_jit.jump();
3544 } else {
3545 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3546 JITCompiler::NonZero,
3547 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()),
3548 TrustedImm32(MasqueradesAsUndefined));
3549 m_jit.move(TrustedImm32(0), result.gpr());
3550 notMasqueradesAsUndefined = m_jit.jump();
3551
3552 isMasqueradesAsUndefined.link(&m_jit);
3553 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3554 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3555 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3556 m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
3557 m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR);
3558 m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3559 }
3560
3561 notMasqueradesAsUndefined.link(&m_jit);
3562 done.link(&m_jit);
3563 booleanResult(result.gpr(), node);
3564 break;
3565 }
3566
3567 case IsUndefinedOrNull: {
3568 JSValueOperand value(this, node->child1());
3569 GPRTemporary result(this, Reuse, value, TagWord);
3570
3571 GPRReg valueTagGPR = value.tagGPR();
3572 GPRReg resultGPR = result.gpr();
3573
3574 m_jit.move(valueTagGPR, resultGPR);
3575 static_assert((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1), "");
3576 m_jit.or32(CCallHelpers::TrustedImm32(1), resultGPR);
3577 m_jit.compare32(CCallHelpers::Equal, resultGPR, CCallHelpers::TrustedImm32(JSValue::NullTag), resultGPR);
3578
3579 booleanResult(resultGPR, node);
3580 break;
3581 }
3582
3583
3584 case IsBoolean: {
3585 JSValueOperand value(this, node->child1());
3586 GPRTemporary result(this, Reuse, value, TagWord);
3587
3588 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
3589 booleanResult(result.gpr(), node);
3590 break;
3591 }
3592
3593 case IsNumber: {
3594 JSValueOperand value(this, node->child1());
3595 GPRTemporary result(this, Reuse, value, TagWord);
3596
3597 m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
3598 m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
3599 booleanResult(result.gpr(), node);
3600 break;
3601 }
3602
3603 case NumberIsInteger: {
3604 JSValueOperand input(this, node->child1());
3605 JSValueRegs inputRegs = input.jsValueRegs();
3606 flushRegisters();
3607 GPRFlushedCallResult result(this);
3608 GPRReg resultGPR = result.gpr();
3609 callOperation(operationNumberIsInteger, resultGPR, inputRegs);
3610 booleanResult(resultGPR, node);
3611 break;
3612 }
3613
3614 case IsObject: {
3615 compileIsObject(node);
3616 break;
3617 }
3618
3619 case IsObjectOrNull: {
3620 compileIsObjectOrNull(node);
3621 break;
3622 }
3623
3624 case IsFunction: {
3625 compileIsFunction(node);
3626 break;
3627 }
3628
3629 case IsCellWithType: {
3630 compileIsCellWithType(node);
3631 break;
3632 }
3633
3634 case IsTypedArrayView: {
3635 compileIsTypedArrayView(node);
3636 break;
3637 }
3638
3639 case TypeOf: {
3640 compileTypeOf(node);
3641 break;
3642 }
3643
3644 case MapHash: {
3645 JSValueOperand input(this, node->child1());
3646
3647 JSValueRegs inputRegs = input.jsValueRegs();
3648
3649 flushRegisters();
3650 GPRFlushedCallResult result(this);
3651 GPRReg resultGPR = result.gpr();
3652 callOperation(operationMapHash, resultGPR, inputRegs);
3653 m_jit.exceptionCheck();
3654 int32Result(resultGPR, node);
3655 break;
3656 }
3657
3658 case NormalizeMapKey: {
3659 compileNormalizeMapKey(node);
3660 break;
3661 }
3662
3663 case GetMapBucket: {
3664 SpeculateCellOperand map(this, node->child1());
3665 JSValueOperand key(this, node->child2());
3666 SpeculateInt32Operand hash(this, node->child3());
3667
3668 GPRReg mapGPR = map.gpr();
3669 JSValueRegs keyRegs = key.jsValueRegs();
3670 GPRReg hashGPR = hash.gpr();
3671
3672 if (node->child1().useKind() == MapObjectUse)
3673 speculateMapObject(node->child1(), mapGPR);
3674 else if (node->child1().useKind() == SetObjectUse)
3675 speculateSetObject(node->child1(), mapGPR);
3676 else
3677 RELEASE_ASSERT_NOT_REACHED();
3678
3679 flushRegisters();
3680 GPRFlushedCallResult result(this);
3681 GPRReg resultGPR = result.gpr();
3682 if (node->child1().useKind() == MapObjectUse)
3683 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3684 else
3685 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3686 m_jit.exceptionCheck();
3687 cellResult(resultGPR, node);
3688 break;
3689 }
3690
3691 case GetMapBucketHead:
3692 compileGetMapBucketHead(node);
3693 break;
3694
3695 case GetMapBucketNext:
3696 compileGetMapBucketNext(node);
3697 break;
3698
3699 case LoadKeyFromMapBucket:
3700 compileLoadKeyFromMapBucket(node);
3701 break;
3702
3703 case LoadValueFromMapBucket:
3704 compileLoadValueFromMapBucket(node);
3705 break;
3706
3707 case ExtractValueFromWeakMapGet:
3708 compileExtractValueFromWeakMapGet(node);
3709 break;
3710
3711 case SetAdd:
3712 compileSetAdd(node);
3713 break;
3714
3715 case MapSet:
3716 compileMapSet(node);
3717 break;
3718
3719 case WeakMapGet:
3720 compileWeakMapGet(node);
3721 break;
3722
3723 case WeakSetAdd:
3724 compileWeakSetAdd(node);
3725 break;
3726
3727 case WeakMapSet:
3728 compileWeakMapSet(node);
3729 break;
3730
3731 case Flush:
3732 break;
3733
3734 case Call:
3735 case TailCall:
3736 case TailCallInlinedCaller:
3737 case Construct:
3738 case CallVarargs:
3739 case TailCallVarargs:
3740 case TailCallVarargsInlinedCaller:
3741 case ConstructVarargs:
3742 case CallForwardVarargs:
3743 case TailCallForwardVarargs:
3744 case TailCallForwardVarargsInlinedCaller:
3745 case ConstructForwardVarargs:
3746 case CallEval:
3747 case DirectCall:
3748 case DirectConstruct:
3749 case DirectTailCall:
3750 case DirectTailCallInlinedCaller:
3751 emitCall(node);
3752 break;
3753
3754 case LoadVarargs: {
3755 compileLoadVarargs(node);
3756 break;
3757 }
3758
3759 case ForwardVarargs: {
3760 compileForwardVarargs(node);
3761 break;
3762 }
3763
3764 case CreateActivation: {
3765 compileCreateActivation(node);
3766 break;
3767 }
3768
3769 case PushWithScope: {
3770 compilePushWithScope(node);
3771 break;
3772 }
3773
3774 case CreateDirectArguments: {
3775 compileCreateDirectArguments(node);
3776 break;
3777 }
3778
3779 case GetFromArguments: {
3780 compileGetFromArguments(node);
3781 break;
3782 }
3783
3784 case PutToArguments: {
3785 compilePutToArguments(node);
3786 break;
3787 }
3788
3789 case GetArgument: {
3790 compileGetArgument(node);
3791 break;
3792 }
3793
3794 case CreateScopedArguments: {
3795 compileCreateScopedArguments(node);
3796 break;
3797 }
3798
3799 case CreateClonedArguments: {
3800 compileCreateClonedArguments(node);
3801 break;
3802 }
3803
3804 case CreateRest: {
3805 compileCreateRest(node);
3806 break;
3807 }
3808
3809 case GetRestLength: {
3810 compileGetRestLength(node);
3811 break;
3812 }
3813
3814 case NewFunction:
3815 case NewGeneratorFunction:
3816 case NewAsyncFunction:
3817 case NewAsyncGeneratorFunction:
3818 compileNewFunction(node);
3819 break;
3820
3821 case SetFunctionName:
3822 compileSetFunctionName(node);
3823 break;
3824
3825 case InById:
3826 compileInById(node);
3827 break;
3828
3829 case InByVal:
3830 compileInByVal(node);
3831 break;
3832
3833 case HasOwnProperty: {
3834#if CPU(X86)
3835 ASSERT(node->child2().useKind() == UntypedUse);
3836 SpeculateCellOperand object(this, node->child1());
3837 JSValueOperand key(this, node->child2());
3838 GPRTemporary result(this, Reuse, object);
3839
3840 JSValueRegs keyRegs = key.jsValueRegs();
3841 GPRReg objectGPR = object.gpr();
3842 GPRReg resultGPR = result.gpr();
3843
3844 speculateObject(node->child1());
3845
3846 flushRegisters();
3847 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs);
3848 booleanResult(resultGPR, node);
3849#else
3850 SpeculateCellOperand object(this, node->child1());
3851 GPRTemporary uniquedStringImpl(this);
3852 GPRTemporary temp(this);
3853 GPRTemporary hash(this);
3854 GPRTemporary structureID(this);
3855 GPRTemporary result(this);
3856
3857 Optional<SpeculateCellOperand> keyAsCell;
3858 Optional<JSValueOperand> keyAsValue;
3859 JSValueRegs keyRegs;
3860 if (node->child2().useKind() == UntypedUse) {
3861 keyAsValue.emplace(this, node->child2());
3862 keyRegs = keyAsValue->jsValueRegs();
3863 } else {
3864 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse);
3865 keyAsCell.emplace(this, node->child2());
3866 keyRegs = JSValueRegs::payloadOnly(keyAsCell->gpr());
3867 }
3868
3869 GPRReg objectGPR = object.gpr();
3870 GPRReg implGPR = uniquedStringImpl.gpr();
3871 GPRReg tempGPR = temp.gpr();
3872 GPRReg hashGPR = hash.gpr();
3873 GPRReg structureIDGPR = structureID.gpr();
3874 GPRReg resultGPR = result.gpr();
3875
3876 speculateObject(node->child1());
3877
3878 MacroAssembler::JumpList slowPath;
3879 switch (node->child2().useKind()) {
3880 case SymbolUse: {
3881 speculateSymbol(node->child2(), keyRegs.payloadGPR());
3882 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR);
3883 break;
3884 }
3885 case StringUse: {
3886 speculateString(node->child2(), keyRegs.payloadGPR());
3887 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR);
3888 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
3889 slowPath.append(m_jit.branchTest32(
3890 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
3891 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
3892 break;
3893 }
3894 case UntypedUse: {
3895 slowPath.append(m_jit.branchIfNotCell(keyRegs));
3896 auto isNotString = m_jit.branchIfNotString(keyRegs.payloadGPR());
3897 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR);
3898 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
3899 slowPath.append(m_jit.branchTest32(
3900 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
3901 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
3902 auto hasUniquedImpl = m_jit.jump();
3903
3904 isNotString.link(&m_jit);
3905 slowPath.append(m_jit.branchIfNotSymbol(keyRegs.payloadGPR()));
3906 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR);
3907
3908 hasUniquedImpl.link(&m_jit);
3909 break;
3910 }
3911 default:
3912 RELEASE_ASSERT_NOT_REACHED();
3913 }
3914
3915 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero
3916 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only
3917 // ever load the result from the cache if the cache entry matches what we are querying for.
3918 // So we either get super lucky and use zero for the hash and somehow collide with the entity
3919 // we're looking for, or we realize we're comparing against another entity, and go to the
3920 // slow path anyways.
3921 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR);
3922 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR);
3923 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR);
3924 m_jit.add32(structureIDGPR, hashGPR);
3925 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR);
3926 m_jit.mul32(TrustedImm32(sizeof(HasOwnPropertyCache::Entry)), hashGPR, hashGPR);
3927 ASSERT(m_jit.vm()->hasOwnPropertyCache());
3928 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR);
3929 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual,
3930 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR));
3931 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR);
3932 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR);
3933 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR));
3934 auto done = m_jit.jump();
3935
3936 slowPath.link(&m_jit);
3937 silentSpillAllRegisters(resultGPR);
3938 if (node->child2().useKind() != UntypedUse) {
3939 m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), tempGPR);
3940 keyRegs = JSValueRegs(tempGPR, keyRegs.payloadGPR());
3941 }
3942 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs);
3943 silentFillAllRegisters();
3944 m_jit.exceptionCheck();
3945
3946 done.link(&m_jit);
3947 booleanResult(resultGPR, node);
3948#endif // CPU(X86)
3949 break;
3950 }
3951
3952 case StoreBarrier:
3953 case FencedStoreBarrier: {
3954 compileStoreBarrier(node);
3955 break;
3956 }
3957
3958 case GetEnumerableLength: {
3959 compileGetEnumerableLength(node);
3960 break;
3961 }
3962 case HasGenericProperty: {
3963 compileHasGenericProperty(node);
3964 break;
3965 }
3966 case HasStructureProperty: {
3967 compileHasStructureProperty(node);
3968 break;
3969 }
3970 case HasIndexedProperty: {
3971 compileHasIndexedProperty(node);
3972 break;
3973 }
3974 case GetDirectPname: {
3975 compileGetDirectPname(node);
3976 break;
3977 }
3978 case GetPropertyEnumerator: {
3979 compileGetPropertyEnumerator(node);
3980 break;
3981 }
3982 case GetEnumeratorStructurePname:
3983 case GetEnumeratorGenericPname: {
3984 compileGetEnumeratorPname(node);
3985 break;
3986 }
3987 case ToIndexString: {
3988 compileToIndexString(node);
3989 break;
3990 }
3991 case ProfileType: {
3992 compileProfileType(node);
3993 break;
3994 }
3995 case ProfileControlFlow: {
3996 GPRTemporary scratch1(this);
3997 BasicBlockLocation* basicBlockLocation = node->basicBlockLocation();
3998 basicBlockLocation->emitExecuteCode(m_jit, scratch1.gpr());
3999 noResult(node);
4000 break;
4001 }
4002
4003 case LogShadowChickenPrologue: {
4004 compileLogShadowChickenPrologue(node);
4005 break;
4006 }
4007
4008 case LogShadowChickenTail: {
4009 compileLogShadowChickenTail(node);
4010 break;
4011 }
4012
4013 case ForceOSRExit: {
4014 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
4015 break;
4016 }
4017
4018 case InvalidationPoint:
4019 emitInvalidationPoint(node);
4020 break;
4021
4022 case CheckTraps:
4023 compileCheckTraps(node);
4024 break;
4025
4026 case CountExecution:
4027 m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
4028 break;
4029
4030 case SuperSamplerBegin:
4031 m_jit.add32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4032 break;
4033
4034 case SuperSamplerEnd:
4035 m_jit.sub32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4036 break;
4037
4038 case Phantom:
4039 case Check:
4040 case CheckVarargs:
4041 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
4042 noResult(node);
4043 break;
4044
4045 case PhantomLocal:
4046 case LoopHint:
4047 // This is a no-op.
4048 noResult(node);
4049 break;
4050
4051 case MaterializeNewObject:
4052 compileMaterializeNewObject(node);
4053 break;
4054
4055 case PutDynamicVar: {
4056 compilePutDynamicVar(node);
4057 break;
4058 }
4059
4060 case GetDynamicVar: {
4061 compileGetDynamicVar(node);
4062 break;
4063 }
4064
4065 case ResolveScopeForHoistingFuncDeclInEval: {
4066 compileResolveScopeForHoistingFuncDeclInEval(node);
4067 break;
4068 }
4069
4070 case ResolveScope: {
4071 compileResolveScope(node);
4072 break;
4073 }
4074
4075 case CallDOM:
4076 compileCallDOM(node);
4077 break;
4078
4079 case CallDOMGetter:
4080 compileCallDOMGetter(node);
4081 break;
4082
4083 case CheckSubClass:
4084 compileCheckSubClass(node);
4085 break;
4086
4087 case Unreachable:
4088 unreachable(node);
4089 break;
4090
4091 case ExtractCatchLocal: {
4092 compileExtractCatchLocal(node);
4093 break;
4094 }
4095
4096 case ClearCatchLocals:
4097 compileClearCatchLocals(node);
4098 break;
4099
4100 case CheckStructureOrEmpty:
4101 DFG_CRASH(m_jit.graph(), node, "CheckStructureOrEmpty only used in 64-bit DFG");
4102 break;
4103
4104 case FilterCallLinkStatus:
4105 case FilterGetByIdStatus:
4106 case FilterPutByIdStatus:
4107 case FilterInByIdStatus:
4108 m_interpreter.filterICStatus(node);
4109 noResult(node);
4110 break;
4111
4112 case LastNodeType:
4113 case Phi:
4114 case Upsilon:
4115 case ExtractOSREntryLocal:
4116 case CheckTierUpInLoop:
4117 case CheckTierUpAtReturn:
4118 case CheckTierUpAndOSREnter:
4119 case Int52Rep:
4120 case FiatInt52:
4121 case Int52Constant:
4122 case CheckInBounds:
4123 case ArithIMul:
4124 case MultiGetByOffset:
4125 case MultiPutByOffset:
4126 case CheckBadCell:
4127 case BottomValue:
4128 case PhantomNewObject:
4129 case PhantomNewFunction:
4130 case PhantomNewGeneratorFunction:
4131 case PhantomNewAsyncFunction:
4132 case PhantomNewAsyncGeneratorFunction:
4133 case PhantomCreateActivation:
4134 case PhantomNewRegexp:
4135 case PutHint:
4136 case CheckStructureImmediate:
4137 case MaterializeCreateActivation:
4138 case PutStack:
4139 case KillStack:
4140 case GetStack:
4141 case GetMyArgumentByVal:
4142 case GetMyArgumentByValOutOfBounds:
4143 case GetVectorLength:
4144 case PhantomCreateRest:
4145 case PhantomSpread:
4146 case PhantomNewArrayWithSpread:
4147 case PhantomNewArrayBuffer:
4148 case AtomicsIsLockFree:
4149 case AtomicsAdd:
4150 case AtomicsAnd:
4151 case AtomicsCompareExchange:
4152 case AtomicsExchange:
4153 case AtomicsLoad:
4154 case AtomicsOr:
4155 case AtomicsStore:
4156 case AtomicsSub:
4157 case AtomicsXor:
4158 case IdentityWithProfile:
4159 case InitializeEntrypointArguments:
4160 case EntrySwitch:
4161 case CPUIntrinsic:
4162 case AssertNotEmpty:
4163 case DataViewGetInt:
4164 case DataViewGetFloat:
4165 case DataViewSet:
4166 DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend");
4167 break;
4168 }
4169
4170 if (!m_compileOkay)
4171 return;
4172
4173 if (node->hasResult() && node->mustGenerate())
4174 use(node);
4175}
4176
4177void SpeculativeJIT::moveTrueTo(GPRReg gpr)
4178{
4179 m_jit.move(TrustedImm32(1), gpr);
4180}
4181
4182void SpeculativeJIT::moveFalseTo(GPRReg gpr)
4183{
4184 m_jit.move(TrustedImm32(0), gpr);
4185}
4186
4187void SpeculativeJIT::blessBoolean(GPRReg)
4188{
4189}
4190
4191void SpeculativeJIT::compileArithRandom(Node* node)
4192{
4193 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
4194
4195 flushRegisters();
4196
4197 FPRResult result(this);
4198 callOperation(operationRandom, result.fpr(), globalObject);
4199 // operationRandom does not raise any exception.
4200 doubleResult(result.fpr(), node);
4201}
4202
4203#endif
4204
4205} } // namespace JSC::DFG
4206
4207#endif
4208