Ignore:
Timestamp:
Jul 22, 2009, 3:17:10 PM (16 years ago)
Author:
[email protected]
Message:

2009-07-22 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

With ENABLE(ASSEMBLER_WX_EXCLUSIVE), only change permissions once per repatch event.
( https://bugs.webkit.org/show_bug.cgi?id=27564 )

Currently we change permissions forwards and backwards for each instruction modified,
instead we should only change permissions once per complete repatching event.

2.5% progression running with ENABLE(ASSEMBLER_WX_EXCLUSIVE) enabled,
which recoups 1/3 of the penalty of running with this mode enabled.

  • assembler/ARMAssembler.cpp: (JSC::ARMAssembler::linkBranch):
    • Replace usage of MakeWritable with cacheFlush.


  • assembler/ARMAssembler.h: (JSC::ARMAssembler::patchPointerInternal): (JSC::ARMAssembler::repatchLoadPtrToLEA):
    • Replace usage of MakeWritable with cacheFlush.
  • assembler/ARMv7Assembler.h: (JSC::ARMv7Assembler::relinkJump): (JSC::ARMv7Assembler::relinkCall): (JSC::ARMv7Assembler::repatchInt32): (JSC::ARMv7Assembler::repatchPointer): (JSC::ARMv7Assembler::repatchLoadPtrToLEA): (JSC::ARMv7Assembler::setInt32):
    • Replace usage of MakeWritable with cacheFlush.
  • assembler/LinkBuffer.h: (JSC::LinkBuffer::performFinalization):
    • Make explicit call to cacheFlush.
  • assembler/MacroAssemblerCodeRef.h: (JSC::MacroAssemblerCodeRef::MacroAssemblerCodeRef):
    • Make size always available.
  • assembler/RepatchBuffer.h: (JSC::RepatchBuffer::RepatchBuffer): (JSC::RepatchBuffer::~RepatchBuffer):
    • Add calls to MakeWritable & makeExecutable.
  • assembler/X86Assembler.h: (JSC::X86Assembler::relinkJump): (JSC::X86Assembler::relinkCall): (JSC::X86Assembler::repatchInt32): (JSC::X86Assembler::repatchPointer): (JSC::X86Assembler::repatchLoadPtrToLEA):
    • Remove usage of MakeWritable.
  • bytecode/CodeBlock.h: (JSC::CodeBlock::getJITCode):
    • Provide access to CodeBlock's JITCode.
  • jit/ExecutableAllocator.h: (JSC::ExecutableAllocator::makeExecutable): (JSC::ExecutableAllocator::cacheFlush):
    • Remove MakeWritable, make cacheFlush public.
  • jit/JIT.cpp: (JSC::ctiPatchNearCallByReturnAddress): (JSC::ctiPatchCallByReturnAddress): (JSC::JIT::privateCompile): (JSC::JIT::unlinkCall): (JSC::JIT::linkCall):
    • Add CodeBlock argument to RepatchBuffer.
  • jit/JIT.h:
    • Pass CodeBlock argument for use by RepatchBuffer.
  • jit/JITCode.h: (JSC::JITCode::start): (JSC::JITCode::size):
    • Provide access to code start & size.
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchMethodCallProto): (JSC::JIT::patchPutByIdReplace): (JSC::JIT::privateCompilePatchGetArrayLength): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain):
    • Add CodeBlock argument to RepatchBuffer.
  • jit/JITStubs.cpp: (JSC::JITThunks::tryCachePutByID): (JSC::JITThunks::tryCacheGetByID): (JSC::JITStubs::DEFINE_STUB_FUNCTION):
    • Pass CodeBlock argument for use by RepatchBuffer.
File:
1 edited

Legend:

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

    r45039 r46247  
    359359    // Uncacheable: give up.
    360360    if (!slot.isCacheable()) {
    361         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
     361        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
    362362        return;
    363363    }
     
    367367
    368368    if (structure->isDictionary()) {
    369         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
     369        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
    370370        return;
    371371    }
     
    373373    // If baseCell != base, then baseCell must be a proxy for another object.
    374374    if (baseCell != slot.base()) {
    375         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
     375        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
    376376        return;
    377377    }
     
    385385        StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    386386        if (!prototypeChain->isCacheable()) {
    387             ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
     387            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_put_by_id_generic));
    388388            return;
    389389        }
     
    395395    stubInfo->initPutByIdReplace(structure);
    396396
    397     JIT::patchPutByIdReplace(stubInfo, structure, slot.cachedOffset(), returnAddress);
     397    JIT::patchPutByIdReplace(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
    398398}
    399399
     
    405405    // FIXME: Cache property access for immediates.
    406406    if (!baseValue.isCell()) {
    407         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
     407        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
    408408        return;
    409409    }
     
    419419        // The tradeoff of compiling an patched inline string length access routine does not seem
    420420        // to pay off, so we currently only do this for arrays.
    421         ctiPatchCallByReturnAddress(returnAddress, globalData->jitStubs.ctiStringLengthTrampoline());
     421        ctiPatchCallByReturnAddress(codeBlock, returnAddress, globalData->jitStubs.ctiStringLengthTrampoline());
    422422        return;
    423423    }
     
    425425    // Uncacheable: give up.
    426426    if (!slot.isCacheable()) {
    427         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
     427        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
    428428        return;
    429429    }
     
    433433
    434434    if (structure->isDictionary()) {
    435         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
     435        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
    436436        return;
    437437    }
     
    448448        stubInfo->initGetByIdSelf(structure);
    449449
    450         JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress);
     450        JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress);
    451451        return;
    452452    }
     
    476476    StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    477477    if (!prototypeChain->isCacheable()) {
    478         ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
     478        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(JITStubs::cti_op_get_by_id_generic));
    479479        return;
    480480    }
     
    778778    stackFrame.args[0].jsValue().put(callFrame, ident, stackFrame.args[2].jsValue(), slot);
    779779
    780     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second));
     780    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_id_second));
    781781
    782782    CHECK_FOR_EXCEPTION_AT_END();
     
    832832    JSValue result = baseValue.get(callFrame, ident, slot);
    833833
    834     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second));
     834    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_second));
    835835
    836836    CHECK_FOR_EXCEPTION_AT_END();
     
    849849    JSValue result = baseValue.get(callFrame, ident, slot);
    850850
    851     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second));
     851    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_method_check_second));
    852852
    853853    CHECK_FOR_EXCEPTION_AT_END();
     
    901901        // Check to see if the function is on the object's prototype.  Patch up the code to optimize.
    902902        if (slot.slotBase() == structure->prototypeForLookup(callFrame))
    903             JIT::patchMethodCallProto(methodCallLinkInfo, callee, structure, slotBaseObject);
     903            JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, slotBaseObject);
    904904        // Check to see if the function is on the object itself.
    905905        // Since we generate the method-check to check both the structure and a prototype-structure (since this
     
    909909        // purpose.  The object is in no way exposed, and as such the check will always pass.
    910910        else if (slot.slotBase() == baseValue)
    911             JIT::patchMethodCallProto(methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy());
     911            JIT::patchMethodCallProto(callFrame->codeBlock(), methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy());
    912912
    913913        // For now let any other case be cached as a normal get_by_id.
     
    915915
    916916    // Revert the get_by_id op back to being a regular get_by_id - allow it to cache like normal, if it needs to.
    917     ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
     917    ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id));
    918918
    919919    return JSValue::encode(result);
     
    976976
    977977        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
    978             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
    979     } else {
    980         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
    981     }
     978            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
     979    } else
     980        ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic));
    982981    return JSValue::encode(result);
    983982}
     
    10251024
    10261025    if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
    1027         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     1026        ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    10281027        return JSValue::encode(result);
    10291028    }
     
    10371036
    10381037    if (slot.slotBase() == baseValue)
    1039         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     1038        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    10401039    else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) {
    10411040        // Since we're accessing a prototype in a loop, it's a good bet that it
     
    10501049
    10511050        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
    1052             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
     1051            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
    10531052    } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) {
    10541053        StructureChain* protoChain = structure->prototypeChain(callFrame);
    10551054        if (!protoChain->isCacheable()) {
    1056             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     1055            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    10571056            return JSValue::encode(result);
    10581057        }
     
    10631062
    10641063        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
    1065             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
     1064            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
    10661065    } else
    1067         ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     1066        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    10681067
    10691068    return JSValue::encode(result);
     
    12721271    JSFunction* callee = asFunction(stackFrame.args[0].jsValue());
    12731272
    1274     ctiPatchNearCallByReturnAddress(stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());
     1273    ctiPatchNearCallByReturnAddress(stackFrame.callFrame->callerFrame()->codeBlock(), stackFrame.args[1].returnAddress(), globalData->jitStubs.ctiVirtualCallLink());
    12751274
    12761275    return callee->body()->generatedJITCode().addressForCall().executableAddress();
     
    12911290
    12921291    CallLinkInfo* callLinkInfo = &stackFrame.callFrame->callerFrame()->codeBlock()->getCallLinkInfo(stackFrame.args[1].returnAddress());
    1293     JIT::linkCall(callee, codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
     1292    JIT::linkCall(callee, stackFrame.callFrame->callerFrame()->codeBlock(), codeBlock, jitCode, callLinkInfo, stackFrame.args[2].int32(), stackFrame.globalData);
    12941293
    12951294    return jitCode.addressForCall().executableAddress();
     
    15311530        } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) {
    15321531            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
    1533             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
     1532            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string));
    15341533            result = asString(baseValue)->getIndex(stackFrame.globalData, i);
    15351534        } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
    15361535            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
    1537             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
     1536            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array));
    15381537            return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i));
    15391538        } else
     
    15671566            result = baseValue.get(callFrame, i);
    15681567            if (!isJSString(globalData, baseValue))
    1569                 ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
     1568                ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
    15701569        }
    15711570    } else {
     
    16001599        result = baseValue.get(callFrame, i);
    16011600        if (!isJSByteArray(globalData, baseValue))
    1602             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
     1601            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val));
    16031602    } else {
    16041603        Identifier property(callFrame, subscript.toString(callFrame));
     
    16931692        } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
    16941693            JSByteArray* jsByteArray = asByteArray(baseValue);
    1695             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
     1694            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array));
    16961695            // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks.
    16971696            if (value.isInt32Fast()) {
     
    17771776
    17781777        if (!isJSByteArray(globalData, baseValue))
    1779             ctiPatchCallByReturnAddress(STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
     1778            ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val));
    17801779        baseValue.put(callFrame, i, value);
    17811780    } else {
Note: See TracChangeset for help on using the changeset viewer.