1/* 2 * Copyright (C) 2008, 2012, 2013, 2014 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 JIT_h 27#define JIT_h 28 29#if ENABLE(JIT) 30 31// We've run into some problems where changing the size of the class JIT leads to 32// performance fluctuations. Try forcing alignment in an attempt to stabalize this. 33#if COMPILER(GCC) 34#define JIT_CLASS_ALIGNMENT __attribute__ ((aligned (32))) 35#else 36#define JIT_CLASS_ALIGNMENT 37#endif 38 39#define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(expected), static_cast<int>(actual)); 40 41#include "CodeBlock.h" 42#include "CompactJITCodeMap.h" 43#include "Interpreter.h" 44#include "JITDisassembler.h" 45#include "JITInlineCacheGenerator.h" 46#include "JSInterfaceJIT.h" 47#include "LegacyProfiler.h" 48#include "Opcode.h" 49#include "ResultType.h" 50#include "SamplingTool.h" 51#include "UnusedPointer.h" 52 53namespace JSC { 54 55 class ArrayAllocationProfile; 56 class CodeBlock; 57 class FunctionExecutable; 58 class JIT; 59 class JSPropertyNameIterator; 60 class Identifier; 61 class Interpreter; 62 class JSScope; 63 class JSStack; 64 class MarkedAllocator; 65 class Register; 66 class StructureChain; 67 68 struct CallLinkInfo; 69 struct Instruction; 70 struct OperandTypes; 71 struct PolymorphicAccessStructureList; 72 struct SimpleJumpTable; 73 struct StringJumpTable; 74 struct StructureStubInfo; 75 76 struct CallRecord { 77 MacroAssembler::Call from; 78 unsigned bytecodeOffset; 79 void* to; 80 81 CallRecord() 82 { 83 } 84 85 CallRecord(MacroAssembler::Call from, unsigned bytecodeOffset, void* to = 0) 86 : from(from) 87 , bytecodeOffset(bytecodeOffset) 88 , to(to) 89 { 90 } 91 }; 92 93 struct JumpTable { 94 MacroAssembler::Jump from; 95 unsigned toBytecodeOffset; 96 97 JumpTable(MacroAssembler::Jump f, unsigned t) 98 : from(f) 99 , toBytecodeOffset(t) 100 { 101 } 102 }; 103 104 struct SlowCaseEntry { 105 MacroAssembler::Jump from; 106 unsigned to; 107 unsigned hint; 108 109 SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0) 110 : from(f) 111 , to(t) 112 , hint(h) 113 { 114 } 115 }; 116 117 struct SwitchRecord { 118 enum Type { 119 Immediate, 120 Character, 121 String 122 }; 123 124 Type type; 125 126 union { 127 SimpleJumpTable* simpleJumpTable; 128 StringJumpTable* stringJumpTable; 129 } jumpTable; 130 131 unsigned bytecodeOffset; 132 unsigned defaultOffset; 133 134 SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset, Type type) 135 : type(type) 136 , bytecodeOffset(bytecodeOffset) 137 , defaultOffset(defaultOffset) 138 { 139 this->jumpTable.simpleJumpTable = jumpTable; 140 } 141 142 SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeOffset, unsigned defaultOffset) 143 : type(String) 144 , bytecodeOffset(bytecodeOffset) 145 , defaultOffset(defaultOffset) 146 { 147 this->jumpTable.stringJumpTable = jumpTable; 148 } 149 }; 150 151 struct ByValCompilationInfo { 152 ByValCompilationInfo() { } 153 154 ByValCompilationInfo(unsigned bytecodeIndex, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, MacroAssembler::Label doneTarget) 155 : bytecodeIndex(bytecodeIndex) 156 , badTypeJump(badTypeJump) 157 , arrayMode(arrayMode) 158 , doneTarget(doneTarget) 159 { 160 } 161 162 unsigned bytecodeIndex; 163 MacroAssembler::PatchableJump badTypeJump; 164 JITArrayMode arrayMode; 165 MacroAssembler::Label doneTarget; 166 MacroAssembler::Label slowPathTarget; 167 MacroAssembler::Call returnAddress; 168 }; 169 170 struct CallCompilationInfo { 171 MacroAssembler::DataLabelPtr hotPathBegin; 172 MacroAssembler::Call hotPathOther; 173 MacroAssembler::Call callReturnLocation; 174 CallLinkInfo* callLinkInfo; 175 }; 176 177 // Near calls can only be patched to other JIT code, regular calls can be patched to JIT code or relinked to stub functions. 178 void ctiPatchNearCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction); 179 void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction); 180 void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction); 181 182 class JIT : private JSInterfaceJIT { 183 friend class JITSlowPathCall; 184 friend class JITStubCall; 185 186 using MacroAssembler::Jump; 187 using MacroAssembler::JumpList; 188 using MacroAssembler::Label; 189 190 static const uintptr_t patchGetByIdDefaultStructure = unusedPointer; 191 static const int patchGetByIdDefaultOffset = 0; 192 // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler 193 // will compress the displacement, and we may not be able to fit a patched offset. 194 static const int patchPutByIdDefaultOffset = 256; 195 196 public: 197 static CompilationResult compile(VM* vm, CodeBlock* codeBlock, JITCompilationEffort effort) 198 { 199 return JIT(vm, codeBlock).privateCompile(effort); 200 } 201 202 static void compileClosureCall(VM* vm, CallLinkInfo* callLinkInfo, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, Structure* expectedStructure, ExecutableBase* expectedExecutable, MacroAssemblerCodePtr codePtr) 203 { 204 JIT jit(vm, callerCodeBlock); 205 jit.m_bytecodeOffset = callLinkInfo->codeOrigin.bytecodeIndex; 206 jit.privateCompileClosureCall(callLinkInfo, calleeCodeBlock, expectedStructure, expectedExecutable, codePtr); 207 } 208 209 static void compileGetByVal(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 210 { 211 JIT jit(vm, codeBlock); 212 jit.m_bytecodeOffset = byValInfo->bytecodeIndex; 213 jit.privateCompileGetByVal(byValInfo, returnAddress, arrayMode); 214 } 215 216 static void compilePutByVal(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 217 { 218 JIT jit(vm, codeBlock); 219 jit.m_bytecodeOffset = byValInfo->bytecodeIndex; 220 jit.privateCompilePutByVal(byValInfo, returnAddress, arrayMode); 221 } 222 223 static void compileDirectPutByVal(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode) 224 { 225 JIT jit(vm, codeBlock); 226 jit.m_bytecodeOffset = byValInfo->bytecodeIndex; 227 jit.privateCompilePutByVal(byValInfo, returnAddress, arrayMode); 228 } 229 230 static CodeRef compileCTINativeCall(VM* vm, NativeFunction func) 231 { 232 if (!vm->canUseJIT()) { 233 return CodeRef::createLLIntCodeRef(llint_native_call_trampoline); 234 } 235 JIT jit(vm, 0); 236 return jit.privateCompileCTINativeCall(vm, func); 237 } 238 239 static unsigned frameRegisterCountFor(CodeBlock*); 240 static int stackPointerOffsetFor(CodeBlock*); 241 242 private: 243 JIT(VM*, CodeBlock* = 0); 244 245 void privateCompileMainPass(); 246 void privateCompileLinkPass(); 247 void privateCompileSlowCases(); 248 CompilationResult privateCompile(JITCompilationEffort); 249 250 void privateCompileClosureCall(CallLinkInfo*, CodeBlock* calleeCodeBlock, Structure*, ExecutableBase*, MacroAssemblerCodePtr); 251 252 void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); 253 void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode); 254 255 Label privateCompileCTINativeCall(VM*, bool isConstruct = false); 256 CodeRef privateCompileCTINativeCall(VM*, NativeFunction); 257 void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress); 258 259 // Add a call out from JIT code, without an exception check. 260 Call appendCall(const FunctionPtr& function) 261 { 262 Call functionCall = call(); 263 m_calls.append(CallRecord(functionCall, m_bytecodeOffset, function.value())); 264 return functionCall; 265 } 266 267#if OS(WINDOWS) && CPU(X86_64) 268 Call appendCallWithSlowPathReturnType(const FunctionPtr& function) 269 { 270 Call functionCall = callWithSlowPathReturnType(); 271 m_calls.append(CallRecord(functionCall, m_bytecodeOffset, function.value())); 272 return functionCall; 273 } 274#endif 275 276 void exceptionCheck(Jump jumpToHandler) 277 { 278 m_exceptionChecks.append(jumpToHandler); 279 } 280 281 void exceptionCheck() 282 { 283 m_exceptionChecks.append(emitExceptionCheck()); 284 } 285 286 void exceptionCheckWithCallFrameRollback() 287 { 288 m_exceptionChecksWithCallFrameRollback.append(emitExceptionCheck()); 289 } 290 291 void privateCompileExceptionHandlers(); 292 293 void addSlowCase(Jump); 294 void addSlowCase(JumpList); 295 void addSlowCase(); 296 void addJump(Jump, int); 297 void emitJumpSlowToHot(Jump, int); 298 299 void compileOpCall(OpcodeID, Instruction*, unsigned callLinkInfoIndex); 300 void compileOpCallSlowCase(OpcodeID, Instruction*, Vector<SlowCaseEntry>::iterator&, unsigned callLinkInfoIndex); 301 void compileLoadVarargs(Instruction*); 302 void compileCallEval(Instruction*); 303 void compileCallEvalSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&); 304 void emitPutCallResult(Instruction*); 305 306 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; 307 void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type); 308 bool isOperandConstantImmediateDouble(int src); 309 310 void emitLoadDouble(int index, FPRegisterID value); 311 void emitLoadInt32ToDouble(int index, FPRegisterID value); 312 Jump emitJumpIfCellNotObject(RegisterID cellReg); 313 314 enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterBase, ShouldFilterValue, ShouldFilterBaseAndValue }; 315 // value register in write barrier is used before any scratch registers 316 // so may safely be the same as either of the scratch registers. 317 void emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode); 318 void emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode); 319 void emitWriteBarrier(JSCell* owner); 320 321 template<typename StructureType> // StructureType can be RegisterID or ImmPtr. 322 void emitAllocateJSObject(RegisterID allocator, StructureType, RegisterID result, RegisterID scratch); 323 324 // This assumes that the value to profile is in regT0 and that regT3 is available for 325 // scratch. 326 void emitValueProfilingSite(ValueProfile*); 327 void emitValueProfilingSite(unsigned bytecodeOffset); 328 void emitValueProfilingSite(); 329 void emitArrayProfilingSiteWithCell(RegisterID cell, RegisterID indexingType, ArrayProfile*); 330 void emitArrayProfilingSiteForBytecodeIndexWithCell(RegisterID cell, RegisterID indexingType, unsigned bytecodeIndex); 331 void emitArrayProfileStoreToHoleSpecialCase(ArrayProfile*); 332 void emitArrayProfileOutOfBoundsSpecialCase(ArrayProfile*); 333 334 JITArrayMode chooseArrayMode(ArrayProfile*); 335 336 // Property is in regT1, base is in regT0. regT2 contains indexing type. 337 // Property is int-checked and zero extended. Base is cell checked. 338 // Structure is already profiled. Returns the slow cases. Fall-through 339 // case contains result in regT0, and it is not yet profiled. 340 JumpList emitInt32GetByVal(Instruction* instruction, PatchableJump& badType) { return emitContiguousGetByVal(instruction, badType, Int32Shape); } 341 JumpList emitDoubleGetByVal(Instruction*, PatchableJump& badType); 342 JumpList emitContiguousGetByVal(Instruction*, PatchableJump& badType, IndexingType expectedShape = ContiguousShape); 343 JumpList emitArrayStorageGetByVal(Instruction*, PatchableJump& badType); 344 JumpList emitIntTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType); 345 JumpList emitFloatTypedArrayGetByVal(Instruction*, PatchableJump& badType, TypedArrayType); 346 347 // Property is in regT0, base is in regT0. regT2 contains indecing type. 348 // The value to store is not yet loaded. Property is int-checked and 349 // zero-extended. Base is cell checked. Structure is already profiled. 350 // returns the slow cases. 351 JumpList emitInt32PutByVal(Instruction* currentInstruction, PatchableJump& badType) 352 { 353 return emitGenericContiguousPutByVal(currentInstruction, badType, Int32Shape); 354 } 355 JumpList emitDoublePutByVal(Instruction* currentInstruction, PatchableJump& badType) 356 { 357 return emitGenericContiguousPutByVal(currentInstruction, badType, DoubleShape); 358 } 359 JumpList emitContiguousPutByVal(Instruction* currentInstruction, PatchableJump& badType) 360 { 361 return emitGenericContiguousPutByVal(currentInstruction, badType); 362 } 363 JumpList emitGenericContiguousPutByVal(Instruction*, PatchableJump& badType, IndexingType indexingShape = ContiguousShape); 364 JumpList emitArrayStoragePutByVal(Instruction*, PatchableJump& badType); 365 JumpList emitIntTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType); 366 JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType); 367 368 enum FinalObjectMode { MayBeFinal, KnownNotFinal }; 369 370 template <typename T> Jump branchStructure(RelationalCondition, T leftHandSide, Structure*); 371 372#if USE(JSVALUE32_64) 373 bool getOperandConstantImmediateInt(int op1, int op2, int& op, int32_t& constant); 374 375 void emitLoadTag(int index, RegisterID tag); 376 void emitLoadPayload(int index, RegisterID payload); 377 378 void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload); 379 void emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister); 380 void emitLoad2(int index1, RegisterID tag1, RegisterID payload1, int index2, RegisterID tag2, RegisterID payload2); 381 382 void emitStore(int index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister); 383 void emitStore(int index, const JSValue constant, RegisterID base = callFrameRegister); 384 void emitStoreInt32(int index, RegisterID payload, bool indexIsInt32 = false); 385 void emitStoreInt32(int index, TrustedImm32 payload, bool indexIsInt32 = false); 386 void emitStoreCell(int index, RegisterID payload, bool indexIsCell = false); 387 void emitStoreBool(int index, RegisterID payload, bool indexIsBool = false); 388 void emitStoreDouble(int index, FPRegisterID value); 389 390 void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex); 391 void emitJumpSlowCaseIfNotJSCell(int virtualRegisterIndex, RegisterID tag); 392 393 void compileGetByIdHotPath(const Identifier*); 394 void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, PropertyOffset cachedOffset); 395 void compileGetDirectOffset(JSObject* base, RegisterID resultTag, RegisterID resultPayload, PropertyOffset cachedOffset); 396 void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID offset, FinalObjectMode = MayBeFinal); 397 void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, PropertyOffset cachedOffset); 398 399 // Arithmetic opcode helpers 400 void emitAdd32Constant(int dst, int op, int32_t constant, ResultType opType); 401 void emitSub32Constant(int dst, int op, int32_t constant, ResultType opType); 402 void emitBinaryDoubleOp(OpcodeID, int dst, int op1, int op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true); 403 404#else // USE(JSVALUE32_64) 405 void emitGetVirtualRegister(int src, RegisterID dst); 406 void emitGetVirtualRegister(VirtualRegister src, RegisterID dst); 407 void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2); 408 void emitGetVirtualRegisters(VirtualRegister src1, RegisterID dst1, VirtualRegister src2, RegisterID dst2); 409 void emitPutVirtualRegister(int dst, RegisterID from = regT0); 410 void emitPutVirtualRegister(VirtualRegister dst, RegisterID from = regT0); 411 void emitStoreCell(int dst, RegisterID payload, bool /* only used in JSValue32_64 */ = false) 412 { 413 emitPutVirtualRegister(dst, payload); 414 } 415 void emitStoreCell(VirtualRegister dst, RegisterID payload) 416 { 417 emitPutVirtualRegister(dst, payload); 418 } 419 420 int32_t getConstantOperandImmediateInt(int src); 421 422 Jump emitJumpIfJSCell(RegisterID); 423 Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID); 424 void emitJumpSlowCaseIfJSCell(RegisterID); 425 void emitJumpSlowCaseIfNotJSCell(RegisterID); 426 void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg); 427 Jump emitJumpIfImmediateInteger(RegisterID); 428 Jump emitJumpIfNotImmediateInteger(RegisterID); 429 Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); 430 void emitJumpSlowCaseIfNotImmediateInteger(RegisterID); 431 void emitJumpSlowCaseIfNotImmediateNumber(RegisterID); 432 void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); 433 434 void emitFastArithReTagImmediate(RegisterID src, RegisterID dest); 435 436 void emitTagAsBoolImmediate(RegisterID reg); 437 void compileBinaryArithOp(OpcodeID, int dst, int src1, int src2, OperandTypes opi); 438 void compileBinaryArithOpSlowCase(Instruction*, OpcodeID, Vector<SlowCaseEntry>::iterator&, int dst, int src1, int src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase); 439 440 void compileGetByIdHotPath(int baseVReg, const Identifier*); 441 void compileGetDirectOffset(RegisterID base, RegisterID result, PropertyOffset cachedOffset); 442 void compileGetDirectOffset(JSObject* base, RegisterID result, PropertyOffset cachedOffset); 443 void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch, FinalObjectMode = MayBeFinal); 444 void compilePutDirectOffset(RegisterID base, RegisterID value, PropertyOffset cachedOffset); 445 446#endif // USE(JSVALUE32_64) 447 448 void emit_compareAndJump(OpcodeID, int op1, int op2, unsigned target, RelationalCondition); 449 void emit_compareAndJumpSlow(int op1, int op2, unsigned target, DoubleCondition, size_t (JIT_OPERATION *operation)(ExecState*, EncodedJSValue, EncodedJSValue), bool invert, Vector<SlowCaseEntry>::iterator&); 450 451 void emit_op_touch_entry(Instruction*); 452 void emit_op_add(Instruction*); 453 void emit_op_bitand(Instruction*); 454 void emit_op_bitor(Instruction*); 455 void emit_op_bitxor(Instruction*); 456 void emit_op_call(Instruction*); 457 void emit_op_call_eval(Instruction*); 458 void emit_op_call_varargs(Instruction*); 459 void emit_op_construct_varargs(Instruction*); 460 void emit_op_captured_mov(Instruction*); 461 void emit_op_catch(Instruction*); 462 void emit_op_construct(Instruction*); 463 void emit_op_get_callee(Instruction*); 464 void emit_op_create_this(Instruction*); 465 void emit_op_to_this(Instruction*); 466 void emit_op_create_arguments(Instruction*); 467 void emit_op_debug(Instruction*); 468 void emit_op_del_by_id(Instruction*); 469 void emit_op_div(Instruction*); 470 void emit_op_end(Instruction*); 471 void emit_op_enter(Instruction*); 472 void emit_op_create_activation(Instruction*); 473 void emit_op_eq(Instruction*); 474 void emit_op_eq_null(Instruction*); 475 void emit_op_get_by_id(Instruction*); 476 void emit_op_get_arguments_length(Instruction*); 477 void emit_op_get_by_val(Instruction*); 478 void emit_op_get_argument_by_val(Instruction*); 479 void emit_op_get_by_pname(Instruction*); 480 void emit_op_init_lazy_reg(Instruction*); 481 void emit_op_check_has_instance(Instruction*); 482 void emit_op_instanceof(Instruction*); 483 void emit_op_is_undefined(Instruction*); 484 void emit_op_is_boolean(Instruction*); 485 void emit_op_is_number(Instruction*); 486 void emit_op_is_string(Instruction*); 487 void emit_op_jeq_null(Instruction*); 488 void emit_op_jfalse(Instruction*); 489 void emit_op_jmp(Instruction*); 490 void emit_op_jneq_null(Instruction*); 491 void emit_op_jneq_ptr(Instruction*); 492 void emit_op_jless(Instruction*); 493 void emit_op_jlesseq(Instruction*); 494 void emit_op_jgreater(Instruction*); 495 void emit_op_jgreatereq(Instruction*); 496 void emit_op_jnless(Instruction*); 497 void emit_op_jnlesseq(Instruction*); 498 void emit_op_jngreater(Instruction*); 499 void emit_op_jngreatereq(Instruction*); 500 void emit_op_jtrue(Instruction*); 501 void emit_op_loop_hint(Instruction*); 502 void emit_op_lshift(Instruction*); 503 void emit_op_mod(Instruction*); 504 void emit_op_mov(Instruction*); 505 void emit_op_mul(Instruction*); 506 void emit_op_negate(Instruction*); 507 void emit_op_neq(Instruction*); 508 void emit_op_neq_null(Instruction*); 509 void emit_op_new_array(Instruction*); 510 void emit_op_new_array_with_size(Instruction*); 511 void emit_op_new_array_buffer(Instruction*); 512 void emit_op_new_func(Instruction*); 513 void emit_op_new_captured_func(Instruction*); 514 void emit_op_new_func_exp(Instruction*); 515 void emit_op_new_object(Instruction*); 516 void emit_op_new_regexp(Instruction*); 517 void emit_op_get_pnames(Instruction*); 518 void emit_op_next_pname(Instruction*); 519 void emit_op_not(Instruction*); 520 void emit_op_nstricteq(Instruction*); 521 void emit_op_pop_scope(Instruction*); 522 void emit_op_dec(Instruction*); 523 void emit_op_inc(Instruction*); 524 void emit_op_profile_did_call(Instruction*); 525 void emit_op_profile_will_call(Instruction*); 526 void emit_op_push_name_scope(Instruction*); 527 void emit_op_push_with_scope(Instruction*); 528 void emit_op_put_by_id(Instruction*); 529 void emit_op_put_by_index(Instruction*); 530 void emit_op_put_by_val(Instruction*); 531 void emit_op_put_getter_setter(Instruction*); 532 void emit_op_init_global_const(Instruction*); 533 void emit_op_ret(Instruction*); 534 void emit_op_ret_object_or_this(Instruction*); 535 void emit_op_rshift(Instruction*); 536 void emit_op_strcat(Instruction*); 537 void emit_op_stricteq(Instruction*); 538 void emit_op_sub(Instruction*); 539 void emit_op_switch_char(Instruction*); 540 void emit_op_switch_imm(Instruction*); 541 void emit_op_switch_string(Instruction*); 542 void emit_op_tear_off_activation(Instruction*); 543 void emit_op_tear_off_arguments(Instruction*); 544 void emit_op_throw(Instruction*); 545 void emit_op_throw_static_error(Instruction*); 546 void emit_op_to_number(Instruction*); 547 void emit_op_to_primitive(Instruction*); 548 void emit_op_unexpected_load(Instruction*); 549 void emit_op_unsigned(Instruction*); 550 void emit_op_urshift(Instruction*); 551 552 void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&); 553 void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&); 554 void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&); 555 void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&); 556 void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&); 557 void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&); 558 void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&); 559 void emitSlow_op_construct_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&); 560 void emitSlow_op_captured_mov(Instruction*, Vector<SlowCaseEntry>::iterator&); 561 void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&); 562 void emitSlow_op_to_this(Instruction*, Vector<SlowCaseEntry>::iterator&); 563 void emitSlow_op_create_this(Instruction*, Vector<SlowCaseEntry>::iterator&); 564 void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&); 565 void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&); 566 void emitSlow_op_get_callee(Instruction*, Vector<SlowCaseEntry>::iterator&); 567 void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); 568 void emitSlow_op_get_arguments_length(Instruction*, Vector<SlowCaseEntry>::iterator&); 569 void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 570 void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 571 void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&); 572 void emitSlow_op_check_has_instance(Instruction*, Vector<SlowCaseEntry>::iterator&); 573 void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&); 574 void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&); 575 void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); 576 void emitSlow_op_jlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); 577 void emitSlow_op_jgreater(Instruction*, Vector<SlowCaseEntry>::iterator&); 578 void emitSlow_op_jgreatereq(Instruction*, Vector<SlowCaseEntry>::iterator&); 579 void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&); 580 void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); 581 void emitSlow_op_jngreater(Instruction*, Vector<SlowCaseEntry>::iterator&); 582 void emitSlow_op_jngreatereq(Instruction*, Vector<SlowCaseEntry>::iterator&); 583 void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&); 584 void emitSlow_op_loop_hint(Instruction*, Vector<SlowCaseEntry>::iterator&); 585 void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&); 586 void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&); 587 void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&); 588 void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&); 589 void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&); 590 void emitSlow_op_new_object(Instruction*, Vector<SlowCaseEntry>::iterator&); 591 void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&); 592 void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&); 593 void emitSlow_op_dec(Instruction*, Vector<SlowCaseEntry>::iterator&); 594 void emitSlow_op_inc(Instruction*, Vector<SlowCaseEntry>::iterator&); 595 void emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); 596 void emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); 597 void emitSlow_op_rshift(Instruction*, Vector<SlowCaseEntry>::iterator&); 598 void emitSlow_op_stricteq(Instruction*, Vector<SlowCaseEntry>::iterator&); 599 void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&); 600 void emitSlow_op_to_number(Instruction*, Vector<SlowCaseEntry>::iterator&); 601 void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&); 602 void emitSlow_op_unsigned(Instruction*, Vector<SlowCaseEntry>::iterator&); 603 void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&); 604 605 void emit_op_resolve_scope(Instruction*); 606 void emit_op_get_from_scope(Instruction*); 607 void emit_op_put_to_scope(Instruction*); 608 void emitSlow_op_resolve_scope(Instruction*, Vector<SlowCaseEntry>::iterator&); 609 void emitSlow_op_get_from_scope(Instruction*, Vector<SlowCaseEntry>::iterator&); 610 void emitSlow_op_put_to_scope(Instruction*, Vector<SlowCaseEntry>::iterator&); 611 612 void emitRightShift(Instruction*, bool isUnsigned); 613 void emitRightShiftSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&, bool isUnsigned); 614 615 void emitVarInjectionCheck(bool needsVarInjectionChecks); 616 void emitResolveClosure(int dst, bool needsVarInjectionChecks, unsigned depth); 617 void emitLoadWithStructureCheck(int scope, Structure** structureSlot); 618 void emitGetGlobalProperty(uintptr_t* operandSlot); 619 void emitGetGlobalVar(uintptr_t operand); 620 void emitGetClosureVar(int scope, uintptr_t operand); 621 void emitPutGlobalProperty(uintptr_t* operandSlot, int value); 622#if USE(JSVALUE64) 623 void emitNotifyWrite(RegisterID value, RegisterID scratch, VariableWatchpointSet*); 624#else 625 void emitNotifyWrite(RegisterID tag, RegisterID payload, RegisterID scratch, VariableWatchpointSet*); 626#endif 627 void emitPutGlobalVar(uintptr_t operand, int value, VariableWatchpointSet*); 628 void emitPutClosureVar(int scope, uintptr_t operand, int value); 629 630 void emitInitRegister(int dst); 631 632 void emitPutIntToCallFrameHeader(RegisterID from, JSStack::CallFrameHeaderEntry); 633 void emitGetFromCallFrameHeaderPtr(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister); 634 void emitGetFromCallFrameHeader32(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister); 635#if USE(JSVALUE64) 636 void emitGetFromCallFrameHeader64(JSStack::CallFrameHeaderEntry, RegisterID to, RegisterID from = callFrameRegister); 637#endif 638 639 JSValue getConstantOperand(int src); 640 bool isOperandConstantImmediateInt(int src); 641 bool isOperandConstantImmediateChar(int src); 642 643 Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter) 644 { 645 return iter++->from; 646 } 647 void linkSlowCase(Vector<SlowCaseEntry>::iterator& iter) 648 { 649 iter->from.link(this); 650 ++iter; 651 } 652 void linkDummySlowCase(Vector<SlowCaseEntry>::iterator& iter) 653 { 654 ASSERT(!iter->from.isSet()); 655 ++iter; 656 } 657 void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int virtualRegisterIndex); 658 659 MacroAssembler::Call appendCallWithExceptionCheck(const FunctionPtr&); 660#if OS(WINDOWS) && CPU(X86_64) 661 MacroAssembler::Call appendCallWithExceptionCheckAndSlowPathReturnType(const FunctionPtr&); 662#endif 663 MacroAssembler::Call appendCallWithCallFrameRollbackOnException(const FunctionPtr&); 664 MacroAssembler::Call appendCallWithExceptionCheckSetJSValueResult(const FunctionPtr&, int); 665 MacroAssembler::Call appendCallWithExceptionCheckSetJSValueResultWithProfile(const FunctionPtr&, int); 666 667 enum WithProfileTag { WithProfile }; 668 669 MacroAssembler::Call callOperation(C_JITOperation_E); 670 MacroAssembler::Call callOperation(C_JITOperation_EO, GPRReg); 671 MacroAssembler::Call callOperation(C_JITOperation_ESt, Structure*); 672 MacroAssembler::Call callOperation(C_JITOperation_EZ, int32_t); 673 MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, int32_t, int32_t); 674 MacroAssembler::Call callOperation(J_JITOperation_E, int); 675 MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg); 676 MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, GPRReg, int32_t); 677 MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, const JSValue*, int32_t); 678 MacroAssembler::Call callOperation(J_JITOperation_EC, int, JSCell*); 679 MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*); 680 MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg); 681#if USE(JSVALUE64) 682 MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, StringImpl*); 683#else 684 MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, GPRReg, StringImpl*); 685#endif 686 MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, const Identifier*); 687 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg); 688#if USE(JSVALUE64) 689 MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_EJJ, int, GPRReg, GPRReg); 690#else 691 MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg); 692#endif 693 MacroAssembler::Call callOperation(J_JITOperation_EP, int, void*); 694 MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_EPc, int, Instruction*); 695 MacroAssembler::Call callOperation(J_JITOperation_EZ, int, int32_t); 696 MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, size_t); 697 MacroAssembler::Call callOperation(S_JITOperation_ECC, RegisterID, RegisterID); 698 MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID); 699 MacroAssembler::Call callOperation(S_JITOperation_EJJ, RegisterID, RegisterID); 700 MacroAssembler::Call callOperation(S_JITOperation_EOJss, RegisterID, RegisterID); 701 MacroAssembler::Call callOperation(Sprt_JITOperation_EZ, int32_t); 702 MacroAssembler::Call callOperation(V_JITOperation_E); 703 MacroAssembler::Call callOperation(V_JITOperation_EC, RegisterID); 704 MacroAssembler::Call callOperation(V_JITOperation_ECC, RegisterID, RegisterID); 705 MacroAssembler::Call callOperation(V_JITOperation_ECICC, RegisterID, const Identifier*, RegisterID, RegisterID); 706 MacroAssembler::Call callOperation(V_JITOperation_EIdJZ, const Identifier*, RegisterID, int32_t); 707 MacroAssembler::Call callOperation(V_JITOperation_EJ, RegisterID); 708#if USE(JSVALUE64) 709 MacroAssembler::Call callOperationNoExceptionCheck(V_JITOperation_EJ, RegisterID); 710#else 711 MacroAssembler::Call callOperationNoExceptionCheck(V_JITOperation_EJ, RegisterID, RegisterID); 712#endif 713 MacroAssembler::Call callOperation(V_JITOperation_EJIdJJ, RegisterID, const Identifier*, RegisterID, RegisterID); 714#if USE(JSVALUE64) 715 MacroAssembler::Call callOperation(F_JITOperation_EFJJZ, RegisterID, RegisterID, RegisterID, int32_t); 716 MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, StringImpl*); 717#else 718 MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, StringImpl*); 719#endif 720 MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID); 721 MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, int32_t, RegisterID); 722 MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, int32_t); 723 MacroAssembler::Call callOperation(V_JITOperation_EPc, Instruction*); 724 MacroAssembler::Call callOperation(V_JITOperation_EZ, int32_t); 725 MacroAssembler::Call callOperationWithCallFrameRollbackOnException(J_JITOperation_E); 726 MacroAssembler::Call callOperationNoExceptionCheck(J_JITOperation_EE, RegisterID); 727 MacroAssembler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb, CodeBlock*); 728 MacroAssembler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E); 729#if USE(JSVALUE32_64) 730 MacroAssembler::Call callOperation(F_JITOperation_EFJJZ, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, int32_t); 731 MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t); 732 MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg, GPRReg); 733 MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg, GPRReg); 734 MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, GPRReg, const Identifier*); 735 MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg); 736 MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, GPRReg, size_t); 737 MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID, RegisterID); 738 MacroAssembler::Call callOperation(S_JITOperation_EJJ, RegisterID, RegisterID, RegisterID, RegisterID); 739 MacroAssembler::Call callOperation(V_JITOperation_EIdJZ, const Identifier*, RegisterID, RegisterID, int32_t); 740 MacroAssembler::Call callOperation(V_JITOperation_EJ, RegisterID, RegisterID); 741 MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID); 742 MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, RegisterID, int32_t); 743 MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, RegisterID, int32_t, RegisterID, RegisterID); 744#endif 745 746 Jump checkStructure(RegisterID reg, Structure* structure); 747 748 void updateTopCallFrame(); 749 750 Call emitNakedCall(CodePtr function = CodePtr()); 751 752 // Loads the character value of a single character string into dst. 753 void emitLoadCharacterString(RegisterID src, RegisterID dst, JumpList& failures); 754 755#if ENABLE(DFG_JIT) 756 void emitEnterOptimizationCheck(); 757#else 758 void emitEnterOptimizationCheck() { } 759#endif 760 761#ifndef NDEBUG 762 void printBytecodeOperandTypes(int src1, int src2); 763#endif 764 765#if ENABLE(SAMPLING_FLAGS) 766 void setSamplingFlag(int32_t); 767 void clearSamplingFlag(int32_t); 768#endif 769 770#if ENABLE(SAMPLING_COUNTERS) 771 void emitCount(AbstractSamplingCounter&, int32_t = 1); 772#endif 773 774#if ENABLE(OPCODE_SAMPLING) 775 void sampleInstruction(Instruction*, bool = false); 776#endif 777 778#if ENABLE(CODEBLOCK_SAMPLING) 779 void sampleCodeBlock(CodeBlock*); 780#else 781 void sampleCodeBlock(CodeBlock*) {} 782#endif 783 784#if ENABLE(DFG_JIT) 785 bool canBeOptimized() { return m_canBeOptimized; } 786 bool canBeOptimizedOrInlined() { return m_canBeOptimizedOrInlined; } 787 bool shouldEmitProfiling() { return m_shouldEmitProfiling; } 788#else 789 bool canBeOptimized() { return false; } 790 bool canBeOptimizedOrInlined() { return false; } 791 // Enables use of value profiler with tiered compilation turned off, 792 // in which case all code gets profiled. 793 bool shouldEmitProfiling() { return false; } 794#endif 795 796 Interpreter* m_interpreter; 797 798 Vector<CallRecord> m_calls; 799 Vector<Label> m_labels; 800 Vector<JITGetByIdGenerator> m_getByIds; 801 Vector<JITPutByIdGenerator> m_putByIds; 802 Vector<ByValCompilationInfo> m_byValCompilationInfo; 803 Vector<CallCompilationInfo> m_callCompilationInfo; 804 Vector<JumpTable> m_jmpTable; 805 806 unsigned m_bytecodeOffset; 807 Vector<SlowCaseEntry> m_slowCases; 808 Vector<SwitchRecord> m_switches; 809 810 JumpList m_exceptionChecks; 811 JumpList m_exceptionChecksWithCallFrameRollback; 812 813 unsigned m_getByIdIndex; 814 unsigned m_putByIdIndex; 815 unsigned m_byValInstructionIndex; 816 unsigned m_callLinkInfoIndex; 817 818 OwnPtr<JITDisassembler> m_disassembler; 819 RefPtr<Profiler::Compilation> m_compilation; 820 WeakRandom m_randomGenerator; 821 static CodeRef stringGetByValStubGenerator(VM*); 822 823 bool m_canBeOptimized; 824 bool m_canBeOptimizedOrInlined; 825 bool m_shouldEmitProfiling; 826 } JIT_CLASS_ALIGNMENT; 827 828} // namespace JSC 829 830#endif // ENABLE(JIT) 831 832#endif // JIT_h 833