Changeset 38311 in webkit for trunk/JavaScriptCore/VM/EvalCodeCache.h
- Timestamp:
- Nov 11, 2008, 12:06:11 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/VM/EvalCodeCache.h
r38302 r38311 1 1 /* 2 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>4 3 * 5 4 * Redistribution and use in source and binary forms, with or without … … 28 27 */ 29 28 30 #ifndef CodeBlock_h31 #define CodeBlock_h29 #ifndef EvalCodeCache_h 30 #define EvalCodeCache_h 32 31 33 #include "Instruction.h"34 32 #include "JSGlobalObject.h" 35 33 #include "Nodes.h" 36 34 #include "Parser.h" 37 #include "RegExp.h"38 35 #include "SourceCode.h" 39 36 #include "UString.h" 37 #include <wtf/HashMap.h> 40 38 #include <wtf/RefPtr.h> 41 #include <wtf/Vector.h>42 39 43 40 namespace 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) - 163 };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 #endif80 };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 matches155 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 #endif166 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 #endif186 };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 #endif196 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 #endif212 };213 41 214 42 class EvalCodeCache { … … 246 74 }; 247 75 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 #endif255 , 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 #endif273 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_SAMPLING304 void dump(ExecState*) const;305 void printStructureIDs(const Instruction*) const;306 void printStructureID(const char* name, const Instruction*, int operand) const;307 #endif308 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 #endif327 328 int numCalleeRegisters;329 330 // NOTE: numConstants holds the number of constant registers allocated331 // by the code generator, not the number of constant registers used.332 // (Duplicate constants are uniqued during code generation, and spare333 // 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 pool352 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 #endif369 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 #endif376 377 };378 379 // Program code is not marked by any function, so we make the global object380 // 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 406 76 } // namespace JSC 407 77 408 #endif // CodeBlock_h78 #endif // EvalCodeCache_h
Note:
See TracChangeset
for help on using the changeset viewer.