📄 jit.cpp
字号:
/* * Copyright (C) 2008, 2009 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. */#include "config.h"#include "JIT.h"#if ENABLE(JIT)#include "CodeBlock.h"#include "JITInlineMethods.h"#include "JSArray.h"#include "JSFunction.h"#include "Interpreter.h"#include "ResultType.h"#include "SamplingTool.h"#ifndef NDEBUG#include <stdio.h>#endifusing namespace std;namespace JSC {#if COMPILER(GCC) && PLATFORM(X86)COMPILE_ASSERT(STUB_ARGS_code == 0x0C, STUB_ARGS_code_is_0x0C);COMPILE_ASSERT(STUB_ARGS_callFrame == 0x0E, STUB_ARGS_callFrame_is_0x0E);#if PLATFORM(DARWIN)#define SYMBOL_STRING(name) "_" #name#else#define SYMBOL_STRING(name) #name#endifasm(".globl " SYMBOL_STRING(ctiTrampoline) "\n"SYMBOL_STRING(ctiTrampoline) ":" "\n" "pushl %ebp" "\n" "movl %esp, %ebp" "\n" "pushl %esi" "\n" "pushl %edi" "\n" "pushl %ebx" "\n" "subl $0x1c, %esp" "\n" "movl $512, %esi" "\n" "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = STUB_ARGS_callFrame (see assertion above) "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above) "addl $0x1c, %esp" "\n" "popl %ebx" "\n" "popl %edi" "\n" "popl %esi" "\n" "popl %ebp" "\n" "ret" "\n");asm(".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"#if USE(JIT_STUB_ARGUMENT_VA_LIST) "call " SYMBOL_STRING(_ZN3JSC8JITStubs12cti_vm_throwEPvz) "\n"#else#if USE(JIT_STUB_ARGUMENT_REGISTER) "movl %esp, %ecx" "\n"#else // JIT_STUB_ARGUMENT_STACK "movl %esp, 0(%esp)" "\n"#endif "call " SYMBOL_STRING(_ZN3JSC8JITStubs12cti_vm_throwEPPv) "\n"#endif "addl $0x1c, %esp" "\n" "popl %ebx" "\n" "popl %edi" "\n" "popl %esi" "\n" "popl %ebp" "\n" "ret" "\n"); #elif COMPILER(GCC) && PLATFORM(X86_64)COMPILE_ASSERT(STUB_ARGS_code == 0x10, STUB_ARGS_code_is_0x10);COMPILE_ASSERT(STUB_ARGS_callFrame == 0x12, STUB_ARGS_callFrame_is_0x12);#if PLATFORM(DARWIN)#define SYMBOL_STRING(name) "_" #name#else#define SYMBOL_STRING(name) #name#endifasm(".globl " SYMBOL_STRING(ctiTrampoline) "\n"SYMBOL_STRING(ctiTrampoline) ":" "\n" "pushq %rbp" "\n" "movq %rsp, %rbp" "\n" "pushq %r12" "\n" "pushq %r13" "\n" "pushq %r14" "\n" "pushq %r15" "\n" "pushq %rbx" "\n" "subq $0x48, %rsp" "\n" "movq $512, %r12" "\n" "movq $0xFFFF000000000000, %r14" "\n" "movq $0xFFFF000000000002, %r15" "\n" "movq 0x90(%rsp), %r13" "\n" // Ox90 = 0x12 * 8, 0x12 = STUB_ARGS_callFrame (see assertion above) "call *0x80(%rsp)" "\n" // Ox80 = 0x10 * 8, 0x10 = STUB_ARGS_code (see assertion above) "addq $0x48, %rsp" "\n" "popq %rbx" "\n" "popq %r15" "\n" "popq %r14" "\n" "popq %r13" "\n" "popq %r12" "\n" "popq %rbp" "\n" "ret" "\n");asm(".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"#if USE(JIT_STUB_ARGUMENT_REGISTER) "movq %rsp, %rdi" "\n" "call " SYMBOL_STRING(_ZN3JSC8JITStubs12cti_vm_throwEPPv) "\n"#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK#error "JIT_STUB_ARGUMENT configuration not supported."#endif "addq $0x48, %rsp" "\n" "popq %rbx" "\n" "popq %r15" "\n" "popq %r14" "\n" "popq %r13" "\n" "popq %r12" "\n" "popq %rbp" "\n" "ret" "\n"); #elif COMPILER(MSVC)extern "C" { __declspec(naked) JSValueEncodedAsPointer* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*) { __asm { push ebp; mov ebp, esp; push esi; push edi; push ebx; sub esp, 0x1c; mov esi, 512; mov ecx, esp; mov edi, [esp + 0x38]; call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = STUB_ARGS_code (see assertion above) add esp, 0x1c; pop ebx; pop edi; pop esi; pop ebp; ret; } } __declspec(naked) void ctiVMThrowTrampoline() { __asm {#if USE(JIT_STUB_ARGUMENT_REGISTER) mov ecx, esp;#else // JIT_STUB_ARGUMENT_VA_LIST or JIT_STUB_ARGUMENT_STACK#error "JIT_STUB_ARGUMENT configuration not supported."#endif call JSC::JITStubs::cti_vm_throw; add esp, 0x1c; pop ebx; pop edi; pop esi; pop ebp; ret; } } }#endifvoid ctiSetReturnAddress(void** addressOfReturnAddress, void* newDestinationToReturnTo){ *addressOfReturnAddress = newDestinationToReturnTo;}void ctiPatchCallByReturnAddress(MacroAssembler::ProcessorReturnAddress returnAddress, void* newCalleeFunction){ returnAddress.relinkCallerToFunction(newCalleeFunction);}void ctiPatchNearCallByReturnAddress(MacroAssembler::ProcessorReturnAddress returnAddress, void* newCalleeFunction){ returnAddress.relinkNearCallerToFunction(newCalleeFunction);}JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock) : m_interpreter(globalData->interpreter) , m_globalData(globalData) , m_codeBlock(codeBlock) , m_labels(codeBlock ? codeBlock->instructions().size() : 0) , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0) , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0) , m_lastResultBytecodeRegister(std::numeric_limits<int>::max()) , m_jumpTargetsPosition(0){}void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type){ unsigned dst = currentInstruction[1].u.operand; unsigned src1 = currentInstruction[2].u.operand; unsigned src2 = currentInstruction[3].u.operand; emitGetVirtualRegisters(src1, regT0, src2, regT1); // Jump to a slow case if either operand is a number, or if both are JSCell*s. move(regT0, regT2); orPtr(regT1, regT2); addSlowCase(emitJumpIfJSCell(regT2)); addSlowCase(emitJumpIfImmediateNumber(regT2)); if (type == OpStrictEq) set32(Equal, regT1, regT0, regT0); else set32(NotEqual, regT1, regT0, regT0); emitTagAsBoolImmediate(regT0); emitPutVirtualRegister(dst);}void JIT::emitTimeoutCheck(){ Jump skipTimeout = branchSub32(NonZero, Imm32(1), timeoutCheckRegister); emitCTICall(JITStubs::cti_timeout_check); move(regT0, timeoutCheckRegister); skipTimeout.link(this); killLastResultRegister();}#define NEXT_OPCODE(name) \ m_bytecodeIndex += OPCODE_LENGTH(name); \ break;#define CTI_COMPILE_BINARY_OP(name) \ case name: { \ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); \ emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, regT2); \ emitCTICall(JITStubs::cti_##name); \ emitPutVirtualRegister(currentInstruction[1].u.operand); \ NEXT_OPCODE(name); \ }#define CTI_COMPILE_UNARY_OP(name) \ case name: { \ emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, regT2); \ emitCTICall(JITStubs::cti_##name); \ emitPutVirtualRegister(currentInstruction[1].u.operand); \ NEXT_OPCODE(name); \ }#define RECORD_JUMP_TARGET(targetOffset) \ do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)void JIT::privateCompileMainPass(){ Instruction* instructionsBegin = m_codeBlock->instructions().begin(); unsigned instructionCount = m_codeBlock->instructions().size(); unsigned propertyAccessInstructionIndex = 0; unsigned globalResolveInfoIndex = 0; unsigned callLinkInfoIndex = 0; for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) { Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex; ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -