1/* 2 * Copyright (C) 2008, 2012, 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef JITInlines_h 27#define JITInlines_h 28 29#if ENABLE(JIT) 30 31#include "JSCInlines.h" 32 33namespace JSC { 34 35ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(int src) 36{ 37 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isDouble(); 38} 39 40ALWAYS_INLINE JSValue JIT::getConstantOperand(int src) 41{ 42 ASSERT(m_codeBlock->isConstantRegisterIndex(src)); 43 return m_codeBlock->getConstant(src); 44} 45 46ALWAYS_INLINE void JIT::emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry entry) 47{ 48#if USE(JSVALUE32_64) 49 store32(TrustedImm32(Int32Tag), intTagFor(entry, callFrameRegister)); 50 store32(from, intPayloadFor(entry, callFrameRegister)); 51#else 52 store64(from, addressFor(entry, callFrameRegister)); 53#endif 54} 55 56ALWAYS_INLINE void JIT::emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) 57{ 58 loadPtr(Address(from, entry * sizeof(Register)), to); 59} 60 61ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) 62{ 63 load32(Address(from, entry * sizeof(Register)), to); 64} 65 66#if USE(JSVALUE64) 67ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader64(JSStack::CallFrameHeaderEntry entry, RegisterID to, RegisterID from) 68{ 69 load64(Address(from, entry * sizeof(Register)), to); 70} 71#endif 72 73ALWAYS_INLINE void JIT::emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures) 74{ 75 failures.append(branchStructure(NotEqual, Address(src, JSCell::structureIDOffset()), m_vm->stringStructure.get())); 76 failures.append(branch32(NotEqual, MacroAssembler::Address(src, ThunkHelpers::jsStringLengthOffset()), TrustedImm32(1))); 77 loadPtr(MacroAssembler::Address(src, ThunkHelpers::jsStringValueOffset()), dst); 78 failures.append(branchTest32(Zero, dst)); 79 loadPtr(MacroAssembler::Address(dst, StringImpl::flagsOffset()), regT1); 80 loadPtr(MacroAssembler::Address(dst, StringImpl::dataOffset()), dst); 81 82 JumpList is16Bit; 83 JumpList cont8Bit; 84 is16Bit.append(branchTest32(Zero, regT1, TrustedImm32(StringImpl::flagIs8Bit()))); 85 load8(MacroAssembler::Address(dst, 0), dst); 86 cont8Bit.append(jump()); 87 is16Bit.link(this); 88 load16(MacroAssembler::Address(dst, 0), dst); 89 cont8Bit.link(this); 90} 91 92ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function) 93{ 94 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 95 Call nakedCall = nearCall(); 96 m_calls.append(CallRecord(nakedCall, m_bytecodeOffset, function.executableAddress())); 97 return nakedCall; 98} 99 100ALWAYS_INLINE void JIT::updateTopCallFrame() 101{ 102 ASSERT(static_cast<int>(m_bytecodeOffset) >= 0); 103#if USE(JSVALUE32_64) 104 Instruction* instruction = m_codeBlock->instructions().begin() + m_bytecodeOffset + 1; 105 uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction); 106#else 107 uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(m_bytecodeOffset + 1); 108#endif 109 store32(TrustedImm32(locationBits), intTagFor(JSStack::ArgumentCount)); 110 storePtr(callFrameRegister, &m_vm->topCallFrame); 111} 112 113ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheck(const FunctionPtr& function) 114{ 115 updateTopCallFrame(); 116 MacroAssembler::Call call = appendCall(function); 117 exceptionCheck(); 118 return call; 119} 120 121#if OS(WINDOWS) && CPU(X86_64) 122ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckAndSlowPathReturnType(const FunctionPtr& function) 123{ 124 updateTopCallFrame(); 125 MacroAssembler::Call call = appendCallWithSlowPathReturnType(function); 126 exceptionCheck(); 127 return call; 128} 129#endif 130 131ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithCallFrameRollbackOnException(const FunctionPtr& function) 132{ 133 updateTopCallFrame(); // The callee is responsible for setting topCallFrame to their caller 134 MacroAssembler::Call call = appendCall(function); 135 exceptionCheckWithCallFrameRollback(); 136 return call; 137} 138 139ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckSetJSValueResult(const FunctionPtr& function, int dst) 140{ 141 MacroAssembler::Call call = appendCallWithExceptionCheck(function); 142#if USE(JSVALUE64) 143 emitPutVirtualRegister(dst, returnValueGPR); 144#else 145 emitStore(dst, returnValueGPR2, returnValueGPR); 146#endif 147 return call; 148} 149 150ALWAYS_INLINE MacroAssembler::Call JIT::appendCallWithExceptionCheckSetJSValueResultWithProfile(const FunctionPtr& function, int dst) 151{ 152 MacroAssembler::Call call = appendCallWithExceptionCheck(function); 153 emitValueProfilingSite(); 154#if USE(JSVALUE64) 155 emitPutVirtualRegister(dst, returnValueGPR); 156#else 157 emitStore(dst, returnValueGPR2, returnValueGPR); 158#endif 159 return call; 160} 161 162ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_E operation) 163{ 164 setupArgumentsExecState(); 165 return appendCallWithExceptionCheck(operation); 166} 167 168ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EO operation, GPRReg arg) 169{ 170 setupArgumentsWithExecState(arg); 171 return appendCallWithExceptionCheck(operation); 172} 173 174ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_ESt operation, Structure* structure) 175{ 176 setupArgumentsWithExecState(TrustedImmPtr(structure)); 177 return appendCallWithExceptionCheck(operation); 178} 179 180ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(C_JITOperation_EZ operation, int32_t arg) 181{ 182 setupArgumentsWithExecState(TrustedImm32(arg)); 183 return appendCallWithExceptionCheck(operation); 184} 185 186ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_E operation, int dst) 187{ 188 setupArgumentsExecState(); 189 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 190} 191 192ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJcpZ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2, int32_t arg3) 193{ 194 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2, TrustedImm32(arg3)); 195 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 196} 197 198ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJcpZ operation, int dst, ArrayAllocationProfile* arg1, const JSValue* arg2, int32_t arg3) 199{ 200 setupArgumentsWithExecState(TrustedImmPtr(arg1), TrustedImmPtr(arg2), TrustedImm32(arg3)); 201 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 202} 203 204ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EC operation, int dst, JSCell* cell) 205{ 206 setupArgumentsWithExecState(TrustedImmPtr(cell)); 207 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 208} 209 210ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, JSCell* cell) 211{ 212 setupArgumentsWithExecState(TrustedImmPtr(cell)); 213 return appendCallWithExceptionCheck(operation); 214} 215 216ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EP operation, int dst, void* pointer) 217{ 218 setupArgumentsWithExecState(TrustedImmPtr(pointer)); 219 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 220} 221 222ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(WithProfileTag, J_JITOperation_EPc operation, int dst, Instruction* bytecodePC) 223{ 224 setupArgumentsWithExecState(TrustedImmPtr(bytecodePC)); 225 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst); 226} 227 228ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EZ operation, int dst, int32_t arg) 229{ 230 setupArgumentsWithExecState(TrustedImm32(arg)); 231 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 232} 233 234ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_ECC operation, RegisterID regOp1, RegisterID regOp2) 235{ 236 setupArgumentsWithExecState(regOp1, regOp2); 237 return appendCallWithExceptionCheck(operation); 238} 239 240ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EOJss operation, RegisterID regOp1, RegisterID regOp2) 241{ 242 setupArgumentsWithExecState(regOp1, regOp2); 243 return appendCallWithExceptionCheck(operation); 244} 245 246ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Sprt_JITOperation_EZ operation, int32_t op) 247{ 248#if OS(WINDOWS) && CPU(X86_64) 249 setupArgumentsWithExecStateForCallWithSlowPathReturnType(TrustedImm32(op)); 250 return appendCallWithExceptionCheckAndSlowPathReturnType(operation); 251#else 252 setupArgumentsWithExecState(TrustedImm32(op)); 253 return appendCallWithExceptionCheck(operation); 254#endif 255} 256 257ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_E operation) 258{ 259 setupArgumentsExecState(); 260 return appendCallWithExceptionCheck(operation); 261} 262 263ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, RegisterID regOp) 264{ 265 setupArgumentsWithExecState(regOp); 266 return appendCallWithExceptionCheck(operation); 267} 268 269ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECC operation, RegisterID regOp1, RegisterID regOp2) 270{ 271 setupArgumentsWithExecState(regOp1, regOp2); 272 return appendCallWithExceptionCheck(operation); 273} 274 275ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EPc operation, Instruction* bytecodePC) 276{ 277 setupArgumentsWithExecState(TrustedImmPtr(bytecodePC)); 278 return appendCallWithExceptionCheck(operation); 279} 280 281ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZ operation, int32_t op) 282{ 283 setupArgumentsWithExecState(TrustedImm32(op)); 284 return appendCallWithExceptionCheck(operation); 285} 286 287ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(J_JITOperation_E operation) 288{ 289 setupArgumentsExecState(); 290 return appendCallWithCallFrameRollbackOnException(operation); 291} 292 293ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(J_JITOperation_EE operation, RegisterID regOp) 294{ 295 setupArgumentsWithExecState(regOp); 296 updateTopCallFrame(); 297 return appendCall(operation); 298} 299 300ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb operation, CodeBlock* pointer) 301{ 302 setupArgumentsWithExecState(TrustedImmPtr(pointer)); 303 return appendCallWithCallFrameRollbackOnException(operation); 304} 305 306ALWAYS_INLINE MacroAssembler::Call JIT::callOperationWithCallFrameRollbackOnException(Z_JITOperation_E operation) 307{ 308 setupArgumentsExecState(); 309 return appendCallWithCallFrameRollbackOnException(operation); 310} 311 312 313#if USE(JSVALUE64) 314ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3) 315{ 316 setupArgumentsWithExecState(arg1, TrustedImm32(arg2), TrustedImm32(arg3)); 317 return appendCallWithExceptionCheck(operation); 318} 319 320ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJJZ operation, GPRReg arg1, GPRReg arg2, GPRReg arg3, int32_t arg4) 321{ 322 setupArgumentsWithExecState(arg1, arg2, arg3, TrustedImm32(arg4)); 323 return appendCallWithExceptionCheck(operation); 324} 325 326ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ESsiJJI operation, StructureStubInfo* stubInfo, RegisterID regOp1, RegisterID regOp2, StringImpl* uid) 327{ 328 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), regOp1, regOp2, TrustedImmPtr(uid)); 329 return appendCallWithExceptionCheck(operation); 330} 331 332ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJ operation, RegisterID regOp1, RegisterID regOp2, RegisterID regOp3) 333{ 334 setupArgumentsWithExecState(regOp1, regOp2, regOp3); 335 return appendCallWithExceptionCheck(operation); 336} 337 338ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1, StringImpl* uid) 339{ 340 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid)); 341 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst); 342} 343 344ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1, GPRReg arg2) 345{ 346 setupArgumentsWithExecState(arg1, arg2); 347 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst); 348} 349 350ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2) 351{ 352 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2); 353 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 354} 355 356ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJ operation, int dst, GPRReg arg1) 357{ 358 setupArgumentsWithExecState(arg1); 359 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 360} 361 362ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJIdc operation, int dst, GPRReg arg1, const Identifier* arg2) 363{ 364 setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2)); 365 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 366} 367 368ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, int dst, GPRReg arg1, GPRReg arg2) 369{ 370 setupArgumentsWithExecState(arg1, arg2); 371 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 372} 373 374ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1) 375{ 376 setupArgumentsWithExecState(arg1); 377 updateTopCallFrame(); 378 return appendCall(operation); 379} 380 381ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(P_JITOperation_EJS operation, GPRReg arg1, size_t arg2) 382{ 383 setupArgumentsWithExecState(arg1, TrustedImmPtr(arg2)); 384 return appendCallWithExceptionCheck(operation); 385} 386 387ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJ operation, RegisterID regOp) 388{ 389 setupArgumentsWithExecState(regOp); 390 return appendCallWithExceptionCheck(operation); 391} 392 393ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJJ operation, RegisterID regOp1, RegisterID regOp2) 394{ 395 setupArgumentsWithExecState(regOp1, regOp2); 396 return appendCallWithExceptionCheck(operation); 397} 398 399ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EIdJZ operation, const Identifier* identOp1, RegisterID regOp2, int32_t op3) 400{ 401 setupArgumentsWithExecState(TrustedImmPtr(identOp1), regOp2, TrustedImm32(op3)); 402 return appendCallWithExceptionCheck(operation); 403} 404 405ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJ operation, RegisterID regOp) 406{ 407 setupArgumentsWithExecState(regOp); 408 return appendCallWithExceptionCheck(operation); 409} 410 411ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJIdJJ operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3, RegisterID regOp4) 412{ 413 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3, regOp4); 414 return appendCallWithExceptionCheck(operation); 415} 416 417ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZ operation, RegisterID regOp1, int32_t op2) 418{ 419 setupArgumentsWithExecState(regOp1, TrustedImm32(op2)); 420 return appendCallWithExceptionCheck(operation); 421} 422 423ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZJ operation, RegisterID regOp1, int32_t op2, RegisterID regOp3) 424{ 425 setupArgumentsWithExecState(regOp1, TrustedImm32(op2), regOp3); 426 return appendCallWithExceptionCheck(operation); 427} 428 429#else // USE(JSVALUE32_64) 430 431// EncodedJSValue in JSVALUE32_64 is a 64-bit integer. When being compiled in ARM EABI, it must be aligned even-numbered register (r0, r2 or [sp]). 432// To avoid assemblies from using wrong registers, let's occupy r1 or r3 with a dummy argument when necessary. 433#if (COMPILER_SUPPORTS(EABI) && CPU(ARM)) || CPU(MIPS) 434#define EABI_32BIT_DUMMY_ARG TrustedImm32(0), 435#else 436#define EABI_32BIT_DUMMY_ARG 437#endif 438 439// JSVALUE32_64 is a 64-bit integer that cannot be put half in an argument register and half on stack when using SH4 architecture. 440// To avoid this, let's occupy the 4th argument register (r7) with a dummy argument when necessary. This must only be done when there 441// is no other 32-bit value argument behind this 64-bit JSValue. 442#if CPU(SH4) 443#define SH4_32BIT_DUMMY_ARG TrustedImm32(0), 444#else 445#define SH4_32BIT_DUMMY_ARG 446#endif 447 448ALWAYS_INLINE MacroAssembler::Call JIT::callOperationNoExceptionCheck(V_JITOperation_EJ operation, GPRReg arg1Tag, GPRReg arg1Payload) 449{ 450 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag); 451 updateTopCallFrame(); 452 return appendCall(operation); 453} 454 455ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3) 456{ 457 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImm32(arg2), TrustedImm32(arg3)); 458 return appendCallWithExceptionCheck(operation); 459} 460 461ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJJZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, GPRReg arg3Tag, GPRReg arg3Payload, int32_t arg4) 462{ 463 setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, arg3Payload, arg3Tag, TrustedImm32(arg4)); 464 return appendCallWithExceptionCheck(operation); 465} 466 467ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EAapJ operation, int dst, ArrayAllocationProfile* arg1, GPRReg arg2Tag, GPRReg arg2Payload) 468{ 469 setupArgumentsWithExecState(TrustedImmPtr(arg1), arg2Payload, arg2Tag); 470 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 471} 472 473ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload) 474{ 475 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag); 476 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 477} 478 479ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_ESsiJI operation, int dst, StructureStubInfo* stubInfo, GPRReg arg1Tag, GPRReg arg1Payload, StringImpl* uid) 480{ 481 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1Payload, arg1Tag, TrustedImmPtr(uid)); 482 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst); 483} 484 485ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJIdc operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, const Identifier* arg2) 486{ 487 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(arg2)); 488 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 489} 490 491ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload) 492{ 493 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag); 494 return appendCallWithExceptionCheckSetJSValueResult(operation, dst); 495} 496 497ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload) 498{ 499 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag); 500 return appendCallWithExceptionCheckSetJSValueResultWithProfile(operation, dst); 501} 502 503ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(P_JITOperation_EJS operation, GPRReg arg1Tag, GPRReg arg1Payload, size_t arg2) 504{ 505 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImmPtr(arg2)); 506 return appendCallWithExceptionCheck(operation); 507} 508 509ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJ operation, RegisterID argTag, RegisterID argPayload) 510{ 511 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG argPayload, argTag); 512 return appendCallWithExceptionCheck(operation); 513} 514 515ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(S_JITOperation_EJJ operation, RegisterID arg1Tag, RegisterID arg1Payload, RegisterID arg2Tag, RegisterID arg2Payload) 516{ 517 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag); 518 return appendCallWithExceptionCheck(operation); 519} 520 521ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ECICC operation, RegisterID regOp1, const Identifier* identOp2, RegisterID regOp3, RegisterID regOp4) 522{ 523 setupArgumentsWithExecState(regOp1, TrustedImmPtr(identOp2), regOp3, regOp4); 524 return appendCallWithExceptionCheck(operation); 525} 526 527ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload) 528{ 529 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag); 530 return appendCallWithExceptionCheck(operation); 531} 532 533ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EIdJZ operation, const Identifier* identOp1, RegisterID regOp2Tag, RegisterID regOp2Payload, int32_t op3) 534{ 535 setupArgumentsWithExecState(TrustedImmPtr(identOp1), regOp2Payload, regOp2Tag, TrustedImm32(op3)); 536 return appendCallWithExceptionCheck(operation); 537} 538 539ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_ESsiJJI operation, StructureStubInfo* stubInfo, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, StringImpl* uid) 540{ 541 setupArgumentsWithExecState(TrustedImmPtr(stubInfo), regOp1Payload, regOp1Tag, regOp2Payload, regOp2Tag, TrustedImmPtr(uid)); 542 return appendCallWithExceptionCheck(operation); 543} 544 545ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, RegisterID regOp3Tag, RegisterID regOp3Payload) 546{ 547 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag); 548 return appendCallWithExceptionCheck(operation); 549} 550 551ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, int32_t op2) 552{ 553 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, TrustedImm32(op2)); 554 return appendCallWithExceptionCheck(operation); 555} 556 557ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJZJ operation, RegisterID regOp1Tag, RegisterID regOp1Payload, int32_t op2, RegisterID regOp3Tag, RegisterID regOp3Payload) 558{ 559 setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, TrustedImm32(op2), EABI_32BIT_DUMMY_ARG regOp3Payload, regOp3Tag); 560 return appendCallWithExceptionCheck(operation); 561} 562 563#undef EABI_32BIT_DUMMY_ARG 564#undef SH4_32BIT_DUMMY_ARG 565 566#endif // USE(JSVALUE32_64) 567 568ALWAYS_INLINE JIT::Jump JIT::checkStructure(RegisterID reg, Structure* structure) 569{ 570 return branchStructure(NotEqual, Address(reg, JSCell::structureIDOffset()), structure); 571} 572 573ALWAYS_INLINE void JIT::linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator& iter, int vReg) 574{ 575 if (!m_codeBlock->isKnownNotImmediate(vReg)) 576 linkSlowCase(iter); 577} 578 579ALWAYS_INLINE void JIT::addSlowCase(Jump jump) 580{ 581 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 582 583 m_slowCases.append(SlowCaseEntry(jump, m_bytecodeOffset)); 584} 585 586ALWAYS_INLINE void JIT::addSlowCase(JumpList jumpList) 587{ 588 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 589 590 const JumpList::JumpVector& jumpVector = jumpList.jumps(); 591 size_t size = jumpVector.size(); 592 for (size_t i = 0; i < size; ++i) 593 m_slowCases.append(SlowCaseEntry(jumpVector[i], m_bytecodeOffset)); 594} 595 596ALWAYS_INLINE void JIT::addSlowCase() 597{ 598 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 599 600 Jump emptyJump; // Doing it this way to make Windows happy. 601 m_slowCases.append(SlowCaseEntry(emptyJump, m_bytecodeOffset)); 602} 603 604ALWAYS_INLINE void JIT::addJump(Jump jump, int relativeOffset) 605{ 606 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 607 608 m_jmpTable.append(JumpTable(jump, m_bytecodeOffset + relativeOffset)); 609} 610 611ALWAYS_INLINE void JIT::emitJumpSlowToHot(Jump jump, int relativeOffset) 612{ 613 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 614 615 jump.linkTo(m_labels[m_bytecodeOffset + relativeOffset], this); 616} 617 618ALWAYS_INLINE JIT::Jump JIT::emitJumpIfCellNotObject(RegisterID cellReg) 619{ 620 return branch8(Below, Address(cellReg, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType)); 621} 622 623#if ENABLE(SAMPLING_FLAGS) 624ALWAYS_INLINE void JIT::setSamplingFlag(int32_t flag) 625{ 626 ASSERT(flag >= 1); 627 ASSERT(flag <= 32); 628 or32(TrustedImm32(1u << (flag - 1)), AbsoluteAddress(SamplingFlags::addressOfFlags())); 629} 630 631ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag) 632{ 633 ASSERT(flag >= 1); 634 ASSERT(flag <= 32); 635 and32(TrustedImm32(~(1u << (flag - 1))), AbsoluteAddress(SamplingFlags::addressOfFlags())); 636} 637#endif 638 639#if ENABLE(SAMPLING_COUNTERS) 640ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, int32_t count) 641{ 642 add64(TrustedImm32(count), AbsoluteAddress(counter.addressOfCounter())); 643} 644#endif 645 646#if ENABLE(OPCODE_SAMPLING) 647#if CPU(X86_64) 648ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction) 649{ 650 move(TrustedImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx); 651 storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86Registers::ecx); 652} 653#else 654ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction) 655{ 656 storePtr(TrustedImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot()); 657} 658#endif 659#endif 660 661#if ENABLE(CODEBLOCK_SAMPLING) 662#if CPU(X86_64) 663ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) 664{ 665 move(TrustedImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx); 666 storePtr(TrustedImmPtr(codeBlock), X86Registers::ecx); 667} 668#else 669ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) 670{ 671 storePtr(TrustedImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot()); 672} 673#endif 674#endif 675 676ALWAYS_INLINE bool JIT::isOperandConstantImmediateChar(int src) 677{ 678 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isString() && asString(getConstantOperand(src).asCell())->length() == 1; 679} 680 681template<typename StructureType> 682inline void JIT::emitAllocateJSObject(RegisterID allocator, StructureType structure, RegisterID result, RegisterID scratch) 683{ 684 loadPtr(Address(allocator, MarkedAllocator::offsetOfFreeListHead()), result); 685 addSlowCase(branchTestPtr(Zero, result)); 686 687 // remove the object from the free list 688 loadPtr(Address(result), scratch); 689 storePtr(scratch, Address(allocator, MarkedAllocator::offsetOfFreeListHead())); 690 691 // initialize the object's property storage pointer 692 storePtr(TrustedImmPtr(0), Address(result, JSObject::butterflyOffset())); 693 694 // initialize the object's structure 695 emitStoreStructureWithTypeInfo(structure, result, scratch); 696} 697 698inline void JIT::emitValueProfilingSite(ValueProfile* valueProfile) 699{ 700 ASSERT(shouldEmitProfiling()); 701 ASSERT(valueProfile); 702 703 const RegisterID value = regT0; 704#if USE(JSVALUE32_64) 705 const RegisterID valueTag = regT1; 706#endif 707 708 // We're in a simple configuration: only one bucket, so we can just do a direct 709 // store. 710#if USE(JSVALUE64) 711 store64(value, valueProfile->m_buckets); 712#else 713 EncodedValueDescriptor* descriptor = bitwise_cast<EncodedValueDescriptor*>(valueProfile->m_buckets); 714 store32(value, &descriptor->asBits.payload); 715 store32(valueTag, &descriptor->asBits.tag); 716#endif 717} 718 719inline void JIT::emitValueProfilingSite(unsigned bytecodeOffset) 720{ 721 if (!shouldEmitProfiling()) 722 return; 723 emitValueProfilingSite(m_codeBlock->valueProfileForBytecodeOffset(bytecodeOffset)); 724} 725 726inline void JIT::emitValueProfilingSite() 727{ 728 emitValueProfilingSite(m_bytecodeOffset); 729} 730 731inline void JIT::emitArrayProfilingSiteWithCell(RegisterID cell, RegisterID indexingType, ArrayProfile* arrayProfile) 732{ 733 if (shouldEmitProfiling()) { 734 load32(MacroAssembler::Address(cell, JSCell::structureIDOffset()), indexingType); 735 store32(indexingType, arrayProfile->addressOfLastSeenStructureID()); 736 } 737 738 load8(Address(cell, JSCell::indexingTypeOffset()), indexingType); 739} 740 741inline void JIT::emitArrayProfilingSiteForBytecodeIndexWithCell(RegisterID cell, RegisterID indexingType, unsigned bytecodeIndex) 742{ 743 emitArrayProfilingSiteWithCell(cell, indexingType, m_codeBlock->getOrAddArrayProfile(bytecodeIndex)); 744} 745 746inline void JIT::emitArrayProfileStoreToHoleSpecialCase(ArrayProfile* arrayProfile) 747{ 748 store8(TrustedImm32(1), arrayProfile->addressOfMayStoreToHole()); 749} 750 751inline void JIT::emitArrayProfileOutOfBoundsSpecialCase(ArrayProfile* arrayProfile) 752{ 753 store8(TrustedImm32(1), arrayProfile->addressOfOutOfBounds()); 754} 755 756static inline bool arrayProfileSaw(ArrayModes arrayModes, IndexingType capability) 757{ 758 return arrayModesInclude(arrayModes, capability); 759} 760 761inline JITArrayMode JIT::chooseArrayMode(ArrayProfile* profile) 762{ 763 ConcurrentJITLocker locker(m_codeBlock->m_lock); 764 profile->computeUpdatedPrediction(locker, m_codeBlock); 765 ArrayModes arrayModes = profile->observedArrayModes(locker); 766 if (arrayProfileSaw(arrayModes, DoubleShape)) 767 return JITDouble; 768 if (arrayProfileSaw(arrayModes, Int32Shape)) 769 return JITInt32; 770 if (arrayProfileSaw(arrayModes, ArrayStorageShape)) 771 return JITArrayStorage; 772 return JITContiguous; 773} 774 775#if USE(JSVALUE32_64) 776 777inline void JIT::emitLoadTag(int index, RegisterID tag) 778{ 779 if (m_codeBlock->isConstantRegisterIndex(index)) { 780 move(Imm32(getConstantOperand(index).tag()), tag); 781 return; 782 } 783 784 load32(tagFor(index), tag); 785} 786 787inline void JIT::emitLoadPayload(int index, RegisterID payload) 788{ 789 if (m_codeBlock->isConstantRegisterIndex(index)) { 790 move(Imm32(getConstantOperand(index).payload()), payload); 791 return; 792 } 793 794 load32(payloadFor(index), payload); 795} 796 797inline void JIT::emitLoad(const JSValue& v, RegisterID tag, RegisterID payload) 798{ 799 move(Imm32(v.payload()), payload); 800 move(Imm32(v.tag()), tag); 801} 802 803inline void JIT::emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base) 804{ 805 RELEASE_ASSERT(tag != payload); 806 807 if (base == callFrameRegister) { 808 RELEASE_ASSERT(payload != base); 809 emitLoadPayload(index, payload); 810 emitLoadTag(index, tag); 811 return; 812 } 813 814 if (payload == base) { // avoid stomping base 815 load32(tagFor(index, base), tag); 816 load32(payloadFor(index, base), payload); 817 return; 818 } 819 820 load32(payloadFor(index, base), payload); 821 load32(tagFor(index, base), tag); 822} 823 824inline void JIT::emitLoad2(int index1, RegisterID tag1, RegisterID payload1, int index2, RegisterID tag2, RegisterID payload2) 825{ 826 emitLoad(index2, tag2, payload2); 827 emitLoad(index1, tag1, payload1); 828} 829 830inline void JIT::emitLoadDouble(int index, FPRegisterID value) 831{ 832 if (m_codeBlock->isConstantRegisterIndex(index)) { 833 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); 834 loadDouble(TrustedImmPtr(&inConstantPool), value); 835 } else 836 loadDouble(addressFor(index), value); 837} 838 839inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value) 840{ 841 if (m_codeBlock->isConstantRegisterIndex(index)) { 842 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); 843 char* bytePointer = reinterpret_cast<char*>(&inConstantPool); 844 convertInt32ToDouble(AbsoluteAddress(bytePointer + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), value); 845 } else 846 convertInt32ToDouble(payloadFor(index), value); 847} 848 849inline void JIT::emitStore(int index, RegisterID tag, RegisterID payload, RegisterID base) 850{ 851 store32(payload, payloadFor(index, base)); 852 store32(tag, tagFor(index, base)); 853} 854 855inline void JIT::emitStoreInt32(int index, RegisterID payload, bool indexIsInt32) 856{ 857 store32(payload, payloadFor(index, callFrameRegister)); 858 if (!indexIsInt32) 859 store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); 860} 861 862inline void JIT::emitStoreInt32(int index, TrustedImm32 payload, bool indexIsInt32) 863{ 864 store32(payload, payloadFor(index, callFrameRegister)); 865 if (!indexIsInt32) 866 store32(TrustedImm32(JSValue::Int32Tag), tagFor(index, callFrameRegister)); 867} 868 869inline void JIT::emitStoreCell(int index, RegisterID payload, bool indexIsCell) 870{ 871 store32(payload, payloadFor(index, callFrameRegister)); 872 if (!indexIsCell) 873 store32(TrustedImm32(JSValue::CellTag), tagFor(index, callFrameRegister)); 874} 875 876inline void JIT::emitStoreBool(int index, RegisterID payload, bool indexIsBool) 877{ 878 store32(payload, payloadFor(index, callFrameRegister)); 879 if (!indexIsBool) 880 store32(TrustedImm32(JSValue::BooleanTag), tagFor(index, callFrameRegister)); 881} 882 883inline void JIT::emitStoreDouble(int index, FPRegisterID value) 884{ 885 storeDouble(value, addressFor(index)); 886} 887 888inline void JIT::emitStore(int index, const JSValue constant, RegisterID base) 889{ 890 store32(Imm32(constant.payload()), payloadFor(index, base)); 891 store32(Imm32(constant.tag()), tagFor(index, base)); 892} 893 894ALWAYS_INLINE void JIT::emitInitRegister(int dst) 895{ 896 emitStore(dst, jsUndefined()); 897} 898 899inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex) 900{ 901 if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) { 902 if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex)) 903 addSlowCase(jump()); 904 else 905 addSlowCase(emitJumpIfNotJSCell(virtualRegisterIndex)); 906 } 907} 908 909inline void JIT::emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag) 910{ 911 if (!m_codeBlock->isKnownNotImmediate(virtualRegisterIndex)) { 912 if (m_codeBlock->isConstantRegisterIndex(virtualRegisterIndex)) 913 addSlowCase(jump()); 914 else 915 addSlowCase(branch32(NotEqual, tag, TrustedImm32(JSValue::CellTag))); 916 } 917} 918 919ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(int src) 920{ 921 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32(); 922} 923 924ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(int op1, int op2, int& op, int32_t& constant) 925{ 926 if (isOperandConstantImmediateInt(op1)) { 927 constant = getConstantOperand(op1).asInt32(); 928 op = op2; 929 return true; 930 } 931 932 if (isOperandConstantImmediateInt(op2)) { 933 constant = getConstantOperand(op2).asInt32(); 934 op = op1; 935 return true; 936 } 937 938 return false; 939} 940 941#else // USE(JSVALUE32_64) 942 943// get arg puts an arg from the SF register array into a h/w register 944ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst) 945{ 946 ASSERT(m_bytecodeOffset != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set. 947 948 // TODO: we want to reuse values that are already in registers if we can - add a register allocator! 949 if (m_codeBlock->isConstantRegisterIndex(src)) { 950 JSValue value = m_codeBlock->getConstant(src); 951 if (!value.isNumber()) 952 move(TrustedImm64(JSValue::encode(value)), dst); 953 else 954 move(Imm64(JSValue::encode(value)), dst); 955 return; 956 } 957 958 load64(Address(callFrameRegister, src * sizeof(Register)), dst); 959} 960 961ALWAYS_INLINE void JIT::emitGetVirtualRegister(VirtualRegister src, RegisterID dst) 962{ 963 emitGetVirtualRegister(src.offset(), dst); 964} 965 966ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2) 967{ 968 emitGetVirtualRegister(src1, dst1); 969 emitGetVirtualRegister(src2, dst2); 970} 971 972ALWAYS_INLINE void JIT::emitGetVirtualRegisters(VirtualRegister src1, RegisterID dst1, VirtualRegister src2, RegisterID dst2) 973{ 974 emitGetVirtualRegisters(src1.offset(), dst1, src2.offset(), dst2); 975} 976 977ALWAYS_INLINE int32_t JIT::getConstantOperandImmediateInt(int src) 978{ 979 return getConstantOperand(src).asInt32(); 980} 981 982ALWAYS_INLINE bool JIT::isOperandConstantImmediateInt(int src) 983{ 984 return m_codeBlock->isConstantRegisterIndex(src) && getConstantOperand(src).isInt32(); 985} 986 987ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, RegisterID from) 988{ 989 store64(from, Address(callFrameRegister, dst * sizeof(Register))); 990} 991 992ALWAYS_INLINE void JIT::emitPutVirtualRegister(VirtualRegister dst, RegisterID from) 993{ 994 emitPutVirtualRegister(dst.offset(), from); 995} 996 997ALWAYS_INLINE void JIT::emitInitRegister(int dst) 998{ 999 store64(TrustedImm64(JSValue::encode(jsUndefined())), Address(callFrameRegister, dst * sizeof(Register))); 1000} 1001 1002ALWAYS_INLINE JIT::Jump JIT::emitJumpIfJSCell(RegisterID reg) 1003{ 1004 return branchTest64(Zero, reg, tagMaskRegister); 1005} 1006 1007ALWAYS_INLINE JIT::Jump JIT::emitJumpIfBothJSCells(RegisterID reg1, RegisterID reg2, RegisterID scratch) 1008{ 1009 move(reg1, scratch); 1010 or64(reg2, scratch); 1011 return emitJumpIfJSCell(scratch); 1012} 1013 1014ALWAYS_INLINE void JIT::emitJumpSlowCaseIfJSCell(RegisterID reg) 1015{ 1016 addSlowCase(emitJumpIfJSCell(reg)); 1017} 1018 1019ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg) 1020{ 1021 addSlowCase(emitJumpIfNotJSCell(reg)); 1022} 1023 1024ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, int vReg) 1025{ 1026 if (!m_codeBlock->isKnownNotImmediate(vReg)) 1027 emitJumpSlowCaseIfNotJSCell(reg); 1028} 1029 1030inline void JIT::emitLoadDouble(int index, FPRegisterID value) 1031{ 1032 if (m_codeBlock->isConstantRegisterIndex(index)) { 1033 WriteBarrier<Unknown>& inConstantPool = m_codeBlock->constantRegister(index); 1034 loadDouble(TrustedImmPtr(&inConstantPool), value); 1035 } else 1036 loadDouble(addressFor(index), value); 1037} 1038 1039inline void JIT::emitLoadInt32ToDouble(int index, FPRegisterID value) 1040{ 1041 if (m_codeBlock->isConstantRegisterIndex(index)) { 1042 ASSERT(isOperandConstantImmediateInt(index)); 1043 convertInt32ToDouble(Imm32(getConstantOperand(index).asInt32()), value); 1044 } else 1045 convertInt32ToDouble(addressFor(index), value); 1046} 1047 1048ALWAYS_INLINE JIT::Jump JIT::emitJumpIfImmediateInteger(RegisterID reg) 1049{ 1050 return branch64(AboveOrEqual, reg, tagTypeNumberRegister); 1051} 1052 1053ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateInteger(RegisterID reg) 1054{ 1055 return branch64(Below, reg, tagTypeNumberRegister); 1056} 1057 1058ALWAYS_INLINE JIT::Jump JIT::emitJumpIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch) 1059{ 1060 move(reg1, scratch); 1061 and64(reg2, scratch); 1062 return emitJumpIfNotImmediateInteger(scratch); 1063} 1064 1065ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateInteger(RegisterID reg) 1066{ 1067 addSlowCase(emitJumpIfNotImmediateInteger(reg)); 1068} 1069 1070ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateIntegers(RegisterID reg1, RegisterID reg2, RegisterID scratch) 1071{ 1072 addSlowCase(emitJumpIfNotImmediateIntegers(reg1, reg2, scratch)); 1073} 1074 1075ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmediateNumber(RegisterID reg) 1076{ 1077 addSlowCase(emitJumpIfNotImmediateNumber(reg)); 1078} 1079 1080ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID src, RegisterID dest) 1081{ 1082 emitFastArithIntToImmNoCheck(src, dest); 1083} 1084 1085ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg) 1086{ 1087 or32(TrustedImm32(static_cast<int32_t>(ValueFalse)), reg); 1088} 1089 1090#endif // USE(JSVALUE32_64) 1091 1092template <typename T> 1093JIT::Jump JIT::branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure) 1094{ 1095#if USE(JSVALUE64) 1096 return branch32(condition, leftHandSide, TrustedImm32(structure->id())); 1097#else 1098 return branchPtr(condition, leftHandSide, TrustedImmPtr(structure)); 1099#endif 1100} 1101 1102template <typename T> 1103MacroAssembler::Jump branchStructure(MacroAssembler& jit, MacroAssembler::RelationalCondition condition, T leftHandSide, Structure* structure) 1104{ 1105#if USE(JSVALUE64) 1106 return jit.branch32(condition, leftHandSide, MacroAssembler::TrustedImm32(structure->id())); 1107#else 1108 return jit.branchPtr(condition, leftHandSide, MacroAssembler::TrustedImmPtr(structure)); 1109#endif 1110} 1111 1112} // namespace JSC 1113 1114#endif // ENABLE(JIT) 1115 1116#endif // JITInlines_h 1117 1118