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.
30 #ifndef BytecodeGenerator_h
31 #define BytecodeGenerator_h
33 #include "CodeBlock.h"
34 #include "HashTraits.h"
35 #include "Instruction.h"
37 #include "LabelScope.h"
38 #include "Interpreter.h"
39 #include "RegisterID.h"
40 #include "SymbolTable.h"
43 #include <wtf/FastAllocBase.h>
44 #include <wtf/PassRefPtr.h>
45 #include <wtf/SegmentedVector.h>
46 #include <wtf/Vector.h>
54 struct FinallyContext
{
56 RegisterID
* retAddrDst
;
59 struct ControlFlowContext
{
61 FinallyContext finallyContext
;
65 RefPtr
<RegisterID
> expectedSubscriptRegister
;
66 RefPtr
<RegisterID
> iterRegister
;
67 RefPtr
<RegisterID
> indexRegister
;
68 RefPtr
<RegisterID
> propertyRegister
;
71 class BytecodeGenerator
: public FastAllocBase
{
73 typedef DeclarationStacks::VarStack VarStack
;
74 typedef DeclarationStacks::FunctionStack FunctionStack
;
76 static void setDumpsGeneratedCode(bool dumpsGeneratedCode
);
77 static bool dumpsGeneratedCode();
79 BytecodeGenerator(ProgramNode
*, const Debugger
*, const ScopeChain
&, SymbolTable
*, ProgramCodeBlock
*);
80 BytecodeGenerator(FunctionBodyNode
*, const Debugger
*, const ScopeChain
&, SymbolTable
*, CodeBlock
*);
81 BytecodeGenerator(EvalNode
*, const Debugger
*, const ScopeChain
&, SymbolTable
*, EvalCodeBlock
*);
83 JSGlobalData
* globalData() const { return m_globalData
; }
84 const CommonIdentifiers
& propertyNames() const { return *m_globalData
->propertyNames
; }
88 // Returns the register corresponding to a local variable, or 0 if no
89 // such register exists. Registers returned by registerFor do not
90 // require explicit reference counting.
91 RegisterID
* registerFor(const Identifier
&);
93 bool willResolveToArguments(const Identifier
&);
94 RegisterID
* uncheckedRegisterForArguments();
96 // Behaves as registerFor does, but ignores dynamic scope as
97 // dynamic scope should not interfere with const initialisation
98 RegisterID
* constRegisterFor(const Identifier
&);
100 // Searches the scope chain in an attempt to statically locate the requested
101 // property. Returns false if for any reason the property cannot be safely
102 // optimised at all. Otherwise it will return the index and depth of the
103 // VariableObject that defines the property. If the property cannot be found
104 // statically, depth will contain the depth of the scope chain where dynamic
105 // lookup must begin.
107 // NB: depth does _not_ include the local scope. eg. a depth of 0 refers
108 // to the scope containing this codeblock.
109 bool findScopedProperty(const Identifier
&, int& index
, size_t& depth
, bool forWriting
, JSObject
*& globalObject
);
111 // Returns the register storing "this"
112 RegisterID
* thisRegister() { return &m_thisRegister
; }
114 bool isLocal(const Identifier
&);
115 bool isLocalConstant(const Identifier
&);
117 // Returns the next available temporary register. Registers returned by
118 // newTemporary require a modified form of reference counting: any
119 // register with a refcount of 0 is considered "available", meaning that
120 // the next instruction may overwrite it.
121 RegisterID
* newTemporary();
123 RegisterID
* highestUsedRegister();
125 // The same as newTemporary(), but this function returns "suggestion" if
126 // "suggestion" is a temporary. This function is helpful in situations
127 // where you've put "suggestion" in a RefPtr, but you'd like to allow
128 // the next instruction to overwrite it anyway.
129 RegisterID
* newTemporaryOr(RegisterID
* suggestion
) { return suggestion
->isTemporary() ? suggestion
: newTemporary(); }
131 // Functions for handling of dst register
133 RegisterID
* ignoredResult() { return &m_ignoredResultRegister
; }
135 // Returns a place to write intermediate values of an operation
136 // which reuses dst if it is safe to do so.
137 RegisterID
* tempDestination(RegisterID
* dst
)
139 return (dst
&& dst
!= ignoredResult() && dst
->isTemporary()) ? dst
: newTemporary();
142 // Returns the place to write the final output of an operation.
143 RegisterID
* finalDestination(RegisterID
* originalDst
, RegisterID
* tempDst
= 0)
145 if (originalDst
&& originalDst
!= ignoredResult())
147 ASSERT(tempDst
!= ignoredResult());
148 if (tempDst
&& tempDst
->isTemporary())
150 return newTemporary();
153 RegisterID
* destinationForAssignResult(RegisterID
* dst
)
155 if (dst
&& dst
!= ignoredResult() && m_codeBlock
->needsFullScopeChain())
156 return dst
->isTemporary() ? dst
: newTemporary();
160 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
161 RegisterID
* moveToDestinationIfNeeded(RegisterID
* dst
, RegisterID
* src
)
163 return dst
== ignoredResult() ? 0 : (dst
&& dst
!= src
) ? emitMove(dst
, src
) : src
;
166 PassRefPtr
<LabelScope
> newLabelScope(LabelScope::Type
, const Identifier
* = 0);
167 PassRefPtr
<Label
> newLabel();
169 // The emitNode functions are just syntactic sugar for calling
170 // Node::emitCode. These functions accept a 0 for the register,
171 // meaning that the node should allocate a register, or ignoredResult(),
172 // meaning that the node need not put the result in a register.
173 // Other emit functions do not accept 0 or ignoredResult().
174 RegisterID
* emitNode(RegisterID
* dst
, Node
* n
)
176 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
177 ASSERT(!dst
|| dst
== ignoredResult() || !dst
->isTemporary() || dst
->refCount());
178 if (!m_codeBlock
->numberOfLineInfos() || m_codeBlock
->lastLineInfo().lineNumber
!= n
->lineNo()) {
179 LineInfo info
= { instructions().size(), n
->lineNo() };
180 m_codeBlock
->addLineInfo(info
);
182 if (m_emitNodeDepth
>= s_maxEmitNodeDepth
)
183 return emitThrowExpressionTooDeepException();
185 RegisterID
* r
= n
->emitBytecode(*this, dst
);
190 RegisterID
* emitNode(Node
* n
)
192 return emitNode(0, n
);
195 void emitNodeInConditionContext(ExpressionNode
* n
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
197 if (!m_codeBlock
->numberOfLineInfos() || m_codeBlock
->lastLineInfo().lineNumber
!= n
->lineNo()) {
198 LineInfo info
= { instructions().size(), n
->lineNo() };
199 m_codeBlock
->addLineInfo(info
);
201 if (m_emitNodeDepth
>= s_maxEmitNodeDepth
)
202 emitThrowExpressionTooDeepException();
204 n
->emitBytecodeInConditionContext(*this, trueTarget
, falseTarget
, fallThroughMeansTrue
);
208 void emitExpressionInfo(unsigned divot
, unsigned startOffset
, unsigned endOffset
)
210 divot
-= m_codeBlock
->sourceOffset();
211 if (divot
> ExpressionRangeInfo::MaxDivot
) {
212 // Overflow has occurred, we can only give line number info for errors for this region
216 } else if (startOffset
> ExpressionRangeInfo::MaxOffset
) {
217 // If the start offset is out of bounds we clear both offsets
218 // so we only get the divot marker. Error message will have to be reduced
219 // to line and column number.
222 } else if (endOffset
> ExpressionRangeInfo::MaxOffset
) {
223 // The end offset is only used for additional context, and is much more likely
224 // to overflow (eg. function call arguments) so we are willing to drop it without
225 // dropping the rest of the range.
229 ExpressionRangeInfo info
;
230 info
.instructionOffset
= instructions().size();
231 info
.divotPoint
= divot
;
232 info
.startOffset
= startOffset
;
233 info
.endOffset
= endOffset
;
234 m_codeBlock
->addExpressionInfo(info
);
237 void emitGetByIdExceptionInfo(OpcodeID opcodeID
)
239 // Only op_construct and op_instanceof need exception info for
240 // a preceding op_get_by_id.
241 ASSERT(opcodeID
== op_construct
|| opcodeID
== op_instanceof
);
242 GetByIdExceptionInfo info
;
243 info
.bytecodeOffset
= instructions().size();
244 info
.isOpConstruct
= (opcodeID
== op_construct
);
245 m_codeBlock
->addGetByIdExceptionInfo(info
);
248 ALWAYS_INLINE
bool leftHandSideNeedsCopy(bool rightHasAssignments
, bool rightIsPure
)
250 return (m_codeType
!= FunctionCode
|| m_codeBlock
->needsFullScopeChain() || rightHasAssignments
) && !rightIsPure
;
253 ALWAYS_INLINE PassRefPtr
<RegisterID
> emitNodeForLeftHandSide(ExpressionNode
* n
, bool rightHasAssignments
, bool rightIsPure
)
255 if (leftHandSideNeedsCopy(rightHasAssignments
, rightIsPure
)) {
256 PassRefPtr
<RegisterID
> dst
= newTemporary();
257 emitNode(dst
.get(), n
);
261 return PassRefPtr
<RegisterID
>(emitNode(n
));
264 RegisterID
* emitLoad(RegisterID
* dst
, bool);
265 RegisterID
* emitLoad(RegisterID
* dst
, double);
266 RegisterID
* emitLoad(RegisterID
* dst
, const Identifier
&);
267 RegisterID
* emitLoad(RegisterID
* dst
, JSValue
);
269 RegisterID
* emitUnaryOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src
);
270 RegisterID
* emitBinaryOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
, OperandTypes
);
271 RegisterID
* emitEqualityOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
);
272 RegisterID
* emitUnaryNoDstOp(OpcodeID
, RegisterID
* src
);
274 RegisterID
* emitNewObject(RegisterID
* dst
);
275 RegisterID
* emitNewArray(RegisterID
* dst
, ElementNode
*); // stops at first elision
277 RegisterID
* emitNewFunction(RegisterID
* dst
, FunctionBodyNode
* body
);
278 RegisterID
* emitNewFunctionExpression(RegisterID
* dst
, FuncExprNode
* func
);
279 RegisterID
* emitNewRegExp(RegisterID
* dst
, RegExp
* regExp
);
281 RegisterID
* emitMove(RegisterID
* dst
, RegisterID
* src
);
283 RegisterID
* emitToJSNumber(RegisterID
* dst
, RegisterID
* src
) { return emitUnaryOp(op_to_jsnumber
, dst
, src
); }
284 RegisterID
* emitPreInc(RegisterID
* srcDst
);
285 RegisterID
* emitPreDec(RegisterID
* srcDst
);
286 RegisterID
* emitPostInc(RegisterID
* dst
, RegisterID
* srcDst
);
287 RegisterID
* emitPostDec(RegisterID
* dst
, RegisterID
* srcDst
);
289 RegisterID
* emitInstanceOf(RegisterID
* dst
, RegisterID
* value
, RegisterID
* base
, RegisterID
* basePrototype
);
290 RegisterID
* emitTypeOf(RegisterID
* dst
, RegisterID
* src
) { return emitUnaryOp(op_typeof
, dst
, src
); }
291 RegisterID
* emitIn(RegisterID
* dst
, RegisterID
* property
, RegisterID
* base
) { return emitBinaryOp(op_in
, dst
, property
, base
, OperandTypes()); }
293 RegisterID
* emitResolve(RegisterID
* dst
, const Identifier
& property
);
294 RegisterID
* emitGetScopedVar(RegisterID
* dst
, size_t skip
, int index
, JSValue globalObject
);
295 RegisterID
* emitPutScopedVar(size_t skip
, int index
, RegisterID
* value
, JSValue globalObject
);
297 RegisterID
* emitResolveBase(RegisterID
* dst
, const Identifier
& property
);
298 RegisterID
* emitResolveWithBase(RegisterID
* baseDst
, RegisterID
* propDst
, const Identifier
& property
);
300 void emitMethodCheck();
302 RegisterID
* emitGetById(RegisterID
* dst
, RegisterID
* base
, const Identifier
& property
);
303 RegisterID
* emitPutById(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
304 RegisterID
* emitDeleteById(RegisterID
* dst
, RegisterID
* base
, const Identifier
&);
305 RegisterID
* emitGetByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
);
306 RegisterID
* emitPutByVal(RegisterID
* base
, RegisterID
* property
, RegisterID
* value
);
307 RegisterID
* emitDeleteByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
);
308 RegisterID
* emitPutByIndex(RegisterID
* base
, unsigned index
, RegisterID
* value
);
309 RegisterID
* emitPutGetter(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
310 RegisterID
* emitPutSetter(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
312 RegisterID
* emitCall(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, ArgumentsNode
*, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
313 RegisterID
* emitCallEval(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, ArgumentsNode
*, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
314 RegisterID
* emitCallVarargs(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, RegisterID
* argCount
, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
315 RegisterID
* emitLoadVarargs(RegisterID
* argCountDst
, RegisterID
* args
);
317 RegisterID
* emitReturn(RegisterID
* src
);
318 RegisterID
* emitEnd(RegisterID
* src
) { return emitUnaryNoDstOp(op_end
, src
); }
320 RegisterID
* emitConstruct(RegisterID
* dst
, RegisterID
* func
, ArgumentsNode
*, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
321 RegisterID
* emitStrcat(RegisterID
* dst
, RegisterID
* src
, int count
);
322 void emitToPrimitive(RegisterID
* dst
, RegisterID
* src
);
324 PassRefPtr
<Label
> emitLabel(Label
*);
325 PassRefPtr
<Label
> emitJump(Label
* target
);
326 PassRefPtr
<Label
> emitJumpIfTrue(RegisterID
* cond
, Label
* target
);
327 PassRefPtr
<Label
> emitJumpIfFalse(RegisterID
* cond
, Label
* target
);
328 PassRefPtr
<Label
> emitJumpIfNotFunctionCall(RegisterID
* cond
, Label
* target
);
329 PassRefPtr
<Label
> emitJumpIfNotFunctionApply(RegisterID
* cond
, Label
* target
);
330 PassRefPtr
<Label
> emitJumpScopes(Label
* target
, int targetScopeDepth
);
332 PassRefPtr
<Label
> emitJumpSubroutine(RegisterID
* retAddrDst
, Label
*);
333 void emitSubroutineReturn(RegisterID
* retAddrSrc
);
335 RegisterID
* emitGetPropertyNames(RegisterID
* dst
, RegisterID
* base
, RegisterID
* i
, RegisterID
* size
, Label
* breakTarget
);
336 RegisterID
* emitNextPropertyName(RegisterID
* dst
, RegisterID
* base
, RegisterID
* i
, RegisterID
* size
, RegisterID
* iter
, Label
* target
);
338 RegisterID
* emitCatch(RegisterID
*, Label
* start
, Label
* end
);
339 void emitThrow(RegisterID
* exc
) { emitUnaryNoDstOp(op_throw
, exc
); }
340 RegisterID
* emitNewError(RegisterID
* dst
, ErrorType type
, JSValue message
);
341 void emitPushNewScope(RegisterID
* dst
, const Identifier
& property
, RegisterID
* value
);
343 RegisterID
* emitPushScope(RegisterID
* scope
);
346 void emitDebugHook(DebugHookID
, int firstLine
, int lastLine
);
348 int scopeDepth() { return m_dynamicScopeDepth
+ m_finallyDepth
; }
349 bool hasFinaliser() { return m_finallyDepth
!= 0; }
351 void pushFinallyContext(Label
* target
, RegisterID
* returnAddrDst
);
352 void popFinallyContext();
354 void pushOptimisedForIn(RegisterID
* expectedBase
, RegisterID
* iter
, RegisterID
* index
, RegisterID
* propertyRegister
)
356 ForInContext context
= { expectedBase
, iter
, index
, propertyRegister
};
357 m_forInContextStack
.append(context
);
360 void popOptimisedForIn()
362 m_forInContextStack
.removeLast();
365 LabelScope
* breakTarget(const Identifier
&);
366 LabelScope
* continueTarget(const Identifier
&);
368 void beginSwitch(RegisterID
*, SwitchInfo::SwitchType
);
369 void endSwitch(uint32_t clauseCount
, RefPtr
<Label
>*, ExpressionNode
**, Label
* defaultLabel
, int32_t min
, int32_t range
);
371 CodeType
codeType() const { return m_codeType
; }
373 void setRegeneratingForExceptionInfo(CodeBlock
* originalCodeBlock
)
375 m_regeneratingForExceptionInfo
= true;
376 m_codeBlockBeingRegeneratedFrom
= originalCodeBlock
;
380 void emitOpcode(OpcodeID
);
381 void retrieveLastBinaryOp(int& dstIndex
, int& src1Index
, int& src2Index
);
382 void retrieveLastUnaryOp(int& dstIndex
, int& srcIndex
);
383 void rewindBinaryOp();
384 void rewindUnaryOp();
386 PassRefPtr
<Label
> emitComplexJumpScopes(Label
* target
, ControlFlowContext
* topScope
, ControlFlowContext
* bottomScope
);
388 typedef HashMap
<EncodedJSValue
, unsigned, EncodedJSValueHash
, EncodedJSValueHashTraits
> JSValueMap
;
390 struct IdentifierMapIndexHashTraits
{
391 typedef int TraitType
;
392 typedef IdentifierMapIndexHashTraits StorageTraits
;
393 static int emptyValue() { return std::numeric_limits
<int>::max(); }
394 static const bool emptyValueIsZero
= false;
395 static const bool needsDestruction
= false;
396 static const bool needsRef
= false;
399 typedef HashMap
<RefPtr
<UString::Rep
>, int, IdentifierRepHash
, HashTraits
<RefPtr
<UString::Rep
> >, IdentifierMapIndexHashTraits
> IdentifierMap
;
400 typedef HashMap
<double, JSValue
> NumberMap
;
401 typedef HashMap
<UString::Rep
*, JSString
*, IdentifierRepHash
> IdentifierStringMap
;
403 RegisterID
* emitCall(OpcodeID
, RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, ArgumentsNode
*, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
405 RegisterID
* newRegister();
407 // Returns the RegisterID corresponding to ident.
408 RegisterID
* addVar(const Identifier
& ident
, bool isConstant
)
411 addVar(ident
, isConstant
, local
);
414 // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
415 bool addVar(const Identifier
&, bool isConstant
, RegisterID
*&);
417 // Returns the RegisterID corresponding to ident.
418 RegisterID
* addGlobalVar(const Identifier
& ident
, bool isConstant
)
421 addGlobalVar(ident
, isConstant
, local
);
424 // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
425 bool addGlobalVar(const Identifier
&, bool isConstant
, RegisterID
*&);
427 RegisterID
* addParameter(const Identifier
&);
429 void preserveLastVar();
431 RegisterID
& registerFor(int index
)
434 return m_calleeRegisters
[index
];
436 if (index
== RegisterFile::OptionalCalleeArguments
)
437 return m_argumentsRegister
;
439 if (m_parameters
.size()) {
440 ASSERT(!m_globals
.size());
441 return m_parameters
[index
+ m_parameters
.size() + RegisterFile::CallFrameHeaderSize
];
444 return m_globals
[-index
- 1];
447 unsigned addConstant(const Identifier
&);
448 RegisterID
* addConstantValue(JSValue
);
449 unsigned addRegExp(RegExp
*);
451 PassRefPtr
<FunctionExecutable
> makeFunction(ExecState
* exec
, FunctionBodyNode
* body
)
453 return FunctionExecutable::create(exec
, body
->ident(), body
->source(), body
->usesArguments(), body
->parameters(), body
->lineNo(), body
->lastLine());
456 PassRefPtr
<FunctionExecutable
> makeFunction(JSGlobalData
* globalData
, FunctionBodyNode
* body
)
458 return FunctionExecutable::create(globalData
, body
->ident(), body
->source(), body
->usesArguments(), body
->parameters(), body
->lineNo(), body
->lastLine());
461 Vector
<Instruction
>& instructions() { return m_codeBlock
->instructions(); }
462 SymbolTable
& symbolTable() { return *m_symbolTable
; }
464 bool shouldOptimizeLocals() { return (m_codeType
!= EvalCode
) && !m_dynamicScopeDepth
; }
465 bool canOptimizeNonLocals() { return (m_codeType
== FunctionCode
) && !m_dynamicScopeDepth
&& !m_codeBlock
->usesEval(); }
467 RegisterID
* emitThrowExpressionTooDeepException();
469 void createArgumentsIfNecessary();
471 bool m_shouldEmitDebugHooks
;
472 bool m_shouldEmitProfileHooks
;
474 const ScopeChain
* m_scopeChain
;
475 SymbolTable
* m_symbolTable
;
477 ScopeNode
* m_scopeNode
;
478 CodeBlock
* m_codeBlock
;
480 // Some of these objects keep pointers to one another. They are arranged
481 // to ensure a sane destruction order that avoids references to freed memory.
482 HashSet
<RefPtr
<UString::Rep
>, IdentifierRepHash
> m_functions
;
483 RegisterID m_ignoredResultRegister
;
484 RegisterID m_thisRegister
;
485 RegisterID m_argumentsRegister
;
486 int m_activationRegisterIndex
;
487 SegmentedVector
<RegisterID
, 32> m_constantPoolRegisters
;
488 SegmentedVector
<RegisterID
, 32> m_calleeRegisters
;
489 SegmentedVector
<RegisterID
, 32> m_parameters
;
490 SegmentedVector
<RegisterID
, 32> m_globals
;
491 SegmentedVector
<Label
, 32> m_labels
;
492 SegmentedVector
<LabelScope
, 8> m_labelScopes
;
493 RefPtr
<RegisterID
> m_lastVar
;
495 int m_dynamicScopeDepth
;
496 int m_baseScopeDepth
;
499 Vector
<ControlFlowContext
> m_scopeContextStack
;
500 Vector
<SwitchInfo
> m_switchContextStack
;
501 Vector
<ForInContext
> m_forInContextStack
;
503 int m_nextGlobalIndex
;
504 int m_nextParameterIndex
;
505 int m_firstConstantIndex
;
506 int m_nextConstantOffset
;
507 unsigned m_globalConstantIndex
;
509 int m_globalVarStorageOffset
;
512 IdentifierMap m_identifierMap
;
513 JSValueMap m_jsValueMap
;
514 NumberMap m_numberMap
;
515 IdentifierStringMap m_stringMap
;
517 JSGlobalData
* m_globalData
;
519 OpcodeID m_lastOpcodeID
;
521 unsigned m_emitNodeDepth
;
523 bool m_regeneratingForExceptionInfo
;
524 CodeBlock
* m_codeBlockBeingRegeneratedFrom
;
526 static const unsigned s_maxEmitNodeDepth
= 5000;
531 #endif // BytecodeGenerator_h