1/* 2 * Copyright (C) 2011, 2012, 2013, 2014 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 "DFGAbstractInterpreterInlines.h" 34#include "DFGCallArrayAllocatorSlowPathGenerator.h" 35#include "DFGOperations.h" 36#include "DFGSlowPathGenerator.h" 37#include "Debugger.h" 38#include "JSActivation.h" 39#include "ObjectPrototype.h" 40#include "JSCInlines.h" 41 42namespace JSC { namespace DFG { 43 44#if USE(JSVALUE32_64) 45 46bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr) 47{ 48 // FIXME: For double we could fill with a FPR. 49 UNUSED_PARAM(fpr); 50 51 VirtualRegister virtualRegister = edge->virtualRegister(); 52 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 53 54 switch (info.registerFormat()) { 55 case DataFormatNone: { 56 57 if (edge->hasConstant()) { 58 tagGPR = allocate(); 59 payloadGPR = allocate(); 60 m_jit.move(Imm32(valueOfJSConstant(edge.node()).tag()), tagGPR); 61 m_jit.move(Imm32(valueOfJSConstant(edge.node()).payload()), payloadGPR); 62 m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant); 63 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant); 64 info.fillJSValue(*m_stream, tagGPR, payloadGPR, isInt32Constant(edge.node()) ? DataFormatJSInt32 : DataFormatJS); 65 } else { 66 DataFormat spillFormat = info.spillFormat(); 67 ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage); 68 tagGPR = allocate(); 69 payloadGPR = allocate(); 70 switch (spillFormat) { 71 case DataFormatInt32: 72 m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR); 73 spillFormat = DataFormatJSInt32; // This will be used as the new register format. 74 break; 75 case DataFormatCell: 76 m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR); 77 spillFormat = DataFormatJSCell; // This will be used as the new register format. 78 break; 79 case DataFormatBoolean: 80 m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR); 81 spillFormat = DataFormatJSBoolean; // This will be used as the new register format. 82 break; 83 default: 84 m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR); 85 break; 86 } 87 m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR); 88 m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled); 89 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled); 90 info.fillJSValue(*m_stream, tagGPR, payloadGPR, spillFormat == DataFormatJSDouble ? DataFormatJS : spillFormat); 91 } 92 93 return true; 94 } 95 96 case DataFormatInt32: 97 case DataFormatCell: 98 case DataFormatBoolean: { 99 GPRReg gpr = info.gpr(); 100 // If the register has already been locked we need to take a copy. 101 if (m_gprs.isLocked(gpr)) { 102 payloadGPR = allocate(); 103 m_jit.move(gpr, payloadGPR); 104 } else { 105 payloadGPR = gpr; 106 m_gprs.lock(gpr); 107 } 108 tagGPR = allocate(); 109 uint32_t tag = JSValue::EmptyValueTag; 110 DataFormat fillFormat = DataFormatJS; 111 switch (info.registerFormat()) { 112 case DataFormatInt32: 113 tag = JSValue::Int32Tag; 114 fillFormat = DataFormatJSInt32; 115 break; 116 case DataFormatCell: 117 tag = JSValue::CellTag; 118 fillFormat = DataFormatJSCell; 119 break; 120 case DataFormatBoolean: 121 tag = JSValue::BooleanTag; 122 fillFormat = DataFormatJSBoolean; 123 break; 124 default: 125 RELEASE_ASSERT_NOT_REACHED(); 126 break; 127 } 128 m_jit.move(TrustedImm32(tag), tagGPR); 129 m_gprs.release(gpr); 130 m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS); 131 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS); 132 info.fillJSValue(*m_stream, tagGPR, payloadGPR, fillFormat); 133 return true; 134 } 135 136 case DataFormatJSDouble: 137 case DataFormatJS: 138 case DataFormatJSInt32: 139 case DataFormatJSCell: 140 case DataFormatJSBoolean: { 141 tagGPR = info.tagGPR(); 142 payloadGPR = info.payloadGPR(); 143 m_gprs.lock(tagGPR); 144 m_gprs.lock(payloadGPR); 145 return true; 146 } 147 148 case DataFormatStorage: 149 case DataFormatDouble: 150 // this type currently never occurs 151 RELEASE_ASSERT_NOT_REACHED(); 152 153 default: 154 RELEASE_ASSERT_NOT_REACHED(); 155 return true; 156 } 157} 158 159void SpeculativeJIT::cachedGetById( 160 CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, 161 unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode) 162{ 163 // This is a hacky fix for when the register allocator decides to alias the base payload with the result tag. This only happens 164 // in the case of GetByIdFlush, which has a relatively expensive register allocation story already so we probably don't need to 165 // trip over one move instruction. 166 if (basePayloadGPR == resultTagGPR) { 167 RELEASE_ASSERT(basePayloadGPR != resultPayloadGPR); 168 169 if (baseTagGPROrNone == resultPayloadGPR) { 170 m_jit.swap(basePayloadGPR, baseTagGPROrNone); 171 baseTagGPROrNone = resultTagGPR; 172 } else 173 m_jit.move(basePayloadGPR, resultPayloadGPR); 174 basePayloadGPR = resultPayloadGPR; 175 } 176 177 JITGetByIdGenerator gen( 178 m_jit.codeBlock(), codeOrigin, usedRegisters(), 179 JSValueRegs(baseTagGPROrNone, basePayloadGPR), 180 JSValueRegs(resultTagGPR, resultPayloadGPR), spillMode); 181 182 gen.generateFastPath(m_jit); 183 184 JITCompiler::JumpList slowCases; 185 if (slowPathTarget.isSet()) 186 slowCases.append(slowPathTarget); 187 slowCases.append(gen.slowPathJump()); 188 189 OwnPtr<SlowPathGenerator> slowPath; 190 if (baseTagGPROrNone == InvalidGPRReg) { 191 slowPath = slowPathCall( 192 slowCases, this, operationGetByIdOptimize, 193 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), 194 static_cast<int32_t>(JSValue::CellTag), basePayloadGPR, 195 identifierUID(identifierNumber)); 196 } else { 197 slowPath = slowPathCall( 198 slowCases, this, operationGetByIdOptimize, 199 JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), baseTagGPROrNone, 200 basePayloadGPR, identifierUID(identifierNumber)); 201 } 202 203 m_jit.addGetById(gen, slowPath.get()); 204 addSlowPathGenerator(slowPath.release()); 205} 206 207void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode) 208{ 209 JITPutByIdGenerator gen( 210 m_jit.codeBlock(), codeOrigin, usedRegisters(), 211 JSValueRegs::payloadOnly(basePayloadGPR), JSValueRegs(valueTagGPR, valuePayloadGPR), 212 scratchGPR, spillMode, m_jit.ecmaModeFor(codeOrigin), putKind); 213 214 gen.generateFastPath(m_jit); 215 216 JITCompiler::JumpList slowCases; 217 if (slowPathTarget.isSet()) 218 slowCases.append(slowPathTarget); 219 slowCases.append(gen.slowPathJump()); 220 221 OwnPtr<SlowPathGenerator> slowPath = slowPathCall( 222 slowCases, this, gen.slowPathFunction(), NoResult, gen.stubInfo(), valueTagGPR, 223 valuePayloadGPR, basePayloadGPR, identifierUID(identifierNumber)); 224 225 m_jit.addPutById(gen, slowPath.get()); 226 addSlowPathGenerator(slowPath.release()); 227} 228 229void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert) 230{ 231 JSValueOperand arg(this, operand); 232 GPRReg argTagGPR = arg.tagGPR(); 233 GPRReg argPayloadGPR = arg.payloadGPR(); 234 235 GPRTemporary resultPayload(this, Reuse, arg, PayloadWord); 236 GPRReg resultPayloadGPR = resultPayload.gpr(); 237 238 JITCompiler::Jump notCell; 239 JITCompiler::Jump notMasqueradesAsUndefined; 240 if (masqueradesAsUndefinedWatchpointIsStillValid()) { 241 if (!isKnownCell(operand.node())) 242 notCell = branchNotCell(arg.jsValueRegs()); 243 244 m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR); 245 notMasqueradesAsUndefined = m_jit.jump(); 246 } else { 247 GPRTemporary localGlobalObject(this); 248 GPRTemporary remoteGlobalObject(this); 249 250 if (!isKnownCell(operand.node())) 251 notCell = branchNotCell(arg.jsValueRegs()); 252 253 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8( 254 JITCompiler::NonZero, 255 JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 256 JITCompiler::TrustedImm32(MasqueradesAsUndefined)); 257 258 m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR); 259 notMasqueradesAsUndefined = m_jit.jump(); 260 261 isMasqueradesAsUndefined.link(&m_jit); 262 GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); 263 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); 264 m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR); 265 m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultPayloadGPR); 266 m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); 267 m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR); 268 } 269 270 if (!isKnownCell(operand.node())) { 271 JITCompiler::Jump done = m_jit.jump(); 272 273 notCell.link(&m_jit); 274 // null or undefined? 275 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 276 m_jit.move(argTagGPR, resultPayloadGPR); 277 m_jit.or32(TrustedImm32(1), resultPayloadGPR); 278 m_jit.compare32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultPayloadGPR, TrustedImm32(JSValue::NullTag), resultPayloadGPR); 279 280 done.link(&m_jit); 281 } 282 283 notMasqueradesAsUndefined.link(&m_jit); 284 285 booleanResult(resultPayloadGPR, m_currentNode); 286} 287 288void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, Node* branchNode, bool invert) 289{ 290 BasicBlock* taken = branchNode->branchData()->taken.block; 291 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 292 293 if (taken == nextBlock()) { 294 invert = !invert; 295 BasicBlock* tmp = taken; 296 taken = notTaken; 297 notTaken = tmp; 298 } 299 300 JSValueOperand arg(this, operand); 301 GPRReg argTagGPR = arg.tagGPR(); 302 GPRReg argPayloadGPR = arg.payloadGPR(); 303 304 GPRTemporary result(this, Reuse, arg, TagWord); 305 GPRReg resultGPR = result.gpr(); 306 307 JITCompiler::Jump notCell; 308 309 if (masqueradesAsUndefinedWatchpointIsStillValid()) { 310 if (!isKnownCell(operand.node())) 311 notCell = branchNotCell(arg.jsValueRegs()); 312 313 jump(invert ? taken : notTaken, ForceJump); 314 } else { 315 GPRTemporary localGlobalObject(this); 316 GPRTemporary remoteGlobalObject(this); 317 318 if (!isKnownCell(operand.node())) 319 notCell = branchNotCell(arg.jsValueRegs()); 320 321 branchTest8(JITCompiler::Zero, 322 JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 323 JITCompiler::TrustedImm32(MasqueradesAsUndefined), 324 invert ? taken : notTaken); 325 326 GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); 327 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); 328 m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR); 329 m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultGPR); 330 m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR); 331 branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken); 332 } 333 334 if (!isKnownCell(operand.node())) { 335 jump(notTaken, ForceJump); 336 337 notCell.link(&m_jit); 338 // null or undefined? 339 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 340 m_jit.move(argTagGPR, resultGPR); 341 m_jit.or32(TrustedImm32(1), resultGPR); 342 branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(JSValue::NullTag), taken); 343 } 344 345 jump(notTaken); 346} 347 348bool SpeculativeJIT::nonSpeculativeCompareNull(Node* node, Edge operand, bool invert) 349{ 350 unsigned branchIndexInBlock = detectPeepHoleBranch(); 351 if (branchIndexInBlock != UINT_MAX) { 352 Node* branchNode = m_block->at(branchIndexInBlock); 353 354 ASSERT(node->adjustedRefCount() == 1); 355 356 nonSpeculativePeepholeBranchNull(operand, branchNode, invert); 357 358 use(node->child1()); 359 use(node->child2()); 360 m_indexInBlock = branchIndexInBlock; 361 m_currentNode = branchNode; 362 363 return true; 364 } 365 366 nonSpeculativeNonPeepholeCompareNull(operand, invert); 367 368 return false; 369} 370 371void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction) 372{ 373 BasicBlock* taken = branchNode->branchData()->taken.block; 374 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 375 376 JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero; 377 378 // The branch instruction will branch to the taken block. 379 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through. 380 if (taken == nextBlock()) { 381 cond = JITCompiler::invert(cond); 382 callResultCondition = JITCompiler::Zero; 383 BasicBlock* tmp = taken; 384 taken = notTaken; 385 notTaken = tmp; 386 } 387 388 JSValueOperand arg1(this, node->child1()); 389 JSValueOperand arg2(this, node->child2()); 390 GPRReg arg1TagGPR = arg1.tagGPR(); 391 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 392 GPRReg arg2TagGPR = arg2.tagGPR(); 393 GPRReg arg2PayloadGPR = arg2.payloadGPR(); 394 395 JITCompiler::JumpList slowPath; 396 397 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) { 398 GPRResult result(this); 399 GPRReg resultGPR = result.gpr(); 400 401 arg1.use(); 402 arg2.use(); 403 404 flushRegisters(); 405 callOperation(helperFunction, resultGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 406 407 branchTest32(callResultCondition, resultGPR, taken); 408 } else { 409 GPRTemporary result(this); 410 GPRReg resultGPR = result.gpr(); 411 412 arg1.use(); 413 arg2.use(); 414 415 if (!isKnownInteger(node->child1().node())) 416 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); 417 if (!isKnownInteger(node->child2().node())) 418 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); 419 420 branch32(cond, arg1PayloadGPR, arg2PayloadGPR, taken); 421 422 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) { 423 jump(notTaken, ForceJump); 424 425 slowPath.link(&m_jit); 426 427 silentSpillAllRegisters(resultGPR); 428 callOperation(helperFunction, resultGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 429 silentFillAllRegisters(resultGPR); 430 431 branchTest32(callResultCondition, resultGPR, taken); 432 } 433 } 434 435 jump(notTaken); 436 437 m_indexInBlock = m_block->size() - 1; 438 m_currentNode = branchNode; 439} 440 441template<typename JumpType> 442class CompareAndBoxBooleanSlowPathGenerator 443 : public CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg> { 444public: 445 CompareAndBoxBooleanSlowPathGenerator( 446 JumpType from, SpeculativeJIT* jit, 447 S_JITOperation_EJJ function, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, 448 GPRReg arg2Tag, GPRReg arg2Payload) 449 : CallSlowPathGenerator<JumpType, S_JITOperation_EJJ, GPRReg>( 450 from, jit, function, NeedToSpill, result) 451 , m_arg1Tag(arg1Tag) 452 , m_arg1Payload(arg1Payload) 453 , m_arg2Tag(arg2Tag) 454 , m_arg2Payload(arg2Payload) 455 { 456 } 457 458protected: 459 virtual void generateInternal(SpeculativeJIT* jit) 460 { 461 this->setUp(jit); 462 this->recordCall( 463 jit->callOperation( 464 this->m_function, this->m_result, m_arg1Tag, m_arg1Payload, m_arg2Tag, 465 m_arg2Payload)); 466 jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result); 467 this->tearDown(jit); 468 } 469 470private: 471 GPRReg m_arg1Tag; 472 GPRReg m_arg1Payload; 473 GPRReg m_arg2Tag; 474 GPRReg m_arg2Payload; 475}; 476 477void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction) 478{ 479 JSValueOperand arg1(this, node->child1()); 480 JSValueOperand arg2(this, node->child2()); 481 GPRReg arg1TagGPR = arg1.tagGPR(); 482 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 483 GPRReg arg2TagGPR = arg2.tagGPR(); 484 GPRReg arg2PayloadGPR = arg2.payloadGPR(); 485 486 JITCompiler::JumpList slowPath; 487 488 if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) { 489 GPRResult result(this); 490 GPRReg resultPayloadGPR = result.gpr(); 491 492 arg1.use(); 493 arg2.use(); 494 495 flushRegisters(); 496 callOperation(helperFunction, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 497 498 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 499 } else { 500 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord); 501 GPRReg resultPayloadGPR = resultPayload.gpr(); 502 503 arg1.use(); 504 arg2.use(); 505 506 if (!isKnownInteger(node->child1().node())) 507 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg1TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); 508 if (!isKnownInteger(node->child2().node())) 509 slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, arg2TagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag))); 510 511 m_jit.compare32(cond, arg1PayloadGPR, arg2PayloadGPR, resultPayloadGPR); 512 513 if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) { 514 addSlowPathGenerator(adoptPtr( 515 new CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>( 516 slowPath, this, helperFunction, resultPayloadGPR, arg1TagGPR, 517 arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR))); 518 } 519 520 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 521 } 522} 523 524void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert) 525{ 526 BasicBlock* taken = branchNode->branchData()->taken.block; 527 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 528 529 // The branch instruction will branch to the taken block. 530 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through. 531 if (taken == nextBlock()) { 532 invert = !invert; 533 BasicBlock* tmp = taken; 534 taken = notTaken; 535 notTaken = tmp; 536 } 537 538 JSValueOperand arg1(this, node->child1()); 539 JSValueOperand arg2(this, node->child2()); 540 GPRReg arg1TagGPR = arg1.tagGPR(); 541 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 542 GPRReg arg2TagGPR = arg2.tagGPR(); 543 GPRReg arg2PayloadGPR = arg2.payloadGPR(); 544 545 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord); 546 GPRReg resultPayloadGPR = resultPayload.gpr(); 547 548 arg1.use(); 549 arg2.use(); 550 551 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) { 552 // see if we get lucky: if the arguments are cells and they reference the same 553 // cell, then they must be strictly equal. 554 branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR, invert ? notTaken : taken); 555 556 silentSpillAllRegisters(resultPayloadGPR); 557 callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 558 silentFillAllRegisters(resultPayloadGPR); 559 560 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken); 561 } else { 562 // FIXME: Add fast paths for twoCells, number etc. 563 564 silentSpillAllRegisters(resultPayloadGPR); 565 callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 566 silentFillAllRegisters(resultPayloadGPR); 567 568 branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken); 569 } 570 571 jump(notTaken); 572} 573 574void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert) 575{ 576 JSValueOperand arg1(this, node->child1()); 577 JSValueOperand arg2(this, node->child2()); 578 GPRReg arg1TagGPR = arg1.tagGPR(); 579 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 580 GPRReg arg2TagGPR = arg2.tagGPR(); 581 GPRReg arg2PayloadGPR = arg2.payloadGPR(); 582 583 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord); 584 GPRReg resultPayloadGPR = resultPayload.gpr(); 585 586 arg1.use(); 587 arg2.use(); 588 589 if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) { 590 // see if we get lucky: if the arguments are cells and they reference the same 591 // cell, then they must be strictly equal. 592 // FIXME: this should flush registers instead of silent spill/fill. 593 JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR); 594 595 m_jit.move(JITCompiler::TrustedImm32(!invert), resultPayloadGPR); 596 JITCompiler::Jump done = m_jit.jump(); 597 598 notEqualCase.link(&m_jit); 599 600 silentSpillAllRegisters(resultPayloadGPR); 601 callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 602 silentFillAllRegisters(resultPayloadGPR); 603 604 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR); 605 606 done.link(&m_jit); 607 } else { 608 // FIXME: Add fast paths. 609 610 silentSpillAllRegisters(resultPayloadGPR); 611 callOperation(operationCompareStrictEq, resultPayloadGPR, arg1TagGPR, arg1PayloadGPR, arg2TagGPR, arg2PayloadGPR); 612 silentFillAllRegisters(resultPayloadGPR); 613 614 m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR); 615 } 616 617 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 618} 619 620void SpeculativeJIT::compileMiscStrictEq(Node* node) 621{ 622 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 623 JSValueOperand op2(this, node->child2(), ManualOperandSpeculation); 624 GPRTemporary result(this); 625 626 if (node->child1().useKind() == MiscUse) 627 speculateMisc(node->child1(), op1.jsValueRegs()); 628 if (node->child2().useKind() == MiscUse) 629 speculateMisc(node->child2(), op2.jsValueRegs()); 630 631 m_jit.move(TrustedImm32(0), result.gpr()); 632 JITCompiler::Jump notEqual = m_jit.branch32(JITCompiler::NotEqual, op1.tagGPR(), op2.tagGPR()); 633 m_jit.compare32(JITCompiler::Equal, op1.payloadGPR(), op2.payloadGPR(), result.gpr()); 634 notEqual.link(&m_jit); 635 booleanResult(result.gpr(), node); 636} 637 638void SpeculativeJIT::emitCall(Node* node) 639{ 640 if (node->op() != Call) 641 ASSERT(node->op() == Construct); 642 643 // For constructors, the this argument is not passed but we have to make space 644 // for it. 645 int dummyThisArgument = node->op() == Call ? 0 : 1; 646 647 CallLinkInfo::CallType callType = node->op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; 648 649 Edge calleeEdge = m_jit.graph().m_varArgChildren[node->firstChild()]; 650 JSValueOperand callee(this, calleeEdge); 651 GPRReg calleeTagGPR = callee.tagGPR(); 652 GPRReg calleePayloadGPR = callee.payloadGPR(); 653 use(calleeEdge); 654 655 // The call instruction's first child is either the function (normal call) or the 656 // receiver (method call). subsequent children are the arguments. 657 int numPassedArgs = node->numChildren() - 1; 658 659 int numArgs = numPassedArgs + dummyThisArgument; 660 661 m_jit.store32(MacroAssembler::TrustedImm32(numArgs), calleeFramePayloadSlot(JSStack::ArgumentCount)); 662 m_jit.store32(calleePayloadGPR, calleeFramePayloadSlot(JSStack::Callee)); 663 m_jit.store32(calleeTagGPR, calleeFrameTagSlot(JSStack::Callee)); 664 665 for (int i = 0; i < numPassedArgs; i++) { 666 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i]; 667 JSValueOperand arg(this, argEdge); 668 GPRReg argTagGPR = arg.tagGPR(); 669 GPRReg argPayloadGPR = arg.payloadGPR(); 670 use(argEdge); 671 672 m_jit.store32(argTagGPR, calleeArgumentTagSlot(i + dummyThisArgument)); 673 m_jit.store32(argPayloadGPR, calleeArgumentPayloadSlot(i + dummyThisArgument)); 674 } 675 676 flushRegisters(); 677 678 GPRResult resultPayload(this); 679 GPRResult2 resultTag(this); 680 GPRReg resultPayloadGPR = resultPayload.gpr(); 681 GPRReg resultTagGPR = resultTag.gpr(); 682 683 JITCompiler::DataLabelPtr targetToCheck; 684 JITCompiler::JumpList slowPath; 685 686 m_jit.emitStoreCodeOrigin(node->origin.semantic); 687 688 slowPath.append(branchNotCell(callee.jsValueRegs())); 689 slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck)); 690 m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultPayloadGPR); 691 m_jit.storePtr(resultPayloadGPR, calleeFramePayloadSlot(JSStack::ScopeChain)); 692 m_jit.storePtr(MacroAssembler::TrustedImm32(JSValue::CellTag), calleeFrameTagSlot(JSStack::ScopeChain)); 693 694 JITCompiler::Call fastCall = m_jit.nearCall(); 695 696 JITCompiler::Jump done = m_jit.jump(); 697 698 slowPath.link(&m_jit); 699 700 // Callee payload needs to be in regT0, tag in regT1 701 if (calleeTagGPR == GPRInfo::regT0) { 702 if (calleePayloadGPR == GPRInfo::regT1) 703 m_jit.swap(GPRInfo::regT1, GPRInfo::regT0); 704 else { 705 m_jit.move(calleeTagGPR, GPRInfo::regT1); 706 m_jit.move(calleePayloadGPR, GPRInfo::regT0); 707 } 708 } else { 709 m_jit.move(calleePayloadGPR, GPRInfo::regT0); 710 m_jit.move(calleeTagGPR, GPRInfo::regT1); 711 } 712 CallLinkInfo* info = m_jit.codeBlock()->addCallLinkInfo(); 713 m_jit.move(MacroAssembler::TrustedImmPtr(info), GPRInfo::regT2); 714 JITCompiler::Call slowCall = m_jit.nearCall(); 715 716 done.link(&m_jit); 717 718 m_jit.setupResults(resultPayloadGPR, resultTagGPR); 719 720 jsValueResult(resultTagGPR, resultPayloadGPR, node, DataFormatJS, UseChildrenCalledExplicitly); 721 722 info->callType = callType; 723 info->codeOrigin = node->origin.semantic; 724 info->calleeGPR = calleePayloadGPR; 725 m_jit.addJSCall(fastCall, slowCall, targetToCheck, info); 726} 727 728template<bool strict> 729GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat) 730{ 731 AbstractValue& value = m_state.forNode(edge); 732 SpeculatedType type = value.m_type; 733 ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32)); 734 m_interpreter.filter(value, SpecInt32); 735 VirtualRegister virtualRegister = edge->virtualRegister(); 736 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 737 738 if (edge->hasConstant() && !isInt32Constant(edge.node())) { 739 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 740 returnFormat = DataFormatInt32; 741 return allocate(); 742 } 743 744 switch (info.registerFormat()) { 745 case DataFormatNone: { 746 if (edge->hasConstant()) { 747 ASSERT(isInt32Constant(edge.node())); 748 GPRReg gpr = allocate(); 749 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 750 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 751 info.fillInt32(*m_stream, gpr); 752 returnFormat = DataFormatInt32; 753 return gpr; 754 } 755 756 DataFormat spillFormat = info.spillFormat(); 757 ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32); 758 759 // If we know this was spilled as an integer we can fill without checking. 760 if (type & ~SpecInt32) 761 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag))); 762 763 GPRReg gpr = allocate(); 764 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr); 765 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 766 info.fillInt32(*m_stream, gpr); 767 returnFormat = DataFormatInt32; 768 return gpr; 769 } 770 771 case DataFormatJSInt32: 772 case DataFormatJS: { 773 // Check the value is an integer. 774 GPRReg tagGPR = info.tagGPR(); 775 GPRReg payloadGPR = info.payloadGPR(); 776 m_gprs.lock(tagGPR); 777 m_gprs.lock(payloadGPR); 778 if (type & ~SpecInt32) 779 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag))); 780 m_gprs.unlock(tagGPR); 781 m_gprs.release(tagGPR); 782 m_gprs.release(payloadGPR); 783 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger); 784 info.fillInt32(*m_stream, payloadGPR); 785 // If !strict we're done, return. 786 returnFormat = DataFormatInt32; 787 return payloadGPR; 788 } 789 790 case DataFormatInt32: { 791 GPRReg gpr = info.gpr(); 792 m_gprs.lock(gpr); 793 returnFormat = DataFormatInt32; 794 return gpr; 795 } 796 797 case DataFormatCell: 798 case DataFormatBoolean: 799 case DataFormatJSDouble: 800 case DataFormatJSCell: 801 case DataFormatJSBoolean: 802 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 803 returnFormat = DataFormatInt32; 804 return allocate(); 805 806 case DataFormatDouble: 807 case DataFormatStorage: 808 default: 809 RELEASE_ASSERT_NOT_REACHED(); 810 return InvalidGPRReg; 811 } 812} 813 814GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat) 815{ 816 return fillSpeculateInt32Internal<false>(edge, returnFormat); 817} 818 819GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge) 820{ 821 DataFormat mustBeDataFormatInt32; 822 GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32); 823 ASSERT(mustBeDataFormatInt32 == DataFormatInt32); 824 return result; 825} 826 827FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge) 828{ 829 ASSERT(isDouble(edge.useKind())); 830 ASSERT(edge->hasDoubleResult()); 831 VirtualRegister virtualRegister = edge->virtualRegister(); 832 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 833 834 if (info.registerFormat() == DataFormatNone) { 835 836 if (edge->hasConstant()) { 837 RELEASE_ASSERT(isNumberConstant(edge.node())); 838 FPRReg fpr = fprAllocate(); 839 m_jit.loadDouble(TrustedImmPtr(addressOfDoubleConstant(edge.node())), fpr); 840 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant); 841 info.fillDouble(*m_stream, fpr); 842 return fpr; 843 } 844 845 RELEASE_ASSERT(info.spillFormat() == DataFormatDouble); 846 FPRReg fpr = fprAllocate(); 847 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 848 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled); 849 info.fillDouble(*m_stream, fpr); 850 return fpr; 851 } 852 853 RELEASE_ASSERT(info.registerFormat() == DataFormatDouble); 854 FPRReg fpr = info.fpr(); 855 m_fprs.lock(fpr); 856 return fpr; 857} 858 859GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge) 860{ 861 AbstractValue& value = m_state.forNode(edge); 862 SpeculatedType type = value.m_type; 863 ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell)); 864 m_interpreter.filter(value, SpecCell); 865 VirtualRegister virtualRegister = edge->virtualRegister(); 866 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 867 868 switch (info.registerFormat()) { 869 case DataFormatNone: { 870 if (info.spillFormat() == DataFormatInt32) { 871 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 872 return allocate(); 873 } 874 875 if (edge->hasConstant()) { 876 JSValue jsValue = valueOfJSConstant(edge.node()); 877 GPRReg gpr = allocate(); 878 if (jsValue.isCell()) { 879 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 880 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr); 881 info.fillCell(*m_stream, gpr); 882 return gpr; 883 } 884 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 885 return gpr; 886 } 887 888 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell); 889 if (type & ~SpecCell) { 890 speculationCheck( 891 BadType, 892 JSValueSource(JITCompiler::addressFor(virtualRegister)), 893 edge, 894 m_jit.branch32( 895 MacroAssembler::NotEqual, 896 JITCompiler::tagFor(virtualRegister), 897 TrustedImm32(JSValue::CellTag))); 898 } 899 GPRReg gpr = allocate(); 900 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr); 901 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 902 info.fillCell(*m_stream, gpr); 903 return gpr; 904 } 905 906 case DataFormatCell: { 907 GPRReg gpr = info.gpr(); 908 m_gprs.lock(gpr); 909 return gpr; 910 } 911 912 case DataFormatJSCell: 913 case DataFormatJS: { 914 GPRReg tagGPR = info.tagGPR(); 915 GPRReg payloadGPR = info.payloadGPR(); 916 m_gprs.lock(tagGPR); 917 m_gprs.lock(payloadGPR); 918 if (type & ~SpecCell) { 919 speculationCheck( 920 BadType, JSValueRegs(tagGPR, payloadGPR), edge, 921 branchNotCell(info.jsValueRegs())); 922 } 923 m_gprs.unlock(tagGPR); 924 m_gprs.release(tagGPR); 925 m_gprs.release(payloadGPR); 926 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell); 927 info.fillCell(*m_stream, payloadGPR); 928 return payloadGPR; 929 } 930 931 case DataFormatJSInt32: 932 case DataFormatInt32: 933 case DataFormatJSDouble: 934 case DataFormatJSBoolean: 935 case DataFormatBoolean: 936 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 937 return allocate(); 938 939 case DataFormatDouble: 940 case DataFormatStorage: 941 RELEASE_ASSERT_NOT_REACHED(); 942 943 default: 944 RELEASE_ASSERT_NOT_REACHED(); 945 return InvalidGPRReg; 946 } 947} 948 949GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge) 950{ 951 AbstractValue& value = m_state.forNode(edge); 952 SpeculatedType type = value.m_type; 953 m_interpreter.filter(value, SpecBoolean); 954 VirtualRegister virtualRegister = edge->virtualRegister(); 955 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 956 957 switch (info.registerFormat()) { 958 case DataFormatNone: { 959 if (info.spillFormat() == DataFormatInt32) { 960 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 961 return allocate(); 962 } 963 964 if (edge->hasConstant()) { 965 JSValue jsValue = valueOfJSConstant(edge.node()); 966 GPRReg gpr = allocate(); 967 if (jsValue.isBoolean()) { 968 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 969 m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr); 970 info.fillBoolean(*m_stream, gpr); 971 return gpr; 972 } 973 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 974 return gpr; 975 } 976 977 ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean); 978 979 if (type & ~SpecBoolean) 980 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag))); 981 982 GPRReg gpr = allocate(); 983 m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr); 984 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 985 info.fillBoolean(*m_stream, gpr); 986 return gpr; 987 } 988 989 case DataFormatBoolean: { 990 GPRReg gpr = info.gpr(); 991 m_gprs.lock(gpr); 992 return gpr; 993 } 994 995 case DataFormatJSBoolean: 996 case DataFormatJS: { 997 GPRReg tagGPR = info.tagGPR(); 998 GPRReg payloadGPR = info.payloadGPR(); 999 m_gprs.lock(tagGPR); 1000 m_gprs.lock(payloadGPR); 1001 if (type & ~SpecBoolean) 1002 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag))); 1003 1004 m_gprs.unlock(tagGPR); 1005 m_gprs.release(tagGPR); 1006 m_gprs.release(payloadGPR); 1007 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean); 1008 info.fillBoolean(*m_stream, payloadGPR); 1009 return payloadGPR; 1010 } 1011 1012 case DataFormatJSInt32: 1013 case DataFormatInt32: 1014 case DataFormatJSDouble: 1015 case DataFormatJSCell: 1016 case DataFormatCell: 1017 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1018 return allocate(); 1019 1020 case DataFormatDouble: 1021 case DataFormatStorage: 1022 RELEASE_ASSERT_NOT_REACHED(); 1023 1024 default: 1025 RELEASE_ASSERT_NOT_REACHED(); 1026 return InvalidGPRReg; 1027 } 1028} 1029 1030void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge) 1031{ 1032#if ENABLE(GGC) 1033 ASSERT(!isKnownNotCell(valueEdge.node())); 1034 1035 SpeculateCellOperand base(this, baseEdge); 1036 JSValueOperand value(this, valueEdge); 1037 GPRTemporary scratch1(this); 1038 GPRTemporary scratch2(this); 1039 1040 writeBarrier(base.gpr(), value.tagGPR(), valueEdge, scratch1.gpr(), scratch2.gpr()); 1041#else 1042 UNUSED_PARAM(baseEdge); 1043 UNUSED_PARAM(valueEdge); 1044#endif 1045} 1046 1047void SpeculativeJIT::compileObjectEquality(Node* node) 1048{ 1049 SpeculateCellOperand op1(this, node->child1()); 1050 SpeculateCellOperand op2(this, node->child2()); 1051 GPRReg op1GPR = op1.gpr(); 1052 GPRReg op2GPR = op2.gpr(); 1053 1054 if (masqueradesAsUndefinedWatchpointIsStillValid()) { 1055 DFG_TYPE_CHECK( 1056 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1057 MacroAssembler::Equal, 1058 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1059 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1060 DFG_TYPE_CHECK( 1061 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1062 MacroAssembler::Equal, 1063 MacroAssembler::Address(op2GPR, JSCell::structureIDOffset()), 1064 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1065 } else { 1066 DFG_TYPE_CHECK( 1067 JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr( 1068 MacroAssembler::Equal, 1069 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1070 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1071 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 1072 m_jit.branchTest8( 1073 MacroAssembler::NonZero, 1074 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 1075 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1076 1077 DFG_TYPE_CHECK( 1078 JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr( 1079 MacroAssembler::Equal, 1080 MacroAssembler::Address(op2GPR, JSCell::structureIDOffset()), 1081 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1082 speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 1083 m_jit.branchTest8( 1084 MacroAssembler::NonZero, 1085 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 1086 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1087 } 1088 1089 GPRTemporary resultPayload(this, Reuse, op2); 1090 GPRReg resultPayloadGPR = resultPayload.gpr(); 1091 1092 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); 1093 m_jit.move(TrustedImm32(1), resultPayloadGPR); 1094 MacroAssembler::Jump done = m_jit.jump(); 1095 falseCase.link(&m_jit); 1096 m_jit.move(TrustedImm32(0), resultPayloadGPR); 1097 done.link(&m_jit); 1098 1099 booleanResult(resultPayloadGPR, node); 1100} 1101 1102void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild) 1103{ 1104 SpeculateCellOperand op1(this, leftChild); 1105 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1106 GPRTemporary result(this); 1107 1108 GPRReg op1GPR = op1.gpr(); 1109 GPRReg op2TagGPR = op2.tagGPR(); 1110 GPRReg op2PayloadGPR = op2.payloadGPR(); 1111 GPRReg resultGPR = result.gpr(); 1112 1113 bool masqueradesAsUndefinedWatchpointValid = 1114 masqueradesAsUndefinedWatchpointIsStillValid(); 1115 1116 if (masqueradesAsUndefinedWatchpointValid) { 1117 DFG_TYPE_CHECK( 1118 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1119 MacroAssembler::Equal, 1120 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1121 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1122 } else { 1123 DFG_TYPE_CHECK( 1124 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1125 MacroAssembler::Equal, 1126 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1127 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1128 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1129 m_jit.branchTest8( 1130 MacroAssembler::NonZero, 1131 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 1132 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1133 } 1134 1135 1136 // It seems that most of the time when programs do a == b where b may be either null/undefined 1137 // or an object, b is usually an object. Balance the branches to make that case fast. 1138 MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs()); 1139 1140 // We know that within this branch, rightChild must be a cell. 1141 if (masqueradesAsUndefinedWatchpointValid) { 1142 DFG_TYPE_CHECK( 1143 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1144 m_jit.branchPtr( 1145 MacroAssembler::Equal, 1146 MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()), 1147 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1148 } else { 1149 DFG_TYPE_CHECK( 1150 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1151 m_jit.branchPtr( 1152 MacroAssembler::Equal, 1153 MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()), 1154 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1155 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1156 m_jit.branchTest8( 1157 MacroAssembler::NonZero, 1158 MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()), 1159 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1160 } 1161 1162 // At this point we know that we can perform a straight-forward equality comparison on pointer 1163 // values because both left and right are pointers to objects that have no special equality 1164 // protocols. 1165 MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR); 1166 MacroAssembler::Jump trueCase = m_jit.jump(); 1167 1168 rightNotCell.link(&m_jit); 1169 1170 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1171 // prove that it is either null or undefined. 1172 if (needsTypeCheck(rightChild, SpecCell | SpecOther)) { 1173 m_jit.move(op2TagGPR, resultGPR); 1174 m_jit.or32(TrustedImm32(1), resultGPR); 1175 1176 typeCheck( 1177 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther, 1178 m_jit.branch32( 1179 MacroAssembler::NotEqual, resultGPR, 1180 MacroAssembler::TrustedImm32(JSValue::NullTag))); 1181 } 1182 1183 falseCase.link(&m_jit); 1184 m_jit.move(TrustedImm32(0), resultGPR); 1185 MacroAssembler::Jump done = m_jit.jump(); 1186 trueCase.link(&m_jit); 1187 m_jit.move(TrustedImm32(1), resultGPR); 1188 done.link(&m_jit); 1189 1190 booleanResult(resultGPR, m_currentNode); 1191} 1192 1193void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode) 1194{ 1195 BasicBlock* taken = branchNode->branchData()->taken.block; 1196 BasicBlock* notTaken = branchNode->branchData()->notTaken.block; 1197 1198 SpeculateCellOperand op1(this, leftChild); 1199 JSValueOperand op2(this, rightChild, ManualOperandSpeculation); 1200 GPRTemporary result(this); 1201 1202 GPRReg op1GPR = op1.gpr(); 1203 GPRReg op2TagGPR = op2.tagGPR(); 1204 GPRReg op2PayloadGPR = op2.payloadGPR(); 1205 GPRReg resultGPR = result.gpr(); 1206 1207 bool masqueradesAsUndefinedWatchpointValid = 1208 masqueradesAsUndefinedWatchpointIsStillValid(); 1209 1210 if (masqueradesAsUndefinedWatchpointValid) { 1211 DFG_TYPE_CHECK( 1212 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1213 MacroAssembler::Equal, 1214 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1215 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1216 } else { 1217 DFG_TYPE_CHECK( 1218 JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr( 1219 MacroAssembler::Equal, 1220 MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 1221 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1222 speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 1223 m_jit.branchTest8( 1224 MacroAssembler::NonZero, 1225 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 1226 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1227 } 1228 1229 // It seems that most of the time when programs do a == b where b may be either null/undefined 1230 // or an object, b is usually an object. Balance the branches to make that case fast. 1231 MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs()); 1232 1233 // We know that within this branch, rightChild must be a cell. 1234 if (masqueradesAsUndefinedWatchpointValid) { 1235 DFG_TYPE_CHECK( 1236 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1237 m_jit.branchPtr( 1238 MacroAssembler::Equal, 1239 MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()), 1240 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1241 } else { 1242 DFG_TYPE_CHECK( 1243 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, 1244 m_jit.branchPtr( 1245 MacroAssembler::Equal, 1246 MacroAssembler::Address(op2PayloadGPR, JSCell::structureIDOffset()), 1247 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1248 speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 1249 m_jit.branchTest8( 1250 MacroAssembler::NonZero, 1251 MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()), 1252 MacroAssembler::TrustedImm32(MasqueradesAsUndefined))); 1253 } 1254 1255 // At this point we know that we can perform a straight-forward equality comparison on pointer 1256 // values because both left and right are pointers to objects that have no special equality 1257 // protocols. 1258 branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken); 1259 1260 // We know that within this branch, rightChild must not be a cell. Check if that is enough to 1261 // prove that it is either null or undefined. 1262 if (!needsTypeCheck(rightChild, SpecCell | SpecOther)) 1263 rightNotCell.link(&m_jit); 1264 else { 1265 jump(notTaken, ForceJump); 1266 1267 rightNotCell.link(&m_jit); 1268 m_jit.move(op2TagGPR, resultGPR); 1269 m_jit.or32(TrustedImm32(1), resultGPR); 1270 1271 typeCheck( 1272 JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther, 1273 m_jit.branch32( 1274 MacroAssembler::NotEqual, resultGPR, 1275 MacroAssembler::TrustedImm32(JSValue::NullTag))); 1276 } 1277 1278 jump(notTaken); 1279} 1280 1281void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition) 1282{ 1283 SpeculateInt32Operand op1(this, node->child1()); 1284 SpeculateInt32Operand op2(this, node->child2()); 1285 GPRTemporary resultPayload(this); 1286 1287 m_jit.compare32(condition, op1.gpr(), op2.gpr(), resultPayload.gpr()); 1288 1289 // If we add a DataFormatBool, we should use it here. 1290 booleanResult(resultPayload.gpr(), node); 1291} 1292 1293void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition) 1294{ 1295 SpeculateDoubleOperand op1(this, node->child1()); 1296 SpeculateDoubleOperand op2(this, node->child2()); 1297 GPRTemporary resultPayload(this); 1298 1299 m_jit.move(TrustedImm32(1), resultPayload.gpr()); 1300 MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr()); 1301 m_jit.move(TrustedImm32(0), resultPayload.gpr()); 1302 trueCase.link(&m_jit); 1303 1304 booleanResult(resultPayload.gpr(), node); 1305} 1306 1307void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse) 1308{ 1309 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1310 GPRTemporary resultPayload(this); 1311 GPRReg valueTagGPR = value.tagGPR(); 1312 GPRReg valuePayloadGPR = value.payloadGPR(); 1313 GPRReg resultPayloadGPR = resultPayload.gpr(); 1314 GPRTemporary structure; 1315 GPRReg structureGPR = InvalidGPRReg; 1316 1317 bool masqueradesAsUndefinedWatchpointValid = 1318 masqueradesAsUndefinedWatchpointIsStillValid(); 1319 1320 if (!masqueradesAsUndefinedWatchpointValid) { 1321 // The masquerades as undefined case will use the structure register, so allocate it here. 1322 // Do this at the top of the function to avoid branching around a register allocation. 1323 GPRTemporary realStructure(this); 1324 structure.adopt(realStructure); 1325 structureGPR = structure.gpr(); 1326 } 1327 1328 MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs()); 1329 if (masqueradesAsUndefinedWatchpointValid) { 1330 DFG_TYPE_CHECK( 1331 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1332 m_jit.branchPtr( 1333 MacroAssembler::Equal, 1334 MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), 1335 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1336 } else { 1337 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), structureGPR); 1338 1339 DFG_TYPE_CHECK( 1340 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1341 m_jit.branchPtr( 1342 MacroAssembler::Equal, 1343 structureGPR, 1344 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1345 1346 MacroAssembler::Jump isNotMasqueradesAsUndefined = 1347 m_jit.branchTest8( 1348 MacroAssembler::Zero, 1349 MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()), 1350 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)); 1351 1352 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1353 m_jit.branchPtr( 1354 MacroAssembler::Equal, 1355 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 1356 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)))); 1357 1358 isNotMasqueradesAsUndefined.link(&m_jit); 1359 } 1360 m_jit.move(TrustedImm32(0), resultPayloadGPR); 1361 MacroAssembler::Jump done = m_jit.jump(); 1362 1363 notCell.link(&m_jit); 1364 1365 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 1366 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1367 m_jit.move(valueTagGPR, resultPayloadGPR); 1368 m_jit.or32(TrustedImm32(1), resultPayloadGPR); 1369 typeCheck( 1370 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther, 1371 m_jit.branch32( 1372 MacroAssembler::NotEqual, 1373 resultPayloadGPR, 1374 TrustedImm32(JSValue::NullTag))); 1375 } 1376 m_jit.move(TrustedImm32(1), resultPayloadGPR); 1377 1378 done.link(&m_jit); 1379 1380 booleanResult(resultPayloadGPR, m_currentNode); 1381} 1382 1383void SpeculativeJIT::compileLogicalNot(Node* node) 1384{ 1385 switch (node->child1().useKind()) { 1386 case BooleanUse: { 1387 SpeculateBooleanOperand value(this, node->child1()); 1388 GPRTemporary result(this, Reuse, value); 1389 m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr()); 1390 booleanResult(result.gpr(), node); 1391 return; 1392 } 1393 1394 case ObjectOrOtherUse: { 1395 compileObjectOrOtherLogicalNot(node->child1()); 1396 return; 1397 } 1398 1399 case Int32Use: { 1400 SpeculateInt32Operand value(this, node->child1()); 1401 GPRTemporary resultPayload(this, Reuse, value); 1402 m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr()); 1403 booleanResult(resultPayload.gpr(), node); 1404 return; 1405 } 1406 1407 case DoubleRepUse: { 1408 SpeculateDoubleOperand value(this, node->child1()); 1409 FPRTemporary scratch(this); 1410 GPRTemporary resultPayload(this); 1411 m_jit.move(TrustedImm32(0), resultPayload.gpr()); 1412 MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr()); 1413 m_jit.move(TrustedImm32(1), resultPayload.gpr()); 1414 nonZero.link(&m_jit); 1415 booleanResult(resultPayload.gpr(), node); 1416 return; 1417 } 1418 1419 case UntypedUse: { 1420 JSValueOperand arg1(this, node->child1()); 1421 GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord); 1422 GPRReg arg1TagGPR = arg1.tagGPR(); 1423 GPRReg arg1PayloadGPR = arg1.payloadGPR(); 1424 GPRReg resultPayloadGPR = resultPayload.gpr(); 1425 1426 arg1.use(); 1427 1428 JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag)); 1429 1430 m_jit.move(arg1PayloadGPR, resultPayloadGPR); 1431 1432 addSlowPathGenerator( 1433 slowPathCall( 1434 slowCase, this, operationConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR, 1435 arg1PayloadGPR)); 1436 1437 m_jit.xor32(TrustedImm32(1), resultPayloadGPR); 1438 booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly); 1439 return; 1440 } 1441 case StringUse: 1442 return compileStringZeroLength(node); 1443 1444 default: 1445 RELEASE_ASSERT_NOT_REACHED(); 1446 break; 1447 } 1448} 1449 1450void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken) 1451{ 1452 JSValueOperand value(this, nodeUse, ManualOperandSpeculation); 1453 GPRTemporary scratch(this); 1454 GPRReg valueTagGPR = value.tagGPR(); 1455 GPRReg valuePayloadGPR = value.payloadGPR(); 1456 GPRReg scratchGPR = scratch.gpr(); 1457 1458 MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs()); 1459 if (masqueradesAsUndefinedWatchpointIsStillValid()) { 1460 DFG_TYPE_CHECK( 1461 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1462 m_jit.branchPtr( 1463 MacroAssembler::Equal, 1464 MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), 1465 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1466 } else { 1467 m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), scratchGPR); 1468 1469 DFG_TYPE_CHECK( 1470 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject, 1471 m_jit.branchPtr( 1472 MacroAssembler::Equal, 1473 scratchGPR, 1474 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()))); 1475 1476 JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8( 1477 JITCompiler::Zero, 1478 MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()), 1479 TrustedImm32(MasqueradesAsUndefined)); 1480 1481 speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 1482 m_jit.branchPtr( 1483 MacroAssembler::Equal, 1484 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 1485 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)))); 1486 1487 isNotMasqueradesAsUndefined.link(&m_jit); 1488 } 1489 jump(taken, ForceJump); 1490 1491 notCell.link(&m_jit); 1492 1493 COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag); 1494 if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) { 1495 m_jit.move(valueTagGPR, scratchGPR); 1496 m_jit.or32(TrustedImm32(1), scratchGPR); 1497 typeCheck( 1498 JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther, 1499 m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag))); 1500 } 1501 1502 jump(notTaken); 1503 1504 noResult(m_currentNode); 1505} 1506 1507void SpeculativeJIT::emitBranch(Node* node) 1508{ 1509 BasicBlock* taken = node->branchData()->taken.block; 1510 BasicBlock* notTaken = node->branchData()->notTaken.block; 1511 1512 switch (node->child1().useKind()) { 1513 case BooleanUse: { 1514 SpeculateBooleanOperand value(this, node->child1()); 1515 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; 1516 1517 if (taken == nextBlock()) { 1518 condition = MacroAssembler::Zero; 1519 BasicBlock* tmp = taken; 1520 taken = notTaken; 1521 notTaken = tmp; 1522 } 1523 1524 branchTest32(condition, value.gpr(), TrustedImm32(1), taken); 1525 jump(notTaken); 1526 1527 noResult(node); 1528 return; 1529 } 1530 1531 case ObjectOrOtherUse: { 1532 emitObjectOrOtherBranch(node->child1(), taken, notTaken); 1533 return; 1534 } 1535 1536 case DoubleRepUse: 1537 case Int32Use: { 1538 if (node->child1().useKind() == Int32Use) { 1539 bool invert = false; 1540 1541 if (taken == nextBlock()) { 1542 invert = true; 1543 BasicBlock* tmp = taken; 1544 taken = notTaken; 1545 notTaken = tmp; 1546 } 1547 1548 SpeculateInt32Operand value(this, node->child1()); 1549 branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken); 1550 } else { 1551 SpeculateDoubleOperand value(this, node->child1()); 1552 FPRTemporary scratch(this); 1553 branchDoubleNonZero(value.fpr(), scratch.fpr(), taken); 1554 } 1555 1556 jump(notTaken); 1557 1558 noResult(node); 1559 return; 1560 } 1561 1562 case UntypedUse: { 1563 JSValueOperand value(this, node->child1()); 1564 value.fill(); 1565 GPRReg valueTagGPR = value.tagGPR(); 1566 GPRReg valuePayloadGPR = value.payloadGPR(); 1567 1568 GPRTemporary result(this); 1569 GPRReg resultGPR = result.gpr(); 1570 1571 use(node->child1()); 1572 1573 JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag)); 1574 JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag)); 1575 1576 fastPath.link(&m_jit); 1577 branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken); 1578 jump(taken, ForceJump); 1579 1580 slowPath.link(&m_jit); 1581 silentSpillAllRegisters(resultGPR); 1582 callOperation(operationConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR); 1583 silentFillAllRegisters(resultGPR); 1584 1585 branchTest32(JITCompiler::NonZero, resultGPR, taken); 1586 jump(notTaken); 1587 1588 noResult(node, UseChildrenCalledExplicitly); 1589 return; 1590 } 1591 1592 default: 1593 RELEASE_ASSERT_NOT_REACHED(); 1594 break; 1595 } 1596} 1597 1598template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType> 1599void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag) 1600{ 1601 Edge child4 = m_jit.graph().varArgChild(node, 3); 1602 1603 ArrayMode arrayMode = node->arrayMode(); 1604 1605 GPRReg baseReg = base.gpr(); 1606 GPRReg propertyReg = property.gpr(); 1607 1608 StorageOperand storage(this, child4); 1609 GPRReg storageReg = storage.gpr(); 1610 1611 if (node->op() == PutByValAlias) { 1612 // Store the value to the array. 1613 GPRReg propertyReg = property.gpr(); 1614 m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 1615 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 1616 1617 noResult(node); 1618 return; 1619 } 1620 1621 MacroAssembler::Jump slowCase; 1622 1623 if (arrayMode.isInBounds()) { 1624 speculationCheck( 1625 OutOfBounds, JSValueRegs(), 0, 1626 m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 1627 } else { 1628 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); 1629 1630 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())); 1631 1632 if (!arrayMode.isOutOfBounds()) 1633 speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase); 1634 1635 m_jit.add32(TrustedImm32(1), propertyReg); 1636 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())); 1637 m_jit.sub32(TrustedImm32(1), propertyReg); 1638 1639 inBounds.link(&m_jit); 1640 } 1641 1642 m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 1643 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 1644 1645 base.use(); 1646 property.use(); 1647 value.use(); 1648 storage.use(); 1649 1650 if (arrayMode.isOutOfBounds()) { 1651 if (node->op() == PutByValDirect) { 1652 addSlowPathGenerator(slowPathCall( 1653 slowCase, this, 1654 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict, 1655 NoResult, baseReg, propertyReg, valueTag, valuePayloadReg)); 1656 } else { 1657 addSlowPathGenerator(slowPathCall( 1658 slowCase, this, 1659 m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, 1660 NoResult, baseReg, propertyReg, valueTag, valuePayloadReg)); 1661 } 1662 } 1663 1664 noResult(node, UseChildrenCalledExplicitly); 1665} 1666 1667void SpeculativeJIT::compile(Node* node) 1668{ 1669 NodeType op = node->op(); 1670 1671#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) 1672 m_jit.clearRegisterAllocationOffsets(); 1673#endif 1674 1675 switch (op) { 1676 case JSConstant: 1677 case DoubleConstant: 1678 initConstantInfo(node); 1679 break; 1680 1681 case PhantomArguments: 1682 initConstantInfo(node); 1683 break; 1684 1685 case WeakJSConstant: 1686 m_jit.addWeakReference(node->weakConstant()); 1687 initConstantInfo(node); 1688 break; 1689 1690 case Identity: { 1691 RELEASE_ASSERT_NOT_REACHED(); 1692 break; 1693 } 1694 1695 case GetLocal: { 1696 AbstractValue& value = m_state.variables().operand(node->local()); 1697 1698 // If the CFA is tracking this variable and it found that the variable 1699 // cannot have been assigned, then don't attempt to proceed. 1700 if (value.isClear()) { 1701 // FIXME: We should trap instead. 1702 // https://bugs.webkit.org/show_bug.cgi?id=110383 1703 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 1704 break; 1705 } 1706 1707 switch (node->variableAccessData()->flushFormat()) { 1708 case FlushedDouble: { 1709 FPRTemporary result(this); 1710 m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr()); 1711 VirtualRegister virtualRegister = node->virtualRegister(); 1712 m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble); 1713 generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr()); 1714 break; 1715 } 1716 1717 case FlushedInt32: { 1718 GPRTemporary result(this); 1719 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr()); 1720 1721 // Like int32Result, but don't useChildren - our children are phi nodes, 1722 // and don't represent values within this dataflow with virtual registers. 1723 VirtualRegister virtualRegister = node->virtualRegister(); 1724 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger); 1725 generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr()); 1726 break; 1727 } 1728 1729 case FlushedCell: { 1730 GPRTemporary result(this); 1731 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr()); 1732 1733 // Like cellResult, but don't useChildren - our children are phi nodes, 1734 // and don't represent values within this dataflow with virtual registers. 1735 VirtualRegister virtualRegister = node->virtualRegister(); 1736 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell); 1737 generationInfoFromVirtualRegister(virtualRegister).initCell(node, node->refCount(), result.gpr()); 1738 break; 1739 } 1740 1741 case FlushedBoolean: { 1742 GPRTemporary result(this); 1743 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr()); 1744 1745 // Like booleanResult, but don't useChildren - our children are phi nodes, 1746 // and don't represent values within this dataflow with virtual registers. 1747 VirtualRegister virtualRegister = node->virtualRegister(); 1748 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean); 1749 generationInfoFromVirtualRegister(virtualRegister).initBoolean(node, node->refCount(), result.gpr()); 1750 break; 1751 } 1752 1753 case FlushedJSValue: 1754 case FlushedArguments: { 1755 GPRTemporary result(this); 1756 GPRTemporary tag(this); 1757 m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr()); 1758 m_jit.load32(JITCompiler::tagFor(node->machineLocal()), tag.gpr()); 1759 1760 // Like jsValueResult, but don't useChildren - our children are phi nodes, 1761 // and don't represent values within this dataflow with virtual registers. 1762 VirtualRegister virtualRegister = node->virtualRegister(); 1763 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS); 1764 m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS); 1765 1766 generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS); 1767 break; 1768 } 1769 1770 default: 1771 RELEASE_ASSERT_NOT_REACHED(); 1772 } 1773 break; 1774 } 1775 1776 case GetLocalUnlinked: { 1777 GPRTemporary payload(this); 1778 GPRTemporary tag(this); 1779 m_jit.load32(JITCompiler::payloadFor(node->unlinkedMachineLocal()), payload.gpr()); 1780 m_jit.load32(JITCompiler::tagFor(node->unlinkedMachineLocal()), tag.gpr()); 1781 jsValueResult(tag.gpr(), payload.gpr(), node); 1782 break; 1783 } 1784 1785 case MovHint: 1786 case ZombieHint: 1787 case Check: { 1788 RELEASE_ASSERT_NOT_REACHED(); 1789 break; 1790 } 1791 1792 case SetLocal: { 1793 switch (node->variableAccessData()->flushFormat()) { 1794 case FlushedDouble: { 1795 SpeculateDoubleOperand value(this, node->child1()); 1796 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal())); 1797 noResult(node); 1798 // Indicate that it's no longer necessary to retrieve the value of 1799 // this bytecode variable from registers or other locations in the stack, 1800 // but that it is stored as a double. 1801 recordSetLocal(DataFormatDouble); 1802 break; 1803 } 1804 1805 case FlushedInt32: { 1806 SpeculateInt32Operand value(this, node->child1()); 1807 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal())); 1808 noResult(node); 1809 recordSetLocal(DataFormatInt32); 1810 break; 1811 } 1812 1813 case FlushedCell: { 1814 SpeculateCellOperand cell(this, node->child1()); 1815 GPRReg cellGPR = cell.gpr(); 1816 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->machineLocal())); 1817 noResult(node); 1818 recordSetLocal(DataFormatCell); 1819 break; 1820 } 1821 1822 case FlushedBoolean: { 1823 SpeculateBooleanOperand value(this, node->child1()); 1824 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal())); 1825 noResult(node); 1826 recordSetLocal(DataFormatBoolean); 1827 break; 1828 } 1829 1830 case FlushedJSValue: 1831 case FlushedArguments: { 1832 JSValueOperand value(this, node->child1()); 1833 m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal())); 1834 m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal())); 1835 noResult(node); 1836 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat())); 1837 break; 1838 } 1839 1840 default: 1841 RELEASE_ASSERT_NOT_REACHED(); 1842 break; 1843 } 1844 break; 1845 } 1846 1847 case SetArgument: 1848 // This is a no-op; it just marks the fact that the argument is being used. 1849 // But it may be profitable to use this as a hook to run speculation checks 1850 // on arguments, thereby allowing us to trivially eliminate such checks if 1851 // the argument is not used. 1852 recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat())); 1853 break; 1854 1855 case BitAnd: 1856 case BitOr: 1857 case BitXor: 1858 if (isInt32Constant(node->child1().node())) { 1859 SpeculateInt32Operand op2(this, node->child2()); 1860 GPRTemporary result(this, Reuse, op2); 1861 1862 bitOp(op, valueOfInt32Constant(node->child1().node()), op2.gpr(), result.gpr()); 1863 1864 int32Result(result.gpr(), node); 1865 } else if (isInt32Constant(node->child2().node())) { 1866 SpeculateInt32Operand op1(this, node->child1()); 1867 GPRTemporary result(this, Reuse, op1); 1868 1869 bitOp(op, valueOfInt32Constant(node->child2().node()), op1.gpr(), result.gpr()); 1870 1871 int32Result(result.gpr(), node); 1872 } else { 1873 SpeculateInt32Operand op1(this, node->child1()); 1874 SpeculateInt32Operand op2(this, node->child2()); 1875 GPRTemporary result(this, Reuse, op1, op2); 1876 1877 GPRReg reg1 = op1.gpr(); 1878 GPRReg reg2 = op2.gpr(); 1879 bitOp(op, reg1, reg2, result.gpr()); 1880 1881 int32Result(result.gpr(), node); 1882 } 1883 break; 1884 1885 case BitRShift: 1886 case BitLShift: 1887 case BitURShift: 1888 if (isInt32Constant(node->child2().node())) { 1889 SpeculateInt32Operand op1(this, node->child1()); 1890 GPRTemporary result(this, Reuse, op1); 1891 1892 shiftOp(op, op1.gpr(), valueOfInt32Constant(node->child2().node()) & 0x1f, result.gpr()); 1893 1894 int32Result(result.gpr(), node); 1895 } else { 1896 // Do not allow shift amount to be used as the result, MacroAssembler does not permit this. 1897 SpeculateInt32Operand op1(this, node->child1()); 1898 SpeculateInt32Operand op2(this, node->child2()); 1899 GPRTemporary result(this, Reuse, op1); 1900 1901 GPRReg reg1 = op1.gpr(); 1902 GPRReg reg2 = op2.gpr(); 1903 shiftOp(op, reg1, reg2, result.gpr()); 1904 1905 int32Result(result.gpr(), node); 1906 } 1907 break; 1908 1909 case UInt32ToNumber: { 1910 compileUInt32ToNumber(node); 1911 break; 1912 } 1913 1914 case DoubleAsInt32: { 1915 compileDoubleAsInt32(node); 1916 break; 1917 } 1918 1919 case ValueToInt32: { 1920 compileValueToInt32(node); 1921 break; 1922 } 1923 1924 case DoubleRep: { 1925 compileDoubleRep(node); 1926 break; 1927 } 1928 1929 case ValueRep: { 1930 compileValueRep(node); 1931 break; 1932 } 1933 1934 case ValueAdd: { 1935 JSValueOperand op1(this, node->child1()); 1936 JSValueOperand op2(this, node->child2()); 1937 1938 GPRReg op1TagGPR = op1.tagGPR(); 1939 GPRReg op1PayloadGPR = op1.payloadGPR(); 1940 GPRReg op2TagGPR = op2.tagGPR(); 1941 GPRReg op2PayloadGPR = op2.payloadGPR(); 1942 1943 flushRegisters(); 1944 1945 GPRResult2 resultTag(this); 1946 GPRResult resultPayload(this); 1947 if (isKnownNotNumber(node->child1().node()) || isKnownNotNumber(node->child2().node())) 1948 callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR); 1949 else 1950 callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR); 1951 1952 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 1953 break; 1954 } 1955 1956 case ArithAdd: 1957 compileAdd(node); 1958 break; 1959 1960 case MakeRope: 1961 compileMakeRope(node); 1962 break; 1963 1964 case ArithSub: 1965 compileArithSub(node); 1966 break; 1967 1968 case ArithNegate: 1969 compileArithNegate(node); 1970 break; 1971 1972 case ArithMul: 1973 compileArithMul(node); 1974 break; 1975 1976 case ArithDiv: { 1977 compileArithDiv(node); 1978 break; 1979 } 1980 1981 case ArithMod: { 1982 compileArithMod(node); 1983 break; 1984 } 1985 1986 case ArithAbs: { 1987 switch (node->child1().useKind()) { 1988 case Int32Use: { 1989 SpeculateStrictInt32Operand op1(this, node->child1()); 1990 GPRTemporary result(this, Reuse, op1); 1991 GPRTemporary scratch(this); 1992 1993 m_jit.move(op1.gpr(), result.gpr()); 1994 m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr()); 1995 m_jit.add32(scratch.gpr(), result.gpr()); 1996 m_jit.xor32(scratch.gpr(), result.gpr()); 1997 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31))); 1998 int32Result(result.gpr(), node); 1999 break; 2000 } 2001 2002 2003 case DoubleRepUse: { 2004 SpeculateDoubleOperand op1(this, node->child1()); 2005 FPRTemporary result(this); 2006 2007 m_jit.absDouble(op1.fpr(), result.fpr()); 2008 doubleResult(result.fpr(), node); 2009 break; 2010 } 2011 2012 default: 2013 RELEASE_ASSERT_NOT_REACHED(); 2014 break; 2015 } 2016 break; 2017 } 2018 2019 case ArithMin: 2020 case ArithMax: { 2021 switch (node->binaryUseKind()) { 2022 case Int32Use: { 2023 SpeculateStrictInt32Operand op1(this, node->child1()); 2024 SpeculateStrictInt32Operand op2(this, node->child2()); 2025 GPRTemporary result(this, Reuse, op1); 2026 2027 GPRReg op1GPR = op1.gpr(); 2028 GPRReg op2GPR = op2.gpr(); 2029 GPRReg resultGPR = result.gpr(); 2030 2031 MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1GPR, op2GPR); 2032 m_jit.move(op2GPR, resultGPR); 2033 if (op1GPR != resultGPR) { 2034 MacroAssembler::Jump done = m_jit.jump(); 2035 op1Less.link(&m_jit); 2036 m_jit.move(op1GPR, resultGPR); 2037 done.link(&m_jit); 2038 } else 2039 op1Less.link(&m_jit); 2040 2041 int32Result(resultGPR, node); 2042 break; 2043 } 2044 2045 case DoubleRepUse: { 2046 SpeculateDoubleOperand op1(this, node->child1()); 2047 SpeculateDoubleOperand op2(this, node->child2()); 2048 FPRTemporary result(this, op1); 2049 2050 FPRReg op1FPR = op1.fpr(); 2051 FPRReg op2FPR = op2.fpr(); 2052 FPRReg resultFPR = result.fpr(); 2053 2054 MacroAssembler::JumpList done; 2055 2056 MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR); 2057 2058 // op2 is eather the lesser one or one of then is NaN 2059 MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR); 2060 2061 // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 2062 // op1 + op2 and putting it into result. 2063 m_jit.addDouble(op1FPR, op2FPR, resultFPR); 2064 done.append(m_jit.jump()); 2065 2066 op2Less.link(&m_jit); 2067 m_jit.moveDouble(op2FPR, resultFPR); 2068 2069 if (op1FPR != resultFPR) { 2070 done.append(m_jit.jump()); 2071 2072 op1Less.link(&m_jit); 2073 m_jit.moveDouble(op1FPR, resultFPR); 2074 } else 2075 op1Less.link(&m_jit); 2076 2077 done.link(&m_jit); 2078 2079 doubleResult(resultFPR, node); 2080 break; 2081 } 2082 2083 default: 2084 RELEASE_ASSERT_NOT_REACHED(); 2085 break; 2086 } 2087 break; 2088 } 2089 2090 case ArithSqrt: { 2091 SpeculateDoubleOperand op1(this, node->child1()); 2092 FPRTemporary result(this, op1); 2093 2094 m_jit.sqrtDouble(op1.fpr(), result.fpr()); 2095 2096 doubleResult(result.fpr(), node); 2097 break; 2098 } 2099 2100 case ArithFRound: { 2101 SpeculateDoubleOperand op1(this, node->child1()); 2102 FPRTemporary result(this, op1); 2103 2104 m_jit.convertDoubleToFloat(op1.fpr(), result.fpr()); 2105 m_jit.convertFloatToDouble(result.fpr(), result.fpr()); 2106 2107 doubleResult(result.fpr(), node); 2108 break; 2109 } 2110 2111 case ArithSin: { 2112 SpeculateDoubleOperand op1(this, node->child1()); 2113 FPRReg op1FPR = op1.fpr(); 2114 2115 flushRegisters(); 2116 2117 FPRResult result(this); 2118 callOperation(sin, result.fpr(), op1FPR); 2119 doubleResult(result.fpr(), node); 2120 break; 2121 } 2122 2123 case ArithCos: { 2124 SpeculateDoubleOperand op1(this, node->child1()); 2125 FPRReg op1FPR = op1.fpr(); 2126 2127 flushRegisters(); 2128 2129 FPRResult result(this); 2130 callOperation(cos, result.fpr(), op1FPR); 2131 doubleResult(result.fpr(), node); 2132 break; 2133 } 2134 2135 case LogicalNot: 2136 compileLogicalNot(node); 2137 break; 2138 2139 case CompareLess: 2140 if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess)) 2141 return; 2142 break; 2143 2144 case CompareLessEq: 2145 if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq)) 2146 return; 2147 break; 2148 2149 case CompareGreater: 2150 if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater)) 2151 return; 2152 break; 2153 2154 case CompareGreaterEq: 2155 if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq)) 2156 return; 2157 break; 2158 2159 case CompareEqConstant: 2160 ASSERT(isNullConstant(node->child2().node())); 2161 if (nonSpeculativeCompareNull(node, node->child1())) 2162 return; 2163 break; 2164 2165 case CompareEq: 2166 if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq)) 2167 return; 2168 break; 2169 2170 case CompareStrictEq: 2171 if (compileStrictEq(node)) 2172 return; 2173 break; 2174 2175 case StringCharCodeAt: { 2176 compileGetCharCodeAt(node); 2177 break; 2178 } 2179 2180 case StringCharAt: { 2181 // Relies on StringCharAt node having same basic layout as GetByVal 2182 compileGetByValOnString(node); 2183 break; 2184 } 2185 2186 case StringFromCharCode: { 2187 compileFromCharCode(node); 2188 break; 2189 } 2190 2191 case CheckArray: { 2192 checkArray(node); 2193 break; 2194 } 2195 2196 case Arrayify: 2197 case ArrayifyToStructure: { 2198 arrayify(node); 2199 break; 2200 } 2201 2202 case GetByVal: { 2203 switch (node->arrayMode().type()) { 2204 case Array::SelectUsingPredictions: 2205 case Array::ForceExit: 2206 RELEASE_ASSERT_NOT_REACHED(); 2207 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2208 break; 2209 case Array::Generic: { 2210 SpeculateCellOperand base(this, node->child1()); // Save a register, speculate cell. We'll probably be right. 2211 JSValueOperand property(this, node->child2()); 2212 GPRReg baseGPR = base.gpr(); 2213 GPRReg propertyTagGPR = property.tagGPR(); 2214 GPRReg propertyPayloadGPR = property.payloadGPR(); 2215 2216 flushRegisters(); 2217 GPRResult2 resultTag(this); 2218 GPRResult resultPayload(this); 2219 callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR); 2220 2221 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2222 break; 2223 } 2224 case Array::Int32: 2225 case Array::Contiguous: { 2226 if (node->arrayMode().isInBounds()) { 2227 SpeculateStrictInt32Operand property(this, node->child2()); 2228 StorageOperand storage(this, node->child3()); 2229 2230 GPRReg propertyReg = property.gpr(); 2231 GPRReg storageReg = storage.gpr(); 2232 2233 if (!m_compileOkay) 2234 return; 2235 2236 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2237 2238 GPRTemporary resultPayload(this); 2239 if (node->arrayMode().type() == Array::Int32) { 2240 speculationCheck( 2241 OutOfBounds, JSValueRegs(), 0, 2242 m_jit.branch32( 2243 MacroAssembler::Equal, 2244 MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), 2245 TrustedImm32(JSValue::EmptyValueTag))); 2246 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); 2247 int32Result(resultPayload.gpr(), node); 2248 break; 2249 } 2250 2251 GPRTemporary resultTag(this); 2252 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr()); 2253 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag))); 2254 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); 2255 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2256 break; 2257 } 2258 2259 SpeculateCellOperand base(this, node->child1()); 2260 SpeculateStrictInt32Operand property(this, node->child2()); 2261 StorageOperand storage(this, node->child3()); 2262 2263 GPRReg baseReg = base.gpr(); 2264 GPRReg propertyReg = property.gpr(); 2265 GPRReg storageReg = storage.gpr(); 2266 2267 if (!m_compileOkay) 2268 return; 2269 2270 GPRTemporary resultTag(this); 2271 GPRTemporary resultPayload(this); 2272 GPRReg resultTagReg = resultTag.gpr(); 2273 GPRReg resultPayloadReg = resultPayload.gpr(); 2274 2275 MacroAssembler::JumpList slowCases; 2276 2277 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2278 2279 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg); 2280 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg); 2281 slowCases.append(m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag))); 2282 2283 addSlowPathGenerator( 2284 slowPathCall( 2285 slowCases, this, operationGetByValArrayInt, 2286 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg)); 2287 2288 jsValueResult(resultTagReg, resultPayloadReg, node); 2289 break; 2290 } 2291 case Array::Double: { 2292 if (node->arrayMode().isInBounds()) { 2293 SpeculateStrictInt32Operand property(this, node->child2()); 2294 StorageOperand storage(this, node->child3()); 2295 2296 GPRReg propertyReg = property.gpr(); 2297 GPRReg storageReg = storage.gpr(); 2298 2299 if (!m_compileOkay) 2300 return; 2301 2302 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2303 2304 FPRTemporary result(this); 2305 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr()); 2306 if (!node->arrayMode().isSaneChain()) 2307 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr())); 2308 doubleResult(result.fpr(), node); 2309 break; 2310 } 2311 2312 SpeculateCellOperand base(this, node->child1()); 2313 SpeculateStrictInt32Operand property(this, node->child2()); 2314 StorageOperand storage(this, node->child3()); 2315 2316 GPRReg baseReg = base.gpr(); 2317 GPRReg propertyReg = property.gpr(); 2318 GPRReg storageReg = storage.gpr(); 2319 2320 if (!m_compileOkay) 2321 return; 2322 2323 GPRTemporary resultTag(this); 2324 GPRTemporary resultPayload(this); 2325 FPRTemporary temp(this); 2326 GPRReg resultTagReg = resultTag.gpr(); 2327 GPRReg resultPayloadReg = resultPayload.gpr(); 2328 FPRReg tempReg = temp.fpr(); 2329 2330 MacroAssembler::JumpList slowCases; 2331 2332 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()))); 2333 2334 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg); 2335 slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg)); 2336 boxDouble(tempReg, resultTagReg, resultPayloadReg); 2337 2338 addSlowPathGenerator( 2339 slowPathCall( 2340 slowCases, this, operationGetByValArrayInt, 2341 JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg)); 2342 2343 jsValueResult(resultTagReg, resultPayloadReg, node); 2344 break; 2345 } 2346 case Array::ArrayStorage: 2347 case Array::SlowPutArrayStorage: { 2348 if (node->arrayMode().isInBounds()) { 2349 SpeculateStrictInt32Operand property(this, node->child2()); 2350 StorageOperand storage(this, node->child3()); 2351 GPRReg propertyReg = property.gpr(); 2352 GPRReg storageReg = storage.gpr(); 2353 2354 if (!m_compileOkay) 2355 return; 2356 2357 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()))); 2358 2359 GPRTemporary resultTag(this); 2360 GPRTemporary resultPayload(this); 2361 2362 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr()); 2363 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag))); 2364 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr()); 2365 2366 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2367 break; 2368 } 2369 2370 SpeculateCellOperand base(this, node->child1()); 2371 SpeculateStrictInt32Operand property(this, node->child2()); 2372 StorageOperand storage(this, node->child3()); 2373 GPRReg propertyReg = property.gpr(); 2374 GPRReg storageReg = storage.gpr(); 2375 GPRReg baseReg = base.gpr(); 2376 2377 if (!m_compileOkay) 2378 return; 2379 2380 GPRTemporary resultTag(this); 2381 GPRTemporary resultPayload(this); 2382 GPRReg resultTagReg = resultTag.gpr(); 2383 GPRReg resultPayloadReg = resultPayload.gpr(); 2384 2385 JITCompiler::Jump outOfBounds = m_jit.branch32( 2386 MacroAssembler::AboveOrEqual, propertyReg, 2387 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())); 2388 2389 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg); 2390 JITCompiler::Jump hole = m_jit.branch32( 2391 MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)); 2392 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg); 2393 2394 JITCompiler::JumpList slowCases; 2395 slowCases.append(outOfBounds); 2396 slowCases.append(hole); 2397 addSlowPathGenerator( 2398 slowPathCall( 2399 slowCases, this, operationGetByValArrayInt, 2400 JSValueRegs(resultTagReg, resultPayloadReg), 2401 baseReg, propertyReg)); 2402 2403 jsValueResult(resultTagReg, resultPayloadReg, node); 2404 break; 2405 } 2406 case Array::String: 2407 compileGetByValOnString(node); 2408 break; 2409 case Array::Arguments: 2410 compileGetByValOnArguments(node); 2411 break; 2412 default: { 2413 TypedArrayType type = node->arrayMode().typedArrayType(); 2414 if (isInt(type)) 2415 compileGetByValOnIntTypedArray(node, type); 2416 else 2417 compileGetByValOnFloatTypedArray(node, type); 2418 } } 2419 break; 2420 } 2421 2422 case PutByValDirect: 2423 case PutByVal: 2424 case PutByValAlias: { 2425 Edge child1 = m_jit.graph().varArgChild(node, 0); 2426 Edge child2 = m_jit.graph().varArgChild(node, 1); 2427 Edge child3 = m_jit.graph().varArgChild(node, 2); 2428 Edge child4 = m_jit.graph().varArgChild(node, 3); 2429 2430 ArrayMode arrayMode = node->arrayMode().modeForPut(); 2431 bool alreadyHandled = false; 2432 2433 switch (arrayMode.type()) { 2434 case Array::SelectUsingPredictions: 2435 case Array::ForceExit: 2436 RELEASE_ASSERT_NOT_REACHED(); 2437 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 2438 alreadyHandled = true; 2439 break; 2440 case Array::Generic: { 2441 ASSERT(node->op() == PutByVal || node->op() == PutByValDirect); 2442 2443 SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right. 2444 JSValueOperand property(this, child2); 2445 JSValueOperand value(this, child3); 2446 GPRReg baseGPR = base.gpr(); 2447 GPRReg propertyTagGPR = property.tagGPR(); 2448 GPRReg propertyPayloadGPR = property.payloadGPR(); 2449 GPRReg valueTagGPR = value.tagGPR(); 2450 GPRReg valuePayloadGPR = value.payloadGPR(); 2451 2452 flushRegisters(); 2453 if (node->op() == PutByValDirect) 2454 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR); 2455 else 2456 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR); 2457 2458 noResult(node); 2459 alreadyHandled = true; 2460 break; 2461 } 2462 default: 2463 break; 2464 } 2465 2466 if (alreadyHandled) 2467 break; 2468 2469 SpeculateCellOperand base(this, child1); 2470 SpeculateStrictInt32Operand property(this, child2); 2471 2472 GPRReg baseReg = base.gpr(); 2473 GPRReg propertyReg = property.gpr(); 2474 2475 switch (arrayMode.type()) { 2476 case Array::Int32: { 2477 SpeculateInt32Operand value(this, child3); 2478 2479 GPRReg valuePayloadReg = value.gpr(); 2480 2481 if (!m_compileOkay) 2482 return; 2483 2484 compileContiguousPutByVal(node, base, property, value, valuePayloadReg, TrustedImm32(JSValue::Int32Tag)); 2485 break; 2486 } 2487 case Array::Contiguous: { 2488 JSValueOperand value(this, child3); 2489 2490 GPRReg valueTagReg = value.tagGPR(); 2491 GPRReg valuePayloadReg = value.payloadGPR(); 2492 2493 if (!m_compileOkay) 2494 return; 2495 2496 compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg); 2497 break; 2498 } 2499 case Array::Double: { 2500 compileDoublePutByVal(node, base, property); 2501 break; 2502 } 2503 case Array::ArrayStorage: 2504 case Array::SlowPutArrayStorage: { 2505 JSValueOperand value(this, child3); 2506 2507 GPRReg valueTagReg = value.tagGPR(); 2508 GPRReg valuePayloadReg = value.payloadGPR(); 2509 2510 if (!m_compileOkay) 2511 return; 2512 2513 StorageOperand storage(this, child4); 2514 GPRReg storageReg = storage.gpr(); 2515 2516 if (node->op() == PutByValAlias) { 2517 // Store the value to the array. 2518 GPRReg propertyReg = property.gpr(); 2519 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2520 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2521 2522 noResult(node); 2523 break; 2524 } 2525 2526 MacroAssembler::JumpList slowCases; 2527 2528 MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())); 2529 if (!arrayMode.isOutOfBounds()) 2530 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds); 2531 else 2532 slowCases.append(beyondArrayBounds); 2533 2534 // Check if we're writing to a hole; if so increment m_numValuesInVector. 2535 if (arrayMode.isInBounds()) { 2536 speculationCheck( 2537 StoreToHole, JSValueRegs(), 0, 2538 m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag))); 2539 } else { 2540 MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); 2541 if (arrayMode.isSlowPut()) { 2542 // This is sort of strange. If we wanted to optimize this code path, we would invert 2543 // the above branch. But it's simply not worth it since this only happens if we're 2544 // already having a bad time. 2545 slowCases.append(m_jit.jump()); 2546 } else { 2547 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset())); 2548 2549 // If we're writing to a hole we might be growing the array; 2550 MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); 2551 m_jit.add32(TrustedImm32(1), propertyReg); 2552 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset())); 2553 m_jit.sub32(TrustedImm32(1), propertyReg); 2554 2555 lengthDoesNotNeedUpdate.link(&m_jit); 2556 } 2557 notHoleValue.link(&m_jit); 2558 } 2559 2560 // Store the value to the array. 2561 m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2562 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2563 2564 base.use(); 2565 property.use(); 2566 value.use(); 2567 storage.use(); 2568 2569 if (!slowCases.empty()) { 2570 if (node->op() == PutByValDirect) { 2571 addSlowPathGenerator(slowPathCall( 2572 slowCases, this, 2573 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict, 2574 NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); 2575 } else { 2576 addSlowPathGenerator(slowPathCall( 2577 slowCases, this, 2578 m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, 2579 NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg)); 2580 } 2581 } 2582 2583 noResult(node, UseChildrenCalledExplicitly); 2584 break; 2585 } 2586 2587 case Array::Arguments: 2588 // FIXME: we could at some point make this work. Right now we're assuming that the register 2589 // pressure would be too great. 2590 RELEASE_ASSERT_NOT_REACHED(); 2591 break; 2592 2593 default: { 2594 TypedArrayType type = arrayMode.typedArrayType(); 2595 if (isInt(type)) 2596 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type); 2597 else 2598 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type); 2599 } } 2600 break; 2601 } 2602 2603 case RegExpExec: { 2604 if (compileRegExpExec(node)) 2605 return; 2606 2607 if (!node->adjustedRefCount()) { 2608 SpeculateCellOperand base(this, node->child1()); 2609 SpeculateCellOperand argument(this, node->child2()); 2610 GPRReg baseGPR = base.gpr(); 2611 GPRReg argumentGPR = argument.gpr(); 2612 2613 flushRegisters(); 2614 GPRResult result(this); 2615 callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); 2616 2617 // Must use jsValueResult because otherwise we screw up register 2618 // allocation, which thinks that this node has a result. 2619 booleanResult(result.gpr(), node); 2620 break; 2621 } 2622 2623 SpeculateCellOperand base(this, node->child1()); 2624 SpeculateCellOperand argument(this, node->child2()); 2625 GPRReg baseGPR = base.gpr(); 2626 GPRReg argumentGPR = argument.gpr(); 2627 2628 flushRegisters(); 2629 GPRResult2 resultTag(this); 2630 GPRResult resultPayload(this); 2631 callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR); 2632 2633 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 2634 break; 2635 } 2636 2637 case RegExpTest: { 2638 SpeculateCellOperand base(this, node->child1()); 2639 SpeculateCellOperand argument(this, node->child2()); 2640 GPRReg baseGPR = base.gpr(); 2641 GPRReg argumentGPR = argument.gpr(); 2642 2643 flushRegisters(); 2644 GPRResult result(this); 2645 callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); 2646 2647 // If we add a DataFormatBool, we should use it here. 2648 booleanResult(result.gpr(), node); 2649 break; 2650 } 2651 2652 case ArrayPush: { 2653 ASSERT(node->arrayMode().isJSArray()); 2654 2655 SpeculateCellOperand base(this, node->child1()); 2656 GPRTemporary storageLength(this); 2657 2658 GPRReg baseGPR = base.gpr(); 2659 GPRReg storageLengthGPR = storageLength.gpr(); 2660 2661 StorageOperand storage(this, node->child3()); 2662 GPRReg storageGPR = storage.gpr(); 2663 2664 switch (node->arrayMode().type()) { 2665 case Array::Int32: { 2666 SpeculateInt32Operand value(this, node->child2()); 2667 GPRReg valuePayloadGPR = value.gpr(); 2668 2669 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 2670 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 2671 m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2672 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2673 m_jit.add32(TrustedImm32(1), storageLengthGPR); 2674 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 2675 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 2676 2677 addSlowPathGenerator( 2678 slowPathCall( 2679 slowPath, this, operationArrayPush, 2680 JSValueRegs(storageGPR, storageLengthGPR), 2681 TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR)); 2682 2683 jsValueResult(storageGPR, storageLengthGPR, node); 2684 break; 2685 } 2686 2687 case Array::Contiguous: { 2688 JSValueOperand value(this, node->child2()); 2689 GPRReg valueTagGPR = value.tagGPR(); 2690 GPRReg valuePayloadGPR = value.payloadGPR(); 2691 2692 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 2693 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 2694 m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2695 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2696 m_jit.add32(TrustedImm32(1), storageLengthGPR); 2697 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 2698 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 2699 2700 addSlowPathGenerator( 2701 slowPathCall( 2702 slowPath, this, operationArrayPush, 2703 JSValueRegs(storageGPR, storageLengthGPR), 2704 valueTagGPR, valuePayloadGPR, baseGPR)); 2705 2706 jsValueResult(storageGPR, storageLengthGPR, node); 2707 break; 2708 } 2709 2710 case Array::Double: { 2711 SpeculateDoubleOperand value(this, node->child2()); 2712 FPRReg valueFPR = value.fpr(); 2713 2714 DFG_TYPE_CHECK( 2715 JSValueRegs(), node->child2(), SpecDoubleReal, 2716 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2717 2718 m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR); 2719 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 2720 m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight)); 2721 m_jit.add32(TrustedImm32(1), storageLengthGPR); 2722 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 2723 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 2724 2725 addSlowPathGenerator( 2726 slowPathCall( 2727 slowPath, this, operationArrayPushDouble, 2728 JSValueRegs(storageGPR, storageLengthGPR), 2729 valueFPR, baseGPR)); 2730 2731 jsValueResult(storageGPR, storageLengthGPR, node); 2732 break; 2733 } 2734 2735 case Array::ArrayStorage: { 2736 JSValueOperand value(this, node->child2()); 2737 GPRReg valueTagGPR = value.tagGPR(); 2738 GPRReg valuePayloadGPR = value.payloadGPR(); 2739 2740 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 2741 2742 // Refuse to handle bizarre lengths. 2743 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe))); 2744 2745 MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 2746 2747 m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2748 m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2749 2750 m_jit.add32(TrustedImm32(1), storageLengthGPR); 2751 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 2752 m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 2753 m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR); 2754 2755 addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR)); 2756 2757 jsValueResult(storageGPR, storageLengthGPR, node); 2758 break; 2759 } 2760 2761 default: 2762 CRASH(); 2763 break; 2764 } 2765 break; 2766 } 2767 2768 case ArrayPop: { 2769 ASSERT(node->arrayMode().isJSArray()); 2770 2771 SpeculateCellOperand base(this, node->child1()); 2772 StorageOperand storage(this, node->child2()); 2773 GPRTemporary valueTag(this); 2774 GPRTemporary valuePayload(this); 2775 2776 GPRReg baseGPR = base.gpr(); 2777 GPRReg valueTagGPR = valueTag.gpr(); 2778 GPRReg valuePayloadGPR = valuePayload.gpr(); 2779 GPRReg storageGPR = storage.gpr(); 2780 2781 switch (node->arrayMode().type()) { 2782 case Array::Int32: 2783 case Array::Contiguous: { 2784 m_jit.load32( 2785 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR); 2786 MacroAssembler::Jump undefinedCase = 2787 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR); 2788 m_jit.sub32(TrustedImm32(1), valuePayloadGPR); 2789 m_jit.store32( 2790 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 2791 m_jit.load32( 2792 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), 2793 valueTagGPR); 2794 MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 2795 m_jit.store32( 2796 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag), 2797 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2798 m_jit.load32( 2799 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), 2800 valuePayloadGPR); 2801 2802 addSlowPathGenerator( 2803 slowPathMove( 2804 undefinedCase, this, 2805 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR, 2806 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR)); 2807 addSlowPathGenerator( 2808 slowPathCall( 2809 slowCase, this, operationArrayPopAndRecoverLength, 2810 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); 2811 2812 jsValueResult(valueTagGPR, valuePayloadGPR, node); 2813 break; 2814 } 2815 2816 case Array::Double: { 2817 FPRTemporary temp(this); 2818 FPRReg tempFPR = temp.fpr(); 2819 2820 m_jit.load32( 2821 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR); 2822 MacroAssembler::Jump undefinedCase = 2823 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR); 2824 m_jit.sub32(TrustedImm32(1), valuePayloadGPR); 2825 m_jit.store32( 2826 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 2827 m_jit.loadDouble( 2828 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight), 2829 tempFPR); 2830 MacroAssembler::Jump slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR); 2831 JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN); 2832 m_jit.store32( 2833 MacroAssembler::TrustedImm32(nan.u.asBits.tag), 2834 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2835 m_jit.store32( 2836 MacroAssembler::TrustedImm32(nan.u.asBits.payload), 2837 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 2838 boxDouble(tempFPR, valueTagGPR, valuePayloadGPR); 2839 2840 addSlowPathGenerator( 2841 slowPathMove( 2842 undefinedCase, this, 2843 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR, 2844 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR)); 2845 addSlowPathGenerator( 2846 slowPathCall( 2847 slowCase, this, operationArrayPopAndRecoverLength, 2848 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); 2849 2850 jsValueResult(valueTagGPR, valuePayloadGPR, node); 2851 break; 2852 } 2853 2854 case Array::ArrayStorage: { 2855 GPRTemporary storageLength(this); 2856 GPRReg storageLengthGPR = storageLength.gpr(); 2857 2858 m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR); 2859 2860 JITCompiler::JumpList setUndefinedCases; 2861 setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR)); 2862 2863 m_jit.sub32(TrustedImm32(1), storageLengthGPR); 2864 2865 MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())); 2866 2867 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR); 2868 m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR); 2869 2870 m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset())); 2871 2872 setUndefinedCases.append(m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR)); 2873 2874 m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 2875 2876 m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector))); 2877 2878 addSlowPathGenerator( 2879 slowPathMove( 2880 setUndefinedCases, this, 2881 MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR, 2882 MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR)); 2883 2884 addSlowPathGenerator( 2885 slowPathCall( 2886 slowCase, this, operationArrayPop, 2887 JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR)); 2888 2889 jsValueResult(valueTagGPR, valuePayloadGPR, node); 2890 break; 2891 } 2892 2893 default: 2894 CRASH(); 2895 break; 2896 } 2897 break; 2898 } 2899 2900 case DFG::Jump: { 2901 jump(node->targetBlock()); 2902 noResult(node); 2903 break; 2904 } 2905 2906 case Branch: 2907 emitBranch(node); 2908 break; 2909 2910 case Switch: 2911 emitSwitch(node); 2912 break; 2913 2914 case Return: { 2915 ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2); 2916 ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR); 2917 ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister); 2918 2919 // Return the result in returnValueGPR. 2920 JSValueOperand op1(this, node->child1()); 2921 op1.fill(); 2922 if (op1.isDouble()) 2923 boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR); 2924 else { 2925 if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR) 2926 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2); 2927 else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) { 2928 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR); 2929 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2); 2930 } else { 2931 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2); 2932 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR); 2933 } 2934 } 2935 2936 m_jit.emitFunctionEpilogue(); 2937 m_jit.ret(); 2938 2939 noResult(node); 2940 break; 2941 } 2942 2943 case Throw: 2944 case ThrowReferenceError: { 2945 // We expect that throw statements are rare and are intended to exit the code block 2946 // anyway, so we just OSR back to the old JIT for now. 2947 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 2948 break; 2949 } 2950 2951 case BooleanToNumber: { 2952 switch (node->child1().useKind()) { 2953 case BooleanUse: { 2954 SpeculateBooleanOperand value(this, node->child1()); 2955 GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add). 2956 2957 m_jit.move(value.gpr(), result.gpr()); 2958 2959 int32Result(result.gpr(), node); 2960 break; 2961 } 2962 2963 case UntypedUse: { 2964 JSValueOperand value(this, node->child1()); 2965 GPRTemporary resultTag(this); 2966 GPRTemporary resultPayload(this); 2967 2968 GPRReg valueTagGPR = value.tagGPR(); 2969 GPRReg valuePayloadGPR = value.payloadGPR(); 2970 GPRReg resultTagGPR = resultTag.gpr(); 2971 GPRReg resultPayloadGPR = resultPayload.gpr(); 2972 2973 m_jit.move(valuePayloadGPR, resultPayloadGPR); 2974 JITCompiler::Jump isBoolean = m_jit.branch32( 2975 JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::BooleanTag)); 2976 m_jit.move(valueTagGPR, resultTagGPR); 2977 JITCompiler::Jump done = m_jit.jump(); 2978 isBoolean.link(&m_jit); 2979 m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR); 2980 done.link(&m_jit); 2981 2982 jsValueResult(resultTagGPR, resultPayloadGPR, node); 2983 break; 2984 } 2985 2986 default: 2987 RELEASE_ASSERT_NOT_REACHED(); 2988 break; 2989 } 2990 break; 2991 } 2992 2993 case ToPrimitive: { 2994 RELEASE_ASSERT(node->child1().useKind() == UntypedUse); 2995 JSValueOperand op1(this, node->child1()); 2996 GPRTemporary resultTag(this, Reuse, op1, TagWord); 2997 GPRTemporary resultPayload(this, Reuse, op1, PayloadWord); 2998 2999 GPRReg op1TagGPR = op1.tagGPR(); 3000 GPRReg op1PayloadGPR = op1.payloadGPR(); 3001 GPRReg resultTagGPR = resultTag.gpr(); 3002 GPRReg resultPayloadGPR = resultPayload.gpr(); 3003 3004 op1.use(); 3005 3006 if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean))) { 3007 m_jit.move(op1TagGPR, resultTagGPR); 3008 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3009 } else { 3010 MacroAssembler::Jump alreadyPrimitive = branchNotCell(op1.jsValueRegs()); 3011 MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureIDOffset()), MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())); 3012 3013 alreadyPrimitive.link(&m_jit); 3014 m_jit.move(op1TagGPR, resultTagGPR); 3015 m_jit.move(op1PayloadGPR, resultPayloadGPR); 3016 3017 addSlowPathGenerator( 3018 slowPathCall( 3019 notPrimitive, this, operationToPrimitive, 3020 JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR)); 3021 } 3022 3023 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3024 break; 3025 } 3026 3027 case ToString: { 3028 if (node->child1().useKind() == UntypedUse) { 3029 JSValueOperand op1(this, node->child1()); 3030 GPRReg op1PayloadGPR = op1.payloadGPR(); 3031 GPRReg op1TagGPR = op1.tagGPR(); 3032 3033 GPRResult result(this); 3034 GPRReg resultGPR = result.gpr(); 3035 3036 flushRegisters(); 3037 3038 JITCompiler::Jump done; 3039 if (node->child1()->prediction() & SpecString) { 3040 JITCompiler::Jump slowPath1 = branchNotCell(op1.jsValueRegs()); 3041 JITCompiler::Jump slowPath2 = m_jit.branchPtr( 3042 JITCompiler::NotEqual, 3043 JITCompiler::Address(op1PayloadGPR, JSCell::structureIDOffset()), 3044 TrustedImmPtr(m_jit.vm()->stringStructure.get())); 3045 m_jit.move(op1PayloadGPR, resultGPR); 3046 done = m_jit.jump(); 3047 slowPath1.link(&m_jit); 3048 slowPath2.link(&m_jit); 3049 } 3050 callOperation(operationToString, resultGPR, op1TagGPR, op1PayloadGPR); 3051 if (done.isSet()) 3052 done.link(&m_jit); 3053 cellResult(resultGPR, node); 3054 break; 3055 } 3056 3057 compileToStringOnCell(node); 3058 break; 3059 } 3060 3061 case NewStringObject: { 3062 compileNewStringObject(node); 3063 break; 3064 } 3065 3066 case NewArray: { 3067 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic); 3068 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) { 3069 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()); 3070 ASSERT(structure->indexingType() == node->indexingType()); 3071 ASSERT( 3072 hasUndecided(structure->indexingType()) 3073 || hasInt32(structure->indexingType()) 3074 || hasDouble(structure->indexingType()) 3075 || hasContiguous(structure->indexingType())); 3076 3077 unsigned numElements = node->numChildren(); 3078 3079 GPRTemporary result(this); 3080 GPRTemporary storage(this); 3081 3082 GPRReg resultGPR = result.gpr(); 3083 GPRReg storageGPR = storage.gpr(); 3084 3085 emitAllocateJSArray(resultGPR, structure, storageGPR, numElements); 3086 3087 // At this point, one way or another, resultGPR and storageGPR have pointers to 3088 // the JSArray and the Butterfly, respectively. 3089 3090 ASSERT(!hasUndecided(structure->indexingType()) || !node->numChildren()); 3091 3092 for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) { 3093 Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]; 3094 switch (node->indexingType()) { 3095 case ALL_BLANK_INDEXING_TYPES: 3096 case ALL_UNDECIDED_INDEXING_TYPES: 3097 CRASH(); 3098 break; 3099 case ALL_DOUBLE_INDEXING_TYPES: { 3100 SpeculateDoubleOperand operand(this, use); 3101 FPRReg opFPR = operand.fpr(); 3102 DFG_TYPE_CHECK( 3103 JSValueRegs(), use, SpecDoubleReal, 3104 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3105 3106 m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx)); 3107 break; 3108 } 3109 case ALL_INT32_INDEXING_TYPES: { 3110 SpeculateInt32Operand operand(this, use); 3111 m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3112 m_jit.store32(operand.gpr(), MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3113 break; 3114 } 3115 case ALL_CONTIGUOUS_INDEXING_TYPES: { 3116 JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]); 3117 GPRReg opTagGPR = operand.tagGPR(); 3118 GPRReg opPayloadGPR = operand.payloadGPR(); 3119 m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3120 m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3121 break; 3122 } 3123 default: 3124 CRASH(); 3125 break; 3126 } 3127 } 3128 3129 // Yuck, we should *really* have a way of also returning the storageGPR. But 3130 // that's the least of what's wrong with this code. We really shouldn't be 3131 // allocating the array after having computed - and probably spilled to the 3132 // stack - all of the things that will go into the array. The solution to that 3133 // bigger problem will also likely fix the redundancy in reloading the storage 3134 // pointer that we currently have. 3135 3136 cellResult(resultGPR, node); 3137 break; 3138 } 3139 3140 if (!node->numChildren()) { 3141 flushRegisters(); 3142 GPRResult result(this); 3143 callOperation( 3144 operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())); 3145 cellResult(result.gpr(), node); 3146 break; 3147 } 3148 3149 size_t scratchSize = sizeof(EncodedJSValue) * node->numChildren(); 3150 ScratchBuffer* scratchBuffer = m_jit.vm()->scratchBufferForSize(scratchSize); 3151 EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0; 3152 3153 for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) { 3154 // Need to perform the speculations that this node promises to perform. If we're 3155 // emitting code here and the indexing type is not array storage then there is 3156 // probably something hilarious going on and we're already failing at all the 3157 // things, but at least we're going to be sound. 3158 Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]; 3159 switch (node->indexingType()) { 3160 case ALL_BLANK_INDEXING_TYPES: 3161 case ALL_UNDECIDED_INDEXING_TYPES: 3162 CRASH(); 3163 break; 3164 case ALL_DOUBLE_INDEXING_TYPES: { 3165 SpeculateDoubleOperand operand(this, use); 3166 FPRReg opFPR = operand.fpr(); 3167 DFG_TYPE_CHECK( 3168 JSValueRegs(), use, SpecFullRealNumber, 3169 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3170 3171 m_jit.storeDouble(opFPR, TrustedImmPtr(reinterpret_cast<char*>(buffer + operandIdx))); 3172 break; 3173 } 3174 case ALL_INT32_INDEXING_TYPES: { 3175 SpeculateInt32Operand operand(this, use); 3176 GPRReg opGPR = operand.gpr(); 3177 m_jit.store32(TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); 3178 m_jit.store32(opGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); 3179 break; 3180 } 3181 case ALL_CONTIGUOUS_INDEXING_TYPES: 3182 case ALL_ARRAY_STORAGE_INDEXING_TYPES: { 3183 JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx]); 3184 GPRReg opTagGPR = operand.tagGPR(); 3185 GPRReg opPayloadGPR = operand.payloadGPR(); 3186 3187 m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); 3188 m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); 3189 operand.use(); 3190 break; 3191 } 3192 default: 3193 CRASH(); 3194 break; 3195 } 3196 } 3197 3198 switch (node->indexingType()) { 3199 case ALL_DOUBLE_INDEXING_TYPES: 3200 case ALL_INT32_INDEXING_TYPES: 3201 useChildren(node); 3202 break; 3203 default: 3204 break; 3205 } 3206 3207 flushRegisters(); 3208 3209 if (scratchSize) { 3210 GPRTemporary scratch(this); 3211 3212 // Tell GC mark phase how much of the scratch buffer is active during call. 3213 m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr()); 3214 m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr()); 3215 } 3216 3217 GPRResult result(this); 3218 3219 callOperation( 3220 operationNewArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), 3221 static_cast<void*>(buffer), node->numChildren()); 3222 3223 if (scratchSize) { 3224 GPRTemporary scratch(this); 3225 3226 m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr()); 3227 m_jit.storePtr(TrustedImmPtr(0), scratch.gpr()); 3228 } 3229 3230 cellResult(result.gpr(), node, UseChildrenCalledExplicitly); 3231 break; 3232 } 3233 3234 case NewArrayWithSize: { 3235 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic); 3236 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) { 3237 SpeculateStrictInt32Operand size(this, node->child1()); 3238 GPRTemporary result(this); 3239 GPRTemporary storage(this); 3240 GPRTemporary scratch(this); 3241 GPRTemporary scratch2(this); 3242 3243 GPRReg sizeGPR = size.gpr(); 3244 GPRReg resultGPR = result.gpr(); 3245 GPRReg storageGPR = storage.gpr(); 3246 GPRReg scratchGPR = scratch.gpr(); 3247 GPRReg scratch2GPR = scratch2.gpr(); 3248 3249 MacroAssembler::JumpList slowCases; 3250 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX))); 3251 3252 ASSERT((1 << 3) == sizeof(JSValue)); 3253 m_jit.move(sizeGPR, scratchGPR); 3254 m_jit.lshift32(TrustedImm32(3), scratchGPR); 3255 m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR); 3256 slowCases.append( 3257 emitAllocateBasicStorage(resultGPR, storageGPR)); 3258 m_jit.subPtr(scratchGPR, storageGPR); 3259 Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()); 3260 emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases); 3261 3262 m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())); 3263 m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength())); 3264 3265 if (hasDouble(node->indexingType())) { 3266 JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN); 3267 3268 m_jit.move(sizeGPR, scratchGPR); 3269 MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR); 3270 MacroAssembler::Label loop = m_jit.label(); 3271 m_jit.sub32(TrustedImm32(1), scratchGPR); 3272 m_jit.store32(TrustedImm32(nan.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag))); 3273 m_jit.store32(TrustedImm32(nan.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload))); 3274 m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &m_jit); 3275 done.link(&m_jit); 3276 } 3277 3278 addSlowPathGenerator(adoptPtr( 3279 new CallArrayAllocatorWithVariableSizeSlowPathGenerator( 3280 slowCases, this, operationNewArrayWithSize, resultGPR, 3281 globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), 3282 globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage), 3283 sizeGPR))); 3284 3285 cellResult(resultGPR, node); 3286 break; 3287 } 3288 3289 SpeculateStrictInt32Operand size(this, node->child1()); 3290 GPRReg sizeGPR = size.gpr(); 3291 flushRegisters(); 3292 GPRResult result(this); 3293 GPRReg resultGPR = result.gpr(); 3294 GPRReg structureGPR = selectScratchGPR(sizeGPR); 3295 MacroAssembler::Jump bigLength = m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)); 3296 m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())), structureGPR); 3297 MacroAssembler::Jump done = m_jit.jump(); 3298 bigLength.link(&m_jit); 3299 m_jit.move(TrustedImmPtr(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithArrayStorage)), structureGPR); 3300 done.link(&m_jit); 3301 callOperation( 3302 operationNewArrayWithSize, resultGPR, structureGPR, sizeGPR); 3303 cellResult(resultGPR, node); 3304 break; 3305 } 3306 3307 case NewArrayBuffer: { 3308 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic); 3309 IndexingType indexingType = node->indexingType(); 3310 if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(indexingType)) { 3311 unsigned numElements = node->numConstants(); 3312 3313 GPRTemporary result(this); 3314 GPRTemporary storage(this); 3315 3316 GPRReg resultGPR = result.gpr(); 3317 GPRReg storageGPR = storage.gpr(); 3318 3319 emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements); 3320 3321 if (node->indexingType() == ArrayWithDouble) { 3322 JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant()); 3323 for (unsigned index = 0; index < node->numConstants(); ++index) { 3324 union { 3325 int32_t halves[2]; 3326 double value; 3327 } u; 3328 u.value = data[index].asNumber(); 3329 m_jit.store32(Imm32(u.halves[0]), MacroAssembler::Address(storageGPR, sizeof(double) * index)); 3330 m_jit.store32(Imm32(u.halves[1]), MacroAssembler::Address(storageGPR, sizeof(double) * index + sizeof(int32_t))); 3331 } 3332 } else { 3333 int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node->startConstant())); 3334 for (unsigned index = 0; index < node->numConstants() * 2; ++index) { 3335 m_jit.store32( 3336 Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index)); 3337 } 3338 } 3339 3340 cellResult(resultGPR, node); 3341 break; 3342 } 3343 3344 flushRegisters(); 3345 GPRResult result(this); 3346 3347 callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()), node->startConstant(), node->numConstants()); 3348 3349 cellResult(result.gpr(), node); 3350 break; 3351 } 3352 3353 case NewTypedArray: { 3354 switch (node->child1().useKind()) { 3355 case Int32Use: 3356 compileNewTypedArray(node); 3357 break; 3358 case UntypedUse: { 3359 JSValueOperand argument(this, node->child1()); 3360 GPRReg argumentTagGPR = argument.tagGPR(); 3361 GPRReg argumentPayloadGPR = argument.payloadGPR(); 3362 3363 flushRegisters(); 3364 3365 GPRResult result(this); 3366 GPRReg resultGPR = result.gpr(); 3367 3368 JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic); 3369 callOperation( 3370 operationNewTypedArrayWithOneArgumentForType(node->typedArrayType()), 3371 resultGPR, globalObject->typedArrayStructure(node->typedArrayType()), 3372 argumentTagGPR, argumentPayloadGPR); 3373 3374 cellResult(resultGPR, node); 3375 break; 3376 } 3377 default: 3378 RELEASE_ASSERT_NOT_REACHED(); 3379 break; 3380 } 3381 break; 3382 } 3383 3384 case NewRegexp: { 3385 flushRegisters(); 3386 GPRResult resultPayload(this); 3387 GPRResult2 resultTag(this); 3388 3389 callOperation(operationNewRegexp, resultTag.gpr(), resultPayload.gpr(), m_jit.codeBlock()->regexp(node->regexpIndex())); 3390 3391 // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag. 3392 cellResult(resultPayload.gpr(), node); 3393 break; 3394 } 3395 3396 case ToThis: { 3397 ASSERT(node->child1().useKind() == UntypedUse); 3398 JSValueOperand thisValue(this, node->child1()); 3399 GPRTemporary temp(this); 3400 GPRTemporary tempTag(this); 3401 GPRReg thisValuePayloadGPR = thisValue.payloadGPR(); 3402 GPRReg thisValueTagGPR = thisValue.tagGPR(); 3403 GPRReg tempGPR = temp.gpr(); 3404 GPRReg tempTagGPR = tempTag.gpr(); 3405 3406 MacroAssembler::JumpList slowCases; 3407 slowCases.append(branchNotCell(thisValue.jsValueRegs())); 3408 slowCases.append(m_jit.branch8( 3409 MacroAssembler::NotEqual, 3410 MacroAssembler::Address(thisValuePayloadGPR, JSCell::typeInfoTypeOffset()), 3411 TrustedImm32(FinalObjectType))); 3412 m_jit.move(thisValuePayloadGPR, tempGPR); 3413 m_jit.move(thisValueTagGPR, tempTagGPR); 3414 J_JITOperation_EJ function; 3415 if (m_jit.graph().executableFor(node->origin.semantic)->isStrictMode()) 3416 function = operationToThisStrict; 3417 else 3418 function = operationToThis; 3419 addSlowPathGenerator( 3420 slowPathCall( 3421 slowCases, this, function, 3422 JSValueRegs(tempTagGPR, tempGPR), thisValueTagGPR, thisValuePayloadGPR)); 3423 3424 jsValueResult(tempTagGPR, tempGPR, node); 3425 break; 3426 } 3427 3428 case CreateThis: { 3429 // Note that there is not so much profit to speculate here. The only things we 3430 // speculate on are (1) that it's a cell, since that eliminates cell checks 3431 // later if the proto is reused, and (2) if we have a FinalObject prediction 3432 // then we speculate because we want to get recompiled if it isn't (since 3433 // otherwise we'd start taking slow path a lot). 3434 3435 SpeculateCellOperand callee(this, node->child1()); 3436 GPRTemporary result(this); 3437 GPRTemporary allocator(this); 3438 GPRTemporary structure(this); 3439 GPRTemporary scratch(this); 3440 3441 GPRReg calleeGPR = callee.gpr(); 3442 GPRReg resultGPR = result.gpr(); 3443 GPRReg allocatorGPR = allocator.gpr(); 3444 GPRReg structureGPR = structure.gpr(); 3445 GPRReg scratchGPR = scratch.gpr(); 3446 3447 MacroAssembler::JumpList slowPath; 3448 3449 m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorGPR); 3450 m_jit.loadPtr(JITCompiler::Address(calleeGPR, JSFunction::offsetOfAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureGPR); 3451 slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, allocatorGPR)); 3452 emitAllocateJSObject(resultGPR, allocatorGPR, structureGPR, TrustedImmPtr(0), scratchGPR, slowPath); 3453 3454 addSlowPathGenerator(slowPathCall(slowPath, this, operationCreateThis, resultGPR, calleeGPR, node->inlineCapacity())); 3455 3456 cellResult(resultGPR, node); 3457 break; 3458 } 3459 3460 case AllocationProfileWatchpoint: 3461 case TypedArrayWatchpoint: { 3462 noResult(node); 3463 break; 3464 } 3465 3466 case NewObject: { 3467 GPRTemporary result(this); 3468 GPRTemporary allocator(this); 3469 GPRTemporary scratch(this); 3470 3471 GPRReg resultGPR = result.gpr(); 3472 GPRReg allocatorGPR = allocator.gpr(); 3473 GPRReg scratchGPR = scratch.gpr(); 3474 3475 MacroAssembler::JumpList slowPath; 3476 3477 Structure* structure = node->structure(); 3478 size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity()); 3479 MarkedAllocator* allocatorPtr = &m_jit.vm()->heap.allocatorForObjectWithoutDestructor(allocationSize); 3480 3481 m_jit.move(TrustedImmPtr(allocatorPtr), allocatorGPR); 3482 emitAllocateJSObject(resultGPR, allocatorGPR, TrustedImmPtr(structure), TrustedImmPtr(0), scratchGPR, slowPath); 3483 3484 addSlowPathGenerator(slowPathCall(slowPath, this, operationNewObject, resultGPR, structure)); 3485 3486 cellResult(resultGPR, node); 3487 break; 3488 } 3489 3490 case GetCallee: { 3491 GPRTemporary result(this); 3492 m_jit.loadPtr(JITCompiler::payloadFor(JSStack::Callee), result.gpr()); 3493 cellResult(result.gpr(), node); 3494 break; 3495 } 3496 3497 case GetScope: { 3498 SpeculateCellOperand function(this, node->child1()); 3499 GPRTemporary result(this, Reuse, function); 3500 m_jit.loadPtr(JITCompiler::Address(function.gpr(), JSFunction::offsetOfScopeChain()), result.gpr()); 3501 cellResult(result.gpr(), node); 3502 break; 3503 } 3504 3505 case GetMyScope: { 3506 GPRTemporary result(this); 3507 GPRReg resultGPR = result.gpr(); 3508 3509 m_jit.loadPtr(JITCompiler::payloadFor(JSStack::ScopeChain), resultGPR); 3510 cellResult(resultGPR, node); 3511 break; 3512 } 3513 3514 case SkipTopScope: { 3515 SpeculateCellOperand scope(this, node->child1()); 3516 GPRTemporary result(this, Reuse, scope); 3517 GPRReg resultGPR = result.gpr(); 3518 m_jit.move(scope.gpr(), resultGPR); 3519 JITCompiler::Jump activationNotCreated = 3520 m_jit.branchTestPtr( 3521 JITCompiler::Zero, 3522 JITCompiler::payloadFor( 3523 static_cast<VirtualRegister>(m_jit.graph().machineActivationRegister()))); 3524 m_jit.loadPtr(JITCompiler::Address(resultGPR, JSScope::offsetOfNext()), resultGPR); 3525 activationNotCreated.link(&m_jit); 3526 cellResult(resultGPR, node); 3527 break; 3528 } 3529 3530 case SkipScope: { 3531 SpeculateCellOperand scope(this, node->child1()); 3532 GPRTemporary result(this, Reuse, scope); 3533 m_jit.loadPtr(JITCompiler::Address(scope.gpr(), JSScope::offsetOfNext()), result.gpr()); 3534 cellResult(result.gpr(), node); 3535 break; 3536 } 3537 3538 case GetClosureRegisters: { 3539 if (WriteBarrierBase<Unknown>* registers = m_jit.graph().tryGetRegisters(node->child1().node())) { 3540 GPRTemporary result(this); 3541 GPRReg resultGPR = result.gpr(); 3542 m_jit.move(TrustedImmPtr(registers), resultGPR); 3543 storageResult(resultGPR, node); 3544 break; 3545 } 3546 3547 SpeculateCellOperand scope(this, node->child1()); 3548 GPRTemporary result(this); 3549 GPRReg scopeGPR = scope.gpr(); 3550 GPRReg resultGPR = result.gpr(); 3551 3552 m_jit.loadPtr(JITCompiler::Address(scopeGPR, JSVariableObject::offsetOfRegisters()), resultGPR); 3553 storageResult(resultGPR, node); 3554 break; 3555 } 3556 case GetClosureVar: { 3557 StorageOperand registers(this, node->child1()); 3558 GPRTemporary resultTag(this); 3559 GPRTemporary resultPayload(this); 3560 GPRReg registersGPR = registers.gpr(); 3561 GPRReg resultTagGPR = resultTag.gpr(); 3562 GPRReg resultPayloadGPR = resultPayload.gpr(); 3563 m_jit.load32(JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR); 3564 m_jit.load32(JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR); 3565 jsValueResult(resultTagGPR, resultPayloadGPR, node); 3566 break; 3567 } 3568 case PutClosureVar: { 3569 StorageOperand registers(this, node->child2()); 3570 JSValueOperand value(this, node->child3()); 3571 GPRTemporary scratchRegister(this); 3572 3573 GPRReg registersGPR = registers.gpr(); 3574 GPRReg valueTagGPR = value.tagGPR(); 3575 GPRReg valuePayloadGPR = value.payloadGPR(); 3576 3577 speculate(node, node->child1()); 3578 3579 m_jit.store32(valueTagGPR, JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 3580 m_jit.store32(valuePayloadGPR, JITCompiler::Address(registersGPR, node->varNumber() * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 3581 noResult(node); 3582 break; 3583 } 3584 3585 case GetById: { 3586 ASSERT(node->prediction()); 3587 3588 switch (node->child1().useKind()) { 3589 case CellUse: { 3590 SpeculateCellOperand base(this, node->child1()); 3591 GPRTemporary resultTag(this); 3592 GPRTemporary resultPayload(this, Reuse, base); 3593 3594 GPRReg baseGPR = base.gpr(); 3595 GPRReg resultTagGPR = resultTag.gpr(); 3596 GPRReg resultPayloadGPR = resultPayload.gpr(); 3597 3598 base.use(); 3599 3600 cachedGetById(node->origin.semantic, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber()); 3601 3602 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3603 break; 3604 } 3605 3606 case UntypedUse: { 3607 JSValueOperand base(this, node->child1()); 3608 GPRTemporary resultTag(this); 3609 GPRTemporary resultPayload(this, Reuse, base, TagWord); 3610 3611 GPRReg baseTagGPR = base.tagGPR(); 3612 GPRReg basePayloadGPR = base.payloadGPR(); 3613 GPRReg resultTagGPR = resultTag.gpr(); 3614 GPRReg resultPayloadGPR = resultPayload.gpr(); 3615 3616 base.use(); 3617 3618 JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs()); 3619 3620 cachedGetById(node->origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell); 3621 3622 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3623 break; 3624 } 3625 3626 default: 3627 RELEASE_ASSERT_NOT_REACHED(); 3628 break; 3629 } 3630 break; 3631 } 3632 3633 case GetByIdFlush: { 3634 if (!node->prediction()) { 3635 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 3636 break; 3637 } 3638 3639 switch (node->child1().useKind()) { 3640 case CellUse: { 3641 SpeculateCellOperand base(this, node->child1()); 3642 3643 GPRReg baseGPR = base.gpr(); 3644 3645 GPRResult resultPayload(this); 3646 GPRResult2 resultTag(this); 3647 GPRReg resultPayloadGPR = resultPayload.gpr(); 3648 GPRReg resultTagGPR = resultTag.gpr(); 3649 3650 base.use(); 3651 3652 flushRegisters(); 3653 3654 cachedGetById(node->origin.semantic, InvalidGPRReg, baseGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), JITCompiler::Jump(), DontSpill); 3655 3656 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3657 break; 3658 } 3659 3660 case UntypedUse: { 3661 JSValueOperand base(this, node->child1()); 3662 GPRReg baseTagGPR = base.tagGPR(); 3663 GPRReg basePayloadGPR = base.payloadGPR(); 3664 3665 GPRResult resultPayload(this); 3666 GPRResult2 resultTag(this); 3667 GPRReg resultPayloadGPR = resultPayload.gpr(); 3668 GPRReg resultTagGPR = resultTag.gpr(); 3669 3670 base.use(); 3671 3672 flushRegisters(); 3673 3674 JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs()); 3675 3676 cachedGetById(node->origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCell, DontSpill); 3677 3678 jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly); 3679 break; 3680 } 3681 3682 default: 3683 RELEASE_ASSERT_NOT_REACHED(); 3684 break; 3685 } 3686 break; 3687 } 3688 3689 case GetArrayLength: 3690 compileGetArrayLength(node); 3691 break; 3692 3693 case CheckFunction: { 3694 SpeculateCellOperand function(this, node->child1()); 3695 speculationCheck(BadFunction, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node->function())); 3696 noResult(node); 3697 break; 3698 } 3699 3700 case CheckExecutable: { 3701 SpeculateCellOperand function(this, node->child1()); 3702 speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node->executable())); 3703 noResult(node); 3704 break; 3705 } 3706 3707 case CheckStructure: { 3708 SpeculateCellOperand base(this, node->child1()); 3709 3710 ASSERT(node->structureSet().size()); 3711 3712 if (node->structureSet().size() == 1) { 3713 speculationCheck( 3714 BadCache, JSValueSource::unboxedCell(base.gpr()), 0, 3715 m_jit.branchWeakPtr( 3716 JITCompiler::NotEqual, 3717 JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), 3718 node->structureSet()[0])); 3719 } else { 3720 GPRTemporary structure(this); 3721 3722 m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), structure.gpr()); 3723 3724 JITCompiler::JumpList done; 3725 3726 for (size_t i = 0; i < node->structureSet().size() - 1; ++i) 3727 done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node->structureSet()[i])); 3728 3729 speculationCheck( 3730 BadCache, JSValueSource::unboxedCell(base.gpr()), 0, 3731 m_jit.branchWeakPtr( 3732 JITCompiler::NotEqual, structure.gpr(), node->structureSet().last())); 3733 3734 done.link(&m_jit); 3735 } 3736 3737 noResult(node); 3738 break; 3739 } 3740 3741 case StructureTransitionWatchpoint: { 3742 // There is a fascinating question here of what to do about array profiling. 3743 // We *could* try to tell the OSR exit about where the base of the access is. 3744 // The DFG will have kept it alive, though it may not be in a register, and 3745 // we shouldn't really load it since that could be a waste. For now though, 3746 // we'll just rely on the fact that when a watchpoint fires then that's 3747 // quite a hint already. 3748 3749 m_jit.addWeakReference(node->structure()); 3750 3751#if !ASSERT_DISABLED 3752 SpeculateCellOperand op1(this, node->child1()); 3753 JITCompiler::Jump isOK = m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(op1.gpr(), JSCell::structureIDOffset()), TrustedImmPtr(node->structure())); 3754 m_jit.abortWithReason(DFGIneffectiveWatchpoint); 3755 isOK.link(&m_jit); 3756#else 3757 speculateCell(node->child1()); 3758#endif 3759 3760 noResult(node); 3761 break; 3762 } 3763 3764 case PhantomPutStructure: { 3765 ASSERT(isKnownCell(node->child1().node())); 3766 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node); 3767 noResult(node); 3768 break; 3769 } 3770 3771 case PutStructure: { 3772 m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node); 3773 3774 SpeculateCellOperand base(this, node->child1()); 3775 GPRReg baseGPR = base.gpr(); 3776 3777 m_jit.storePtr(MacroAssembler::TrustedImmPtr(node->structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset())); 3778 3779 noResult(node); 3780 break; 3781 } 3782 3783 case AllocatePropertyStorage: 3784 compileAllocatePropertyStorage(node); 3785 break; 3786 3787 case ReallocatePropertyStorage: 3788 compileReallocatePropertyStorage(node); 3789 break; 3790 3791 case GetButterfly: { 3792 SpeculateCellOperand base(this, node->child1()); 3793 GPRTemporary result(this, Reuse, base); 3794 3795 GPRReg baseGPR = base.gpr(); 3796 GPRReg resultGPR = result.gpr(); 3797 3798 m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), resultGPR); 3799 3800 storageResult(resultGPR, node); 3801 break; 3802 } 3803 3804 case GetIndexedPropertyStorage: { 3805 compileGetIndexedPropertyStorage(node); 3806 break; 3807 } 3808 3809 case ConstantStoragePointer: { 3810 compileConstantStoragePointer(node); 3811 break; 3812 } 3813 3814 case GetTypedArrayByteOffset: { 3815 compileGetTypedArrayByteOffset(node); 3816 break; 3817 } 3818 3819 case GetByOffset: { 3820 StorageOperand storage(this, node->child1()); 3821 GPRTemporary resultTag(this, Reuse, storage); 3822 GPRTemporary resultPayload(this); 3823 3824 GPRReg storageGPR = storage.gpr(); 3825 GPRReg resultTagGPR = resultTag.gpr(); 3826 GPRReg resultPayloadGPR = resultPayload.gpr(); 3827 3828 StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node->storageAccessDataIndex()]; 3829 3830 m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR); 3831 m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR); 3832 3833 jsValueResult(resultTagGPR, resultPayloadGPR, node); 3834 break; 3835 } 3836 3837 case PutByOffset: { 3838 StorageOperand storage(this, node->child1()); 3839 JSValueOperand value(this, node->child3()); 3840 3841 GPRReg storageGPR = storage.gpr(); 3842 GPRReg valueTagGPR = value.tagGPR(); 3843 GPRReg valuePayloadGPR = value.payloadGPR(); 3844 3845 speculate(node, node->child2()); 3846 3847 StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node->storageAccessDataIndex()]; 3848 3849 m_jit.storePtr(valueTagGPR, JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 3850 m_jit.storePtr(valuePayloadGPR, JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 3851 3852 noResult(node); 3853 break; 3854 } 3855 3856 case PutByIdFlush: { 3857 SpeculateCellOperand base(this, node->child1()); 3858 JSValueOperand value(this, node->child2()); 3859 GPRTemporary scratch(this); 3860 3861 GPRReg baseGPR = base.gpr(); 3862 GPRReg valueTagGPR = value.tagGPR(); 3863 GPRReg valuePayloadGPR = value.payloadGPR(); 3864 GPRReg scratchGPR = scratch.gpr(); 3865 flushRegisters(); 3866 3867 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect, MacroAssembler::Jump(), DontSpill); 3868 3869 noResult(node); 3870 break; 3871 } 3872 3873 case PutById: { 3874 SpeculateCellOperand base(this, node->child1()); 3875 JSValueOperand value(this, node->child2()); 3876 GPRTemporary scratch(this); 3877 3878 GPRReg baseGPR = base.gpr(); 3879 GPRReg valueTagGPR = value.tagGPR(); 3880 GPRReg valuePayloadGPR = value.payloadGPR(); 3881 GPRReg scratchGPR = scratch.gpr(); 3882 3883 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), NotDirect); 3884 3885 noResult(node); 3886 break; 3887 } 3888 3889 case PutByIdDirect: { 3890 SpeculateCellOperand base(this, node->child1()); 3891 JSValueOperand value(this, node->child2()); 3892 GPRTemporary scratch(this); 3893 3894 GPRReg baseGPR = base.gpr(); 3895 GPRReg valueTagGPR = value.tagGPR(); 3896 GPRReg valuePayloadGPR = value.payloadGPR(); 3897 GPRReg scratchGPR = scratch.gpr(); 3898 3899 cachedPutById(node->origin.semantic, baseGPR, valueTagGPR, valuePayloadGPR, scratchGPR, node->identifierNumber(), Direct); 3900 3901 noResult(node); 3902 break; 3903 } 3904 3905 case GetGlobalVar: { 3906 GPRTemporary resultPayload(this); 3907 GPRTemporary resultTag(this); 3908 3909 m_jit.move(TrustedImmPtr(node->registerPointer()), resultPayload.gpr()); 3910 m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTag.gpr()); 3911 m_jit.load32(JITCompiler::Address(resultPayload.gpr(), OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayload.gpr()); 3912 3913 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node); 3914 break; 3915 } 3916 3917 case PutGlobalVar: { 3918 JSValueOperand value(this, node->child1()); 3919 3920 // FIXME: if we happen to have a spare register - and _ONLY_ if we happen to have 3921 // a spare register - a good optimization would be to put the register pointer into 3922 // a register and then do a zero offset store followed by a four-offset store (or 3923 // vice-versa depending on endianness). 3924 m_jit.store32(value.tagGPR(), node->registerPointer()->tagPointer()); 3925 m_jit.store32(value.payloadGPR(), node->registerPointer()->payloadPointer()); 3926 3927 noResult(node); 3928 break; 3929 } 3930 3931 case NotifyWrite: { 3932 VariableWatchpointSet* set = node->variableWatchpointSet(); 3933 3934 JSValueOperand value(this, node->child1()); 3935 GPRReg valueTagGPR = value.tagGPR(); 3936 GPRReg valuePayloadGPR = value.payloadGPR(); 3937 3938 GPRTemporary temp(this); 3939 GPRReg tempGPR = temp.gpr(); 3940 3941 m_jit.load8(set->addressOfState(), tempGPR); 3942 3943 JITCompiler::Jump isDone = m_jit.branch32(JITCompiler::Equal, tempGPR, TrustedImm32(IsInvalidated)); 3944 JITCompiler::JumpList notifySlow; 3945 notifySlow.append(m_jit.branch32( 3946 JITCompiler::NotEqual, 3947 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->payloadPointer()), 3948 valuePayloadGPR)); 3949 notifySlow.append(m_jit.branch32( 3950 JITCompiler::NotEqual, 3951 JITCompiler::AbsoluteAddress(set->addressOfInferredValue()->tagPointer()), 3952 valueTagGPR)); 3953 addSlowPathGenerator( 3954 slowPathCall(notifySlow, this, operationNotifyWrite, NoResult, set, valueTagGPR, valuePayloadGPR)); 3955 isDone.link(&m_jit); 3956 3957 noResult(node); 3958 break; 3959 } 3960 3961 case VarInjectionWatchpoint: 3962 case VariableWatchpoint: { 3963 noResult(node); 3964 break; 3965 } 3966 3967 case CheckHasInstance: { 3968 SpeculateCellOperand base(this, node->child1()); 3969 GPRTemporary structure(this); 3970 3971 // Speculate that base 'ImplementsDefaultHasInstance'. 3972 speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest8( 3973 MacroAssembler::Zero, 3974 MacroAssembler::Address(base.gpr(), JSCell::typeInfoFlagsOffset()), 3975 MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance))); 3976 3977 noResult(node); 3978 break; 3979 } 3980 3981 case InstanceOf: { 3982 compileInstanceOf(node); 3983 break; 3984 } 3985 3986 case IsUndefined: { 3987 JSValueOperand value(this, node->child1()); 3988 GPRTemporary result(this); 3989 GPRTemporary localGlobalObject(this); 3990 GPRTemporary remoteGlobalObject(this); 3991 3992 JITCompiler::Jump isCell = branchIsCell(value.jsValueRegs()); 3993 3994 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr()); 3995 JITCompiler::Jump done = m_jit.jump(); 3996 3997 isCell.link(&m_jit); 3998 JITCompiler::Jump notMasqueradesAsUndefined; 3999 if (masqueradesAsUndefinedWatchpointIsStillValid()) { 4000 m_jit.move(TrustedImm32(0), result.gpr()); 4001 notMasqueradesAsUndefined = m_jit.jump(); 4002 } else { 4003 JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8( 4004 JITCompiler::NonZero, 4005 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), 4006 TrustedImm32(MasqueradesAsUndefined)); 4007 m_jit.move(TrustedImm32(0), result.gpr()); 4008 notMasqueradesAsUndefined = m_jit.jump(); 4009 4010 isMasqueradesAsUndefined.link(&m_jit); 4011 GPRReg localGlobalObjectGPR = localGlobalObject.gpr(); 4012 GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr(); 4013 m_jit.move(TrustedImmPtr(m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR); 4014 m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr()); 4015 m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); 4016 m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr()); 4017 } 4018 4019 notMasqueradesAsUndefined.link(&m_jit); 4020 done.link(&m_jit); 4021 booleanResult(result.gpr(), node); 4022 break; 4023 } 4024 4025 case IsBoolean: { 4026 JSValueOperand value(this, node->child1()); 4027 GPRTemporary result(this, Reuse, value, TagWord); 4028 4029 m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr()); 4030 booleanResult(result.gpr(), node); 4031 break; 4032 } 4033 4034 case IsNumber: { 4035 JSValueOperand value(this, node->child1()); 4036 GPRTemporary result(this, Reuse, value, TagWord); 4037 4038 m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr()); 4039 m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr()); 4040 booleanResult(result.gpr(), node); 4041 break; 4042 } 4043 4044 case IsString: { 4045 JSValueOperand value(this, node->child1()); 4046 GPRTemporary result(this, Reuse, value, TagWord); 4047 4048 JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs()); 4049 4050 m_jit.compare8(JITCompiler::Equal, 4051 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), 4052 TrustedImm32(StringType), 4053 result.gpr()); 4054 JITCompiler::Jump done = m_jit.jump(); 4055 4056 isNotCell.link(&m_jit); 4057 m_jit.move(TrustedImm32(0), result.gpr()); 4058 4059 done.link(&m_jit); 4060 booleanResult(result.gpr(), node); 4061 break; 4062 } 4063 4064 case IsObject: { 4065 JSValueOperand value(this, node->child1()); 4066 GPRReg valueTagGPR = value.tagGPR(); 4067 GPRReg valuePayloadGPR = value.payloadGPR(); 4068 GPRResult result(this); 4069 GPRReg resultGPR = result.gpr(); 4070 flushRegisters(); 4071 callOperation(operationIsObject, resultGPR, valueTagGPR, valuePayloadGPR); 4072 booleanResult(result.gpr(), node); 4073 break; 4074 } 4075 4076 case IsFunction: { 4077 JSValueOperand value(this, node->child1()); 4078 GPRReg valueTagGPR = value.tagGPR(); 4079 GPRReg valuePayloadGPR = value.payloadGPR(); 4080 GPRResult result(this); 4081 GPRReg resultGPR = result.gpr(); 4082 flushRegisters(); 4083 callOperation(operationIsFunction, resultGPR, valueTagGPR, valuePayloadGPR); 4084 booleanResult(result.gpr(), node); 4085 break; 4086 } 4087 case TypeOf: { 4088 JSValueOperand value(this, node->child1(), ManualOperandSpeculation); 4089 GPRReg tagGPR = value.tagGPR(); 4090 GPRReg payloadGPR = value.payloadGPR(); 4091 GPRTemporary temp(this); 4092 GPRReg tempGPR = temp.gpr(); 4093 GPRResult result(this); 4094 GPRReg resultGPR = result.gpr(); 4095 JITCompiler::JumpList doneJumps; 4096 4097 flushRegisters(); 4098 4099 ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == CellUse || node->child1().useKind() == StringUse); 4100 4101 JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs()); 4102 if (node->child1().useKind() != UntypedUse) 4103 DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecCell, isNotCell); 4104 4105 if (!node->child1()->shouldSpeculateObject() || node->child1().useKind() == StringUse) { 4106 JITCompiler::Jump notString = m_jit.branch8( 4107 JITCompiler::NotEqual, 4108 JITCompiler::Address(payloadGPR, JSCell::typeInfoTypeOffset()), 4109 TrustedImm32(StringType)); 4110 if (node->child1().useKind() == StringUse) 4111 DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecString, notString); 4112 m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.stringString()), resultGPR); 4113 doneJumps.append(m_jit.jump()); 4114 if (node->child1().useKind() != StringUse) { 4115 notString.link(&m_jit); 4116 callOperation(operationTypeOf, resultGPR, payloadGPR); 4117 doneJumps.append(m_jit.jump()); 4118 } 4119 } else { 4120 callOperation(operationTypeOf, resultGPR, payloadGPR); 4121 doneJumps.append(m_jit.jump()); 4122 } 4123 4124 if (node->child1().useKind() == UntypedUse) { 4125 isNotCell.link(&m_jit); 4126 4127 m_jit.add32(TrustedImm32(1), tagGPR, tempGPR); 4128 JITCompiler::Jump notNumber = m_jit.branch32(JITCompiler::AboveOrEqual, tempGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1)); 4129 m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.numberString()), resultGPR); 4130 doneJumps.append(m_jit.jump()); 4131 notNumber.link(&m_jit); 4132 4133 JITCompiler::Jump notUndefined = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::UndefinedTag)); 4134 m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.undefinedString()), resultGPR); 4135 doneJumps.append(m_jit.jump()); 4136 notUndefined.link(&m_jit); 4137 4138 JITCompiler::Jump notNull = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::NullTag)); 4139 m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.objectString()), resultGPR); 4140 doneJumps.append(m_jit.jump()); 4141 notNull.link(&m_jit); 4142 4143 // Only boolean left 4144 m_jit.move(TrustedImmPtr(m_jit.vm()->smallStrings.booleanString()), resultGPR); 4145 } 4146 doneJumps.link(&m_jit); 4147 cellResult(resultGPR, node); 4148 break; 4149 } 4150 4151 case Flush: 4152 break; 4153 4154 case Call: 4155 case Construct: 4156 emitCall(node); 4157 break; 4158 4159 case CreateActivation: { 4160 JSValueOperand value(this, node->child1()); 4161 GPRTemporary result(this, Reuse, value, PayloadWord); 4162 4163 GPRReg valueTagGPR = value.tagGPR(); 4164 GPRReg valuePayloadGPR = value.payloadGPR(); 4165 GPRReg resultGPR = result.gpr(); 4166 4167 m_jit.move(valuePayloadGPR, resultGPR); 4168 4169 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4170 4171 addSlowPathGenerator( 4172 slowPathCall( 4173 notCreated, this, operationCreateActivation, resultGPR, 4174 framePointerOffsetToGetActivationRegisters())); 4175 4176 cellResult(resultGPR, node); 4177 break; 4178 } 4179 4180 case FunctionReentryWatchpoint: { 4181 noResult(node); 4182 break; 4183 } 4184 4185 case CreateArguments: { 4186 JSValueOperand value(this, node->child1()); 4187 GPRTemporary scratch1(this); 4188 GPRTemporary scratch2(this); 4189 GPRTemporary result(this, Reuse, value, PayloadWord); 4190 4191 GPRReg valueTagGPR = value.tagGPR(); 4192 GPRReg valuePayloadGPR = value.payloadGPR(); 4193 GPRReg scratch1GPR = scratch1.gpr(); 4194 GPRReg scratch2GPR = scratch2.gpr(); 4195 GPRReg resultGPR = result.gpr(); 4196 4197 m_jit.move(valuePayloadGPR, resultGPR); 4198 4199 if (node->origin.semantic.inlineCallFrame) { 4200 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4201 addSlowPathGenerator( 4202 slowPathCall( 4203 notCreated, this, operationCreateInlinedArguments, resultGPR, 4204 node->origin.semantic.inlineCallFrame)); 4205 cellResult(resultGPR, node); 4206 break; 4207 } 4208 4209 FunctionExecutable* executable = jsCast<FunctionExecutable*>(m_jit.graph().executableFor(node->origin.semantic)); 4210 if (m_jit.codeBlock()->hasSlowArguments() 4211 || executable->isStrictMode() 4212 || !executable->parameterCount()) { 4213 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4214 addSlowPathGenerator( 4215 slowPathCall(notCreated, this, operationCreateArguments, resultGPR)); 4216 cellResult(resultGPR, node); 4217 break; 4218 } 4219 4220 JITCompiler::Jump alreadyCreated = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4221 4222 MacroAssembler::JumpList slowPaths; 4223 emitAllocateArguments(resultGPR, scratch1GPR, scratch2GPR, slowPaths); 4224 addSlowPathGenerator( 4225 slowPathCall(slowPaths, this, operationCreateArguments, resultGPR)); 4226 4227 alreadyCreated.link(&m_jit); 4228 cellResult(resultGPR, node); 4229 break; 4230 } 4231 4232 case TearOffActivation: { 4233 JSValueOperand activationValue(this, node->child1()); 4234 GPRTemporary scratch(this); 4235 4236 GPRReg activationValueTagGPR = activationValue.tagGPR(); 4237 GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); 4238 GPRReg scratchGPR = scratch.gpr(); 4239 4240 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, activationValueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4241 4242 SymbolTable* symbolTable = m_jit.symbolTableFor(node->origin.semantic); 4243 int registersOffset = JSActivation::registersOffset(symbolTable); 4244 4245 int bytecodeCaptureStart = symbolTable->captureStart(); 4246 int machineCaptureStart = m_jit.graph().m_machineCaptureStart; 4247 for (int i = symbolTable->captureCount(); i--;) { 4248 m_jit.loadPtr( 4249 JITCompiler::Address( 4250 GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4251 scratchGPR); 4252 m_jit.storePtr( 4253 scratchGPR, JITCompiler::Address( 4254 activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); 4255 m_jit.loadPtr( 4256 JITCompiler::Address( 4257 GPRInfo::callFrameRegister, (machineCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4258 scratchGPR); 4259 m_jit.storePtr( 4260 scratchGPR, JITCompiler::Address( 4261 activationValuePayloadGPR, registersOffset + (bytecodeCaptureStart - i) * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); 4262 } 4263 m_jit.addPtr(TrustedImm32(registersOffset), activationValuePayloadGPR, scratchGPR); 4264 m_jit.storePtr(scratchGPR, JITCompiler::Address(activationValuePayloadGPR, JSActivation::offsetOfRegisters())); 4265 4266 notCreated.link(&m_jit); 4267 noResult(node); 4268 break; 4269 } 4270 4271 case TearOffArguments: { 4272 JSValueOperand unmodifiedArgumentsValue(this, node->child1()); 4273 JSValueOperand activationValue(this, node->child2()); 4274 GPRReg unmodifiedArgumentsValuePayloadGPR = unmodifiedArgumentsValue.payloadGPR(); 4275 GPRReg activationValuePayloadGPR = activationValue.payloadGPR(); 4276 4277 JITCompiler::Jump created = m_jit.branchTest32( 4278 JITCompiler::NonZero, unmodifiedArgumentsValuePayloadGPR); 4279 4280 if (node->origin.semantic.inlineCallFrame) { 4281 addSlowPathGenerator( 4282 slowPathCall( 4283 created, this, operationTearOffInlinedArguments, NoResult, 4284 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR, node->origin.semantic.inlineCallFrame)); 4285 } else { 4286 addSlowPathGenerator( 4287 slowPathCall( 4288 created, this, operationTearOffArguments, NoResult, 4289 unmodifiedArgumentsValuePayloadGPR, activationValuePayloadGPR)); 4290 } 4291 4292 noResult(node); 4293 break; 4294 } 4295 4296 case CheckArgumentsNotCreated: { 4297 ASSERT(!isEmptySpeculation( 4298 m_state.variables().operand( 4299 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)); 4300 speculationCheck( 4301 Uncountable, JSValueRegs(), 0, 4302 m_jit.branch32( 4303 JITCompiler::NotEqual, 4304 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4305 TrustedImm32(JSValue::EmptyValueTag))); 4306 noResult(node); 4307 break; 4308 } 4309 4310 case GetMyArgumentsLength: { 4311 GPRTemporary result(this); 4312 GPRReg resultGPR = result.gpr(); 4313 4314 if (!isEmptySpeculation( 4315 m_state.variables().operand( 4316 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4317 speculationCheck( 4318 ArgumentsEscaped, JSValueRegs(), 0, 4319 m_jit.branch32( 4320 JITCompiler::NotEqual, 4321 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4322 TrustedImm32(JSValue::EmptyValueTag))); 4323 } 4324 4325 ASSERT(!node->origin.semantic.inlineCallFrame); 4326 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR); 4327 m_jit.sub32(TrustedImm32(1), resultGPR); 4328 int32Result(resultGPR, node); 4329 break; 4330 } 4331 4332 case GetMyArgumentsLengthSafe: { 4333 GPRTemporary resultPayload(this); 4334 GPRTemporary resultTag(this); 4335 GPRReg resultPayloadGPR = resultPayload.gpr(); 4336 GPRReg resultTagGPR = resultTag.gpr(); 4337 4338 JITCompiler::Jump created = m_jit.branch32( 4339 JITCompiler::NotEqual, 4340 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4341 TrustedImm32(JSValue::EmptyValueTag)); 4342 4343 if (node->origin.semantic.inlineCallFrame) { 4344 m_jit.move( 4345 Imm32(node->origin.semantic.inlineCallFrame->arguments.size() - 1), 4346 resultPayloadGPR); 4347 } else { 4348 m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultPayloadGPR); 4349 m_jit.sub32(TrustedImm32(1), resultPayloadGPR); 4350 } 4351 m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR); 4352 4353 // FIXME: the slow path generator should perform a forward speculation that the 4354 // result is an integer. For now we postpone the speculation by having this return 4355 // a JSValue. 4356 4357 addSlowPathGenerator( 4358 slowPathCall( 4359 created, this, operationGetArgumentsLength, 4360 JSValueRegs(resultTagGPR, resultPayloadGPR), 4361 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset())); 4362 4363 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4364 break; 4365 } 4366 4367 case GetMyArgumentByVal: { 4368 SpeculateStrictInt32Operand index(this, node->child1()); 4369 GPRTemporary resultPayload(this); 4370 GPRTemporary resultTag(this); 4371 GPRReg indexGPR = index.gpr(); 4372 GPRReg resultPayloadGPR = resultPayload.gpr(); 4373 GPRReg resultTagGPR = resultTag.gpr(); 4374 4375 if (!isEmptySpeculation( 4376 m_state.variables().operand( 4377 m_jit.graph().argumentsRegisterFor(node->origin.semantic)).m_type)) { 4378 speculationCheck( 4379 ArgumentsEscaped, JSValueRegs(), 0, 4380 m_jit.branch32( 4381 JITCompiler::NotEqual, 4382 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4383 TrustedImm32(JSValue::EmptyValueTag))); 4384 } 4385 4386 m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR); 4387 4388 if (node->origin.semantic.inlineCallFrame) { 4389 speculationCheck( 4390 Uncountable, JSValueRegs(), 0, 4391 m_jit.branch32( 4392 JITCompiler::AboveOrEqual, 4393 resultPayloadGPR, 4394 Imm32(node->origin.semantic.inlineCallFrame->arguments.size()))); 4395 } else { 4396 speculationCheck( 4397 Uncountable, JSValueRegs(), 0, 4398 m_jit.branch32( 4399 JITCompiler::AboveOrEqual, 4400 resultPayloadGPR, 4401 JITCompiler::payloadFor(JSStack::ArgumentCount))); 4402 } 4403 4404 JITCompiler::JumpList slowArgument; 4405 JITCompiler::JumpList slowArgumentOutOfBounds; 4406 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4407 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4408 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4409 slowArgumentOutOfBounds.append( 4410 m_jit.branch32( 4411 JITCompiler::AboveOrEqual, indexGPR, 4412 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4413 4414 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4415 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4416 m_jit.load32( 4417 JITCompiler::BaseIndex( 4418 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4419 OBJECT_OFFSETOF(SlowArgument, index)), 4420 resultPayloadGPR); 4421 4422 m_jit.load32( 4423 JITCompiler::BaseIndex( 4424 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4425 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4426 resultTagGPR); 4427 m_jit.load32( 4428 JITCompiler::BaseIndex( 4429 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4430 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4431 resultPayloadGPR); 4432 slowArgument.append(m_jit.jump()); 4433 } 4434 slowArgumentOutOfBounds.link(&m_jit); 4435 4436 m_jit.load32( 4437 JITCompiler::BaseIndex( 4438 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4439 m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4440 resultTagGPR); 4441 m_jit.load32( 4442 JITCompiler::BaseIndex( 4443 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4444 m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4445 resultPayloadGPR); 4446 4447 slowArgument.link(&m_jit); 4448 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4449 break; 4450 } 4451 case GetMyArgumentByValSafe: { 4452 SpeculateStrictInt32Operand index(this, node->child1()); 4453 GPRTemporary resultPayload(this); 4454 GPRTemporary resultTag(this); 4455 GPRReg indexGPR = index.gpr(); 4456 GPRReg resultPayloadGPR = resultPayload.gpr(); 4457 GPRReg resultTagGPR = resultTag.gpr(); 4458 4459 JITCompiler::JumpList slowPath; 4460 slowPath.append( 4461 m_jit.branch32( 4462 JITCompiler::NotEqual, 4463 JITCompiler::tagFor(m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic)), 4464 TrustedImm32(JSValue::EmptyValueTag))); 4465 4466 m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR); 4467 if (node->origin.semantic.inlineCallFrame) { 4468 slowPath.append( 4469 m_jit.branch32( 4470 JITCompiler::AboveOrEqual, 4471 resultPayloadGPR, 4472 Imm32(node->origin.semantic.inlineCallFrame->arguments.size()))); 4473 } else { 4474 slowPath.append( 4475 m_jit.branch32( 4476 JITCompiler::AboveOrEqual, 4477 resultPayloadGPR, 4478 JITCompiler::payloadFor(JSStack::ArgumentCount))); 4479 } 4480 4481 JITCompiler::JumpList slowArgument; 4482 JITCompiler::JumpList slowArgumentOutOfBounds; 4483 if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) { 4484 RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame); 4485 const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get(); 4486 slowArgumentOutOfBounds.append( 4487 m_jit.branch32( 4488 JITCompiler::AboveOrEqual, indexGPR, 4489 Imm32(m_jit.symbolTableFor(node->origin.semantic)->parameterCount()))); 4490 4491 COMPILE_ASSERT(sizeof(SlowArgument) == 8, SlowArgument_size_is_eight_bytes); 4492 m_jit.move(ImmPtr(slowArguments), resultPayloadGPR); 4493 m_jit.load32( 4494 JITCompiler::BaseIndex( 4495 resultPayloadGPR, indexGPR, JITCompiler::TimesEight, 4496 OBJECT_OFFSETOF(SlowArgument, index)), 4497 resultPayloadGPR); 4498 m_jit.load32( 4499 JITCompiler::BaseIndex( 4500 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4501 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4502 resultTagGPR); 4503 m_jit.load32( 4504 JITCompiler::BaseIndex( 4505 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4506 OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4507 resultPayloadGPR); 4508 slowArgument.append(m_jit.jump()); 4509 } 4510 slowArgumentOutOfBounds.link(&m_jit); 4511 4512 m_jit.load32( 4513 JITCompiler::BaseIndex( 4514 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4515 m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), 4516 resultTagGPR); 4517 m_jit.load32( 4518 JITCompiler::BaseIndex( 4519 GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight, 4520 m_jit.offsetOfArgumentsIncludingThis(node->origin.semantic) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), 4521 resultPayloadGPR); 4522 4523 if (node->origin.semantic.inlineCallFrame) { 4524 addSlowPathGenerator( 4525 slowPathCall( 4526 slowPath, this, operationGetInlinedArgumentByVal, 4527 JSValueRegs(resultTagGPR, resultPayloadGPR), 4528 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4529 node->origin.semantic.inlineCallFrame, indexGPR)); 4530 } else { 4531 addSlowPathGenerator( 4532 slowPathCall( 4533 slowPath, this, operationGetArgumentByVal, 4534 JSValueRegs(resultTagGPR, resultPayloadGPR), 4535 m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic).offset(), 4536 indexGPR)); 4537 } 4538 4539 slowArgument.link(&m_jit); 4540 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4541 break; 4542 } 4543 4544 case NewFunctionNoCheck: 4545 compileNewFunctionNoCheck(node); 4546 break; 4547 4548 case NewFunction: { 4549 JSValueOperand value(this, node->child1()); 4550 GPRTemporary resultTag(this, Reuse, value, TagWord); 4551 GPRTemporary resultPayload(this, Reuse, value, PayloadWord); 4552 4553 GPRReg valueTagGPR = value.tagGPR(); 4554 GPRReg valuePayloadGPR = value.payloadGPR(); 4555 GPRReg resultTagGPR = resultTag.gpr(); 4556 GPRReg resultPayloadGPR = resultPayload.gpr(); 4557 4558 m_jit.move(valuePayloadGPR, resultPayloadGPR); 4559 m_jit.move(valueTagGPR, resultTagGPR); 4560 4561 JITCompiler::Jump notCreated = m_jit.branch32(JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag)); 4562 4563 addSlowPathGenerator( 4564 slowPathCall( 4565 notCreated, this, operationNewFunction, JSValueRegs(resultTagGPR, resultPayloadGPR), 4566 m_jit.codeBlock()->functionDecl(node->functionDeclIndex()))); 4567 4568 jsValueResult(resultTagGPR, resultPayloadGPR, node); 4569 break; 4570 } 4571 4572 case NewFunctionExpression: 4573 compileNewFunctionExpression(node); 4574 break; 4575 4576 case In: 4577 compileIn(node); 4578 break; 4579 4580 case StoreBarrier: 4581 case StoreBarrierWithNullCheck: { 4582 compileStoreBarrier(node); 4583 break; 4584 } 4585 4586 case ForceOSRExit: { 4587 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0); 4588 break; 4589 } 4590 4591 case InvalidationPoint: 4592 emitInvalidationPoint(node); 4593 break; 4594 4595 case CheckWatchdogTimer: 4596 ASSERT(m_jit.vm()->watchdog); 4597 speculationCheck( 4598 WatchdogTimerFired, JSValueRegs(), 0, 4599 m_jit.branchTest8( 4600 JITCompiler::NonZero, 4601 JITCompiler::AbsoluteAddress(m_jit.vm()->watchdog->timerDidFireAddress()))); 4602 break; 4603 4604 case CountExecution: 4605 m_jit.add64(TrustedImm32(1), MacroAssembler::AbsoluteAddress(node->executionCounter()->address())); 4606 break; 4607 4608 case Phantom: 4609 case HardPhantom: 4610 DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate); 4611 noResult(node); 4612 break; 4613 4614 case Breakpoint: 4615 case ProfileWillCall: 4616 case ProfileDidCall: 4617 case PhantomLocal: 4618 case LoopHint: 4619 // This is a no-op. 4620 noResult(node); 4621 break; 4622 4623 case Unreachable: 4624 RELEASE_ASSERT_NOT_REACHED(); 4625 break; 4626 4627 case LastNodeType: 4628 case Phi: 4629 case Upsilon: 4630 case GetArgument: 4631 case ExtractOSREntryLocal: 4632 case CheckTierUpInLoop: 4633 case CheckTierUpAtReturn: 4634 case CheckTierUpAndOSREnter: 4635 case Int52Rep: 4636 case FiatInt52: 4637 case Int52Constant: 4638 case CheckInBounds: 4639 case ArithIMul: 4640 case MultiGetByOffset: 4641 case MultiPutByOffset: 4642 RELEASE_ASSERT_NOT_REACHED(); 4643 break; 4644 } 4645 4646 if (!m_compileOkay) 4647 return; 4648 4649 if (node->hasResult() && node->mustGenerate()) 4650 use(node); 4651} 4652 4653#if ENABLE(GGC) 4654void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueTagGPR, Edge valueUse, GPRReg scratch1, GPRReg scratch2) 4655{ 4656 JITCompiler::Jump isNotCell; 4657 if (!isKnownCell(valueUse.node())) 4658 isNotCell = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::CellTag)); 4659 4660 JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(ownerGPR); 4661 storeToWriteBarrierBuffer(ownerGPR, scratch1, scratch2); 4662 ownerNotMarkedOrAlreadyRemembered.link(&m_jit); 4663 4664 if (!isKnownCell(valueUse.node())) 4665 isNotCell.link(&m_jit); 4666} 4667 4668void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueTagGPR, Edge valueUse, GPRReg scratch1, GPRReg scratch2) 4669{ 4670 JITCompiler::Jump isNotCell; 4671 if (!isKnownCell(valueUse.node())) 4672 isNotCell = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::CellTag)); 4673 4674 JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(owner); 4675 storeToWriteBarrierBuffer(owner, scratch1, scratch2); 4676 ownerNotMarkedOrAlreadyRemembered.link(&m_jit); 4677 4678 if (!isKnownCell(valueUse.node())) 4679 isNotCell.link(&m_jit); 4680} 4681#endif // ENABLE(GGC) 4682 4683JITCompiler::Jump SpeculativeJIT::branchIsCell(JSValueRegs regs) 4684{ 4685 return m_jit.branch32(MacroAssembler::Equal, regs.tagGPR(), TrustedImm32(JSValue::CellTag)); 4686} 4687 4688JITCompiler::Jump SpeculativeJIT::branchNotCell(JSValueRegs regs) 4689{ 4690 return m_jit.branch32(MacroAssembler::NotEqual, regs.tagGPR(), TrustedImm32(JSValue::CellTag)); 4691} 4692 4693JITCompiler::Jump SpeculativeJIT::branchIsOther(JSValueRegs regs, GPRReg tempGPR) 4694{ 4695 m_jit.move(regs.tagGPR(), tempGPR); 4696 m_jit.or32(TrustedImm32(1), tempGPR); 4697 return m_jit.branch32( 4698 MacroAssembler::Equal, tempGPR, 4699 MacroAssembler::TrustedImm32(JSValue::NullTag)); 4700} 4701 4702JITCompiler::Jump SpeculativeJIT::branchNotOther(JSValueRegs regs, GPRReg tempGPR) 4703{ 4704 m_jit.move(regs.tagGPR(), tempGPR); 4705 m_jit.or32(TrustedImm32(1), tempGPR); 4706 return m_jit.branch32( 4707 MacroAssembler::NotEqual, tempGPR, 4708 MacroAssembler::TrustedImm32(JSValue::NullTag)); 4709} 4710 4711void SpeculativeJIT::moveTrueTo(GPRReg gpr) 4712{ 4713 m_jit.move(TrustedImm32(1), gpr); 4714} 4715 4716void SpeculativeJIT::moveFalseTo(GPRReg gpr) 4717{ 4718 m_jit.move(TrustedImm32(0), gpr); 4719} 4720 4721void SpeculativeJIT::blessBoolean(GPRReg) 4722{ 4723} 4724 4725#endif 4726 4727} } // namespace JSC::DFG 4728 4729#endif 4730