Ignore:
Timestamp:
Aug 6, 2009, 8:05:42 PM (16 years ago)
Author:
[email protected]
Message:

2009-08-06 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Make get_by_id/put_by_id/method_check/call defer optimization using a data flag rather than a code modification.
( https://bugs.webkit.org/show_bug.cgi?id=27635 )

This improves performance of ENABLE(ASSEMBLER_WX_EXCLUSIVE) builds by 2-2.5%, reducing the overhead to about 2.5%.
(No performance impact with ASSEMBLER_WX_EXCLUSIVE disabled).

  • bytecode/CodeBlock.cpp: (JSC::printStructureStubInfo):
    • Make StructureStubInfo store the type as an integer, rather than an OpcodeID.
  • bytecode/CodeBlock.h: (JSC::): (JSC::CallLinkInfo::seenOnce): (JSC::CallLinkInfo::setSeen): (JSC::MethodCallLinkInfo::seenOnce): (JSC::MethodCallLinkInfo::setSeen):
    • Change a pointer in CallLinkInfo/MethodCallLinkInfo to use a PtrAndFlags, use a flag to track when an op has been executed once.
  • bytecode/StructureStubInfo.cpp: (JSC::StructureStubInfo::deref):
    • Make StructureStubInfo store the type as an integer, rather than an OpcodeID.
  • bytecode/StructureStubInfo.h: (JSC::StructureStubInfo::StructureStubInfo): (JSC::StructureStubInfo::initGetByIdSelf): (JSC::StructureStubInfo::initGetByIdProto): (JSC::StructureStubInfo::initGetByIdChain): (JSC::StructureStubInfo::initGetByIdSelfList): (JSC::StructureStubInfo::initGetByIdProtoList): (JSC::StructureStubInfo::initPutByIdTransition): (JSC::StructureStubInfo::initPutByIdReplace): (JSC::StructureStubInfo::seenOnce): (JSC::StructureStubInfo::setSeen):
    • Make StructureStubInfo store the type as an integer, rather than an OpcodeID, add a flag to track when an op has been executed once.
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitGetById): (JSC::BytecodeGenerator::emitPutById):
    • Make StructureStubInfo store the type as an integer, rather than an OpcodeID.
  • jit/JIT.cpp: (JSC::JIT::privateCompileCTIMachineTrampolines): (JSC::JIT::unlinkCall):
    • Remove the "don't lazy link" stage of calls.
  • jit/JIT.h: (JSC::JIT::compileCTIMachineTrampolines):
    • Remove the "don't lazy link" stage of calls.
  • jit/JITCall.cpp: (JSC::JIT::compileOpCallSlowCase):
    • Remove the "don't lazy link" stage of calls.
  • jit/JITStubs.cpp: (JSC::JITThunks::JITThunks): (JSC::JITThunks::tryCachePutByID): (JSC::JITThunks::tryCacheGetByID): (JSC::JITStubs::DEFINE_STUB_FUNCTION): (JSC::JITStubs::getPolymorphicAccessStructureListSlot):
    • Remove the "don't lazy link" stage of calls, and the "_second" stage of get_by_id/put_by_id/method_check.
  • jit/JITStubs.h: (JSC::JITThunks::ctiStringLengthTrampoline): (JSC::JITStubs::):
    • Remove the "don't lazy link" stage of calls, and the "_second" stage of get_by_id/put_by_id/method_check.
  • wtf/PtrAndFlags.h: (WTF::PtrAndFlags::PtrAndFlags): (WTF::PtrAndFlags::operator!): (WTF::PtrAndFlags::operator->):
    • Add ! and -> operators, add constuctor with pointer argument.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r46831 r46879  
    635635JITThunks::JITThunks(JSGlobalData* globalData)
    636636{
    637     JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallPreLink, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
     637    JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk);
    638638
    639639#if PLATFORM_ARM_ARCH(7)
     
    658658#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    659659
    660 NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot)
     660NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot& slot, StructureStubInfo* stubInfo)
    661661{
    662662    // The interpreter checks for recursion here; I do not believe this can occur in CTI.
     
    684684        return;
    685685    }
    686 
    687     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
    688686
    689687    // Cache hit: Specialize instruction and ref Structures.
     
    706704}
    707705
    708 NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot)
     706NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
    709707{
    710708    // FIXME: Write a test that proves we need to check for recursion here just
     
    744742        return;
    745743    }
    746 
    747     // In the interpreter the last structure is trapped here; in CTI we use the
    748     // *_second method to achieve a similar (but not quite the same) effect.
    749 
    750     StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
    751744
    752745    // Cache hit: Specialize instruction and ref Structures.
     
    778771    size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
    779772    if (!count) {
    780         stubInfo->opcodeID = op_get_by_id_generic;
     773        stubInfo->accessType = access_get_by_id_generic;
    781774        return;
    782775    }
     
    10771070{
    10781071    STUB_INIT_STACK_FRAME(stackFrame);
    1079 
    10801072    CallFrame* callFrame = stackFrame.callFrame;
    10811073    Identifier& ident = stackFrame.args[1].identifier();
     
    10841076    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    10851077
    1086     ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second));
    1087 
    1088     CHECK_FOR_EXCEPTION_AT_END();
    1089 }
    1090 
    1091 DEFINE_STUB_FUNCTION(void, op_put_by_id_second)
    1092 {
    1093     STUB_INIT_STACK_FRAME(stackFrame);
    1094 
    1095     PutPropertySlot slot;
    1096     stackFrame.args[0].jsValue().put(stackFrame.callFrame, stackFrame.args[1].identifier(), stackFrame.args[2].jsValue(), slot);
    1097     JITThunks::tryCachePutByID(stackFrame.callFrame, stackFrame.callFrame->codeBlock(), STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot);
     1078    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     1079    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     1080    if (!stubInfo->seenOnce())
     1081        stubInfo->setSeen();
     1082    else
     1083        JITThunks::tryCachePutByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, stackFrame.args[0].jsValue(), slot, stubInfo);
     1084
    10981085    CHECK_FOR_EXCEPTION_AT_END();
    10991086}
     
    11271114}
    11281115
    1129 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
     1116DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
    11301117{
    11311118    STUB_INIT_STACK_FRAME(stackFrame);
     
    11371124    PropertySlot slot(baseValue);
    11381125    JSValue result = baseValue.get(callFrame, ident, slot);
    1139 
    1140     ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second));
    1141 
    1142     CHECK_FOR_EXCEPTION_AT_END();
    1143     return JSValue::encode(result);
    1144 }
    1145 
    1146 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check)
    1147 {
    1148     STUB_INIT_STACK_FRAME(stackFrame);
    1149 
    1150     CallFrame* callFrame = stackFrame.callFrame;
    1151     Identifier& ident = stackFrame.args[1].identifier();
    1152 
    1153     JSValue baseValue = stackFrame.args[0].jsValue();
    1154     PropertySlot slot(baseValue);
    1155     JSValue result = baseValue.get(callFrame, ident, slot);
    1156 
    1157     ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second));
    1158 
    1159     CHECK_FOR_EXCEPTION_AT_END();
    1160     return JSValue::encode(result);
    1161 }
    1162 
    1163 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_second)
    1164 {
    1165     STUB_INIT_STACK_FRAME(stackFrame);
    1166 
    1167     CallFrame* callFrame = stackFrame.callFrame;
    1168     Identifier& ident = stackFrame.args[1].identifier();
    1169 
    1170     JSValue baseValue = stackFrame.args[0].jsValue();
    1171     PropertySlot slot(baseValue);
    1172     JSValue result = baseValue.get(callFrame, ident, slot);
    1173 
    11741126    CHECK_FOR_EXCEPTION();
     1127
     1128    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     1129    MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
     1130
     1131    if (!methodCallLinkInfo.seenOnce()) {
     1132        methodCallLinkInfo.setSeen();
     1133        return JSValue::encode(result);
     1134    }
    11751135
    11761136    // If we successfully got something, then the base from which it is being accessed must
     
    12031163        // The result fetched should always be the callee!
    12041164        ASSERT(result == JSValue(callee));
    1205         MethodCallLinkInfo& methodCallLinkInfo = callFrame->codeBlock()->getMethodCallLinkInfo(STUB_RETURN_ADDRESS);
    12061165
    12071166        // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
    1208         if (slot.slotBase() == structure->prototypeForLookup(callFrame))
    1209             JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject);
     1167        if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
     1168            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS);
     1169            return JSValue::encode(result);
     1170        }
     1171
    12101172        // Check to see if the function is on the object itself.
    12111173        // Since we generate the method-check to check both the structure and a prototype-structure (since this
     
    12141176        // for now.  For now it performs a check on a special object on the global object only used for this
    12151177        // purpose.  The object is in no way exposed, and as such the check will always pass.
    1216         else if (slot.slotBase() == baseValue)
    1217             JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy());
    1218 
    1219         // For now let any other case be cached as a normal get_by_id.
     1178        if (slot.slotBase() == baseValue) {
     1179            JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy(), STUB_RETURN_ADDRESS);
     1180            return JSValue::encode(result);
     1181        }
    12201182    }
    12211183
    12221184    // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
    1223     ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
    1224 
    1225     return JSValue::encode(result);
    1226 }
    1227 
    1228 DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_second)
    1229 {
    1230     STUB_INIT_STACK_FRAME(stackFrame);
    1231 
     1185    ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
     1186    return JSValue::encode(result);
     1187}
     1188
     1189DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id)
     1190{
     1191    STUB_INIT_STACK_FRAME(stackFrame);
    12321192    CallFrame* callFrame = stackFrame.callFrame;
    12331193    Identifier& ident = stackFrame.args[1].identifier();
     
    12371197    JSValue result = baseValue.get(callFrame, ident, slot);
    12381198
    1239     JITThunks::tryCacheGetByID(callFrame, callFrame->codeBlock(), STUB_RETURN_ADDRESS, baseValue, ident, slot);
     1199    CodeBlock* codeBlock = stackFrame.callFrame->codeBlock();
     1200    StructureStubInfo* stubInfo = &codeBlock->getStubInfo(STUB_RETURN_ADDRESS);
     1201    if (!stubInfo->seenOnce())
     1202        stubInfo->setSeen();
     1203    else
     1204        JITThunks::tryCacheGetByID(callFrame, codeBlock, STUB_RETURN_ADDRESS, baseValue, ident, slot, stubInfo);
    12401205
    12411206    CHECK_FOR_EXCEPTION_AT_END();
     
    12691234        int listIndex = 1;
    12701235
    1271         if (stubInfo->opcodeID == op_get_by_id_self) {
     1236        if (stubInfo->accessType == access_get_by_id_self) {
    12721237            ASSERT(!stubInfo->stubRoutine);
    12731238            polymorphicStructureList = new PolymorphicAccessStructureList(CodeLocationLabel(), stubInfo->u.getByIdSelf.baseObjectStructure);
     
    12931258    listIndex = 1;
    12941259
    1295     switch (stubInfo->opcodeID) {
    1296     case op_get_by_id_proto:
     1260    switch (stubInfo->accessType) {
     1261    case access_get_by_id_proto:
    12971262        prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
    12981263        stubInfo->stubRoutine = CodeLocationLabel();
    12991264        stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
    13001265        break;
    1301     case op_get_by_id_chain:
     1266    case access_get_by_id_chain:
    13021267        prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
    13031268        stubInfo->stubRoutine = CodeLocationLabel();
    13041269        stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
    13051270        break;
    1306     case op_get_by_id_proto_list:
     1271    case access_get_by_id_proto_list:
    13071272        prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
    13081273        listIndex = stubInfo->u.getByIdProtoList.listSize;
     
    15711536
    15721537#if ENABLE(JIT_OPTIMIZE_CALL)
    1573 DEFINE_STUB_FUNCTION(void*, vm_dontLazyLinkCall)
    1574 {
    1575     STUB_INIT_STACK_FRAME(stackFrame);
    1576 
    1577     JSGlobalData* globalData = stackFrame.globalData;
    1578     JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
    1579 
    1580     ctiPatchNearCallByReturnAddress(stackFrame.callFrame->callerFrame()->codeBlock(), stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());
    1581 
    1582     return callee->body()->generatedJITCode().addressForCall().executableAddress();
    1583 }
    1584 
    15851538DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
    15861539{
    15871540    STUB_INIT_STACK_FRAME(stackFrame);
    1588 
    15891541    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
    15901542    JITCode& jitCode = callee->body()->generatedJITCode();
     
    15951547    else
    15961548        codeBlock = &callee->body()->generatedBytecode();
    1597 
    15981549    CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
    1599     JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
     1550
     1551    if (!callLinkInfo->seenOnce())
     1552        callLinkInfo->setSeen();
     1553    else
     1554        JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
    16001555
    16011556    return jitCode.addressForCall().executableAddress();
Note: See TracChangeset for help on using the changeset viewer.