2 * Copyright (C) 2008, 2009, 2010 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 "JITWriteBarrier.h"
37 #include "JSGlobalObject.h"
38 #include "JumpTable.h"
40 #include "RegExpObject.h"
42 #include <wtf/FastAllocBase.h>
43 #include <wtf/PassOwnPtr.h>
44 #include <wtf/RefPtr.h>
45 #include <wtf/Vector.h>
48 #include "StructureStubInfo.h"
51 // Register numbers used in bytecode operations have different meaning according to their ranges:
52 // 0x80000000-0xFFFFFFFF Negative indices from the CallFrame pointer are entries in the call frame, see RegisterFile.h.
53 // 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe.
54 // 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock.
55 static const int FirstConstantRegisterIndex
= 0x40000000;
59 enum HasSeenShouldRepatch
{
65 enum CodeType
{ GlobalCode
, EvalCode
, FunctionCode
};
67 inline int unmodifiedArgumentsRegister(int argumentsRegister
) { return argumentsRegister
- 1; }
69 static ALWAYS_INLINE
int missingThisObjectMarker() { return std::numeric_limits
<int>::max(); }
77 CodeLocationLabel nativeCode
;
81 struct ExpressionRangeInfo
{
83 MaxOffset
= (1 << 7) - 1,
84 MaxDivot
= (1 << 25) - 1
86 uint32_t instructionOffset
: 25;
87 uint32_t divotPoint
: 25;
88 uint32_t startOffset
: 7;
89 uint32_t endOffset
: 7;
93 uint32_t instructionOffset
;
100 : hasSeenShouldRepatch(false)
105 CodeLocationNearCall callReturnLocation
;
106 CodeLocationDataLabelPtr hotPathBegin
;
107 CodeLocationNearCall hotPathOther
;
108 JITWriteBarrier
<JSFunction
> callee
;
109 bool hasSeenShouldRepatch
: 1;
112 bool isLinked() { return callee
; }
115 hasSeenShouldRepatch
= false;
121 return hasSeenShouldRepatch
;
126 hasSeenShouldRepatch
= true;
130 struct MethodCallLinkInfo
{
137 ASSERT(!cachedStructure
);
138 return cachedPrototypeStructure
.isFlagged();
143 ASSERT(!cachedStructure
&& !cachedPrototypeStructure
);
144 // We use the values of cachedStructure & cachedPrototypeStructure to indicate the
146 // - In the initial state, both are null.
147 // - Once this transition has been taken once, cachedStructure is
148 // null and cachedPrototypeStructure is set to a nun-null value.
149 // - Once the call is linked both structures are set to non-null values.
150 cachedPrototypeStructure
.setFlagOnBarrier();
153 CodeLocationCall callReturnLocation
;
154 JITWriteBarrier
<Structure
> cachedStructure
;
155 JITWriteBarrier
<Structure
> cachedPrototypeStructure
;
156 // We'd like this to actually be JSFunction, but InternalFunction and JSFunction
157 // don't have a common parent class and we allow specialisation on both
158 JITWriteBarrier
<JSObjectWithGlobalObject
> cachedFunction
;
159 JITWriteBarrier
<JSObject
> cachedPrototype
;
162 struct GlobalResolveInfo
{
163 GlobalResolveInfo(unsigned bytecodeOffset
)
165 , bytecodeOffset(bytecodeOffset
)
169 WriteBarrier
<Structure
> structure
;
171 unsigned bytecodeOffset
;
174 // This structure is used to map from a call return location
175 // (given as an offset in bytes into the JIT code) back to
176 // the bytecode index of the corresponding bytecode operation.
177 // This is then used to look up the corresponding handler.
178 struct CallReturnOffsetToBytecodeOffset
{
179 CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset
, unsigned bytecodeOffset
)
180 : callReturnOffset(callReturnOffset
)
181 , bytecodeOffset(bytecodeOffset
)
185 unsigned callReturnOffset
;
186 unsigned bytecodeOffset
;
189 // valueAtPosition helpers for the binarySearch algorithm.
191 inline void* getStructureStubInfoReturnLocation(StructureStubInfo
* structureStubInfo
)
193 return structureStubInfo
->callReturnLocation
.executableAddress();
196 inline void* getCallLinkInfoReturnLocation(CallLinkInfo
* callLinkInfo
)
198 return callLinkInfo
->callReturnLocation
.executableAddress();
201 inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo
* methodCallLinkInfo
)
203 return methodCallLinkInfo
->callReturnLocation
.executableAddress();
206 inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset
* pc
)
208 return pc
->callReturnOffset
;
213 WTF_MAKE_FAST_ALLOCATED
;
216 CodeBlock(ScriptExecutable
* ownerExecutable
, CodeType
, JSGlobalObject
*, PassRefPtr
<SourceProvider
>, unsigned sourceOffset
, SymbolTable
* symbolTable
, bool isConstructor
);
218 WriteBarrier
<JSGlobalObject
> m_globalObject
;
222 virtual ~CodeBlock();
224 void visitAggregate(SlotVisitor
&);
226 static void dumpStatistics();
228 #if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
229 void dump(ExecState
*) const;
230 void printStructures(const Instruction
*) const;
231 void printStructure(const char* name
, const Instruction
*, int operand
) const;
234 bool isStrictMode() const { return m_isStrictMode
; }
236 inline bool isKnownNotImmediate(int index
)
238 if (index
== m_thisRegister
&& !m_isStrictMode
)
241 if (isConstantRegisterIndex(index
))
242 return getConstant(index
).isCell();
247 ALWAYS_INLINE
bool isTemporaryRegisterIndex(int index
)
249 return index
>= m_numVars
;
252 HandlerInfo
* handlerForBytecodeOffset(unsigned bytecodeOffset
);
253 int lineNumberForBytecodeOffset(unsigned bytecodeOffset
);
254 void expressionRangeForBytecodeOffset(unsigned bytecodeOffset
, int& divot
, int& startOffset
, int& endOffset
);
258 StructureStubInfo
& getStubInfo(ReturnAddressPtr returnAddress
)
260 return *(binarySearch
<StructureStubInfo
, void*, getStructureStubInfoReturnLocation
>(m_structureStubInfos
.begin(), m_structureStubInfos
.size(), returnAddress
.value()));
263 CallLinkInfo
& getCallLinkInfo(ReturnAddressPtr returnAddress
)
265 return *(binarySearch
<CallLinkInfo
, void*, getCallLinkInfoReturnLocation
>(m_callLinkInfos
.begin(), m_callLinkInfos
.size(), returnAddress
.value()));
268 MethodCallLinkInfo
& getMethodCallLinkInfo(ReturnAddressPtr returnAddress
)
270 return *(binarySearch
<MethodCallLinkInfo
, void*, getMethodCallLinkInfoReturnLocation
>(m_methodCallLinkInfos
.begin(), m_methodCallLinkInfos
.size(), returnAddress
.value()));
273 unsigned bytecodeOffset(ReturnAddressPtr returnAddress
)
277 Vector
<CallReturnOffsetToBytecodeOffset
>& callIndices
= m_rareData
->m_callReturnIndexVector
;
278 if (!callIndices
.size())
280 return binarySearch
<CallReturnOffsetToBytecodeOffset
, unsigned, getCallReturnOffset
>(callIndices
.begin(), callIndices
.size(), getJITCode().offsetOf(returnAddress
.value()))->bytecodeOffset
;
286 #if ENABLE(INTERPRETER)
287 unsigned bytecodeOffset(Instruction
* returnAddress
)
289 return static_cast<Instruction
*>(returnAddress
) - instructions().begin();
293 void setIsNumericCompareFunction(bool isNumericCompareFunction
) { m_isNumericCompareFunction
= isNumericCompareFunction
; }
294 bool isNumericCompareFunction() { return m_isNumericCompareFunction
; }
296 Vector
<Instruction
>& instructions() { return m_instructions
; }
297 void discardBytecode() { m_instructions
.clear(); }
300 unsigned instructionCount() { return m_instructionCount
; }
301 void setInstructionCount(unsigned instructionCount
) { m_instructionCount
= instructionCount
; }
305 JITCode
& getJITCode() { return m_isConstructor
? ownerExecutable()->generatedJITCodeForConstruct() : ownerExecutable()->generatedJITCodeForCall(); }
306 ExecutablePool
* executablePool() { return getJITCode().getExecutablePool(); }
309 ScriptExecutable
* ownerExecutable() const { return m_ownerExecutable
.get(); }
311 void setGlobalData(JSGlobalData
* globalData
) { m_globalData
= globalData
; }
313 void setThisRegister(int thisRegister
) { m_thisRegister
= thisRegister
; }
314 int thisRegister() const { return m_thisRegister
; }
316 void setNeedsFullScopeChain(bool needsFullScopeChain
) { m_needsFullScopeChain
= needsFullScopeChain
; }
317 bool needsFullScopeChain() const { return m_needsFullScopeChain
; }
318 void setUsesEval(bool usesEval
) { m_usesEval
= usesEval
; }
319 bool usesEval() const { return m_usesEval
; }
321 void setArgumentsRegister(int argumentsRegister
)
323 ASSERT(argumentsRegister
!= -1);
324 m_argumentsRegister
= argumentsRegister
;
325 ASSERT(usesArguments());
327 int argumentsRegister()
329 ASSERT(usesArguments());
330 return m_argumentsRegister
;
332 void setActivationRegister(int activationRegister
)
334 m_activationRegister
= activationRegister
;
336 int activationRegister()
338 ASSERT(needsFullScopeChain());
339 return m_activationRegister
;
341 bool usesArguments() const { return m_argumentsRegister
!= -1; }
343 CodeType
codeType() const { return m_codeType
; }
345 SourceProvider
* source() const { return m_source
.get(); }
346 unsigned sourceOffset() const { return m_sourceOffset
; }
348 size_t numberOfJumpTargets() const { return m_jumpTargets
.size(); }
349 void addJumpTarget(unsigned jumpTarget
) { m_jumpTargets
.append(jumpTarget
); }
350 unsigned jumpTarget(int index
) const { return m_jumpTargets
[index
]; }
351 unsigned lastJumpTarget() const { return m_jumpTargets
.last(); }
353 void createActivation(CallFrame
*);
355 void clearEvalCache();
357 #if ENABLE(INTERPRETER)
358 void addPropertyAccessInstruction(unsigned propertyAccessInstruction
)
360 if (!m_globalData
->canUseJIT())
361 m_propertyAccessInstructions
.append(propertyAccessInstruction
);
363 void addGlobalResolveInstruction(unsigned globalResolveInstruction
)
365 if (!m_globalData
->canUseJIT())
366 m_globalResolveInstructions
.append(globalResolveInstruction
);
368 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset
);
371 size_t numberOfStructureStubInfos() const { return m_structureStubInfos
.size(); }
372 void addStructureStubInfo(const StructureStubInfo
& stubInfo
)
374 if (m_globalData
->canUseJIT())
375 m_structureStubInfos
.append(stubInfo
);
377 StructureStubInfo
& structureStubInfo(int index
) { return m_structureStubInfos
[index
]; }
379 void addGlobalResolveInfo(unsigned globalResolveInstruction
)
381 if (m_globalData
->canUseJIT())
382 m_globalResolveInfos
.append(GlobalResolveInfo(globalResolveInstruction
));
384 GlobalResolveInfo
& globalResolveInfo(int index
) { return m_globalResolveInfos
[index
]; }
385 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset
);
387 size_t numberOfCallLinkInfos() const { return m_callLinkInfos
.size(); }
388 void addCallLinkInfo() { m_callLinkInfos
.append(CallLinkInfo()); }
389 CallLinkInfo
& callLinkInfo(int index
) { return m_callLinkInfos
[index
]; }
391 void addMethodCallLinkInfos(unsigned n
) { ASSERT(m_globalData
->canUseJIT()); m_methodCallLinkInfos
.grow(n
); }
392 MethodCallLinkInfo
& methodCallLinkInfo(int index
) { return m_methodCallLinkInfos
[index
]; }
394 unsigned globalResolveInfoCount() const
397 if (m_globalData
->canUseJIT())
398 return m_globalResolveInfos
.size();
403 // Exception handling support
405 size_t numberOfExceptionHandlers() const { return m_rareData
? m_rareData
->m_exceptionHandlers
.size() : 0; }
406 void addExceptionHandler(const HandlerInfo
& hanler
) { createRareDataIfNecessary(); return m_rareData
->m_exceptionHandlers
.append(hanler
); }
407 HandlerInfo
& exceptionHandler(int index
) { ASSERT(m_rareData
); return m_rareData
->m_exceptionHandlers
[index
]; }
409 void addExpressionInfo(const ExpressionRangeInfo
& expressionInfo
)
411 createRareDataIfNecessary();
412 m_rareData
->m_expressionInfo
.append(expressionInfo
);
415 void addLineInfo(unsigned bytecodeOffset
, int lineNo
)
417 createRareDataIfNecessary();
418 Vector
<LineInfo
>& lineInfo
= m_rareData
->m_lineInfo
;
419 if (!lineInfo
.size() || lineInfo
.last().lineNumber
!= lineNo
) {
420 LineInfo info
= { bytecodeOffset
, lineNo
};
421 lineInfo
.append(info
);
425 bool hasExpressionInfo() { return m_rareData
&& m_rareData
->m_expressionInfo
.size(); }
426 bool hasLineInfo() { return m_rareData
&& m_rareData
->m_lineInfo
.size(); }
427 // We only generate exception handling info if the user is debugging
428 // (and may want line number info), or if the function contains exception handler.
429 bool needsCallReturnIndices()
432 (m_rareData
->m_expressionInfo
.size() || m_rareData
->m_lineInfo
.size() || m_rareData
->m_exceptionHandlers
.size());
436 Vector
<CallReturnOffsetToBytecodeOffset
>& callReturnIndexVector()
438 createRareDataIfNecessary();
439 return m_rareData
->m_callReturnIndexVector
;
445 size_t numberOfIdentifiers() const { return m_identifiers
.size(); }
446 void addIdentifier(const Identifier
& i
) { return m_identifiers
.append(i
); }
447 Identifier
& identifier(int index
) { return m_identifiers
[index
]; }
449 size_t numberOfConstantRegisters() const { return m_constantRegisters
.size(); }
450 void addConstant(JSValue v
)
452 m_constantRegisters
.append(WriteBarrier
<Unknown
>());
453 m_constantRegisters
.last().set(m_globalObject
->globalData(), m_ownerExecutable
.get(), v
);
455 WriteBarrier
<Unknown
>& constantRegister(int index
) { return m_constantRegisters
[index
- FirstConstantRegisterIndex
]; }
456 ALWAYS_INLINE
bool isConstantRegisterIndex(int index
) const { return index
>= FirstConstantRegisterIndex
; }
457 ALWAYS_INLINE JSValue
getConstant(int index
) const { return m_constantRegisters
[index
- FirstConstantRegisterIndex
].get(); }
459 unsigned addFunctionDecl(FunctionExecutable
* n
)
461 unsigned size
= m_functionDecls
.size();
462 m_functionDecls
.append(WriteBarrier
<FunctionExecutable
>());
463 m_functionDecls
.last().set(m_globalObject
->globalData(), m_ownerExecutable
.get(), n
);
466 FunctionExecutable
* functionDecl(int index
) { return m_functionDecls
[index
].get(); }
467 int numberOfFunctionDecls() { return m_functionDecls
.size(); }
468 unsigned addFunctionExpr(FunctionExecutable
* n
)
470 unsigned size
= m_functionExprs
.size();
471 m_functionExprs
.append(WriteBarrier
<FunctionExecutable
>());
472 m_functionExprs
.last().set(m_globalObject
->globalData(), m_ownerExecutable
.get(), n
);
475 FunctionExecutable
* functionExpr(int index
) { return m_functionExprs
[index
].get(); }
477 unsigned addRegExp(RegExp
* r
)
479 createRareDataIfNecessary();
480 unsigned size
= m_rareData
->m_regexps
.size();
481 m_rareData
->m_regexps
.append(WriteBarrier
<RegExp
>(*m_globalData
, ownerExecutable(), r
));
484 RegExp
* regexp(int index
) const { ASSERT(m_rareData
); return m_rareData
->m_regexps
[index
].get(); }
486 unsigned addConstantBuffer(unsigned length
)
488 createRareDataIfNecessary();
489 unsigned size
= m_rareData
->m_constantBuffers
.size();
490 m_rareData
->m_constantBuffers
.append(Vector
<JSValue
>(length
));
494 JSValue
* constantBuffer(unsigned index
)
497 return m_rareData
->m_constantBuffers
[index
].data();
500 JSGlobalObject
* globalObject() { return m_globalObject
.get(); }
504 size_t numberOfImmediateSwitchJumpTables() const { return m_rareData
? m_rareData
->m_immediateSwitchJumpTables
.size() : 0; }
505 SimpleJumpTable
& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_immediateSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_immediateSwitchJumpTables
.last(); }
506 SimpleJumpTable
& immediateSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_immediateSwitchJumpTables
[tableIndex
]; }
508 size_t numberOfCharacterSwitchJumpTables() const { return m_rareData
? m_rareData
->m_characterSwitchJumpTables
.size() : 0; }
509 SimpleJumpTable
& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_characterSwitchJumpTables
.append(SimpleJumpTable()); return m_rareData
->m_characterSwitchJumpTables
.last(); }
510 SimpleJumpTable
& characterSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_characterSwitchJumpTables
[tableIndex
]; }
512 size_t numberOfStringSwitchJumpTables() const { return m_rareData
? m_rareData
->m_stringSwitchJumpTables
.size() : 0; }
513 StringJumpTable
& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData
->m_stringSwitchJumpTables
.append(StringJumpTable()); return m_rareData
->m_stringSwitchJumpTables
.last(); }
514 StringJumpTable
& stringSwitchJumpTable(int tableIndex
) { ASSERT(m_rareData
); return m_rareData
->m_stringSwitchJumpTables
[tableIndex
]; }
517 SymbolTable
* symbolTable() { return m_symbolTable
; }
518 SharedSymbolTable
* sharedSymbolTable() { ASSERT(m_codeType
== FunctionCode
); return static_cast<SharedSymbolTable
*>(m_symbolTable
); }
520 EvalCodeCache
& evalCodeCache() { createRareDataIfNecessary(); return m_rareData
->m_evalCodeCache
; }
524 // FIXME: Make these remaining members private.
526 int m_numCalleeRegisters
;
528 int m_numCapturedVars
;
530 bool m_isConstructor
;
533 #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
534 void dump(ExecState
*, const Vector
<Instruction
>::const_iterator
& begin
, Vector
<Instruction
>::const_iterator
&) const;
536 CString
registerName(ExecState
*, int r
) const;
537 void printUnaryOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
538 void printBinaryOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
539 void printConditionalJump(ExecState
*, const Vector
<Instruction
>::const_iterator
&, Vector
<Instruction
>::const_iterator
&, int location
, const char* op
) const;
540 void printGetByIdOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
541 void printPutByIdOp(ExecState
*, int location
, Vector
<Instruction
>::const_iterator
&, const char* op
) const;
543 void visitStructures(SlotVisitor
&, Instruction
* vPC
) const;
545 void createRareDataIfNecessary()
548 m_rareData
= adoptPtr(new RareData
);
551 WriteBarrier
<ScriptExecutable
> m_ownerExecutable
;
552 JSGlobalData
* m_globalData
;
554 Vector
<Instruction
> m_instructions
;
556 unsigned m_instructionCount
;
560 int m_argumentsRegister
;
561 int m_activationRegister
;
563 bool m_needsFullScopeChain
;
565 bool m_isNumericCompareFunction
;
570 RefPtr
<SourceProvider
> m_source
;
571 unsigned m_sourceOffset
;
573 #if ENABLE(INTERPRETER)
574 Vector
<unsigned> m_propertyAccessInstructions
;
575 Vector
<unsigned> m_globalResolveInstructions
;
578 Vector
<StructureStubInfo
> m_structureStubInfos
;
579 Vector
<GlobalResolveInfo
> m_globalResolveInfos
;
580 Vector
<CallLinkInfo
> m_callLinkInfos
;
581 Vector
<MethodCallLinkInfo
> m_methodCallLinkInfos
;
584 Vector
<unsigned> m_jumpTargets
;
587 Vector
<Identifier
> m_identifiers
;
588 COMPILE_ASSERT(sizeof(Register
) == sizeof(WriteBarrier
<Unknown
>), Register_must_be_same_size_as_WriteBarrier_Unknown
);
589 Vector
<WriteBarrier
<Unknown
> > m_constantRegisters
;
590 Vector
<WriteBarrier
<FunctionExecutable
> > m_functionDecls
;
591 Vector
<WriteBarrier
<FunctionExecutable
> > m_functionExprs
;
593 SymbolTable
* m_symbolTable
;
596 WTF_MAKE_FAST_ALLOCATED
;
598 Vector
<HandlerInfo
> m_exceptionHandlers
;
601 Vector
<WriteBarrier
<RegExp
> > m_regexps
;
603 // Buffers used for large array literals
604 Vector
<Vector
<JSValue
> > m_constantBuffers
;
607 Vector
<SimpleJumpTable
> m_immediateSwitchJumpTables
;
608 Vector
<SimpleJumpTable
> m_characterSwitchJumpTables
;
609 Vector
<StringJumpTable
> m_stringSwitchJumpTables
;
611 EvalCodeCache m_evalCodeCache
;
613 // Expression info - present if debugging.
614 Vector
<ExpressionRangeInfo
> m_expressionInfo
;
615 // Line info - present if profiling or debugging.
616 Vector
<LineInfo
> m_lineInfo
;
618 Vector
<CallReturnOffsetToBytecodeOffset
> m_callReturnIndexVector
;
622 friend void WTF::deleteOwnedPtr
<RareData
>(RareData
*);
624 OwnPtr
<RareData
> m_rareData
;
627 // Program code is not marked by any function, so we make the global object
628 // responsible for marking it.
630 class GlobalCodeBlock
: public CodeBlock
{
632 GlobalCodeBlock(ScriptExecutable
* ownerExecutable
, CodeType codeType
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
, unsigned sourceOffset
)
633 : CodeBlock(ownerExecutable
, codeType
, globalObject
, sourceProvider
, sourceOffset
, &m_unsharedSymbolTable
, false)
638 SymbolTable m_unsharedSymbolTable
;
641 class ProgramCodeBlock
: public GlobalCodeBlock
{
643 ProgramCodeBlock(ProgramExecutable
* ownerExecutable
, CodeType codeType
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
)
644 : GlobalCodeBlock(ownerExecutable
, codeType
, globalObject
, sourceProvider
, 0)
649 class EvalCodeBlock
: public GlobalCodeBlock
{
651 EvalCodeBlock(EvalExecutable
* ownerExecutable
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
, int baseScopeDepth
)
652 : GlobalCodeBlock(ownerExecutable
, EvalCode
, globalObject
, sourceProvider
, 0)
653 , m_baseScopeDepth(baseScopeDepth
)
657 int baseScopeDepth() const { return m_baseScopeDepth
; }
659 const Identifier
& variable(unsigned index
) { return m_variables
[index
]; }
660 unsigned numVariables() { return m_variables
.size(); }
661 void adoptVariables(Vector
<Identifier
>& variables
)
663 ASSERT(m_variables
.isEmpty());
664 m_variables
.swap(variables
);
668 int m_baseScopeDepth
;
669 Vector
<Identifier
> m_variables
;
672 class FunctionCodeBlock
: public CodeBlock
{
674 // Rather than using the usual RefCounted::create idiom for SharedSymbolTable we just use new
675 // as we need to initialise the CodeBlock before we could initialise any RefPtr to hold the shared
676 // symbol table, so we just pass as a raw pointer with a ref count of 1. We then manually deref
677 // in the destructor.
678 FunctionCodeBlock(FunctionExecutable
* ownerExecutable
, CodeType codeType
, JSGlobalObject
* globalObject
, PassRefPtr
<SourceProvider
> sourceProvider
, unsigned sourceOffset
, bool isConstructor
)
679 : CodeBlock(ownerExecutable
, codeType
, globalObject
, sourceProvider
, sourceOffset
, SharedSymbolTable::create().leakRef(), isConstructor
)
684 sharedSymbolTable()->deref();
688 inline Register
& ExecState::r(int index
)
690 CodeBlock
* codeBlock
= this->codeBlock();
691 if (codeBlock
->isConstantRegisterIndex(index
))
692 return *reinterpret_cast<Register
*>(&codeBlock
->constantRegister(index
));
696 inline Register
& ExecState::uncheckedR(int index
)
698 ASSERT(index
< FirstConstantRegisterIndex
);
704 #endif // CodeBlock_h