⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jitpropertyaccess.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * 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.  */#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 !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned){    // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.    // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump    // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label    // to jump back to if one of these trampolies finds a match.    emitGetVirtualRegister(baseVReg, regT0);    emitPutJITStubArg(regT0, 1);    emitPutJITStubArgConstant(ident, 2);    emitCTICall(JITStubs::cti_op_get_by_id_generic);    emitPutVirtualRegister(resultVReg);}void JIT::compileGetByIdSlowCase(int, int, Identifier*, Vector<SlowCaseEntry>::iterator&, unsigned){    ASSERT_NOT_REACHED();}void JIT::compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned){    // In order to be able to patch both the Structure, and the object offset, we store one pointer,    // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code    // such that the Structure & offset are always at the same distance from this.    emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);    emitPutJITStubArgConstant(ident, 2);    emitPutJITStubArg(regT0, 1);    emitPutJITStubArg(regT1, 3);    emitCTICall(JITStubs::cti_op_put_by_id_generic);}void JIT::compilePutByIdSlowCase(int, Identifier*, int, Vector<SlowCaseEntry>::iterator&, unsigned){    ASSERT_NOT_REACHED();}#elsevoid JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsigned propertyAccessInstructionIndex){    // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be patched.    // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump    // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label    // to jump back to if one of these trampolies finds a match.    emitGetVirtualRegister(baseVReg, regT0);    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);    Label hotPathBegin(this);    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;    DataLabelPtr structureToCompare;    Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)));    addSlowCase(structureCheck);    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure);    ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase);    loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);    DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0);    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset);    Label putResult(this);    ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult);    emitPutVirtualRegister(resultVReg);}void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex){    // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset    // so that we only need track one pointer into the slow case code - we track a pointer to the location    // of the call (which we can use to look up the patch information), but should a array-length or    // prototype access trampoline fail we want to bail out back to here.  To do so we can subtract back    // the distance from the call to the head of the slow case.    linkSlowCaseIfNotJSCell(iter, baseVReg);    linkSlowCase(iter);#ifndef NDEBUG    Label coldPathBegin(this);#endif    emitPutJITStubArg(regT0, 1);    emitPutJITStubArgConstant(ident, 2);    Call call = emitCTICall(JITStubs::cti_op_get_by_id);    emitPutVirtualRegister(resultVReg);    ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall);    // Track the location of the call; this will be used to recover patch information.    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;}void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsigned propertyAccessInstructionIndex){    // In order to be able to patch both the Structure, and the object offset, we store one pointer,    // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code    // such that the Structure & offset are always at the same distance from this.    emitGetVirtualRegisters(baseVReg, regT0, valueVReg, regT1);    // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);    Label hotPathBegin(this);    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;    // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.    DataLabelPtr structureToCompare;    addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, FIELD_OFFSET(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))));    ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure);    // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.    loadPtr(Address(regT0, FIELD_OFFSET(JSObject, m_propertyStorage)), regT0);    DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset));    ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset);}void JIT::compilePutByIdSlowCase(int baseVReg, Identifier* ident, int, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex){    linkSlowCaseIfNotJSCell(iter, baseVReg);    linkSlowCase(iter);    emitPutJITStubArgConstant(ident, 2);    emitPutJITStubArg(regT0, 1);    emitPutJITStubArg(regT1, 3);    Call call = emitCTICall(JITStubs::cti_op_put_by_id);    // Track the location of the call; this will be used to recover patch information.    m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;}static JSObject* resizePropertyStorage(JSObject* baseObject, int32_t oldSize, int32_t newSize){    baseObject->allocatePropertyStorage(oldSize, newSize);    return baseObject;}static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure){    return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();}void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ProcessorReturnAddress returnAddress){    JumpList failureCases;    // Check eax is an object of the right Structure.    failureCases.append(emitJumpIfNotJSCell(regT0));    failureCases.append(branchPtr(NotEqual, Address(regT0, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(oldStructure)));    JumpList successCases;    //  ecx = baseObject    loadPtr(Address(regT0, FIELD_OFFSET(JSCell, m_structure)), regT2);    // proto(ecx) = baseObject->structure()->prototype()    failureCases.append(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));    loadPtr(Address(regT2, FIELD_OFFSET(Structure, m_prototype)), regT2);        // ecx = baseObject->m_structure    for (RefPtr<Structure>* it = chain->head(); *it; ++it) {        // null check the prototype        successCases.append(branchPtr(Equal, regT2, ImmPtr(JSValuePtr::encode(jsNull()))));        // Check the structure id        failureCases.append(branchPtr(NotEqual, Address(regT2, FIELD_OFFSET(JSCell, m_structure)), ImmPtr(it->get())));                loadPtr(Address(regT2, FIELD_OFFSET(JSCell, m_structure)), regT2);        failureCases.append(branch32(NotEqual, Address(regT2, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));        loadPtr(Address(regT2, FIELD_OFFSET(Structure, m_prototype)), regT2);    }    successCases.link(this);    Call callTarget;    // emit a call only if storage realloc is needed    bool willNeedStorageRealloc = transitionWillNeedStorageRealloc(oldStructure, newStructure);    if (willNeedStorageRealloc) {        pop(X86::ebx);#if PLATFORM(X86_64)        move(Imm32(newStructure->propertyStorageCapacity()), regT1);        move(Imm32(oldStructure->propertyStorageCapacity()), X86::esi);        move(regT0, X86::edi);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -