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 SetArgumentDefinitely:
1976 case SetArgumentMaybe:
1977 // This is a no-op; it just marks the fact that the argument is being used.
1978 // But it may be profitable to use this as a hook to run speculation checks
1979 // on arguments, thereby allowing us to trivially eliminate such checks if
1980 // the argument is not used.
1981 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1982 break;
1983
1984 case ValueBitOr:
1985 case ValueBitAnd:
1986 case ValueBitXor:
1987 compileValueBitwiseOp(node);
1988 break;
1989
1990 case ArithBitAnd:
1991 case ArithBitOr:
1992 case ArithBitXor:
1993 compileBitwiseOp(node);
1994 break;
1995
1996 case ValueBitNot:
1997 compileValueBitNot(node);
1998 break;
1999
2000 case ArithBitNot:
2001 compileBitwiseNot(node);
2002 break;
2003
2004 case BitRShift:
2005 case BitLShift:
2006 case BitURShift:
2007 compileShiftOp(node);
2008 break;
2009
2010 case UInt32ToNumber: {
2011 compileUInt32ToNumber(node);
2012 break;
2013 }
2014
2015 case DoubleAsInt32: {
2016 compileDoubleAsInt32(node);
2017 break;
2018 }
2019
2020 case ValueToInt32: {
2021 compileValueToInt32(node);
2022 break;
2023 }
2024
2025 case DoubleRep: {
2026 compileDoubleRep(node);
2027 break;
2028 }
2029
2030 case ValueRep: {
2031 compileValueRep(node);
2032 break;
2033 }
2034
2035 case ValueNegate:
2036 compileValueNegate(node);
2037 break;
2038
2039 case ValueAdd:
2040 compileValueAdd(node);
2041 break;
2042
2043 case ValueSub:
2044 compileValueSub(node);
2045 break;
2046
2047 case StrCat: {
2048 compileStrCat(node);
2049 break;
2050 }
2051
2052 case ArithAdd:
2053 compileArithAdd(node);
2054 break;
2055
2056 case ArithClz32:
2057 compileArithClz32(node);
2058 break;
2059
2060 case MakeRope:
2061 compileMakeRope(node);
2062 break;
2063
2064 case ArithSub:
2065 compileArithSub(node);
2066 break;
2067
2068 case ArithNegate:
2069 compileArithNegate(node);
2070 break;
2071
2072 case ArithMul:
2073 compileArithMul(node);
2074 break;
2075
2076 case ValueMul:
2077 compileValueMul(node);
2078 break;
2079
2080 case ValueDiv: {
2081 compileValueDiv(node);
2082 break;
2083 }
2084
2085 case ArithDiv: {
2086 compileArithDiv(node);
2087 break;
2088 }
2089
2090 case ValueMod: {
2091 compileValueMod(node);
2092 break;
2093 }
2094
2095 case ArithMod: {
2096 compileArithMod(node);
2097 break;
2098 }
2099
2100 case ArithPow: {
2101 compileArithPow(node);
2102 break;
2103 }
2104
2105 case ArithAbs:
2106 compileArithAbs(node);
2107 break;
2108
2109 case ArithMin:
2110 case ArithMax: {
2111 compileArithMinMax(node);
2112 break;
2113 }
2114
2115 case ArithSqrt:
2116 compileArithSqrt(node);
2117 break;
2118
2119 case ArithFRound:
2120 compileArithFRound(node);
2121 break;
2122
2123 case ArithRandom:
2124 compileArithRandom(node);
2125 break;
2126
2127 case ArithRound:
2128 case ArithFloor:
2129 case ArithCeil:
2130 case ArithTrunc:
2131 compileArithRounding(node);
2132 break;
2133
2134 case ArithUnary:
2135 compileArithUnary(node);
2136 break;
2137
2138 case LogicalNot:
2139 compileLogicalNot(node);
2140 break;
2141
2142 case CompareLess:
2143 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2144 return;
2145 break;
2146
2147 case CompareLessEq:
2148 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2149 return;
2150 break;
2151
2152 case CompareGreater:
2153 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2154 return;
2155 break;
2156
2157 case CompareGreaterEq:
2158 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2159 return;
2160 break;
2161
2162 case CompareBelow:
2163 compileCompareUnsigned(node, JITCompiler::Below);
2164 break;
2165
2166 case CompareBelowEq:
2167 compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2168 break;
2169
2170 case CompareEq:
2171 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2172 return;
2173 break;
2174
2175 case CompareStrictEq:
2176 if (compileStrictEq(node))
2177 return;
2178 break;
2179
2180 case CompareEqPtr:
2181 compileCompareEqPtr(node);
2182 break;
2183
2184 case SameValue:
2185 compileSameValue(node);
2186 break;
2187
2188 case StringCharCodeAt: {
2189 compileGetCharCodeAt(node);
2190 break;
2191 }
2192
2193 case StringCharAt: {
2194 // Relies on StringCharAt node having same basic layout as GetByVal
2195 compileGetByValOnString(node);
2196 break;
2197 }
2198
2199 case StringFromCharCode: {
2200 compileFromCharCode(node);
2201 break;
2202 }
2203
2204 case CheckArray: {
2205 checkArray(node);
2206 break;
2207 }
2208
2209 case Arrayify:
2210 case ArrayifyToStructure: {
2211 arrayify(node);
2212 break;
2213 }
2214
2215 case GetByVal: {
2216 switch (node->arrayMode().type()) {
2217 case Array::SelectUsingPredictions:
2218 case Array::ForceExit:
2219 RELEASE_ASSERT_NOT_REACHED();
2220#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2221 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2222#endif
2223 break;
2224 case Array::Undecided: {
2225 SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2226 GPRTemporary resultTag(this, Reuse, index);
2227 GPRTemporary resultPayload(this);
2228
2229 GPRReg indexGPR = index.gpr();
2230 GPRReg resultTagGPR = resultTag.gpr();
2231 GPRReg resultPayloadGPR = resultPayload.gpr();
2232
2233 speculationCheck(OutOfBounds, JSValueRegs(), node,
2234 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2235
2236 use(m_graph.varArgChild(node, 0));
2237 index.use();
2238
2239 m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
2240 m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
2241 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
2242 break;
2243 }
2244 case Array::Generic: {
2245 if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2246 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2247 compileGetByValForObjectWithString(node);
2248 break;
2249 }
2250
2251 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2252 compileGetByValForObjectWithSymbol(node);
2253 break;
2254 }
2255 }
2256
2257 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
2258 JSValueOperand property(this, m_graph.varArgChild(node, 1));
2259 GPRReg baseGPR = base.gpr();
2260 JSValueRegs propertyRegs = property.jsValueRegs();
2261
2262 flushRegisters();
2263 JSValueRegsFlushedCallResult result(this);
2264 JSValueRegs resultRegs = result.regs();
2265 callOperation(operationGetByValCell, resultRegs, baseGPR, propertyRegs);
2266 m_jit.exceptionCheck();
2267
2268 jsValueResult(resultRegs, node);
2269 break;
2270 }
2271 case Array::Int32:
2272 case Array::Contiguous: {
2273 if (node->arrayMode().isInBounds()) {
2274 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2275 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2276
2277 GPRReg propertyReg = property.gpr();
2278 GPRReg storageReg = storage.gpr();
2279
2280 if (!m_compileOkay)
2281 return;
2282
2283 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2284
2285 GPRTemporary resultPayload(this);
2286 if (node->arrayMode().type() == Array::Int32) {
2287 ASSERT(!node->arrayMode().isSaneChain());
2288
2289 speculationCheck(
2290 OutOfBounds, JSValueRegs(), 0,
2291 m_jit.branch32(
2292 MacroAssembler::Equal,
2293 MacroAssembler::BaseIndex(
2294 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2295 TrustedImm32(JSValue::EmptyValueTag)));
2296 m_jit.load32(
2297 MacroAssembler::BaseIndex(
2298 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2299 resultPayload.gpr());
2300 int32Result(resultPayload.gpr(), node);
2301 break;
2302 }
2303
2304 GPRTemporary resultTag(this);
2305 m_jit.load32(
2306 MacroAssembler::BaseIndex(
2307 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2308 resultTag.gpr());
2309 m_jit.load32(
2310 MacroAssembler::BaseIndex(
2311 storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2312 resultPayload.gpr());
2313 if (node->arrayMode().isSaneChain()) {
2314 JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr());
2315 m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
2316 m_jit.move(TrustedImm32(0), resultPayload.gpr());
2317 notHole.link(&m_jit);
2318 } else {
2319 speculationCheck(
2320 LoadFromHole, JSValueRegs(), 0,
2321 m_jit.branchIfEmpty(resultTag.gpr()));
2322 }
2323 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2324 break;
2325 }
2326
2327 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2328 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2329 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2330
2331 GPRReg baseReg = base.gpr();
2332 GPRReg propertyReg = property.gpr();
2333 GPRReg storageReg = storage.gpr();
2334
2335 if (!m_compileOkay)
2336 return;
2337
2338 GPRTemporary resultTag(this);
2339 GPRTemporary resultPayload(this);
2340 GPRReg resultTagReg = resultTag.gpr();
2341 GPRReg resultPayloadReg = resultPayload.gpr();
2342
2343 MacroAssembler::JumpList slowCases;
2344
2345 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2346
2347 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2348 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2349 slowCases.append(m_jit.branchIfEmpty(resultTagReg));
2350
2351 addSlowPathGenerator(
2352 slowPathCall(
2353 slowCases, this, operationGetByValObjectInt,
2354 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2355
2356 jsValueResult(resultTagReg, resultPayloadReg, node);
2357 break;
2358 }
2359 case Array::Double: {
2360 if (node->arrayMode().isInBounds()) {
2361 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2362 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2363
2364 GPRReg propertyReg = property.gpr();
2365 GPRReg storageReg = storage.gpr();
2366
2367 if (!m_compileOkay)
2368 return;
2369
2370 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2371
2372 FPRTemporary result(this);
2373 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2374 if (!node->arrayMode().isSaneChain())
2375 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
2376 doubleResult(result.fpr(), node);
2377 break;
2378 }
2379
2380 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2381 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2382 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2383
2384 GPRReg baseReg = base.gpr();
2385 GPRReg propertyReg = property.gpr();
2386 GPRReg storageReg = storage.gpr();
2387
2388 if (!m_compileOkay)
2389 return;
2390
2391 GPRTemporary resultTag(this);
2392 GPRTemporary resultPayload(this);
2393 FPRTemporary temp(this);
2394 GPRReg resultTagReg = resultTag.gpr();
2395 GPRReg resultPayloadReg = resultPayload.gpr();
2396 FPRReg tempReg = temp.fpr();
2397
2398 MacroAssembler::JumpList slowCases;
2399
2400 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2401
2402 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2403 slowCases.append(m_jit.branchIfNaN(tempReg));
2404 boxDouble(tempReg, resultTagReg, resultPayloadReg);
2405
2406 addSlowPathGenerator(
2407 slowPathCall(
2408 slowCases, this, operationGetByValObjectInt,
2409 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2410
2411 jsValueResult(resultTagReg, resultPayloadReg, node);
2412 break;
2413 }
2414 case Array::ArrayStorage:
2415 case Array::SlowPutArrayStorage: {
2416 if (node->arrayMode().isInBounds()) {
2417 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2418 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2419 GPRReg propertyReg = property.gpr();
2420 GPRReg storageReg = storage.gpr();
2421
2422 if (!m_compileOkay)
2423 return;
2424
2425 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2426
2427 GPRTemporary resultTag(this);
2428 GPRTemporary resultPayload(this);
2429
2430 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2431 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr()));
2432 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2433
2434 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2435 break;
2436 }
2437
2438 SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2439 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2440 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2441 GPRReg propertyReg = property.gpr();
2442 GPRReg storageReg = storage.gpr();
2443 GPRReg baseReg = base.gpr();
2444
2445 if (!m_compileOkay)
2446 return;
2447
2448 GPRTemporary resultTag(this);
2449 GPRTemporary resultPayload(this);
2450 GPRReg resultTagReg = resultTag.gpr();
2451 GPRReg resultPayloadReg = resultPayload.gpr();
2452
2453 JITCompiler::Jump outOfBounds = m_jit.branch32(
2454 MacroAssembler::AboveOrEqual, propertyReg,
2455 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2456
2457 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2458 JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr());
2459 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2460
2461 JITCompiler::JumpList slowCases;
2462 slowCases.append(outOfBounds);
2463 slowCases.append(hole);
2464 addSlowPathGenerator(
2465 slowPathCall(
2466 slowCases, this, operationGetByValObjectInt,
2467 JSValueRegs(resultTagReg, resultPayloadReg),
2468 baseReg, propertyReg));
2469
2470 jsValueResult(resultTagReg, resultPayloadReg, node);
2471 break;
2472 }
2473 case Array::String:
2474 compileGetByValOnString(node);
2475 break;
2476 case Array::DirectArguments:
2477 compileGetByValOnDirectArguments(node);
2478 break;
2479 case Array::ScopedArguments:
2480 compileGetByValOnScopedArguments(node);
2481 break;
2482 default: {
2483 TypedArrayType type = node->arrayMode().typedArrayType();
2484 if (isInt(type))
2485 compileGetByValOnIntTypedArray(node, type);
2486 else
2487 compileGetByValOnFloatTypedArray(node, type);
2488 } }
2489 break;
2490 }
2491
2492 case StringSlice: {
2493 compileStringSlice(node);
2494 break;
2495 }
2496
2497 case ToLowerCase: {
2498 compileToLowerCase(node);
2499 break;
2500 }
2501
2502 case NumberToStringWithRadix: {
2503 compileNumberToStringWithRadix(node);
2504 break;
2505 }
2506
2507 case NumberToStringWithValidRadixConstant: {
2508 compileNumberToStringWithValidRadixConstant(node);
2509 break;
2510 }
2511
2512 case GetByValWithThis: {
2513 compileGetByValWithThis(node);
2514 break;
2515 }
2516
2517 case PutByValDirect:
2518 case PutByVal:
2519 case PutByValAlias: {
2520 Edge child1 = m_jit.graph().varArgChild(node, 0);
2521 Edge child2 = m_jit.graph().varArgChild(node, 1);
2522 Edge child3 = m_jit.graph().varArgChild(node, 2);
2523 Edge child4 = m_jit.graph().varArgChild(node, 3);
2524
2525 ArrayMode arrayMode = node->arrayMode().modeForPut();
2526 bool alreadyHandled = false;
2527
2528 switch (arrayMode.type()) {
2529 case Array::SelectUsingPredictions:
2530 case Array::ForceExit:
2531 RELEASE_ASSERT_NOT_REACHED();
2532#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2533 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2534 alreadyHandled = true;
2535#endif
2536 break;
2537 case Array::Generic: {
2538 ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
2539
2540 if (child1.useKind() == CellUse) {
2541 if (child2.useKind() == StringUse) {
2542 compilePutByValForCellWithString(node, child1, child2, child3);
2543 alreadyHandled = true;
2544 break;
2545 }
2546
2547 if (child2.useKind() == SymbolUse) {
2548 compilePutByValForCellWithSymbol(node, child1, child2, child3);
2549 alreadyHandled = true;
2550 break;
2551 }
2552 }
2553
2554 SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2555 JSValueOperand property(this, child2);
2556 JSValueOperand value(this, child3);
2557 GPRReg baseGPR = base.gpr();
2558 JSValueRegs propertyRegs = property.jsValueRegs();
2559 JSValueRegs valueRegs = value.jsValueRegs();
2560
2561 flushRegisters();
2562 if (node->op() == PutByValDirect)
2563 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
2564 else
2565 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
2566 m_jit.exceptionCheck();
2567
2568 noResult(node);
2569 alreadyHandled = true;
2570 break;
2571 }
2572 default:
2573 break;
2574 }
2575
2576 if (alreadyHandled)
2577 break;
2578
2579 SpeculateCellOperand base(this, child1);
2580 SpeculateStrictInt32Operand property(this, child2);
2581
2582 GPRReg baseReg = base.gpr();
2583 GPRReg propertyReg = property.gpr();
2584
2585 switch (arrayMode.type()) {
2586 case Array::Int32: {
2587 speculateInt32(child3);
2588 FALLTHROUGH;
2589 }
2590 case Array::Contiguous: {
2591 JSValueOperand value(this, child3, ManualOperandSpeculation);
2592
2593 GPRReg valueTagReg = value.tagGPR();
2594 GPRReg valuePayloadReg = value.payloadGPR();
2595
2596 if (!m_compileOkay)
2597 return;
2598
2599 compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2600 break;
2601 }
2602 case Array::Double: {
2603 compileDoublePutByVal(node, base, property);
2604 break;
2605 }
2606 case Array::ArrayStorage:
2607 case Array::SlowPutArrayStorage: {
2608 JSValueOperand value(this, child3);
2609
2610 GPRReg valueTagReg = value.tagGPR();
2611 GPRReg valuePayloadReg = value.payloadGPR();
2612
2613 if (!m_compileOkay)
2614 return;
2615
2616 StorageOperand storage(this, child4);
2617 GPRReg storageReg = storage.gpr();
2618
2619 if (node->op() == PutByValAlias) {
2620 // Store the value to the array.
2621 GPRReg propertyReg = property.gpr();
2622 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2623 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2624
2625 noResult(node);
2626 break;
2627 }
2628
2629 MacroAssembler::JumpList slowCases;
2630
2631 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2632 if (!arrayMode.isOutOfBounds())
2633 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2634 else
2635 slowCases.append(beyondArrayBounds);
2636
2637 // Check if we're writing to a hole; if so increment m_numValuesInVector.
2638 if (arrayMode.isInBounds()) {
2639 speculationCheck(
2640 StoreToHole, JSValueRegs(), 0,
2641 m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
2642 } else {
2643 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));
2644 if (arrayMode.isSlowPut()) {
2645 // This is sort of strange. If we wanted to optimize this code path, we would invert
2646 // the above branch. But it's simply not worth it since this only happens if we're
2647 // already having a bad time.
2648 slowCases.append(m_jit.jump());
2649 } else {
2650 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2651
2652 // If we're writing to a hole we might be growing the array;
2653 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2654 m_jit.add32(TrustedImm32(1), propertyReg);
2655 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2656 m_jit.sub32(TrustedImm32(1), propertyReg);
2657
2658 lengthDoesNotNeedUpdate.link(&m_jit);
2659 }
2660 notHoleValue.link(&m_jit);
2661 }
2662
2663 // Store the value to the array.
2664 m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2665 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2666
2667 base.use();
2668 property.use();
2669 value.use();
2670 storage.use();
2671
2672 if (!slowCases.empty()) {
2673 if (node->op() == PutByValDirect) {
2674 addSlowPathGenerator(slowPathCall(
2675 slowCases, this,
2676 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2677 NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2678 } else {
2679 addSlowPathGenerator(slowPathCall(
2680 slowCases, this,
2681 m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2682 NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2683 }
2684 }
2685
2686 noResult(node, UseChildrenCalledExplicitly);
2687 break;
2688 }
2689
2690 default: {
2691 TypedArrayType type = arrayMode.typedArrayType();
2692 if (isInt(type))
2693 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2694 else
2695 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2696 } }
2697 break;
2698 }
2699
2700 case PutByValWithThis: {
2701#if CPU(X86)
2702 // We don't have enough registers on X86 to do this
2703 // without setting up the call frame incrementally.
2704 unsigned index = 0;
2705 m_jit.poke(GPRInfo::callFrameRegister, index++);
2706
2707 {
2708 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2709 GPRReg baseTag = base.tagGPR();
2710 GPRReg basePayload = base.payloadGPR();
2711
2712 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2713 GPRReg thisValueTag = thisValue.tagGPR();
2714 GPRReg thisValuePayload = thisValue.payloadGPR();
2715
2716 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2717 GPRReg propertyTag = property.tagGPR();
2718 GPRReg propertyPayload = property.payloadGPR();
2719
2720 m_jit.poke(basePayload, index++);
2721 m_jit.poke(baseTag, index++);
2722
2723 m_jit.poke(thisValuePayload, index++);
2724 m_jit.poke(thisValueTag, index++);
2725
2726 m_jit.poke(propertyPayload, index++);
2727 m_jit.poke(propertyTag, index++);
2728
2729 flushRegisters();
2730 }
2731
2732 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2733 GPRReg valueTag = value.tagGPR();
2734 GPRReg valuePayload = value.payloadGPR();
2735 m_jit.poke(valuePayload, index++);
2736 m_jit.poke(valueTag, index++);
2737
2738 flushRegisters();
2739 appendCall(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis);
2740 m_jit.exceptionCheck();
2741#else
2742 static_assert(GPRInfo::numberOfRegisters >= 8, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
2743
2744 JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2745 JSValueRegs baseRegs = base.jsValueRegs();
2746
2747 JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2748 JSValueRegs thisRegs = thisValue.jsValueRegs();
2749
2750 JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2751 JSValueRegs propertyRegs = property.jsValueRegs();
2752
2753 JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2754 JSValueRegs valueRegs = value.jsValueRegs();
2755
2756 flushRegisters();
2757 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis,
2758 NoResult, baseRegs, thisRegs, propertyRegs, valueRegs);
2759 m_jit.exceptionCheck();
2760#endif // CPU(X86)
2761
2762 noResult(node);
2763 break;
2764 }
2765
2766 case RegExpExec: {
2767 compileRegExpExec(node);
2768 break;
2769 }
2770
2771 case RegExpExecNonGlobalOrSticky: {
2772 compileRegExpExecNonGlobalOrSticky(node);
2773 break;
2774 }
2775
2776 case RegExpMatchFastGlobal: {
2777 compileRegExpMatchFastGlobal(node);
2778 break;
2779 }
2780
2781 case RegExpTest: {
2782 compileRegExpTest(node);
2783 break;
2784 }
2785
2786 case RegExpMatchFast: {
2787 compileRegExpMatchFast(node);
2788 break;
2789 }
2790
2791 case StringReplace:
2792 case StringReplaceRegExp: {
2793 compileStringReplace(node);
2794 break;
2795 }
2796
2797 case GetRegExpObjectLastIndex: {
2798 compileGetRegExpObjectLastIndex(node);
2799 break;
2800 }
2801
2802 case SetRegExpObjectLastIndex: {
2803 compileSetRegExpObjectLastIndex(node);
2804 break;
2805 }
2806
2807 case RecordRegExpCachedResult: {
2808 compileRecordRegExpCachedResult(node);
2809 break;
2810 }
2811
2812 case ArrayPush: {
2813 compileArrayPush(node);
2814 break;
2815 }
2816
2817 case ArrayPop: {
2818 ASSERT(node->arrayMode().isJSArray());
2819
2820 SpeculateCellOperand base(this, node->child1());
2821 StorageOperand storage(this, node->child2());
2822 GPRTemporary valueTag(this);
2823 GPRTemporary valuePayload(this);
2824
2825 GPRReg baseGPR = base.gpr();
2826 GPRReg valueTagGPR = valueTag.gpr();
2827 GPRReg valuePayloadGPR = valuePayload.gpr();
2828 GPRReg storageGPR = storage.gpr();
2829
2830 switch (node->arrayMode().type()) {
2831 case Array::Int32:
2832 case Array::Contiguous: {
2833 m_jit.load32(
2834 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2835 MacroAssembler::Jump undefinedCase =
2836 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2837 m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2838 m_jit.store32(
2839 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2840 m_jit.load32(
2841 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2842 valueTagGPR);
2843 MacroAssembler::Jump slowCase = m_jit.branchIfEmpty(valueTagGPR);
2844 m_jit.store32(
2845 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
2846 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2847 m_jit.load32(
2848 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
2849 valuePayloadGPR);
2850
2851 addSlowPathGenerator(
2852 slowPathMove(
2853 undefinedCase, this,
2854 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2855 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2856 addSlowPathGenerator(
2857 slowPathCall(
2858 slowCase, this, operationArrayPopAndRecoverLength,
2859 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2860
2861 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2862 break;
2863 }
2864
2865 case Array::Double: {
2866 FPRTemporary temp(this);
2867 FPRReg tempFPR = temp.fpr();
2868
2869 m_jit.load32(
2870 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2871 MacroAssembler::Jump undefinedCase =
2872 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2873 m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2874 m_jit.store32(
2875 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2876 m_jit.loadDouble(
2877 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
2878 tempFPR);
2879 MacroAssembler::Jump slowCase = m_jit.branchIfNaN(tempFPR);
2880 JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
2881 m_jit.store32(
2882 MacroAssembler::TrustedImm32(nan.u.asBits.tag),
2883 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2884 m_jit.store32(
2885 MacroAssembler::TrustedImm32(nan.u.asBits.payload),
2886 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2887 boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
2888
2889 addSlowPathGenerator(
2890 slowPathMove(
2891 undefinedCase, this,
2892 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2893 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2894 addSlowPathGenerator(
2895 slowPathCall(
2896 slowCase, this, operationArrayPopAndRecoverLength,
2897 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2898
2899 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2900 break;
2901 }
2902
2903 case Array::ArrayStorage: {
2904 GPRTemporary storageLength(this);
2905 GPRReg storageLengthGPR = storageLength.gpr();
2906
2907 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2908
2909 JITCompiler::JumpList setUndefinedCases;
2910 setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
2911
2912 m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2913
2914 MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2915
2916 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
2917 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
2918
2919 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2920
2921 setUndefinedCases.append(m_jit.branchIfEmpty(valueTagGPR));
2922
2923 m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2924
2925 m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2926
2927 addSlowPathGenerator(
2928 slowPathMove(
2929 setUndefinedCases, this,
2930 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2931 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2932
2933 addSlowPathGenerator(
2934 slowPathCall(
2935 slowCase, this, operationArrayPop,
2936 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2937
2938 jsValueResult(valueTagGPR, valuePayloadGPR, node);
2939 break;
2940 }
2941
2942 default:
2943 CRASH();
2944 break;
2945 }
2946 break;
2947 }
2948
2949 case ArraySlice: {
2950 compileArraySlice(node);
2951 break;
2952 }
2953
2954 case ArrayIndexOf: {
2955 compileArrayIndexOf(node);
2956 break;
2957 }
2958
2959 case DFG::Jump: {
2960 jump(node->targetBlock());
2961 noResult(node);
2962 break;
2963 }
2964
2965 case Branch:
2966 emitBranch(node);
2967 break;
2968
2969 case Switch:
2970 emitSwitch(node);
2971 break;
2972
2973 case Return: {
2974 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
2975 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2976 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2977
2978 // Return the result in returnValueGPR.
2979 JSValueOperand op1(this, node->child1());
2980 op1.fill();
2981 if (op1.isDouble())
2982 boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
2983 else {
2984 if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
2985 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
2986 else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
2987 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2988 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2989 } else {
2990 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2991 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2992 }
2993 }
2994
2995 m_jit.emitRestoreCalleeSaves();
2996 m_jit.emitFunctionEpilogue();
2997 m_jit.ret();
2998
2999 noResult(node);
3000 break;
3001 }
3002
3003 case Throw: {
3004 compileThrow(node);
3005 break;
3006 }
3007
3008 case ThrowStaticError: {
3009 compileThrowStaticError(node);
3010 break;
3011 }
3012
3013 case BooleanToNumber: {
3014 switch (node->child1().useKind()) {
3015 case BooleanUse: {
3016 SpeculateBooleanOperand value(this, node->child1());
3017 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3018
3019 m_jit.move(value.gpr(), result.gpr());
3020
3021 int32Result(result.gpr(), node);
3022 break;
3023 }
3024
3025 case UntypedUse: {
3026 JSValueOperand value(this, node->child1());
3027
3028 if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3029 GPRTemporary result(this);
3030
3031 GPRReg valueGPR = value.payloadGPR();
3032 GPRReg resultGPR = result.gpr();
3033
3034 m_jit.move(valueGPR, resultGPR);
3035 int32Result(result.gpr(), node);
3036 break;
3037 }
3038
3039 GPRTemporary resultTag(this);
3040 GPRTemporary resultPayload(this);
3041
3042 GPRReg valueTagGPR = value.tagGPR();
3043 GPRReg valuePayloadGPR = value.payloadGPR();
3044 GPRReg resultTagGPR = resultTag.gpr();
3045 GPRReg resultPayloadGPR = resultPayload.gpr();
3046
3047 m_jit.move(valuePayloadGPR, resultPayloadGPR);
3048 JITCompiler::Jump isBoolean = m_jit.branchIfBoolean(valueTagGPR, InvalidGPRReg);
3049 m_jit.move(valueTagGPR, resultTagGPR);
3050 JITCompiler::Jump done = m_jit.jump();
3051 isBoolean.link(&m_jit);
3052 m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
3053 done.link(&m_jit);
3054
3055 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3056 break;
3057 }
3058
3059 default:
3060 RELEASE_ASSERT_NOT_REACHED();
3061 break;
3062 }
3063 break;
3064 }
3065
3066 case ToPrimitive: {
3067 compileToPrimitive(node);
3068 break;
3069 }
3070
3071 case ToNumber: {
3072 JSValueOperand argument(this, node->child1());
3073 GPRTemporary resultTag(this, Reuse, argument, TagWord);
3074 GPRTemporary resultPayload(this, Reuse, argument, PayloadWord);
3075
3076 GPRReg argumentPayloadGPR = argument.payloadGPR();
3077 GPRReg argumentTagGPR = argument.tagGPR();
3078 JSValueRegs argumentRegs = argument.jsValueRegs();
3079 JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr());
3080
3081 argument.use();
3082
3083 // We have several attempts to remove ToNumber. But ToNumber still exists.
3084 // It means that converting non-numbers to numbers by this ToNumber is not rare.
3085 // Instead of the slow path generator, we emit callOperation here.
3086 if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3087 flushRegisters();
3088 callOperation(operationToNumber, resultRegs, argumentRegs);
3089 m_jit.exceptionCheck();
3090 } else {
3091 MacroAssembler::Jump notNumber;
3092 {
3093 GPRTemporary scratch(this);
3094 notNumber = m_jit.branchIfNotNumber(argument.jsValueRegs(), scratch.gpr());
3095 }
3096 m_jit.move(argumentTagGPR, resultRegs.tagGPR());
3097 m_jit.move(argumentPayloadGPR, resultRegs.payloadGPR());
3098 MacroAssembler::Jump done = m_jit.jump();
3099
3100 notNumber.link(&m_jit);
3101 silentSpillAllRegisters(resultRegs);
3102 callOperation(operationToNumber, resultRegs, argumentRegs);
3103 silentFillAllRegisters();
3104 m_jit.exceptionCheck();
3105
3106 done.link(&m_jit);
3107 }
3108
3109 jsValueResult(resultRegs.tagGPR(), resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
3110 break;
3111 }
3112
3113 case ToString:
3114 case CallStringConstructor:
3115 case StringValueOf: {
3116 compileToStringOrCallStringConstructorOrStringValueOf(node);
3117 break;
3118 }
3119
3120 case NewStringObject: {
3121 compileNewStringObject(node);
3122 break;
3123 }
3124
3125 case NewSymbol: {
3126 compileNewSymbol(node);
3127 break;
3128 }
3129
3130 case NewArray: {
3131 compileNewArray(node);
3132 break;
3133 }
3134
3135 case NewArrayWithSpread: {
3136 compileNewArrayWithSpread(node);
3137 break;
3138 }
3139
3140 case Spread: {
3141 compileSpread(node);
3142 break;
3143 }
3144
3145 case NewArrayWithSize: {
3146 compileNewArrayWithSize(node);
3147 break;
3148 }
3149
3150 case NewArrayBuffer: {
3151 compileNewArrayBuffer(node);
3152 break;
3153 }
3154
3155 case NewTypedArray: {
3156 compileNewTypedArray(node);
3157 break;
3158 }
3159
3160 case NewRegexp: {
3161 compileNewRegexp(node);
3162 break;
3163 }
3164
3165 case ToObject:
3166 case CallObjectConstructor: {
3167 compileToObjectOrCallObjectConstructor(node);
3168 break;
3169 }
3170
3171 case ToThis: {
3172 compileToThis(node);
3173 break;
3174 }
3175
3176 case ObjectCreate: {
3177 compileObjectCreate(node);
3178 break;
3179 }
3180
3181 case ObjectKeys: {
3182 compileObjectKeys(node);
3183 break;
3184 }
3185
3186 case CreateThis: {
3187 compileCreateThis(node);
3188 break;
3189 }
3190
3191 case NewObject: {
3192 compileNewObject(node);
3193 break;
3194 }
3195
3196 case GetCallee: {
3197 compileGetCallee(node);
3198 break;
3199 }
3200
3201 case SetCallee: {
3202 compileSetCallee(node);
3203 break;
3204 }
3205
3206 case GetArgumentCountIncludingThis: {
3207 compileGetArgumentCountIncludingThis(node);
3208 break;
3209 }
3210
3211 case SetArgumentCountIncludingThis:
3212 compileSetArgumentCountIncludingThis(node);
3213 break;
3214
3215 case GetScope:
3216 compileGetScope(node);
3217 break;
3218
3219 case SkipScope:
3220 compileSkipScope(node);
3221 break;
3222
3223 case GetGlobalObject:
3224 compileGetGlobalObject(node);
3225 break;
3226
3227 case GetGlobalThis:
3228 compileGetGlobalThis(node);
3229 break;
3230
3231 case GetClosureVar: {
3232 compileGetClosureVar(node);
3233 break;
3234 }
3235
3236 case PutClosureVar: {
3237 compilePutClosureVar(node);
3238 break;
3239 }
3240
3241 case TryGetById: {
3242 compileGetById(node, AccessType::TryGet);
3243 break;
3244 }
3245
3246 case GetByIdDirect: {
3247 compileGetById(node, AccessType::GetDirect);
3248 break;
3249 }
3250
3251 case GetByIdDirectFlush: {
3252 compileGetByIdFlush(node, AccessType::GetDirect);
3253 break;
3254 }
3255
3256 case GetById: {
3257 compileGetById(node, AccessType::Get);
3258 break;
3259 }
3260
3261 case GetByIdFlush: {
3262 compileGetByIdFlush(node, AccessType::Get);
3263 break;
3264 }
3265
3266 case GetByIdWithThis: {
3267 if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3268 SpeculateCellOperand base(this, node->child1());
3269 SpeculateCellOperand thisValue(this, node->child2());
3270 GPRTemporary resultTag(this);
3271 GPRTemporary resultPayload(this);
3272
3273 GPRReg baseGPR = base.gpr();
3274 GPRReg thisGPR = thisValue.gpr();
3275 GPRReg resultTagGPR = resultTag.gpr();
3276 GPRReg resultPayloadGPR = resultPayload.gpr();
3277
3278 cachedGetByIdWithThis(node->origin.semantic, InvalidGPRReg, baseGPR, InvalidGPRReg, thisGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber());
3279
3280 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3281 } else {
3282 JSValueOperand base(this, node->child1());
3283 JSValueOperand thisValue(this, node->child2());
3284 GPRTemporary resultTag(this);
3285 GPRTemporary resultPayload(this);
3286
3287 GPRReg baseTagGPR = base.tagGPR();
3288 GPRReg basePayloadGPR = base.payloadGPR();
3289 GPRReg thisTagGPR = thisValue.tagGPR();
3290 GPRReg thisPayloadGPR = thisValue.payloadGPR();
3291 GPRReg resultTagGPR = resultTag.gpr();
3292 GPRReg resultPayloadGPR = resultPayload.gpr();
3293
3294 JITCompiler::JumpList notCellList;
3295 notCellList.append(m_jit.branchIfNotCell(base.jsValueRegs()));
3296 notCellList.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
3297
3298 cachedGetByIdWithThis(node->origin.semantic, baseTagGPR, basePayloadGPR, thisTagGPR, thisPayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCellList);
3299
3300 jsValueResult(resultTagGPR, resultPayloadGPR, node);
3301 }
3302
3303 break;
3304 }
3305
3306 case GetArrayLength:
3307 compileGetArrayLength(node);
3308 break;
3309
3310 case DeleteById: {
3311 compileDeleteById(node);
3312 break;
3313 }
3314
3315 case DeleteByVal: {
3316 compileDeleteByVal(node);
3317 break;
3318 }
3319
3320 case CheckCell: {
3321 compileCheckCell(node);
3322 break;
3323 }
3324
3325 case CheckNotEmpty: {
3326 compileCheckNotEmpty(node);
3327 break;
3328 }
3329
3330 case CheckStringIdent:
3331 compileCheckStringIdent(node);
3332 break;
3333
3334 case GetExecutable: {
3335 compileGetExecutable(node);
3336 break;
3337 }
3338
3339 case CheckStructure: {
3340 compileCheckStructure(node);
3341 break;
3342 }
3343
3344 case PutStructure: {
3345 RegisteredStructure oldStructure = node->transition()->previous;
3346 RegisteredStructure newStructure = node->transition()->next;
3347
3348 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3349
3350 SpeculateCellOperand base(this, node->child1());
3351 GPRReg baseGPR = base.gpr();
3352
3353 ASSERT_UNUSED(oldStructure, oldStructure->indexingMode() == newStructure->indexingMode());
3354 ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3355 ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3356 m_jit.storePtr(TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3357
3358 noResult(node);
3359 break;
3360 }
3361
3362 case AllocatePropertyStorage:
3363 compileAllocatePropertyStorage(node);
3364 break;
3365
3366 case ReallocatePropertyStorage:
3367 compileReallocatePropertyStorage(node);
3368 break;
3369
3370 case NukeStructureAndSetButterfly:
3371 compileNukeStructureAndSetButterfly(node);
3372 break;
3373
3374 case GetButterfly:
3375 compileGetButterfly(node);
3376 break;
3377
3378 case GetIndexedPropertyStorage: {
3379 compileGetIndexedPropertyStorage(node);
3380 break;
3381 }
3382
3383 case ConstantStoragePointer: {
3384 compileConstantStoragePointer(node);
3385 break;
3386 }
3387
3388 case GetTypedArrayByteOffset: {
3389 compileGetTypedArrayByteOffset(node);
3390 break;
3391 }
3392
3393 case GetPrototypeOf: {
3394 compileGetPrototypeOf(node);
3395 break;
3396 }
3397
3398 case GetByOffset: {
3399 compileGetByOffset(node);
3400 break;
3401 }
3402
3403 case GetGetterSetterByOffset: {
3404 StorageOperand storage(this, node->child1());
3405 GPRTemporary resultPayload(this);
3406
3407 GPRReg storageGPR = storage.gpr();
3408 GPRReg resultPayloadGPR = resultPayload.gpr();
3409
3410 StorageAccessData& storageAccessData = node->storageAccessData();
3411
3412 m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3413
3414 cellResult(resultPayloadGPR, node);
3415 break;
3416 }
3417
3418 case MatchStructure: {
3419 compileMatchStructure(node);
3420 break;
3421 }
3422
3423 case GetGetter: {
3424 compileGetGetter(node);
3425 break;
3426 }
3427
3428 case GetSetter: {
3429 compileGetSetter(node);
3430 break;
3431 }
3432
3433 case PutByOffset: {
3434 compilePutByOffset(node);
3435 break;
3436 }
3437
3438 case PutByIdFlush: {
3439 compilePutByIdFlush(node);
3440 break;
3441 }
3442
3443 case PutById: {
3444 compilePutById(node);
3445 break;
3446 }
3447
3448 case PutByIdDirect: {
3449 compilePutByIdDirect(node);
3450 break;
3451 }
3452
3453 case PutByIdWithThis: {
3454 compilePutByIdWithThis(node);
3455 break;
3456 }
3457
3458 case PutGetterById:
3459 case PutSetterById: {
3460 compilePutAccessorById(node);
3461 break;
3462 }
3463
3464 case PutGetterSetterById: {
3465 compilePutGetterSetterById(node);
3466 break;
3467 }
3468
3469 case PutGetterByVal:
3470 case PutSetterByVal: {
3471 compilePutAccessorByVal(node);
3472 break;
3473 }
3474
3475 case DefineDataProperty: {
3476 compileDefineDataProperty(node);
3477 break;
3478 }
3479
3480 case DefineAccessorProperty: {
3481 compileDefineAccessorProperty(node);
3482 break;
3483 }
3484
3485 case GetGlobalLexicalVariable:
3486 case GetGlobalVar: {
3487 compileGetGlobalVariable(node);
3488 break;
3489 }
3490
3491 case PutGlobalVariable: {
3492 compilePutGlobalVariable(node);
3493 break;
3494 }
3495
3496 case NotifyWrite: {
3497 compileNotifyWrite(node);
3498 break;
3499 }
3500
3501 case ParseInt: {
3502 compileParseInt(node);
3503 break;
3504 }
3505
3506 case CheckTypeInfoFlags: {
3507 compileCheckTypeInfoFlags(node);
3508 break;
3509 }
3510
3511 case OverridesHasInstance: {
3512 compileOverridesHasInstance(node);
3513 break;
3514 }
3515
3516 case InstanceOf: {
3517 compileInstanceOf(node);
3518 break;
3519 }
3520
3521 case InstanceOfCustom: {
3522 compileInstanceOfCustom(node);
3523 break;
3524 }
3525
3526 case IsEmpty: {
3527 JSValueOperand value(this, node->child1());
3528 GPRTemporary result(this, Reuse, value, TagWord);
3529 m_jit.comparePtr(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag), result.gpr());
3530 booleanResult(result.gpr(), node);
3531 break;
3532 }
3533
3534 case IsUndefined: {
3535 JSValueOperand value(this, node->child1());
3536 GPRTemporary result(this);
3537 GPRTemporary localGlobalObject(this);
3538 GPRTemporary remoteGlobalObject(this);
3539
3540 JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3541
3542 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
3543 JITCompiler::Jump done = m_jit.jump();
3544
3545 isCell.link(&m_jit);
3546 JITCompiler::Jump notMasqueradesAsUndefined;
3547 if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3548 m_jit.move(TrustedImm32(0), result.gpr());
3549 notMasqueradesAsUndefined = m_jit.jump();
3550 } else {
3551 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3552 JITCompiler::NonZero,
3553 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()),
3554 TrustedImm32(MasqueradesAsUndefined));
3555 m_jit.move(TrustedImm32(0), result.gpr());
3556 notMasqueradesAsUndefined = m_jit.jump();
3557
3558 isMasqueradesAsUndefined.link(&m_jit);
3559 GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3560 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3561 m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3562 m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
3563 m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR);
3564 m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3565 }
3566
3567 notMasqueradesAsUndefined.link(&m_jit);
3568 done.link(&m_jit);
3569 booleanResult(result.gpr(), node);
3570 break;
3571 }
3572
3573 case IsUndefinedOrNull: {
3574 JSValueOperand value(this, node->child1());
3575 GPRTemporary result(this, Reuse, value, TagWord);
3576
3577 GPRReg valueTagGPR = value.tagGPR();
3578 GPRReg resultGPR = result.gpr();
3579
3580 m_jit.move(valueTagGPR, resultGPR);
3581 static_assert((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1), "");
3582 m_jit.or32(CCallHelpers::TrustedImm32(1), resultGPR);
3583 m_jit.compare32(CCallHelpers::Equal, resultGPR, CCallHelpers::TrustedImm32(JSValue::NullTag), resultGPR);
3584
3585 booleanResult(resultGPR, node);
3586 break;
3587 }
3588
3589
3590 case IsBoolean: {
3591 JSValueOperand value(this, node->child1());
3592 GPRTemporary result(this, Reuse, value, TagWord);
3593
3594 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
3595 booleanResult(result.gpr(), node);
3596 break;
3597 }
3598
3599 case IsNumber: {
3600 JSValueOperand value(this, node->child1());
3601 GPRTemporary result(this, Reuse, value, TagWord);
3602
3603 m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
3604 m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
3605 booleanResult(result.gpr(), node);
3606 break;
3607 }
3608
3609 case NumberIsInteger: {
3610 JSValueOperand input(this, node->child1());
3611 JSValueRegs inputRegs = input.jsValueRegs();
3612 flushRegisters();
3613 GPRFlushedCallResult result(this);
3614 GPRReg resultGPR = result.gpr();
3615 callOperation(operationNumberIsInteger, resultGPR, inputRegs);
3616 booleanResult(resultGPR, node);
3617 break;
3618 }
3619
3620 case IsObject: {
3621 compileIsObject(node);
3622 break;
3623 }
3624
3625 case IsObjectOrNull: {
3626 compileIsObjectOrNull(node);
3627 break;
3628 }
3629
3630 case IsFunction: {
3631 compileIsFunction(node);
3632 break;
3633 }
3634
3635 case IsCellWithType: {
3636 compileIsCellWithType(node);
3637 break;
3638 }
3639
3640 case IsTypedArrayView: {
3641 compileIsTypedArrayView(node);
3642 break;
3643 }
3644
3645 case TypeOf: {
3646 compileTypeOf(node);
3647 break;
3648 }
3649
3650 case MapHash: {
3651 JSValueOperand input(this, node->child1());
3652
3653 JSValueRegs inputRegs = input.jsValueRegs();
3654
3655 flushRegisters();
3656 GPRFlushedCallResult result(this);
3657 GPRReg resultGPR = result.gpr();
3658 callOperation(operationMapHash, resultGPR, inputRegs);
3659 m_jit.exceptionCheck();
3660 int32Result(resultGPR, node);
3661 break;
3662 }
3663
3664 case NormalizeMapKey: {
3665 compileNormalizeMapKey(node);
3666 break;
3667 }
3668
3669 case GetMapBucket: {
3670 SpeculateCellOperand map(this, node->child1());
3671 JSValueOperand key(this, node->child2());
3672 SpeculateInt32Operand hash(this, node->child3());
3673
3674 GPRReg mapGPR = map.gpr();
3675 JSValueRegs keyRegs = key.jsValueRegs();
3676 GPRReg hashGPR = hash.gpr();
3677
3678 if (node->child1().useKind() == MapObjectUse)
3679 speculateMapObject(node->child1(), mapGPR);
3680 else if (node->child1().useKind() == SetObjectUse)
3681 speculateSetObject(node->child1(), mapGPR);
3682 else
3683 RELEASE_ASSERT_NOT_REACHED();
3684
3685 flushRegisters();
3686 GPRFlushedCallResult result(this);
3687 GPRReg resultGPR = result.gpr();
3688 if (node->child1().useKind() == MapObjectUse)
3689 callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3690 else
3691 callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3692 m_jit.exceptionCheck();
3693 cellResult(resultGPR, node);
3694 break;
3695 }
3696
3697 case GetMapBucketHead:
3698 compileGetMapBucketHead(node);
3699 break;
3700
3701 case GetMapBucketNext:
3702 compileGetMapBucketNext(node);
3703 break;
3704
3705 case LoadKeyFromMapBucket:
3706 compileLoadKeyFromMapBucket(node);
3707 break;
3708
3709 case LoadValueFromMapBucket:
3710 compileLoadValueFromMapBucket(node);
3711 break;
3712
3713 case ExtractValueFromWeakMapGet:
3714 compileExtractValueFromWeakMapGet(node);
3715 break;
3716
3717 case SetAdd:
3718 compileSetAdd(node);
3719 break;
3720
3721 case MapSet:
3722 compileMapSet(node);
3723 break;
3724
3725 case WeakMapGet:
3726 compileWeakMapGet(node);
3727 break;
3728
3729 case WeakSetAdd:
3730 compileWeakSetAdd(node);
3731 break;
3732
3733 case WeakMapSet:
3734 compileWeakMapSet(node);
3735 break;
3736
3737 case Flush:
3738 break;
3739
3740 case Call:
3741 case TailCall:
3742 case TailCallInlinedCaller:
3743 case Construct:
3744 case CallVarargs:
3745 case TailCallVarargs:
3746 case TailCallVarargsInlinedCaller:
3747 case ConstructVarargs:
3748 case CallForwardVarargs:
3749 case TailCallForwardVarargs:
3750 case TailCallForwardVarargsInlinedCaller:
3751 case ConstructForwardVarargs:
3752 case CallEval:
3753 case DirectCall:
3754 case DirectConstruct:
3755 case DirectTailCall:
3756 case DirectTailCallInlinedCaller:
3757 emitCall(node);
3758 break;
3759
3760 case LoadVarargs: {
3761 compileLoadVarargs(node);
3762 break;
3763 }
3764
3765 case ForwardVarargs: {
3766 compileForwardVarargs(node);
3767 break;
3768 }
3769
3770 case CreateActivation: {
3771 compileCreateActivation(node);
3772 break;
3773 }
3774
3775 case PushWithScope: {
3776 compilePushWithScope(node);
3777 break;
3778 }
3779
3780 case CreateDirectArguments: {
3781 compileCreateDirectArguments(node);
3782 break;
3783 }
3784
3785 case GetFromArguments: {
3786 compileGetFromArguments(node);
3787 break;
3788 }
3789
3790 case PutToArguments: {
3791 compilePutToArguments(node);
3792 break;
3793 }
3794
3795 case GetArgument: {
3796 compileGetArgument(node);
3797 break;
3798 }
3799
3800 case CreateScopedArguments: {
3801 compileCreateScopedArguments(node);
3802 break;
3803 }
3804
3805 case CreateClonedArguments: {
3806 compileCreateClonedArguments(node);
3807 break;
3808 }
3809
3810 case CreateRest: {
3811 compileCreateRest(node);
3812 break;
3813 }
3814
3815 case GetRestLength: {
3816 compileGetRestLength(node);
3817 break;
3818 }
3819
3820 case NewFunction:
3821 case NewGeneratorFunction:
3822 case NewAsyncFunction:
3823 case NewAsyncGeneratorFunction:
3824 compileNewFunction(node);
3825 break;
3826
3827 case SetFunctionName:
3828 compileSetFunctionName(node);
3829 break;
3830
3831 case InById:
3832 compileInById(node);
3833 break;
3834
3835 case InByVal:
3836 compileInByVal(node);
3837 break;
3838
3839 case HasOwnProperty: {
3840#if CPU(X86)
3841 ASSERT(node->child2().useKind() == UntypedUse);
3842 SpeculateCellOperand object(this, node->child1());
3843 JSValueOperand key(this, node->child2());
3844 GPRTemporary result(this, Reuse, object);
3845
3846 JSValueRegs keyRegs = key.jsValueRegs();
3847 GPRReg objectGPR = object.gpr();
3848 GPRReg resultGPR = result.gpr();
3849
3850 speculateObject(node->child1());
3851
3852 flushRegisters();
3853 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs);
3854 booleanResult(resultGPR, node);
3855#else
3856 SpeculateCellOperand object(this, node->child1());
3857 GPRTemporary uniquedStringImpl(this);
3858 GPRTemporary temp(this);
3859 GPRTemporary hash(this);
3860 GPRTemporary structureID(this);
3861 GPRTemporary result(this);
3862
3863 Optional<SpeculateCellOperand> keyAsCell;
3864 Optional<JSValueOperand> keyAsValue;
3865 JSValueRegs keyRegs;
3866 if (node->child2().useKind() == UntypedUse) {
3867 keyAsValue.emplace(this, node->child2());
3868 keyRegs = keyAsValue->jsValueRegs();
3869 } else {
3870 ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == SymbolUse);
3871 keyAsCell.emplace(this, node->child2());
3872 keyRegs = JSValueRegs::payloadOnly(keyAsCell->gpr());
3873 }
3874
3875 GPRReg objectGPR = object.gpr();
3876 GPRReg implGPR = uniquedStringImpl.gpr();
3877 GPRReg tempGPR = temp.gpr();
3878 GPRReg hashGPR = hash.gpr();
3879 GPRReg structureIDGPR = structureID.gpr();
3880 GPRReg resultGPR = result.gpr();
3881
3882 speculateObject(node->child1());
3883
3884 MacroAssembler::JumpList slowPath;
3885 switch (node->child2().useKind()) {
3886 case SymbolUse: {
3887 speculateSymbol(node->child2(), keyRegs.payloadGPR());
3888 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR);
3889 break;
3890 }
3891 case StringUse: {
3892 speculateString(node->child2(), keyRegs.payloadGPR());
3893 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR);
3894 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
3895 slowPath.append(m_jit.branchTest32(
3896 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
3897 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
3898 break;
3899 }
3900 case UntypedUse: {
3901 slowPath.append(m_jit.branchIfNotCell(keyRegs));
3902 auto isNotString = m_jit.branchIfNotString(keyRegs.payloadGPR());
3903 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), JSString::offsetOfValue()), implGPR);
3904 slowPath.append(m_jit.branchIfRopeStringImpl(implGPR));
3905 slowPath.append(m_jit.branchTest32(
3906 MacroAssembler::Zero, MacroAssembler::Address(implGPR, StringImpl::flagsOffset()),
3907 MacroAssembler::TrustedImm32(StringImpl::flagIsAtomic())));
3908 auto hasUniquedImpl = m_jit.jump();
3909
3910 isNotString.link(&m_jit);
3911 slowPath.append(m_jit.branchIfNotSymbol(keyRegs.payloadGPR()));
3912 m_jit.loadPtr(MacroAssembler::Address(keyRegs.payloadGPR(), Symbol::offsetOfSymbolImpl()), implGPR);
3913
3914 hasUniquedImpl.link(&m_jit);
3915 break;
3916 }
3917 default:
3918 RELEASE_ASSERT_NOT_REACHED();
3919 }
3920
3921 // Note that we don't test if the hash is zero here. AtomicStringImpl's can't have a zero
3922 // hash, however, a SymbolImpl may. But, because this is a cache, we don't care. We only
3923 // ever load the result from the cache if the cache entry matches what we are querying for.
3924 // So we either get super lucky and use zero for the hash and somehow collide with the entity
3925 // we're looking for, or we realize we're comparing against another entity, and go to the
3926 // slow path anyways.
3927 m_jit.load32(MacroAssembler::Address(implGPR, UniquedStringImpl::flagsOffset()), hashGPR);
3928 m_jit.urshift32(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), hashGPR);
3929 m_jit.load32(MacroAssembler::Address(objectGPR, JSCell::structureIDOffset()), structureIDGPR);
3930 m_jit.add32(structureIDGPR, hashGPR);
3931 m_jit.and32(TrustedImm32(HasOwnPropertyCache::mask), hashGPR);
3932 m_jit.mul32(TrustedImm32(sizeof(HasOwnPropertyCache::Entry)), hashGPR, hashGPR);
3933 ASSERT(m_jit.vm()->hasOwnPropertyCache());
3934 m_jit.move(TrustedImmPtr(m_jit.vm()->hasOwnPropertyCache()), tempGPR);
3935 slowPath.append(m_jit.branchPtr(MacroAssembler::NotEqual,
3936 MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfImpl()), implGPR));
3937 m_jit.load8(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfResult()), resultGPR);
3938 m_jit.load32(MacroAssembler::BaseIndex(tempGPR, hashGPR, MacroAssembler::TimesOne, HasOwnPropertyCache::Entry::offsetOfStructureID()), tempGPR);
3939 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, tempGPR, structureIDGPR));
3940 auto done = m_jit.jump();
3941
3942 slowPath.link(&m_jit);
3943 silentSpillAllRegisters(resultGPR);
3944 if (node->child2().useKind() != UntypedUse) {
3945 m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), tempGPR);
3946 keyRegs = JSValueRegs(tempGPR, keyRegs.payloadGPR());
3947 }
3948 callOperation(operationHasOwnProperty, resultGPR, objectGPR, keyRegs);
3949 silentFillAllRegisters();
3950 m_jit.exceptionCheck();
3951
3952 done.link(&m_jit);
3953 booleanResult(resultGPR, node);
3954#endif // CPU(X86)
3955 break;
3956 }
3957
3958 case StoreBarrier:
3959 case FencedStoreBarrier: {
3960 compileStoreBarrier(node);
3961 break;
3962 }
3963
3964 case GetEnumerableLength: {
3965 compileGetEnumerableLength(node);
3966 break;
3967 }
3968 case HasGenericProperty: {
3969 compileHasGenericProperty(node);
3970 break;
3971 }
3972 case HasStructureProperty: {
3973 compileHasStructureProperty(node);
3974 break;
3975 }
3976 case HasIndexedProperty: {
3977 compileHasIndexedProperty(node);
3978 break;
3979 }
3980 case GetDirectPname: {
3981 compileGetDirectPname(node);
3982 break;
3983 }
3984 case GetPropertyEnumerator: {
3985 compileGetPropertyEnumerator(node);
3986 break;
3987 }
3988 case GetEnumeratorStructurePname:
3989 case GetEnumeratorGenericPname: {
3990 compileGetEnumeratorPname(node);
3991 break;
3992 }
3993 case ToIndexString: {
3994 compileToIndexString(node);
3995 break;
3996 }
3997 case ProfileType: {
3998 compileProfileType(node);
3999 break;
4000 }
4001 case ProfileControlFlow: {
4002 GPRTemporary scratch1(this);
4003 BasicBlockLocation* basicBlockLocation = node->basicBlockLocation();
4004 basicBlockLocation->emitExecuteCode(m_jit, scratch1.gpr());
4005 noResult(node);
4006 break;
4007 }
4008
4009 case LogShadowChickenPrologue: {
4010 compileLogShadowChickenPrologue(node);
4011 break;
4012 }
4013
4014 case LogShadowChickenTail: {
4015 compileLogShadowChickenTail(node);
4016 break;
4017 }
4018
4019 case ForceOSRExit: {
4020 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
4021 break;
4022 }
4023
4024 case InvalidationPoint:
4025 emitInvalidationPoint(node);
4026 break;
4027
4028 case CheckTraps:
4029 compileCheckTraps(node);
4030 break;
4031
4032 case CountExecution:
4033 m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address()));
4034 break;
4035
4036 case SuperSamplerBegin:
4037 m_jit.add32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4038 break;
4039
4040 case SuperSamplerEnd:
4041 m_jit.sub32(TrustedImm32(1), MacroAssembler::AbsoluteAddress(bitwise_cast<void*>(&g_superSamplerCount)));
4042 break;
4043
4044 case Phantom:
4045 case Check:
4046 case CheckVarargs:
4047 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
4048 noResult(node);
4049 break;
4050
4051 case PhantomLocal:
4052 case LoopHint:
4053 // This is a no-op.
4054 noResult(node);
4055 break;
4056
4057 case MaterializeNewObject:
4058 compileMaterializeNewObject(node);
4059 break;
4060
4061 case PutDynamicVar: {
4062 compilePutDynamicVar(node);
4063 break;
4064 }
4065
4066 case GetDynamicVar: {
4067 compileGetDynamicVar(node);
4068 break;
4069 }
4070
4071 case ResolveScopeForHoistingFuncDeclInEval: {
4072 compileResolveScopeForHoistingFuncDeclInEval(node);
4073 break;
4074 }
4075
4076 case ResolveScope: {
4077 compileResolveScope(node);
4078 break;
4079 }
4080
4081 case CallDOM:
4082 compileCallDOM(node);
4083 break;
4084
4085 case CallDOMGetter:
4086 compileCallDOMGetter(node);
4087 break;
4088
4089 case CheckSubClass:
4090 compileCheckSubClass(node);
4091 break;
4092
4093 case Unreachable:
4094 unreachable(node);
4095 break;
4096
4097 case ExtractCatchLocal: {
4098 compileExtractCatchLocal(node);
4099 break;
4100 }
4101
4102 case ClearCatchLocals:
4103 compileClearCatchLocals(node);
4104 break;
4105
4106 case CheckStructureOrEmpty:
4107 DFG_CRASH(m_jit.graph(), node, "CheckStructureOrEmpty only used in 64-bit DFG");
4108 break;
4109
4110 case FilterCallLinkStatus:
4111 case FilterGetByIdStatus:
4112 case FilterPutByIdStatus:
4113 case FilterInByIdStatus:
4114 m_interpreter.filterICStatus(node);
4115 noResult(node);
4116 break;
4117
4118 case LastNodeType:
4119 case Phi:
4120 case Upsilon:
4121 case ExtractOSREntryLocal:
4122 case CheckTierUpInLoop:
4123 case CheckTierUpAtReturn:
4124 case CheckTierUpAndOSREnter:
4125 case Int52Rep:
4126 case FiatInt52:
4127 case Int52Constant:
4128 case CheckInBounds:
4129 case ArithIMul:
4130 case MultiGetByOffset:
4131 case MultiPutByOffset:
4132 case CheckBadCell:
4133 case BottomValue:
4134 case PhantomNewObject:
4135 case PhantomNewFunction:
4136 case PhantomNewGeneratorFunction:
4137 case PhantomNewAsyncFunction:
4138 case PhantomNewAsyncGeneratorFunction:
4139 case PhantomCreateActivation:
4140 case PhantomNewRegexp:
4141 case PutHint:
4142 case CheckStructureImmediate:
4143 case MaterializeCreateActivation:
4144 case PutStack:
4145 case KillStack:
4146 case GetStack:
4147 case GetMyArgumentByVal:
4148 case GetMyArgumentByValOutOfBounds:
4149 case GetVectorLength:
4150 case PhantomCreateRest:
4151 case PhantomSpread:
4152 case PhantomNewArrayWithSpread:
4153 case PhantomNewArrayBuffer:
4154 case AtomicsIsLockFree:
4155 case AtomicsAdd:
4156 case AtomicsAnd:
4157 case AtomicsCompareExchange:
4158 case AtomicsExchange:
4159 case AtomicsLoad:
4160 case AtomicsOr:
4161 case AtomicsStore:
4162 case AtomicsSub:
4163 case AtomicsXor:
4164 case IdentityWithProfile:
4165 case InitializeEntrypointArguments:
4166 case EntrySwitch:
4167 case CPUIntrinsic:
4168 case AssertNotEmpty:
4169 case DataViewGetInt:
4170 case DataViewGetFloat:
4171 case DataViewSet:
4172 DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend");
4173 break;
4174 }
4175
4176 if (!m_compileOkay)
4177 return;
4178
4179 if (node->hasResult() && node->mustGenerate())
4180 use(node);
4181}
4182
4183void SpeculativeJIT::moveTrueTo(GPRReg gpr)
4184{
4185 m_jit.move(TrustedImm32(1), gpr);
4186}
4187
4188void SpeculativeJIT::moveFalseTo(GPRReg gpr)
4189{
4190 m_jit.move(TrustedImm32(0), gpr);
4191}
4192
4193void SpeculativeJIT::blessBoolean(GPRReg)
4194{
4195}
4196
4197void SpeculativeJIT::compileArithRandom(Node* node)
4198{
4199 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
4200
4201 flushRegisters();
4202
4203 FPRResult result(this);
4204 callOperation(operationRandom, result.fpr(), globalObject);
4205 // operationRandom does not raise any exception.
4206 doubleResult(result.fpr(), node);
4207}
4208
4209#endif
4210
4211} } // namespace JSC::DFG
4212
4213#endif
4214