• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef CodeBlock_h
31 #define CodeBlock_h
32 
33 #include "EvalCodeCache.h"
34 #include "Instruction.h"
35 #include "JSGlobalObject.h"
36 #include "JumpTable.h"
37 #include "Nodes.h"
38 #include "RegExp.h"
39 #include "UString.h"
40 #include <wtf/RefPtr.h>
41 #include <wtf/Vector.h>
42 
43 #if ENABLE(JIT)
44 #include "StructureStubInfo.h"
45 #endif
46 
47 namespace JSC {
48 
49     class ExecState;
50 
51     enum CodeType { GlobalCode, EvalCode, FunctionCode };
52 
missingThisObjectMarker()53     static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
54 
55     struct HandlerInfo {
56         uint32_t start;
57         uint32_t end;
58         uint32_t target;
59         uint32_t scopeDepth;
60 #if ENABLE(JIT)
61         void* nativeCode;
62 #endif
63     };
64 
65 #if ENABLE(JIT)
66     // The code, and the associated pool from which it was allocated.
67     struct JITCodeRef {
68         void* code;
69 #ifndef NDEBUG
70         unsigned codeSize;
71 #endif
72         RefPtr<ExecutablePool> executablePool;
73 
JITCodeRefJITCodeRef74         JITCodeRef()
75             : code(0)
76 #ifndef NDEBUG
77             , codeSize(0)
78 #endif
79         {
80         }
81 
JITCodeRefJITCodeRef82         JITCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool)
83             : code(code)
84 #ifndef NDEBUG
85             , codeSize(0)
86 #endif
87             , executablePool(executablePool)
88         {
89         }
90     };
91 #endif
92 
93     struct ExpressionRangeInfo {
94         enum {
95             MaxOffset = (1 << 7) - 1,
96             MaxDivot = (1 << 25) - 1
97         };
98         uint32_t instructionOffset : 25;
99         uint32_t divotPoint : 25;
100         uint32_t startOffset : 7;
101         uint32_t endOffset : 7;
102     };
103 
104     struct LineInfo {
105         uint32_t instructionOffset;
106         int32_t lineNumber;
107     };
108 
109     // Both op_construct and op_instanceof require a use of op_get_by_id to get
110     // the prototype property from an object. The exception messages for exceptions
111     // thrown by these instances op_get_by_id need to reflect this.
112     struct GetByIdExceptionInfo {
113         unsigned bytecodeOffset : 31;
114         bool isOpConstruct : 1;
115     };
116 
117 #if ENABLE(JIT)
118     struct CallLinkInfo {
CallLinkInfoCallLinkInfo119         CallLinkInfo()
120             : callReturnLocation(0)
121             , hotPathBegin(0)
122             , hotPathOther(0)
123             , coldPathOther(0)
124             , callee(0)
125         {
126         }
127 
128         unsigned bytecodeIndex;
129         void* callReturnLocation;
130         void* hotPathBegin;
131         void* hotPathOther;
132         void* coldPathOther;
133         CodeBlock* callee;
134         unsigned position;
135 
setUnlinkedCallLinkInfo136         void setUnlinked() { callee = 0; }
isLinkedCallLinkInfo137         bool isLinked() { return callee; }
138     };
139 
140     struct FunctionRegisterInfo {
FunctionRegisterInfoFunctionRegisterInfo141         FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
142             : bytecodeOffset(bytecodeOffset)
143             , functionRegisterIndex(functionRegisterIndex)
144         {
145         }
146 
147         unsigned bytecodeOffset;
148         int functionRegisterIndex;
149     };
150 
151     struct GlobalResolveInfo {
GlobalResolveInfoGlobalResolveInfo152         GlobalResolveInfo(unsigned bytecodeOffset)
153             : structure(0)
154             , offset(0)
155             , bytecodeOffset(bytecodeOffset)
156         {
157         }
158 
159         Structure* structure;
160         unsigned offset;
161         unsigned bytecodeOffset;
162     };
163 
164     struct PC {
PCPC165         PC(ptrdiff_t nativePCOffset, unsigned bytecodeIndex)
166             : nativePCOffset(nativePCOffset)
167             , bytecodeIndex(bytecodeIndex)
168         {
169         }
170 
171         ptrdiff_t nativePCOffset;
172         unsigned bytecodeIndex;
173     };
174 
175     // valueAtPosition helpers for the binaryChop algorithm below.
176 
getStructureStubInfoReturnLocation(StructureStubInfo * structureStubInfo)177     inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
178     {
179         return structureStubInfo->callReturnLocation;
180     }
181 
getCallLinkInfoReturnLocation(CallLinkInfo * callLinkInfo)182     inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
183     {
184         return callLinkInfo->callReturnLocation;
185     }
186 
getNativePCOffset(PC * pc)187     inline ptrdiff_t getNativePCOffset(PC* pc)
188     {
189         return pc->nativePCOffset;
190     }
191 
192     // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
193     // compares result with key (KeyTypes should be comparable with '--', '<', '>').
194     // Optimized for cases where the array contains the key, checked by assertions.
195     template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
binaryChop(ArrayType * array,size_t size,KeyType key)196     inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
197     {
198         // The array must contain at least one element (pre-condition, array does conatin key).
199         // If the array only contains one element, no need to do the comparison.
200         while (size > 1) {
201             // Pick an element to check, half way through the array, and read the value.
202             int pos = (size - 1) >> 1;
203             KeyType val = valueAtPosition(&array[pos]);
204 
205             // If the key matches, success!
206             if (val == key)
207                 return &array[pos];
208             // The item we are looking for is smaller than the item being check; reduce the value of 'size',
209             // chopping off the right hand half of the array.
210             else if (key < val)
211                 size = pos;
212             // Discard all values in the left hand half of the array, up to and including the item at pos.
213             else {
214                 size -= (pos + 1);
215                 array += (pos + 1);
216             }
217 
218             // 'size' should never reach zero.
219             ASSERT(size);
220         }
221 
222         // If we reach this point we've chopped down to one element, no need to check it matches
223         ASSERT(size == 1);
224         ASSERT(key == valueAtPosition(&array[0]));
225         return &array[0];
226     }
227 #endif
228 
229     class CodeBlock {
230         friend class JIT;
231     public:
232         CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
233         ~CodeBlock();
234 
235         void mark();
236         void refStructures(Instruction* vPC) const;
237         void derefStructures(Instruction* vPC) const;
238 #if ENABLE(JIT)
239         void unlinkCallers();
240 #endif
241 
242         static void dumpStatistics();
243 
244 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
245         void dump(ExecState*) const;
246         void printStructures(const Instruction*) const;
247         void printStructure(const char* name, const Instruction*, int operand) const;
248 #endif
249 
isKnownNotImmediate(int index)250         inline bool isKnownNotImmediate(int index)
251         {
252             if (index == m_thisRegister)
253                 return true;
254 
255             if (isConstantRegisterIndex(index))
256                 return getConstant(index).isCell();
257 
258             return false;
259         }
260 
isConstantRegisterIndex(int index)261         ALWAYS_INLINE bool isConstantRegisterIndex(int index)
262         {
263             return index >= m_numVars && index < m_numVars + m_numConstants;
264         }
265 
getConstant(int index)266         ALWAYS_INLINE JSValuePtr getConstant(int index)
267         {
268             return m_constantRegisters[index - m_numVars].getJSValue();
269         }
270 
isTemporaryRegisterIndex(int index)271         ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)
272         {
273             return index >= m_numVars + m_numConstants;
274         }
275 
276         HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
277         int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
278         int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
279         bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
280 
281 #if ENABLE(JIT)
addCaller(CallLinkInfo * caller)282         void addCaller(CallLinkInfo* caller)
283         {
284             caller->callee = this;
285             caller->position = m_linkedCallerList.size();
286             m_linkedCallerList.append(caller);
287         }
288 
removeCaller(CallLinkInfo * caller)289         void removeCaller(CallLinkInfo* caller)
290         {
291             unsigned pos = caller->position;
292             unsigned lastPos = m_linkedCallerList.size() - 1;
293 
294             if (pos != lastPos) {
295                 m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
296                 m_linkedCallerList[pos]->position = pos;
297             }
298             m_linkedCallerList.shrink(lastPos);
299         }
300 
getStubInfo(void * returnAddress)301         StructureStubInfo& getStubInfo(void* returnAddress)
302         {
303             return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
304         }
305 
getCallLinkInfo(void * returnAddress)306         CallLinkInfo& getCallLinkInfo(void* returnAddress)
307         {
308             return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
309         }
310 
getBytecodeIndex(CallFrame * callFrame,void * nativePC)311         unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC)
312         {
313             reparseForExceptionInfoIfNecessary(callFrame);
314             ptrdiff_t nativePCOffset = reinterpret_cast<void**>(nativePC) - reinterpret_cast<void**>(m_jitCode.code);
315             return binaryChop<PC, ptrdiff_t, getNativePCOffset>(m_exceptionInfo->m_pcVector.begin(), m_exceptionInfo->m_pcVector.size(), nativePCOffset)->bytecodeIndex;
316         }
317 
318         bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
319 #endif
320 
setIsNumericCompareFunction(bool isNumericCompareFunction)321         void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
isNumericCompareFunction()322         bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
323 
instructions()324         Vector<Instruction>& instructions() { return m_instructions; }
325 #ifndef NDEBUG
setInstructionCount(unsigned instructionCount)326         void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
327 #endif
328 
329 #if ENABLE(JIT)
330         void setJITCode(JITCodeRef& jitCode);
jitCode()331         void* jitCode() { return m_jitCode.code; }
executablePool()332         ExecutablePool* executablePool() { return m_jitCode.executablePool.get(); }
333 #endif
334 
ownerNode()335         ScopeNode* ownerNode() const { return m_ownerNode; }
336 
setGlobalData(JSGlobalData * globalData)337         void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
338 
setThisRegister(int thisRegister)339         void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
thisRegister()340         int thisRegister() const { return m_thisRegister; }
341 
setNeedsFullScopeChain(bool needsFullScopeChain)342         void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
needsFullScopeChain()343         bool needsFullScopeChain() const { return m_needsFullScopeChain; }
setUsesEval(bool usesEval)344         void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
usesEval()345         bool usesEval() const { return m_usesEval; }
setUsesArguments(bool usesArguments)346         void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
usesArguments()347         bool usesArguments() const { return m_usesArguments; }
348 
codeType()349         CodeType codeType() const { return m_codeType; }
350 
source()351         SourceProvider* source() const { return m_source.get(); }
sourceOffset()352         unsigned sourceOffset() const { return m_sourceOffset; }
353 
numberOfJumpTargets()354         size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
addJumpTarget(unsigned jumpTarget)355         void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
jumpTarget(int index)356         unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
lastJumpTarget()357         unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
358 
359 #if !ENABLE(JIT)
addPropertyAccessInstruction(unsigned propertyAccessInstruction)360         void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
addGlobalResolveInstruction(unsigned globalResolveInstruction)361         void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
362         bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
363 #else
numberOfStructureStubInfos()364         size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
addStructureStubInfo(const StructureStubInfo & stubInfo)365         void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
structureStubInfo(int index)366         StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
367 
addGlobalResolveInfo(unsigned globalResolveInstruction)368         void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); }
globalResolveInfo(int index)369         GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
370         bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
371 
numberOfCallLinkInfos()372         size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
addCallLinkInfo()373         void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
callLinkInfo(int index)374         CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
375 
addFunctionRegisterInfo(unsigned bytecodeOffset,int functionIndex)376         void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
377 #endif
378 
379         // Exception handling support
380 
numberOfExceptionHandlers()381         size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
addExceptionHandler(const HandlerInfo & hanler)382         void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
exceptionHandler(int index)383         HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
384 
hasExceptionInfo()385         bool hasExceptionInfo() const { return m_exceptionInfo; }
clearExceptionInfo()386         void clearExceptionInfo() { m_exceptionInfo.clear(); }
387 
addExpressionInfo(const ExpressionRangeInfo & expressionInfo)388         void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
addGetByIdExceptionInfo(const GetByIdExceptionInfo & info)389         void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
390 
numberOfLineInfos()391         size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
addLineInfo(const LineInfo & lineInfo)392         void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
lastLineInfo()393         LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); }
394 
395 #if ENABLE(JIT)
pcVector()396         Vector<PC>& pcVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_pcVector; }
397 #endif
398 
399         // Constant Pool
400 
numberOfIdentifiers()401         size_t numberOfIdentifiers() const { return m_identifiers.size(); }
addIdentifier(const Identifier & i)402         void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
identifier(int index)403         Identifier& identifier(int index) { return m_identifiers[index]; }
404 
numberOfConstantRegisters()405         size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
addConstantRegister(const Register & r)406         void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
constantRegister(int index)407         Register& constantRegister(int index) { return m_constantRegisters[index]; }
408 
addFunctionExpression(FuncExprNode * n)409         unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
functionExpression(int index)410         FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
411 
addFunction(FuncDeclNode * n)412         unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; }
function(int index)413         FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); }
414 
hasFunctions()415         bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); }
416 
addUnexpectedConstant(JSValuePtr v)417         unsigned addUnexpectedConstant(JSValuePtr v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; }
unexpectedConstant(int index)418         JSValuePtr unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; }
419 
addRegExp(RegExp * r)420         unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
regexp(int index)421         RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
422 
423 
424         // Jump Tables
425 
numberOfImmediateSwitchJumpTables()426         size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
addImmediateSwitchJumpTable()427         SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
immediateSwitchJumpTable(int tableIndex)428         SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
429 
numberOfCharacterSwitchJumpTables()430         size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
addCharacterSwitchJumpTable()431         SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
characterSwitchJumpTable(int tableIndex)432         SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
433 
numberOfStringSwitchJumpTables()434         size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
addStringSwitchJumpTable()435         StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
stringSwitchJumpTable(int tableIndex)436         StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
437 
438 
symbolTable()439         SymbolTable& symbolTable() { return m_symbolTable; }
440 
evalCodeCache()441         EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
442 
443         void shrinkToFit();
444 
445         // FIXME: Make these remaining members private.
446 
447         int m_numCalleeRegisters;
448         // NOTE: numConstants holds the number of constant registers allocated
449         // by the code generator, not the number of constant registers used.
450         // (Duplicate constants are uniqued during code generation, and spare
451         // constant registers may be allocated.)
452         int m_numConstants;
453         int m_numVars;
454         int m_numParameters;
455 
456     private:
457 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
458         void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
459 #endif
460 
461         void reparseForExceptionInfoIfNecessary(CallFrame*);
462 
createRareDataIfNecessary()463         void createRareDataIfNecessary()
464         {
465             if (!m_rareData)
466                 m_rareData.set(new RareData);
467         }
468 
469         ScopeNode* m_ownerNode;
470         JSGlobalData* m_globalData;
471 
472         Vector<Instruction> m_instructions;
473 #ifndef NDEBUG
474         unsigned m_instructionCount;
475 #endif
476 #if ENABLE(JIT)
477         JITCodeRef m_jitCode;
478 #endif
479 
480         int m_thisRegister;
481 
482         bool m_needsFullScopeChain;
483         bool m_usesEval;
484         bool m_usesArguments;
485         bool m_isNumericCompareFunction;
486 
487         CodeType m_codeType;
488 
489         RefPtr<SourceProvider> m_source;
490         unsigned m_sourceOffset;
491 
492 #if !ENABLE(JIT)
493         Vector<unsigned> m_propertyAccessInstructions;
494         Vector<unsigned> m_globalResolveInstructions;
495 #else
496         Vector<StructureStubInfo> m_structureStubInfos;
497         Vector<GlobalResolveInfo> m_globalResolveInfos;
498         Vector<CallLinkInfo> m_callLinkInfos;
499         Vector<CallLinkInfo*> m_linkedCallerList;
500 #endif
501 
502         Vector<unsigned> m_jumpTargets;
503 
504         // Constant Pool
505         Vector<Identifier> m_identifiers;
506         Vector<Register> m_constantRegisters;
507         Vector<RefPtr<FuncExprNode> > m_functionExpressions;
508 
509         SymbolTable m_symbolTable;
510 
511         struct ExceptionInfo {
512             Vector<ExpressionRangeInfo> m_expressionInfo;
513             Vector<LineInfo> m_lineInfo;
514             Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
515 
516 #if ENABLE(JIT)
517             Vector<PC> m_pcVector;
518 #endif
519         };
520         OwnPtr<ExceptionInfo> m_exceptionInfo;
521 
522         struct RareData {
523             Vector<HandlerInfo> m_exceptionHandlers;
524 
525             // Rare Constants
526             Vector<RefPtr<FuncDeclNode> > m_functions;
527             Vector<JSValuePtr> m_unexpectedConstants;
528             Vector<RefPtr<RegExp> > m_regexps;
529 
530             // Jump Tables
531             Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
532             Vector<SimpleJumpTable> m_characterSwitchJumpTables;
533             Vector<StringJumpTable> m_stringSwitchJumpTables;
534 
535             EvalCodeCache m_evalCodeCache;
536 
537 #if ENABLE(JIT)
538             Vector<FunctionRegisterInfo> m_functionRegisterInfos;
539 #endif
540         };
541         OwnPtr<RareData> m_rareData;
542     };
543 
544     // Program code is not marked by any function, so we make the global object
545     // responsible for marking it.
546 
547     class ProgramCodeBlock : public CodeBlock {
548     public:
ProgramCodeBlock(ScopeNode * ownerNode,CodeType codeType,JSGlobalObject * globalObject,PassRefPtr<SourceProvider> sourceProvider)549         ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
550             : CodeBlock(ownerNode, codeType, sourceProvider, 0)
551             , m_globalObject(globalObject)
552         {
553             m_globalObject->codeBlocks().add(this);
554         }
555 
~ProgramCodeBlock()556         ~ProgramCodeBlock()
557         {
558             if (m_globalObject)
559                 m_globalObject->codeBlocks().remove(this);
560         }
561 
clearGlobalObject()562         void clearGlobalObject() { m_globalObject = 0; }
563 
564     private:
565         JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
566     };
567 
568     class EvalCodeBlock : public ProgramCodeBlock {
569     public:
EvalCodeBlock(ScopeNode * ownerNode,JSGlobalObject * globalObject,PassRefPtr<SourceProvider> sourceProvider,int baseScopeDepth)570         EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
571             : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
572             , m_baseScopeDepth(baseScopeDepth)
573         {
574         }
575 
baseScopeDepth()576         int baseScopeDepth() const { return m_baseScopeDepth; }
577 
578     private:
579         int m_baseScopeDepth;
580     };
581 
582 } // namespace JSC
583 
584 #endif // CodeBlock_h
585