2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
33 #include "EvalCodeCache.h"
34 #include "Instruction.h"
36 #include "JSGlobalObject.h"
37 #include "JumpTable.h"
39 #include "PtrAndFlags.h"
42 #include <wtf/FastAllocBase.h>
43 #include <wtf/RefPtr.h>
44 #include <wtf/Vector.h>
47 #include "StructureStubInfo.h"
50 // Register numbers used in bytecode operations have different meaning accoring to their ranges:
51 // 0x80000000-0xFFFFFFFF Negative indicies from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
52 // 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
53 // 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
54 static const int FirstConstantRegisterIndex
= 0x40000000;
58 enum HasSeenShouldRepatch
{
64 enum CodeType
{ GlobalCode
, EvalCode
, FunctionCode
};
66 static ALWAYS_INLINE
int missingThisObjectMarker() { return std::numeric_limits
<int>::max(); }
74 CodeLocationLabel nativeCode
;
78 struct ExpressionRangeInfo
{
80 MaxOffset
= (1 << 7) - 1,
81 MaxDivot
= (1 << 25) - 1
83 uint32_t instructionOffset
: 25;
84 uint32_t divotPoint
: 25;
85 uint32_t startOffset
: 7;
86 uint32_t endOffset
: 7;
90 uint32_t instructionOffset
;
94 // Both op_construct and op_instanceof require a use of op_get_by_id to get
95 // the prototype property from an object. The exception messages for exceptions
96 // thrown by these instances op_get_by_id need to reflect this.
97 struct GetByIdExceptionInfo
{
98 unsigned bytecodeOffset
: 31;
99 bool isOpConstruct
: 1;
103 struct CallLinkInfo
{
109 unsigned bytecodeIndex
;
110 CodeLocationNearCall callReturnLocation
;
111 CodeLocationDataLabelPtr hotPathBegin
;
112 CodeLocationNearCall hotPathOther
;
113 PtrAndFlags
<CodeBlock
, HasSeenShouldRepatch
> ownerCodeBlock
;
117 void setUnlinked() { callee
= 0; }
118 bool isLinked() { return callee
; }
122 return ownerCodeBlock
.isFlagSet(hasSeenShouldRepatch
);
127 ownerCodeBlock
.setFlag(hasSeenShouldRepatch
);
131 struct MethodCallLinkInfo
{
139 return cachedPrototypeStructure
.isFlagSet(hasSeenShouldRepatch
);
144 cachedPrototypeStructure
.setFlag(hasSeenShouldRepatch
);
147 CodeLocationCall callReturnLocation
;
148 CodeLocationDataLabelPtr structureLabel
;
149 Structure
* cachedStructure
;
150 PtrAndFlags
<Structure
, HasSeenShouldRepatch
> cachedPrototypeStructure
;
153 struct FunctionRegisterInfo
{
154 FunctionRegisterInfo(unsigned bytecodeOffset
, int functionRegisterIndex
)
155 : bytecodeOffset(bytecodeOffset
)
156 , functionRegisterIndex(functionRegisterIndex
)
160 unsigned bytecodeOffset
;
161 int functionRegisterIndex
;
164 struct GlobalResolveInfo
{
165 GlobalResolveInfo(unsigned bytecodeOffset
)
168 , bytecodeOffset(bytecodeOffset
)
172 Structure
* structure
;
174 unsigned bytecodeOffset
;
177 // This structure is used to map from a call return location
178 // (given as an offset in bytes into the JIT code) back to
179 // the bytecode index of the corresponding bytecode operation.
180 // This is then used to look up the corresponding handler.
181 struct CallReturnOffsetToBytecodeIndex
{
182 CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset
, unsigned bytecodeIndex
)
183 : callReturnOffset(callReturnOffset
)
184 , bytecodeIndex(bytecodeIndex
)
188 unsigned callReturnOffset
;
189 unsigned bytecodeIndex
;
192 // valueAtPosition helpers for the binaryChop algorithm below.
194 inline void* getStructureStubInfoReturnLocation(StructureStubInfo
* structureStubInfo
)
196 return structureStubInfo
->callReturnLocation
.executableAddress();
199 inline void* getCallLinkInfoReturnLocation(CallLinkInfo
* callLinkInfo
)
201 return callLinkInfo
->callReturnLocation
.executableAddress();
204 inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo
* methodCallLinkInfo
)
206 return methodCallLinkInfo
->callReturnLocation
.executableAddress();
209 inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex
* pc
)
211 return pc
->callReturnOffset
;
214 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
215 // compares result with key (KeyTypes should be comparable with '--', '<', '>').
216 // Optimized for cases where the array contains the key, checked by assertions.
217 template<typename ArrayType
, typename KeyType
, KeyType(*valueAtPosition
)(ArrayType
*)>
218 inline ArrayType
* binaryChop(ArrayType
* array
, size_t size
, KeyType key
)
220 // The array must contain at least one element (pre-condition, array does conatin key).
221 // If the array only contains one element, no need to do the comparison.
223 // Pick an element to check, half way through the array, and read the value.
224 int pos
= (size
- 1) >> 1;
225 KeyType val
= valueAtPosition(&array
[pos
]);
227 // If the key matches, success!
230 // The item we are looking for is smaller than the item being check; reduce the value of 'size',
231 // chopping off the right hand half of the array.
234 // Discard all values in the left hand half of the array, up to and including the item at pos.
240 // 'size' should never reach zero.
244 // If we reach this point we've chopped down to one element, no need to check it matches
246 ASSERT(key
== valueAtPosition(&array
[0]));
251 struct ExceptionInfo
: FastAllocBase
{
252 Vector
<ExpressionRangeInfo
> m_expressionInfo
;
253 Vector
<LineInfo
> m_lineInfo
;
254 Vector
<GetByIdExceptionInfo
> m_getByIdExceptionInfo
;
257 Vector
<CallReturnOffsetToBytecodeIndex
> m_callReturnIndexVector
;
261 class CodeBlock
: public FastAllocBase
{
264 CodeBlock(ScriptExecutable
* ownerExecutable
, CodeType
, PassRefPtr
<SourceProvider
>, unsigned sourceOffset
, SymbolTable
* symbolTable
);
266 virtual ~CodeBlock();
268 void markAggregate(MarkStack
&);
269 void refStructures(Instruction
* vPC
) const;
270 void derefStructures(Instruction
* vPC
) const;
271 #if ENABLE(JIT_OPTIMIZE_CALL)
272 void unlinkCallers();
275 static void dumpStatistics();
277 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
278 void dump(ExecState
*) const;
279 void printStructures(const Instruction
*) const;
280 void printStructure(const char* name
, const Instruction
*, int operand
) const;
283 inline bool isKnownNotImmediate(int index
)
285 if (index
== m_thisRegister
)
288 if (isConstantRegisterIndex(index
))
289 return getConstant(index
).isCell();
294 ALWAYS_INLINE
bool isTemporaryRegisterIndex(int index
)
296 return index
>= m_numVars
;
299 HandlerInfo
* handlerForBytecodeOffset(unsigned bytecodeOffset
);
300 int lineNumberForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
);
301 int expressionRangeForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
, int& divot
, int& startOffset
, int& endOffset
);
302 bool getByIdExceptionInfoForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
, OpcodeID
&);
305 void addCaller(CallLinkInfo
* caller
)
307 caller
->callee
= this;
308 caller
->position
= m_linkedCallerList
.size();
309 m_linkedCallerList
.append(caller
);
312 void removeCaller(CallLinkInfo
* caller
)
314 unsigned pos
= caller
->position
;
315 unsigned lastPos
= m_linkedCallerList
.size() - 1;
317 if (pos
!= lastPos
) {
318 m_linkedCallerList
[pos
] = m_linkedCallerList
[lastPos
];
319 m_linkedCallerList
[pos
]->position
= pos
;
321 m_linkedCallerList
.shrink(lastPos
);
324 StructureStubInfo
& getStubInfo(ReturnAddressPtr returnAddress
)
326 return *(binaryChop
<StructureStubInfo
, void*, getStructureStubInfoReturnLocation
>(m_structureStubInfos
.begin(), m_structureStubInfos
.size(), returnAddress
.value()));
329 CallLinkInfo
& getCallLinkInfo(ReturnAddressPtr returnAddress
)
331 return *(binaryChop
<CallLinkInfo
, void*, getCallLinkInfoReturnLocation
>(m_callLinkInfos
.begin(), m_callLinkInfos
.size(), returnAddress
.value()));
334 MethodCallLinkInfo
& getMethodCallLinkInfo(ReturnAddressPtr returnAddress
)
336 return *(binaryChop
<MethodCallLinkInfo
, void*, getMethodCallLinkInfoReturnLocation
>(m_methodCallLinkInfos
.begin(), m_methodCallLinkInfos
.size(), returnAddress
.value()));
339 unsigned getBytecodeIndex(CallFrame
* callFrame
, ReturnAddressPtr returnAddress
)
341 reparseForExceptionInfoIfNecessary(callFrame
);
342 return binaryChop
<CallReturnOffsetToBytecodeIndex
, unsigned, getCallReturnOffset
>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerExecutable()->generatedJITCode().offsetOf(returnAddress
.value()))->bytecodeIndex
;
345 bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset
, int& functionRegisterIndex
);
348 void setIsNumericCompareFunction(bool isNumericCompareFunction
) { m_isNumericCompareFunction
= isNumericCompareFunction
; }
349 bool isNumericCompareFunction() { return m_isNumericCompareFunction
; }
351 Vector
<Instruction
>& instructions() { return m_instructions
; }
352 void discardBytecode() { m_instructions
.clear(); }
355 unsigned instructionCount() { return m_instructionCount
; }
356 void setInstructionCount(unsigned instructionCount
) { m_instructionCount
= instructionCount
; }
360 JITCode
& getJITCode() { return ownerExecutable()->generatedJITCode(); }
361 ExecutablePool
* executablePool() { return ownerExecutable()->getExecutablePool(); }
364 ScriptExecutable
* ownerExecutable() const { return m_ownerExecutable
; }
366 void setGlobalData(JSGlobalData
* globalData
) { m_globalData
= globalData
; }
368 void setThisRegister(int thisRegister
) { m_thisRegister
= thisRegister
; }
369 int thisRegister() const { return m_thisRegister
; }
371 void setNeedsFullScopeChain(bool needsFullScopeChain
) { m_needsFullScopeChain
= needsFullScopeChain
; }
372 bool needsFullScopeChain() const { return m_needsFullScopeChain
; }
373 void setUsesEval(bool usesEval
) { m_usesEval
= usesEval
; }
374 bool usesEval() const { return m_usesEval
; }
375 void setUsesArguments(bool usesArguments
) { m_usesArguments
= usesArguments
; }
376 bool usesArguments() const { return m_usesArguments
; }
378 CodeType
codeType() const { return m_codeType
; }
380 SourceProvider
* source() const { return m_source
.get(); }
381 unsigned sourceOffset() const { return m_sourceOffset
; }
383 size_t numberOfJumpTargets() const { return m_jumpTargets
.size(); }
384 void addJumpTarget(unsigned jumpTarget
) { m_jumpTargets
.append(jumpTarget
); }
385 unsigned jumpTarget(int index
) const { return m_jumpTargets
[index
]; }
386 unsigned lastJumpTarget() const { return m_jumpTargets
.last(); }
389 void addPropertyAccessInstruction(unsigned propertyAccessInstruction
) { m_propertyAccessInstructions
.append(propertyAccessInstruction
); }
390 void addGlobalResolveInstruction(unsigned globalResolveInstruction
) { m_globalResolveInstructions
.append(globalResolveInstruction
); }
391 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset
);
393 size_t numberOfStructureStubInfos() const { return m_structureStubInfos
.size(); }
394 void addStructureStubInfo(const StructureStubInfo
& stubInfo
) { m_structureStubInfos
.append(stubInfo
); }
395 StructureStubInfo
& structureStubInfo(int index
) { return m_structureStubInfos
[index
]; }
397 void addGlobalResolveInfo(unsigned globalResolveInstruction
) { m_globalResolveInfos
.append(GlobalResolveInfo(globalResolveInstruction
)); }
398 GlobalResolveInfo
& globalResolveInfo(int index
) { return m_globalResolveInfos
[index
]; }
399 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset
);
401 size_t numberOfCallLinkInfos() const { return m_callLinkInfos
.size(); }
402 void addCallLinkInfo() { m_callLinkInfos
.append(CallLinkInfo()); }
403 CallLinkInfo
& callLinkInfo(int index
) { return m_callLinkInfos
[index
]; }
405 void addMethodCallLinkInfos(unsigned n
) { m_methodCallLinkInfos
.grow(n
); }
406 MethodCallLinkInfo
& methodCallLinkInfo(int index
) { return m_methodCallLinkInfos
[index
]; }
408 void addFunctionRegisterInfo(unsigned bytecodeOffset
, int functionIndex
) { createRareDataIfNecessary(); m_rareData
->m_functionRegisterInfos
.append(FunctionRegisterInfo(bytecodeOffset
, functionIndex
)); }
411 // Exception handling support
413 size_t numberOfExceptionHandlers() const { return m_rareData
? m_rareData
->m_exceptionHandlers
.size() : 0; }
414 void addExceptionHandler(const HandlerInfo
& hanler
) { createRareDataIfNecessary(); return m_rareData
->m_exceptionHandlers
.append(hanler
); }
415 HandlerInfo
& exceptionHandler(int index
) { ASSERT(m_rareData
); return m_rareData
->m_exceptionHandlers
[index
]; }
417 bool hasExceptionInfo() const { return m_exceptionInfo
; }
418 void clearExceptionInfo() { m_exceptionInfo
.clear(); }
419 ExceptionInfo
* extractExceptionInfo() { ASSERT(m_exceptionInfo
); return m_exceptionInfo
.release(); }
421 void addExpressionInfo(const ExpressionRangeInfo
& expressionInfo
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_expressionInfo
.append(expressionInfo
); }
422 void addGetByIdExceptionInfo(const GetByIdExceptionInfo
& info
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_getByIdExceptionInfo
.append(info
); }
424 size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_lineInfo
.size(); }
425 void addLineInfo(const LineInfo
& lineInfo
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_lineInfo
.append(lineInfo
); }
426 LineInfo
& lastLineInfo() { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_lineInfo
.last(); }
429 Vector
<CallReturnOffsetToBytecodeIndex
>& callReturnIndexVector() { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_callReturnIndexVector
; }
434 size_t numberOfIdentifiers() const { return m_identifiers
.size(); }
435 void addIdentifier(const Identifier
& i
) { return m_identifiers
.append(i
); }
436 Identifier
& identifier(int index
) { return m_identifiers
[index
]; }
438 size_t numberOfConstantRegisters() const { return m_constantRegisters
.size(); }
439 void addConstantRegister(const Register
& r
) { return m_constantRegisters
.append(r
); }
440 Register
& constantRegister(int index
) { return m_constantRegisters
[index
- FirstConstantRegisterIndex
]; }
441 ALWAYS_INLINE
bool isConstantRegisterIndex(int index
) const { return index
>= FirstConstantRegisterIndex
; }
442 ALWAYS_INLINE JSValue
getConstant(int index
) const { return m_constantRegisters
[index
- FirstConstantRegisterIndex
].jsValue(); }
444 unsigned addFunctionDecl(NonNullPassRefPtr
<FunctionExecutable
> n
) { unsigned size
= m_functionDecls
.size(); m_functionDecls
.append(n
); return size
; }
445 FunctionExecutable
* functionDecl(int index
) { return m_functionDecls
[index
].get(); }
446 int numberOfFunctionDecls() { return m_functionDecls
.size(); }
447 unsigned addFunctionExpr(NonNullPassRefPtr
<FunctionExecutable
> n
) { unsigned size
= m_functionExprs
.size(); m_functionExprs
.append(n
); return size
; }
448 FunctionExecutable
* functionExpr(int index
) { return m_functionExprs
[index
].get(); }
450 unsigned addRegExp(RegExp
* r
) { createRareDataIfNecessary(); unsigned size
= m_rareData
->m_regexps
.size(); m_rareData
->m_regexps
.append(r
); return size
; }
451 RegExp
* regexp(int index
) const { ASSERT(m_rareData
); return m_rareData
->m_regexps
[index
].get(); }
456 size_t numberOfImmediateSwitchJumpTables() const { return m_rareData
? m_rareData
->m_immediateSwitchJumpTables
.size() : 0; }
457 SimpleJumpTable
& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_immediateSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_immediateSwitchJumpTables
.last(); }
458 SimpleJumpTable
& immediateSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_immediateSwitchJumpTables
[tableIndex
]; }
460 size_t numberOfCharacterSwitchJumpTables() const { return m_rareData
? m_rareData
->m_characterSwitchJumpTables
.size() : 0; }
461 SimpleJumpTable
& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_characterSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_characterSwitchJumpTables
.last(); }
462 SimpleJumpTable
& characterSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_characterSwitchJumpTables
[tableIndex
]; }
464 size_t numberOfStringSwitchJumpTables() const { return m_rareData
? m_rareData
->m_stringSwitchJumpTables
.size() : 0; }
465 StringJumpTable
& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_stringSwitchJumpTables
.append(StringJumpTable()); return m_rareData
->m_stringSwitchJumpTables
.last(); }
466 StringJumpTable
& stringSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_stringSwitchJumpTables
[tableIndex
]; }
469 SymbolTable
* symbolTable() { return m_symbolTable
; }
470 SharedSymbolTable
* sharedSymbolTable() { ASSERT(m_codeType
== FunctionCode
); return static_cast<SharedSymbolTable
*>(m_symbolTable
); }
472 EvalCodeCache
& evalCodeCache() { createRareDataIfNecessary(); return m_rareData
->m_evalCodeCache
; }
476 // FIXME: Make these remaining members private.
478 int m_numCalleeRegisters
;
483 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
484 void dump(ExecState
*, const Vector
<Instruction
>::const_iterator
& begin
, Vector
<Instruction
>::const_iterator
&) const;
486 CString
registerName(ExecState
*, int r
) const;
487 void printUnaryOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
488 void printBinaryOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
489 void printConditionalJump(ExecState
*, const Vector
<Instruction
>::const_iterator
&, Vector
<Instruction
>::const_iterator
&, int location
, const char* op
) const;
490 void printGetByIdOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
491 void printPutByIdOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
494 void reparseForExceptionInfoIfNecessary(CallFrame
*);
496 void createRareDataIfNecessary()
499 m_rareData
.set(new RareData
);
502 ScriptExecutable
* m_ownerExecutable
;
503 JSGlobalData
* m_globalData
;
505 Vector
<Instruction
> m_instructions
;
507 unsigned m_instructionCount
;
512 bool m_needsFullScopeChain
;
514 bool m_usesArguments
;
515 bool m_isNumericCompareFunction
;
519 RefPtr
<SourceProvider
> m_source
;
520 unsigned m_sourceOffset
;
523 Vector
<unsigned> m_propertyAccessInstructions
;
524 Vector
<unsigned> m_globalResolveInstructions
;
526 Vector
<StructureStubInfo
> m_structureStubInfos
;
527 Vector
<GlobalResolveInfo
> m_globalResolveInfos
;
528 Vector
<CallLinkInfo
> m_callLinkInfos
;
529 Vector
<MethodCallLinkInfo
> m_methodCallLinkInfos
;
530 Vector
<CallLinkInfo
*> m_linkedCallerList
;
533 Vector
<unsigned> m_jumpTargets
;
536 Vector
<Identifier
> m_identifiers
;
537 Vector
<Register
> m_constantRegisters
;
538 Vector
<RefPtr
<FunctionExecutable
> > m_functionDecls
;
539 Vector
<RefPtr
<FunctionExecutable
> > m_functionExprs
;
541 SymbolTable
* m_symbolTable
;
543 OwnPtr
<ExceptionInfo
> m_exceptionInfo
;
545 struct RareData
: FastAllocBase
{
546 Vector
<HandlerInfo
> m_exceptionHandlers
;
549 Vector
<RefPtr
<RegExp
> > m_regexps
;
552 Vector
<SimpleJumpTable
> m_immediateSwitchJumpTables
;
553 Vector
<SimpleJumpTable
> m_characterSwitchJumpTables
;
554 Vector
<StringJumpTable
> m_stringSwitchJumpTables
;
556 EvalCodeCache m_evalCodeCache
;
559 Vector
<FunctionRegisterInfo
> m_functionRegisterInfos
;
562 OwnPtr
<RareData
> m_rareData
;
565 // Program code is not marked by any function, so we make the global object
566 // responsible for marking it.
568 class GlobalCodeBlock
: public CodeBlock
{
570 GlobalCodeBlock(ScriptExecutable
* ownerExecutable
, CodeType codeType
, PassRefPtr
<SourceProvider
> sourceProvider
, unsigned sourceOffset
, JSGlobalObject
* globalObject
)
571 : CodeBlock(ownerExecutable
, codeType
, sourceProvider
, sourceOffset
, &m_unsharedSymbolTable
)
572 , m_globalObject(globalObject
)
574 m_globalObject
->codeBlocks().add(this);
580 m_globalObject
->codeBlocks().remove(this);
583 void clearGlobalObject() { m_globalObject
= 0; }
586 JSGlobalObject
* m_globalObject
; // For program and eval nodes, the global object that marks the constant pool.
587 SymbolTable m_unsharedSymbolTable
;
590 class ProgramCodeBlock
: public GlobalCodeBlock
{
592 ProgramCodeBlock(ProgramExecutable
* ownerExecutable
, CodeType codeType
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
)
593 : GlobalCodeBlock(ownerExecutable
, codeType
, sourceProvider
, 0, globalObject
)
598 class EvalCodeBlock
: public GlobalCodeBlock
{
600 EvalCodeBlock(EvalExecutable
* ownerExecutable
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
, int baseScopeDepth
)
601 : GlobalCodeBlock(ownerExecutable
, EvalCode
, sourceProvider
, 0, globalObject
)
602 , m_baseScopeDepth(baseScopeDepth
)
606 int baseScopeDepth() const { return m_baseScopeDepth
; }
608 const Identifier
& variable(unsigned index
) { return m_variables
[index
]; }
609 unsigned numVariables() { return m_variables
.size(); }
610 void adoptVariables(Vector
<Identifier
>& variables
)
612 ASSERT(m_variables
.isEmpty());
613 m_variables
.swap(variables
);
617 int m_baseScopeDepth
;
618 Vector
<Identifier
> m_variables
;
621 class FunctionCodeBlock
: public CodeBlock
{
623 // Rather than using the usual RefCounted::create idiom for SharedSymbolTable we just use new
624 // as we need to initialise the CodeBlock before we could initialise any RefPtr to hold the shared
625 // symbol table, so we just pass as a raw pointer with a ref count of 1. We then manually deref
626 // in the destructor.
627 FunctionCodeBlock(FunctionExecutable
* ownerExecutable
, CodeType codeType
, PassRefPtr
<SourceProvider
> sourceProvider
, unsigned sourceOffset
)
628 : CodeBlock(ownerExecutable
, codeType
, sourceProvider
, sourceOffset
, new SharedSymbolTable
)
633 sharedSymbolTable()->deref();
637 inline Register
& ExecState::r(int index
)
639 CodeBlock
* codeBlock
= this->codeBlock();
640 if (codeBlock
->isConstantRegisterIndex(index
))
641 return codeBlock
->constantRegister(index
);
647 #endif // CodeBlock_h