Ignore:
Timestamp:
Nov 11, 2008, 12:06:11 PM (17 years ago)
Author:
[email protected]
Message:

2008-11-11 Cameron Zwarich <[email protected]>

Rubber-stamped by Sam Weinig.

Bug 22179: Move EvalCodeCache from CodeBlock.h into its own file
<https://bugs.webkit.org/show_bug.cgi?id=22179>

  • GNUmakefile.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • VM/CodeBlock.h:
  • VM/EvalCodeCache.h: Copied from VM/CodeBlock.h.
  • VM/Machine.cpp:
File:
1 copied

Legend:

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

    r38302 r38311  
    11/*
    22 * Copyright (C) 2008 Apple Inc. All rights reserved.
    3  * Copyright (C) 2008 Cameron Zwarich <[email protected]>
    43 *
    54 * Redistribution and use in source and binary forms, with or without
     
    2827 */
    2928
    30 #ifndef CodeBlock_h
    31 #define CodeBlock_h
     29#ifndef EvalCodeCache_h
     30#define EvalCodeCache_h
    3231
    33 #include "Instruction.h"
    3432#include "JSGlobalObject.h"
    3533#include "Nodes.h"
    3634#include "Parser.h"
    37 #include "RegExp.h"
    3835#include "SourceCode.h"
    3936#include "UString.h"
     37#include <wtf/HashMap.h>
    4038#include <wtf/RefPtr.h>
    41 #include <wtf/Vector.h>
    4239
    4340namespace JSC {
    44 
    45     class ExecState;
    46 
    47     enum CodeType { GlobalCode, EvalCode, FunctionCode };
    48 
    49     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
    50 
    51     struct HandlerInfo {
    52         uint32_t start;
    53         uint32_t end;
    54         uint32_t target;
    55         uint32_t scopeDepth;
    56         void* nativeCode;
    57     };
    58 
    59     struct ExpressionRangeInfo {
    60         enum {
    61             MaxOffset = (1 << 7) - 1,
    62             MaxDivot = (1 << 25) - 1
    63         };
    64         uint32_t instructionOffset : 25;
    65         uint32_t divotPoint : 25;
    66         uint32_t startOffset : 7;
    67         uint32_t endOffset : 7;
    68     };
    69 
    70     struct LineInfo {
    71         uint32_t instructionOffset;
    72         int32_t lineNumber;
    73     };
    74 
    75     struct OffsetLocation {
    76         int32_t branchOffset;
    77 #if ENABLE(CTI)
    78         void* ctiOffset;
    79 #endif
    80     };
    81 
    82     struct StructureStubInfo {
    83         StructureStubInfo(unsigned opcodeIndex)
    84             : opcodeIndex(opcodeIndex)
    85             , stubRoutine(0)
    86             , callReturnLocation(0)
    87             , hotPathBegin(0)
    88         {
    89         }
    90    
    91         unsigned opcodeIndex;
    92         void* stubRoutine;
    93         void* callReturnLocation;
    94         void* hotPathBegin;
    95     };
    96 
    97     struct CallLinkInfo {
    98         CallLinkInfo()
    99             : callReturnLocation(0)
    100             , hotPathBegin(0)
    101             , hotPathOther(0)
    102             , coldPathOther(0)
    103             , callee(0)
    104         {
    105         }
    106    
    107         unsigned opcodeIndex;
    108         void* callReturnLocation;
    109         void* hotPathBegin;
    110         void* hotPathOther;
    111         void* coldPathOther;
    112         CodeBlock* callee;
    113         unsigned position;
    114        
    115         void setUnlinked() { callee = 0; }
    116         bool isLinked() { return callee; }
    117     };
    118 
    119     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
    120     {
    121         return structureStubInfo->callReturnLocation;
    122     }
    123 
    124     // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
    125     // compares result with key (KeyTypes should be comparable with '--', '<', '>').
    126     // Optimized for cases where the array contains the key, checked by assertions.
    127     template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
    128     inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
    129     {
    130         // The array must contain at least one element (pre-condition, array does conatin key).
    131         // If the array only contains one element, no need to do the comparison.
    132         while (size > 1) {
    133             // Pick an element to check, half way through the array, and read the value.
    134             int pos = (size - 1) >> 1;
    135             KeyType val = valueAtPosition(&array[pos]);
    136            
    137             // If the key matches, success!
    138             if (val == key)
    139                 return &array[pos];
    140             // The item we are looking for is smaller than the item being check; reduce the value of 'size',
    141             // chopping off the right hand half of the array.
    142             else if (key < val)
    143                 size = pos;
    144             // Discard all values in the left hand half of the array, up to and including the item at pos.
    145             else {
    146                 size -= (pos + 1);
    147                 array += (pos + 1);
    148             }
    149 
    150             // 'size' should never reach zero.
    151             ASSERT(size);
    152         }
    153        
    154         // If we reach this point we've chopped down to one element, no need to check it matches
    155         ASSERT(size == 1);
    156         ASSERT(key == valueAtPosition(&array[0]));
    157         return &array[0];
    158     }
    159 
    160     struct StringJumpTable {
    161         typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
    162         StringOffsetTable offsetTable;
    163 #if ENABLE(CTI)
    164         void* ctiDefault; // FIXME: it should not be necessary to store this.
    165 #endif
    166 
    167         inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
    168         {
    169             StringOffsetTable::const_iterator end = offsetTable.end();
    170             StringOffsetTable::const_iterator loc = offsetTable.find(value);
    171             if (loc == end)
    172                 return defaultOffset;
    173             return loc->second.branchOffset;
    174         }
    175 
    176 #if ENABLE(CTI)
    177         inline void* ctiForValue(UString::Rep* value)
    178         {
    179             StringOffsetTable::const_iterator end = offsetTable.end();
    180             StringOffsetTable::const_iterator loc = offsetTable.find(value);
    181             if (loc == end)
    182                 return ctiDefault;
    183             return loc->second.ctiOffset;
    184         }
    185 #endif
    186     };
    187 
    188     struct SimpleJumpTable {
    189         // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>
    190         Vector<int32_t> branchOffsets;
    191         int32_t min;
    192 #if ENABLE(CTI)
    193         Vector<void*> ctiOffsets;
    194         void* ctiDefault;
    195 #endif
    196 
    197         int32_t offsetForValue(int32_t value, int32_t defaultOffset);
    198         void add(int32_t key, int32_t offset)
    199         {
    200             if (!branchOffsets[key])
    201                 branchOffsets[key] = offset;
    202         }
    203 
    204 #if ENABLE(CTI)
    205         inline void* ctiForValue(int32_t value)
    206         {
    207             if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
    208                 return ctiOffsets[value - min];
    209             return ctiDefault;
    210         }
    211 #endif
    212     };
    21341
    21442    class EvalCodeCache {
     
    24674    };
    24775
    248     struct CodeBlock {
    249         CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
    250             : ownerNode(ownerNode)
    251             , globalData(0)
    252 #if ENABLE(CTI)
    253             , ctiCode(0)
    254 #endif
    255             , numCalleeRegisters(0)
    256             , numConstants(0)
    257             , numVars(0)
    258             , numParameters(0)
    259             , needsFullScopeChain(ownerNode->needsActivation())
    260             , usesEval(ownerNode->usesEval())
    261             , codeType(codeType)
    262             , source(sourceProvider)
    263             , sourceOffset(sourceOffset)
    264         {
    265             ASSERT(source);
    266         }
    267 
    268         ~CodeBlock();
    269 
    270 #if ENABLE(CTI)
    271         void unlinkCallers();
    272 #endif
    273 
    274         void addCaller(CallLinkInfo* caller)
    275         {
    276             caller->callee = this;
    277             caller->position = linkedCallerList.size();
    278             linkedCallerList.append(caller);
    279         }
    280 
    281         void removeCaller(CallLinkInfo* caller)
    282         {
    283             unsigned pos = caller->position;
    284             unsigned lastPos = linkedCallerList.size() - 1;
    285 
    286             if (pos != lastPos) {
    287                 linkedCallerList[pos] = linkedCallerList[lastPos];
    288                 linkedCallerList[pos]->position = pos;
    289             }
    290             linkedCallerList.shrink(lastPos);
    291         }
    292 
    293         ALWAYS_INLINE bool isConstantRegisterIndex(int index)
    294         {
    295             return index >= numVars && index < numVars + numConstants;
    296         }
    297 
    298         ALWAYS_INLINE JSValue* getConstant(int index)
    299         {
    300             return constantRegisters[index - numVars].getJSValue();
    301         }
    302 
    303 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
    304         void dump(ExecState*) const;
    305         void printStructureIDs(const Instruction*) const;
    306         void printStructureID(const char* name, const Instruction*, int operand) const;
    307 #endif
    308         int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
    309         int lineNumberForVPC(const Instruction* vPC);
    310         bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);
    311         void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);
    312 
    313         void mark();
    314         void refStructureIDs(Instruction* vPC) const;
    315         void derefStructureIDs(Instruction* vPC) const;
    316 
    317         StructureStubInfo& getStubInfo(void* returnAddress)
    318         {
    319             return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(propertyAccessInstructions.begin(), propertyAccessInstructions.size(), returnAddress));
    320         }
    321 
    322         ScopeNode* ownerNode;
    323         JSGlobalData* globalData;
    324 #if ENABLE(CTI)
    325         void* ctiCode;
    326 #endif
    327 
    328         int numCalleeRegisters;
    329 
    330         // NOTE: numConstants holds the number of constant registers allocated
    331         // by the code generator, not the number of constant registers used.
    332         // (Duplicate constants are uniqued during code generation, and spare
    333         // constant registers may be allocated.)
    334         int numConstants;
    335         int numVars;
    336         int numParameters;
    337         int thisRegister;
    338         bool needsFullScopeChain;
    339         bool usesEval;
    340         bool usesArguments;
    341         CodeType codeType;
    342         RefPtr<SourceProvider> source;
    343         unsigned sourceOffset;
    344 
    345         Vector<Instruction> instructions;
    346         Vector<unsigned> globalResolveInstructions;
    347         Vector<StructureStubInfo> propertyAccessInstructions;
    348         Vector<CallLinkInfo> callLinkInfos;
    349         Vector<CallLinkInfo*> linkedCallerList;
    350 
    351         // Constant pool
    352         Vector<Identifier> identifiers;
    353         Vector<RefPtr<FuncDeclNode> > functions;
    354         Vector<RefPtr<FuncExprNode> > functionExpressions;
    355         Vector<Register> constantRegisters;
    356         Vector<JSValue*> unexpectedConstants;
    357         Vector<RefPtr<RegExp> > regexps;
    358         Vector<HandlerInfo> exceptionHandlers;
    359         Vector<ExpressionRangeInfo> expressionInfo;
    360         Vector<LineInfo> lineInfo;
    361 
    362         Vector<SimpleJumpTable> immediateSwitchJumpTables;
    363         Vector<SimpleJumpTable> characterSwitchJumpTables;
    364         Vector<StringJumpTable> stringSwitchJumpTables;
    365 
    366 #if ENABLE(CTI)
    367         HashMap<void*, unsigned> ctiReturnAddressVPCMap;
    368 #endif
    369 
    370         EvalCodeCache evalCodeCache;
    371 
    372     private:
    373 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
    374         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
    375 #endif
    376 
    377     };
    378 
    379     // Program code is not marked by any function, so we make the global object
    380     // responsible for marking it.
    381 
    382     struct ProgramCodeBlock : public CodeBlock {
    383         ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
    384             : CodeBlock(ownerNode, codeType, sourceProvider, 0)
    385             , globalObject(globalObject)
    386         {
    387             globalObject->codeBlocks().add(this);
    388         }
    389 
    390         ~ProgramCodeBlock()
    391         {
    392             if (globalObject)
    393                 globalObject->codeBlocks().remove(this);
    394         }
    395 
    396         JSGlobalObject* globalObject; // For program and eval nodes, the global object that marks the constant pool.
    397     };
    398 
    399     struct EvalCodeBlock : public ProgramCodeBlock {
    400         EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
    401             : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
    402         {
    403         }
    404     };
    405 
    40676} // namespace JSC
    40777
    408 #endif // CodeBlock_h
     78#endif // EvalCodeCache_h
Note: See TracChangeset for help on using the changeset viewer.