Changeset 37831 in webkit for trunk/JavaScriptCore/VM/CodeBlock.h


Ignore:
Timestamp:
Oct 23, 2008, 3:29:54 PM (17 years ago)
Author:
[email protected]
Message:

2008-10-23 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Fix hideous pathological case performance when looking up repatch info, bug #21727.

When repatching JIT code to optimize we look up records providing information about
the generated code (also used to track recsources used in linking to be later released).
The lookup was being performed using a linear scan of all such records.

(1) Split up the different types of reptach information. This means we can search them

separately, and in some cases should reduce their size.

(2) In the case of property accesses, search with a binary chop over the data.
(3) In the case of calls, pass a pointer to the repatch info into the relink function.

  • VM/CTI.cpp: (JSC::CTI::CTI): (JSC::CTI::compileOpCall): (JSC::CTI::privateCompileMainPass): (JSC::CTI::privateCompileSlowCases): (JSC::CTI::privateCompile): (JSC::CTI::unlinkCall): (JSC::CTI::linkCall):
  • VM/CTI.h:
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::~CodeBlock): (JSC::CodeBlock::unlinkCallers): (JSC::CodeBlock::derefStructureIDs):
  • VM/CodeBlock.h: (JSC::StructureStubInfo::StructureStubInfo): (JSC::CallLinkInfo::CallLinkInfo): (JSC::CallLinkInfo::setUnlinked): (JSC::CallLinkInfo::isLinked): (JSC::getStructureStubInfoReturnLocation): (JSC::binaryChop): (JSC::CodeBlock::addCaller): (JSC::CodeBlock::getStubInfo):
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitResolve): (JSC::CodeGenerator::emitGetById): (JSC::CodeGenerator::emitPutById): (JSC::CodeGenerator::emitCall): (JSC::CodeGenerator::emitConstruct):
  • VM/Machine.cpp: (JSC::Machine::cti_vm_lazyLinkCall):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/CodeBlock.h

    r37684 r37831  
    7979    };
    8080
    81     struct CallLinkInfo;
    82 
    8381    struct StructureStubInfo {
    8482        StructureStubInfo(unsigned opcodeIndex)
     
    8785            , callReturnLocation(0)
    8886            , hotPathBegin(0)
    89             , hotPathOther(0)
    90             , coldPathOther(0)
    91             , linkInfoPtr(0)
    9287        {
    9388        }
     
    9792        void* callReturnLocation;
    9893        void* hotPathBegin;
     94    };
     95
     96    struct CallLinkInfo {
     97        CallLinkInfo()
     98            : callReturnLocation(0)
     99            , hotPathBegin(0)
     100            , hotPathOther(0)
     101            , coldPathOther(0)
     102            , callee(0)
     103        {
     104        }
     105   
     106        unsigned opcodeIndex;
     107        void* callReturnLocation;
     108        void* hotPathBegin;
    99109        void* hotPathOther;
    100110        void* coldPathOther;
    101         CallLinkInfo* linkInfoPtr;
    102     };
    103 
    104     struct CallLinkInfo {
    105111        CodeBlock* callee;
    106         StructureStubInfo* callerStructureStubInfo;
    107112        unsigned position;
    108 
    109         CallLinkInfo(CodeBlock* c, StructureStubInfo* css)
    110         {
    111             callee = c;
    112             callerStructureStubInfo = css;
    113         }
    114     };
     113       
     114        void setUnlinked() { callee = 0; }
     115        bool isLinked() { return callee; }
     116    };
     117
     118    inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
     119    {
     120        return structureStubInfo->callReturnLocation;
     121    }
     122
     123    // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
     124    // compares result with key (KeyTypes should be comparable with '--', '<', '>').
     125    // Optimized for cases where the array contains the key, checked by assertions.
     126    template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
     127    inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
     128    {
     129        // The array must contain at least one element (pre-condition, array does conatin key).
     130        // If the array only contains one element, no need to do the comparison.
     131        while (size > 1) {
     132            // Pick an element to check, half way through the array, and read the value.
     133            int pos = (size - 1) >> 1;
     134            KeyType val = valueAtPosition(&array[pos]);
     135           
     136            // If the key matches, success!
     137            if (val == key)
     138                return &array[pos];
     139            // The item we are looking for is smaller than the item being check; reduce the value of 'size',
     140            // chopping off the right hand half of the array.
     141            else if (key < val)
     142                size = pos;
     143            // Discard all values in the left hand half of the array, up to and including the item at pos.
     144            else {
     145                size -= (pos + 1);
     146                array += (pos + 1);
     147            }
     148
     149            // 'size' should never reach zero.
     150            ASSERT(size);
     151        }
     152       
     153        // If we reach this point we've chopped down to one element, no need to check it matches
     154        ASSERT(size == 1);
     155        ASSERT(key == valueAtPosition(&array[0]));
     156        return &array[0];
     157    }
    115158
    116159    struct StringJumpTable {
     
    228271#endif
    229272
    230         void addCaller(StructureStubInfo* caller)
    231         {
    232             CallLinkInfo* callLinkInfo = new CallLinkInfo(this, caller);
    233             caller->linkInfoPtr = callLinkInfo;
    234             callLinkInfo->position = linkedCallerList.size();
    235             linkedCallerList.append(callLinkInfo);
     273        void addCaller(CallLinkInfo* caller)
     274        {
     275            caller->callee = this;
     276            caller->position = linkedCallerList.size();
     277            linkedCallerList.append(caller);
    236278        }
    237279
     
    264306        StructureStubInfo& getStubInfo(void* returnAddress)
    265307        {
    266             // FIXME: would a binary chop be faster here?
    267             for (unsigned i = 0; ; ++i) {
    268                 ASSERT(i < structureIDInstructions.size());
    269                 if (structureIDInstructions[i].callReturnLocation == returnAddress)
    270                     return structureIDInstructions[i];
    271             }
     308            return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(propertyAccessInstructions.begin(), propertyAccessInstructions.size(), returnAddress));
    272309        }
    273310
     
    296333
    297334        Vector<Instruction> instructions;
    298         Vector<StructureStubInfo> structureIDInstructions;
     335        Vector<unsigned> globalResolveInstructions;
     336        Vector<StructureStubInfo> propertyAccessInstructions;
     337        Vector<CallLinkInfo> callLinkInfos;
    299338        Vector<CallLinkInfo*> linkedCallerList;
    300339
Note: See TracChangeset for help on using the changeset viewer.