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"
41 #include <wtf/FastAllocBase.h>
42 #include <wtf/RefPtr.h>
43 #include <wtf/Vector.h>
46 #include "StructureStubInfo.h"
49 // Register numbers used in bytecode operations have different meaning accoring to their ranges:
50 // 0x80000000-0xFFFFFFFF Negative indicies from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
51 // 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
52 // 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
53 static const int FirstConstantRegisterIndex
= 0x40000000;
59 enum CodeType
{ GlobalCode
, EvalCode
, FunctionCode
, NativeCode
};
61 static ALWAYS_INLINE
int missingThisObjectMarker() { return std::numeric_limits
<int>::max(); }
69 CodeLocationLabel nativeCode
;
73 struct ExpressionRangeInfo
{
75 MaxOffset
= (1 << 7) - 1,
76 MaxDivot
= (1 << 25) - 1
78 uint32_t instructionOffset
: 25;
79 uint32_t divotPoint
: 25;
80 uint32_t startOffset
: 7;
81 uint32_t endOffset
: 7;
85 uint32_t instructionOffset
;
89 // Both op_construct and op_instanceof require a use of op_get_by_id to get
90 // the prototype property from an object. The exception messages for exceptions
91 // thrown by these instances op_get_by_id need to reflect this.
92 struct GetByIdExceptionInfo
{
93 unsigned bytecodeOffset
: 31;
94 bool isOpConstruct
: 1;
104 unsigned bytecodeIndex
;
105 CodeLocationNearCall callReturnLocation
;
106 CodeLocationDataLabelPtr hotPathBegin
;
107 CodeLocationNearCall hotPathOther
;
108 CodeBlock
* ownerCodeBlock
;
112 void setUnlinked() { callee
= 0; }
113 bool isLinked() { return callee
; }
116 struct MethodCallLinkInfo
{
119 , cachedPrototypeStructure(0)
123 CodeLocationCall callReturnLocation
;
124 CodeLocationDataLabelPtr structureLabel
;
125 Structure
* cachedStructure
;
126 Structure
* cachedPrototypeStructure
;
129 struct FunctionRegisterInfo
{
130 FunctionRegisterInfo(unsigned bytecodeOffset
, int functionRegisterIndex
)
131 : bytecodeOffset(bytecodeOffset
)
132 , functionRegisterIndex(functionRegisterIndex
)
136 unsigned bytecodeOffset
;
137 int functionRegisterIndex
;
140 struct GlobalResolveInfo
{
141 GlobalResolveInfo(unsigned bytecodeOffset
)
144 , bytecodeOffset(bytecodeOffset
)
148 Structure
* structure
;
150 unsigned bytecodeOffset
;
153 // This structure is used to map from a call return location
154 // (given as an offset in bytes into the JIT code) back to
155 // the bytecode index of the corresponding bytecode operation.
156 // This is then used to look up the corresponding handler.
157 struct CallReturnOffsetToBytecodeIndex
{
158 CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset
, unsigned bytecodeIndex
)
159 : callReturnOffset(callReturnOffset
)
160 , bytecodeIndex(bytecodeIndex
)
164 unsigned callReturnOffset
;
165 unsigned bytecodeIndex
;
168 // valueAtPosition helpers for the binaryChop algorithm below.
170 inline void* getStructureStubInfoReturnLocation(StructureStubInfo
* structureStubInfo
)
172 return structureStubInfo
->callReturnLocation
.executableAddress();
175 inline void* getCallLinkInfoReturnLocation(CallLinkInfo
* callLinkInfo
)
177 return callLinkInfo
->callReturnLocation
.executableAddress();
180 inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo
* methodCallLinkInfo
)
182 return methodCallLinkInfo
->callReturnLocation
.executableAddress();
185 inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex
* pc
)
187 return pc
->callReturnOffset
;
190 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
191 // compares result with key (KeyTypes should be comparable with '--', '<', '>').
192 // Optimized for cases where the array contains the key, checked by assertions.
193 template<typename ArrayType
, typename KeyType
, KeyType(*valueAtPosition
)(ArrayType
*)>
194 inline ArrayType
* binaryChop(ArrayType
* array
, size_t size
, KeyType key
)
196 // The array must contain at least one element (pre-condition, array does conatin key).
197 // If the array only contains one element, no need to do the comparison.
199 // Pick an element to check, half way through the array, and read the value.
200 int pos
= (size
- 1) >> 1;
201 KeyType val
= valueAtPosition(&array
[pos
]);
203 // If the key matches, success!
206 // The item we are looking for is smaller than the item being check; reduce the value of 'size',
207 // chopping off the right hand half of the array.
210 // Discard all values in the left hand half of the array, up to and including the item at pos.
216 // 'size' should never reach zero.
220 // If we reach this point we've chopped down to one element, no need to check it matches
222 ASSERT(key
== valueAtPosition(&array
[0]));
227 class CodeBlock
: public WTF::FastAllocBase
{
230 CodeBlock(ScopeNode
* ownerNode
);
231 CodeBlock(ScopeNode
* ownerNode
, CodeType
, PassRefPtr
<SourceProvider
>, unsigned sourceOffset
);
235 void refStructures(Instruction
* vPC
) const;
236 void derefStructures(Instruction
* vPC
) const;
237 #if ENABLE(JIT_OPTIMIZE_CALL)
238 void unlinkCallers();
241 static void dumpStatistics();
243 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
244 void dump(ExecState
*) const;
245 void printStructures(const Instruction
*) const;
246 void printStructure(const char* name
, const Instruction
*, int operand
) const;
249 inline bool isKnownNotImmediate(int index
)
251 if (index
== m_thisRegister
)
254 if (isConstantRegisterIndex(index
))
255 return getConstant(index
).isCell();
260 ALWAYS_INLINE
bool isTemporaryRegisterIndex(int index
)
262 return index
>= m_numVars
;
265 HandlerInfo
* handlerForBytecodeOffset(unsigned bytecodeOffset
);
266 int lineNumberForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
);
267 int expressionRangeForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
, int& divot
, int& startOffset
, int& endOffset
);
268 bool getByIdExceptionInfoForBytecodeOffset(CallFrame
*, unsigned bytecodeOffset
, OpcodeID
&);
271 void addCaller(CallLinkInfo
* caller
)
273 caller
->callee
= this;
274 caller
->position
= m_linkedCallerList
.size();
275 m_linkedCallerList
.append(caller
);
278 void removeCaller(CallLinkInfo
* caller
)
280 unsigned pos
= caller
->position
;
281 unsigned lastPos
= m_linkedCallerList
.size() - 1;
283 if (pos
!= lastPos
) {
284 m_linkedCallerList
[pos
] = m_linkedCallerList
[lastPos
];
285 m_linkedCallerList
[pos
]->position
= pos
;
287 m_linkedCallerList
.shrink(lastPos
);
290 StructureStubInfo
& getStubInfo(ReturnAddressPtr returnAddress
)
292 return *(binaryChop
<StructureStubInfo
, void*, getStructureStubInfoReturnLocation
>(m_structureStubInfos
.begin(), m_structureStubInfos
.size(), returnAddress
.value()));
295 CallLinkInfo
& getCallLinkInfo(ReturnAddressPtr returnAddress
)
297 return *(binaryChop
<CallLinkInfo
, void*, getCallLinkInfoReturnLocation
>(m_callLinkInfos
.begin(), m_callLinkInfos
.size(), returnAddress
.value()));
300 MethodCallLinkInfo
& getMethodCallLinkInfo(ReturnAddressPtr returnAddress
)
302 return *(binaryChop
<MethodCallLinkInfo
, void*, getMethodCallLinkInfoReturnLocation
>(m_methodCallLinkInfos
.begin(), m_methodCallLinkInfos
.size(), returnAddress
.value()));
305 unsigned getBytecodeIndex(CallFrame
* callFrame
, ReturnAddressPtr returnAddress
)
307 reparseForExceptionInfoIfNecessary(callFrame
);
308 return binaryChop
<CallReturnOffsetToBytecodeIndex
, unsigned, getCallReturnOffset
>(m_exceptionInfo
->m_callReturnIndexVector
.begin(), m_exceptionInfo
->m_callReturnIndexVector
.size(), ownerNode()->generatedJITCode().offsetOf(returnAddress
.value()))->bytecodeIndex
;
311 bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset
, int& functionRegisterIndex
);
314 void setIsNumericCompareFunction(bool isNumericCompareFunction
) { m_isNumericCompareFunction
= isNumericCompareFunction
; }
315 bool isNumericCompareFunction() { return m_isNumericCompareFunction
; }
317 Vector
<Instruction
>& instructions() { return m_instructions
; }
319 void setInstructionCount(unsigned instructionCount
) { m_instructionCount
= instructionCount
; }
323 JITCode
& getJITCode() { return ownerNode()->generatedJITCode(); }
324 void setJITCode(JITCode
);
325 ExecutablePool
* executablePool() { return ownerNode()->getExecutablePool(); }
328 ScopeNode
* ownerNode() const { return m_ownerNode
; }
330 void setGlobalData(JSGlobalData
* globalData
) { m_globalData
= globalData
; }
332 void setThisRegister(int thisRegister
) { m_thisRegister
= thisRegister
; }
333 int thisRegister() const { return m_thisRegister
; }
335 void setNeedsFullScopeChain(bool needsFullScopeChain
) { m_needsFullScopeChain
= needsFullScopeChain
; }
336 bool needsFullScopeChain() const { return m_needsFullScopeChain
; }
337 void setUsesEval(bool usesEval
) { m_usesEval
= usesEval
; }
338 bool usesEval() const { return m_usesEval
; }
339 void setUsesArguments(bool usesArguments
) { m_usesArguments
= usesArguments
; }
340 bool usesArguments() const { return m_usesArguments
; }
342 CodeType
codeType() const { return m_codeType
; }
344 SourceProvider
* source() const { ASSERT(m_codeType
!= NativeCode
); return m_source
.get(); }
345 unsigned sourceOffset() const { ASSERT(m_codeType
!= NativeCode
); return m_sourceOffset
; }
347 size_t numberOfJumpTargets() const { return m_jumpTargets
.size(); }
348 void addJumpTarget(unsigned jumpTarget
) { m_jumpTargets
.append(jumpTarget
); }
349 unsigned jumpTarget(int index
) const { return m_jumpTargets
[index
]; }
350 unsigned lastJumpTarget() const { return m_jumpTargets
.last(); }
353 void addPropertyAccessInstruction(unsigned propertyAccessInstruction
) { m_propertyAccessInstructions
.append(propertyAccessInstruction
); }
354 void addGlobalResolveInstruction(unsigned globalResolveInstruction
) { m_globalResolveInstructions
.append(globalResolveInstruction
); }
355 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset
);
357 size_t numberOfStructureStubInfos() const { return m_structureStubInfos
.size(); }
358 void addStructureStubInfo(const StructureStubInfo
& stubInfo
) { m_structureStubInfos
.append(stubInfo
); }
359 StructureStubInfo
& structureStubInfo(int index
) { return m_structureStubInfos
[index
]; }
361 void addGlobalResolveInfo(unsigned globalResolveInstruction
) { m_globalResolveInfos
.append(GlobalResolveInfo(globalResolveInstruction
)); }
362 GlobalResolveInfo
& globalResolveInfo(int index
) { return m_globalResolveInfos
[index
]; }
363 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset
);
365 size_t numberOfCallLinkInfos() const { return m_callLinkInfos
.size(); }
366 void addCallLinkInfo() { m_callLinkInfos
.append(CallLinkInfo()); }
367 CallLinkInfo
& callLinkInfo(int index
) { return m_callLinkInfos
[index
]; }
369 void addMethodCallLinkInfos(unsigned n
) { m_methodCallLinkInfos
.grow(n
); }
370 MethodCallLinkInfo
& methodCallLinkInfo(int index
) { return m_methodCallLinkInfos
[index
]; }
372 void addFunctionRegisterInfo(unsigned bytecodeOffset
, int functionIndex
) { createRareDataIfNecessary(); m_rareData
->m_functionRegisterInfos
.append(FunctionRegisterInfo(bytecodeOffset
, functionIndex
)); }
375 // Exception handling support
377 size_t numberOfExceptionHandlers() const { return m_rareData
? m_rareData
->m_exceptionHandlers
.size() : 0; }
378 void addExceptionHandler(const HandlerInfo
& hanler
) { createRareDataIfNecessary(); return m_rareData
->m_exceptionHandlers
.append(hanler
); }
379 HandlerInfo
& exceptionHandler(int index
) { ASSERT(m_rareData
); return m_rareData
->m_exceptionHandlers
[index
]; }
381 bool hasExceptionInfo() const { return m_exceptionInfo
; }
382 void clearExceptionInfo() { m_exceptionInfo
.clear(); }
384 void addExpressionInfo(const ExpressionRangeInfo
& expressionInfo
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_expressionInfo
.append(expressionInfo
); }
385 void addGetByIdExceptionInfo(const GetByIdExceptionInfo
& info
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_getByIdExceptionInfo
.append(info
); }
387 size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_lineInfo
.size(); }
388 void addLineInfo(const LineInfo
& lineInfo
) { ASSERT(m_exceptionInfo
); m_exceptionInfo
->m_lineInfo
.append(lineInfo
); }
389 LineInfo
& lastLineInfo() { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_lineInfo
.last(); }
392 Vector
<CallReturnOffsetToBytecodeIndex
>& callReturnIndexVector() { ASSERT(m_exceptionInfo
); return m_exceptionInfo
->m_callReturnIndexVector
; }
397 size_t numberOfIdentifiers() const { return m_identifiers
.size(); }
398 void addIdentifier(const Identifier
& i
) { return m_identifiers
.append(i
); }
399 Identifier
& identifier(int index
) { return m_identifiers
[index
]; }
401 size_t numberOfConstantRegisters() const { return m_constantRegisters
.size(); }
402 void addConstantRegister(const Register
& r
) { return m_constantRegisters
.append(r
); }
403 Register
& constantRegister(int index
) { return m_constantRegisters
[index
- FirstConstantRegisterIndex
]; }
404 ALWAYS_INLINE
bool isConstantRegisterIndex(int index
) { return index
>= FirstConstantRegisterIndex
; }
405 ALWAYS_INLINE JSValue
getConstant(int index
) const { return m_constantRegisters
[index
- FirstConstantRegisterIndex
].jsValue(); }
407 unsigned addFunctionExpression(FuncExprNode
* n
) { unsigned size
= m_functionExpressions
.size(); m_functionExpressions
.append(n
); return size
; }
408 FuncExprNode
* functionExpression(int index
) const { return m_functionExpressions
[index
].get(); }
410 unsigned addFunction(FuncDeclNode
* n
) { createRareDataIfNecessary(); unsigned size
= m_rareData
->m_functions
.size(); m_rareData
->m_functions
.append(n
); return size
; }
411 FuncDeclNode
* function(int index
) const { ASSERT(m_rareData
); return m_rareData
->m_functions
[index
].get(); }
413 bool hasFunctions() const { return m_functionExpressions
.size() || (m_rareData
&& m_rareData
->m_functions
.size()); }
415 unsigned addRegExp(RegExp
* r
) { createRareDataIfNecessary(); unsigned size
= m_rareData
->m_regexps
.size(); m_rareData
->m_regexps
.append(r
); return size
; }
416 RegExp
* regexp(int index
) const { ASSERT(m_rareData
); return m_rareData
->m_regexps
[index
].get(); }
421 size_t numberOfImmediateSwitchJumpTables() const { return m_rareData
? m_rareData
->m_immediateSwitchJumpTables
.size() : 0; }
422 SimpleJumpTable
& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_immediateSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_immediateSwitchJumpTables
.last(); }
423 SimpleJumpTable
& immediateSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_immediateSwitchJumpTables
[tableIndex
]; }
425 size_t numberOfCharacterSwitchJumpTables() const { return m_rareData
? m_rareData
->m_characterSwitchJumpTables
.size() : 0; }
426 SimpleJumpTable
& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_characterSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_characterSwitchJumpTables
.last(); }
427 SimpleJumpTable
& characterSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_characterSwitchJumpTables
[tableIndex
]; }
429 size_t numberOfStringSwitchJumpTables() const { return m_rareData
? m_rareData
->m_stringSwitchJumpTables
.size() : 0; }
430 StringJumpTable
& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_stringSwitchJumpTables
.append(StringJumpTable()); return m_rareData
->m_stringSwitchJumpTables
.last(); }
431 StringJumpTable
& stringSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_stringSwitchJumpTables
[tableIndex
]; }
434 SymbolTable
& symbolTable() { return m_symbolTable
; }
436 EvalCodeCache
& evalCodeCache() { ASSERT(m_codeType
!= NativeCode
); createRareDataIfNecessary(); return m_rareData
->m_evalCodeCache
; }
440 // FIXME: Make these remaining members private.
442 int m_numCalleeRegisters
;
447 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
448 void dump(ExecState
*, const Vector
<Instruction
>::const_iterator
& begin
, Vector
<Instruction
>::const_iterator
&) const;
451 void reparseForExceptionInfoIfNecessary(CallFrame
*);
453 void createRareDataIfNecessary()
455 ASSERT(m_codeType
!= NativeCode
);
457 m_rareData
.set(new RareData
);
460 ScopeNode
* m_ownerNode
;
461 JSGlobalData
* m_globalData
;
463 Vector
<Instruction
> m_instructions
;
465 unsigned m_instructionCount
;
470 bool m_needsFullScopeChain
;
472 bool m_usesArguments
;
473 bool m_isNumericCompareFunction
;
477 RefPtr
<SourceProvider
> m_source
;
478 unsigned m_sourceOffset
;
481 Vector
<unsigned> m_propertyAccessInstructions
;
482 Vector
<unsigned> m_globalResolveInstructions
;
484 Vector
<StructureStubInfo
> m_structureStubInfos
;
485 Vector
<GlobalResolveInfo
> m_globalResolveInfos
;
486 Vector
<CallLinkInfo
> m_callLinkInfos
;
487 Vector
<MethodCallLinkInfo
> m_methodCallLinkInfos
;
488 Vector
<CallLinkInfo
*> m_linkedCallerList
;
491 Vector
<unsigned> m_jumpTargets
;
494 Vector
<Identifier
> m_identifiers
;
495 Vector
<Register
> m_constantRegisters
;
496 Vector
<RefPtr
<FuncExprNode
> > m_functionExpressions
;
498 SymbolTable m_symbolTable
;
500 struct ExceptionInfo
{
501 Vector
<ExpressionRangeInfo
> m_expressionInfo
;
502 Vector
<LineInfo
> m_lineInfo
;
503 Vector
<GetByIdExceptionInfo
> m_getByIdExceptionInfo
;
506 Vector
<CallReturnOffsetToBytecodeIndex
> m_callReturnIndexVector
;
509 OwnPtr
<ExceptionInfo
> m_exceptionInfo
;
512 Vector
<HandlerInfo
> m_exceptionHandlers
;
515 Vector
<RefPtr
<FuncDeclNode
> > m_functions
;
516 Vector
<RefPtr
<RegExp
> > m_regexps
;
519 Vector
<SimpleJumpTable
> m_immediateSwitchJumpTables
;
520 Vector
<SimpleJumpTable
> m_characterSwitchJumpTables
;
521 Vector
<StringJumpTable
> m_stringSwitchJumpTables
;
523 EvalCodeCache m_evalCodeCache
;
526 Vector
<FunctionRegisterInfo
> m_functionRegisterInfos
;
529 OwnPtr
<RareData
> m_rareData
;
532 // Program code is not marked by any function, so we make the global object
533 // responsible for marking it.
535 class ProgramCodeBlock
: public CodeBlock
{
537 ProgramCodeBlock(ScopeNode
* ownerNode
, CodeType codeType
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
)
538 : CodeBlock(ownerNode
, codeType
, sourceProvider
, 0)
539 , m_globalObject(globalObject
)
541 m_globalObject
->codeBlocks().add(this);
547 m_globalObject
->codeBlocks().remove(this);
550 void clearGlobalObject() { m_globalObject
= 0; }
553 JSGlobalObject
* m_globalObject
; // For program and eval nodes, the global object that marks the constant pool.
556 class EvalCodeBlock
: public ProgramCodeBlock
{
558 EvalCodeBlock(ScopeNode
* ownerNode
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
, int baseScopeDepth
)
559 : ProgramCodeBlock(ownerNode
, EvalCode
, globalObject
, sourceProvider
)
560 , m_baseScopeDepth(baseScopeDepth
)
564 int baseScopeDepth() const { return m_baseScopeDepth
; }
567 int m_baseScopeDepth
;
570 inline Register
& ExecState::r(int index
)
572 CodeBlock
* codeBlock
= this->codeBlock();
573 if (codeBlock
->isConstantRegisterIndex(index
))
574 return codeBlock
->constantRegister(index
);
580 #endif // CodeBlock_h