📄 jit.h
字号:
/* * Copyright (C) 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#ifndef JIT_h#define JIT_h#include <wtf/Platform.h>#if ENABLE(JIT)#define WTF_USE_CTI_REPATCH_PIC 1#include "Interpreter.h"#include "JITCode.h"#include "JITStubs.h"#include "Opcode.h"#include "RegisterFile.h"#include "MacroAssembler.h"#include "Profiler.h"#include <bytecode/SamplingTool.h>#include <wtf/AlwaysInline.h>#include <wtf/Vector.h>#if PLATFORM(X86_64)#define STUB_ARGS_offset 0x10#else#define STUB_ARGS_offset 0x0C#endif#define STUB_ARGS_code (STUB_ARGS_offset)#define STUB_ARGS_registerFile (STUB_ARGS_offset + 1)#define STUB_ARGS_callFrame (STUB_ARGS_offset + 2)#define STUB_ARGS_exception (STUB_ARGS_offset + 3)#define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4)#define STUB_ARGS_globalData (STUB_ARGS_offset + 5)#define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame])#define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile])#define ARG_exception static_cast<JSValuePtr*>(ARGS[STUB_ARGS_exception])#define ARG_profilerReference static_cast<Profiler**>(ARGS[STUB_ARGS_profilerReference])#define ARG_globalData static_cast<JSGlobalData*>(ARGS[STUB_ARGS_globalData])#define ARG_setCallFrame(newCallFrame) (ARGS[STUB_ARGS_callFrame] = (newCallFrame))#define ARG_src1 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[1]))#define ARG_src2 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[2]))#define ARG_src3 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[3]))#define ARG_src4 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[4]))#define ARG_src5 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[5]))#define ARG_id1 static_cast<Identifier*>(ARGS[1])#define ARG_id2 static_cast<Identifier*>(ARGS[2])#define ARG_id3 static_cast<Identifier*>(ARGS[3])#define ARG_id4 static_cast<Identifier*>(ARGS[4])#define ARG_int1 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[1]))#define ARG_int2 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[2]))#define ARG_int3 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[3]))#define ARG_int4 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[4]))#define ARG_int5 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[5]))#define ARG_int6 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[6]))#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])#define ARG_regexp1 static_cast<RegExp*>(ARGS[1])#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])#define ARG_returnAddress2 static_cast<void*>(ARGS[2])#define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4])#define STUB_RETURN_ADDRESS_SLOT (ARGS[-1])namespace JSC { class CodeBlock; class JSPropertyNameIterator; class Interpreter; class Register; class RegisterFile; class ScopeChainNode; class SimpleJumpTable; class StringJumpTable; class StructureChain; struct CallLinkInfo; struct Instruction; struct OperandTypes; struct PolymorphicAccessStructureList; struct StructureStubInfo; typedef JSValueEncodedAsPointer* (JIT_STUB *CTIHelper_j)(STUB_ARGS); typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS); typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS); typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS); typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS); typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS); typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS); struct CallRecord { MacroAssembler::Call from; unsigned bytecodeIndex; void* to; CallRecord() { } CallRecord(MacroAssembler::Call from, unsigned bytecodeIndex, void* to = 0) : from(from) , bytecodeIndex(bytecodeIndex) , to(to) { } }; struct JumpTable { MacroAssembler::Jump from; unsigned toBytecodeIndex; JumpTable(MacroAssembler::Jump f, unsigned t) : from(f) , toBytecodeIndex(t) { } }; struct SlowCaseEntry { MacroAssembler::Jump from; unsigned to; unsigned hint; SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0) : from(f) , to(t) , hint(h) { } }; struct SwitchRecord { enum Type { Immediate, Character, String }; Type type; union { SimpleJumpTable* simpleJumpTable; StringJumpTable* stringJumpTable; } jumpTable; unsigned bytecodeIndex; unsigned defaultOffset; SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type) : type(type) , bytecodeIndex(bytecodeIndex) , defaultOffset(defaultOffset) { this->jumpTable.simpleJumpTable = jumpTable; } SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset) : type(String) , bytecodeIndex(bytecodeIndex) , defaultOffset(defaultOffset) { this->jumpTable.stringJumpTable = jumpTable; } }; struct PropertyStubCompilationInfo { MacroAssembler::Call callReturnLocation; MacroAssembler::Label hotPathBegin; }; struct StructureStubCompilationInfo { MacroAssembler::DataLabelPtr hotPathBegin; MacroAssembler::Call hotPathOther; MacroAssembler::Call callReturnLocation; MacroAssembler::Label coldPathOther; }; extern "C" { void ctiVMThrowTrampoline(); }; void ctiSetReturnAddress(void** addressOfReturnAddress, void* newDestinationToReturnTo); void ctiPatchCallByReturnAddress(MacroAssembler::ProcessorReturnAddress returnAddress, void* newCalleeFunction); void ctiPatchNearCallByReturnAddress(MacroAssembler::ProcessorReturnAddress returnAddress, void* newCalleeFunction); class JIT : private MacroAssembler { using MacroAssembler::Jump; using MacroAssembler::JumpList; using MacroAssembler::Label; // NOTES: // // regT0 has two special meanings. The return value from a stub // call will always be in regT0, and by default (unless // a register is specified) emitPutVirtualRegister() will store // the value from regT0. // // tempRegister2 is has no such dependencies. It is important that // on x86/x86-64 it is ecx for performance reasons, since the // MacroAssembler will need to plant register swaps if it is not - // however the code will still function correctly.#if PLATFORM(X86_64) static const RegisterID returnValueRegister = X86::eax; static const RegisterID cachedResultRegister = X86::eax; static const RegisterID firstArgumentRegister = X86::edi; static const RegisterID timeoutCheckRegister = X86::r12; static const RegisterID callFrameRegister = X86::r13; static const RegisterID tagTypeNumberRegister = X86::r14; static const RegisterID tagMaskRegister = X86::r15; static const RegisterID regT0 = X86::eax; static const RegisterID regT1 = X86::edx; static const RegisterID regT2 = X86::ecx; // NOTE: privateCompileCTIMachineTrampolines() relies on this being callee preserved; this should be considered non-interface. static const RegisterID regT3 = X86::ebx;#elif PLATFORM(X86) static const RegisterID returnValueRegister = X86::eax; static const RegisterID cachedResultRegister = X86::eax; // On x86 we always use fastcall conventions = but on // OS X if might make more sense to just use regparm. static const RegisterID firstArgumentRegister = X86::ecx; static const RegisterID timeoutCheckRegister = X86::esi; static const RegisterID callFrameRegister = X86::edi; static const RegisterID regT0 = X86::eax; static const RegisterID regT1 = X86::edx; static const RegisterID regT2 = X86::ecx; // NOTE: privateCompileCTIMachineTrampolines() relies on this being callee preserved; this should be considered non-interface. static const RegisterID regT3 = X86::ebx;#else #error "JIT not supported on this platform."#endif static const int patchGetByIdDefaultStructure = -1; // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler // will compress the displacement, and we may not be able to fit a patched offset. static const int patchGetByIdDefaultOffset = 256;#if USE(JIT_STUB_ARGUMENT_REGISTER)#if PLATFORM(X86_64) static const int ctiArgumentInitSize = 6;#else static const int ctiArgumentInitSize = 2;#endif#elif USE(JIT_STUB_ARGUMENT_STACK) static const int ctiArgumentInitSize = 4;#else // JIT_STUB_ARGUMENT_VA_LIST static const int ctiArgumentInitSize = 0;#endif#if PLATFORM(X86_64) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 10; static const int patchOffsetPutByIdPropertyMapOffset = 31; // These architecture specific value are used to enable patching - see comment on op_get_by_id. static const int patchOffsetGetByIdStructure = 10; static const int patchOffsetGetByIdBranchToSlowCase = 20; static const int patchOffsetGetByIdPropertyMapOffset = 31; static const int patchOffsetGetByIdPutResult = 31;#if ENABLE(OPCODE_SAMPLING) static const int patchOffsetGetByIdSlowCaseCall = 61 + ctiArgumentInitSize;#else static const int patchOffsetGetByIdSlowCaseCall = 38 + ctiArgumentInitSize;#endif static const int patchOffsetOpCallCompareToJump = 9;#else // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 7; static const int patchOffsetPutByIdPropertyMapOffset = 22; // These architecture specific value are used to enable patching - see comment on op_get_by_id. static const int patchOffsetGetByIdStructure = 7; static const int patchOffsetGetByIdBranchToSlowCase = 13; static const int patchOffsetGetByIdPropertyMapOffset = 22; static const int patchOffsetGetByIdPutResult = 22;#if ENABLE(OPCODE_SAMPLING) static const int patchOffsetGetByIdSlowCaseCall = 31 + ctiArgumentInitSize;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -