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/PassRefPtr.h>
44 #include <wtf/SegmentedVector.h>
45 #include <wtf/Vector.h>
54 CallArguments(BytecodeGenerator
& generator
, ArgumentsNode
* argumentsNode
);
56 RegisterID
* thisRegister() { return m_argv
[0].get(); }
57 RegisterID
* argumentRegister(unsigned i
) { return m_argv
[i
+ 1].get(); }
58 unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize
; }
59 unsigned count() { return m_argv
.size(); }
60 RegisterID
* profileHookRegister() { return m_profileHookRegister
.get(); }
61 ArgumentsNode
* argumentsNode() { return m_argumentsNode
; }
64 RefPtr
<RegisterID
> m_profileHookRegister
;
65 ArgumentsNode
* m_argumentsNode
;
66 Vector
<RefPtr
<RegisterID
>, 16> m_argv
;
69 struct FinallyContext
{
71 RegisterID
* retAddrDst
;
74 struct ControlFlowContext
{
76 FinallyContext finallyContext
;
80 RefPtr
<RegisterID
> expectedSubscriptRegister
;
81 RefPtr
<RegisterID
> iterRegister
;
82 RefPtr
<RegisterID
> indexRegister
;
83 RefPtr
<RegisterID
> propertyRegister
;
86 class BytecodeGenerator
{
87 WTF_MAKE_FAST_ALLOCATED
;
89 typedef DeclarationStacks::VarStack VarStack
;
90 typedef DeclarationStacks::FunctionStack FunctionStack
;
92 static void setDumpsGeneratedCode(bool dumpsGeneratedCode
);
93 static bool dumpsGeneratedCode();
95 BytecodeGenerator(ProgramNode
*, ScopeChainNode
*, SymbolTable
*, ProgramCodeBlock
*);
96 BytecodeGenerator(FunctionBodyNode
*, ScopeChainNode
*, SymbolTable
*, CodeBlock
*);
97 BytecodeGenerator(EvalNode
*, ScopeChainNode
*, SymbolTable
*, EvalCodeBlock
*);
99 JSGlobalData
* globalData() const { return m_globalData
; }
100 const CommonIdentifiers
& propertyNames() const { return *m_globalData
->propertyNames
; }
102 bool isConstructor() { return m_codeBlock
->m_isConstructor
; }
104 JSObject
* generate();
106 // Returns the register corresponding to a local variable, or 0 if no
107 // such register exists. Registers returned by registerFor do not
108 // require explicit reference counting.
109 RegisterID
* registerFor(const Identifier
&);
111 // Returns the agument number if this is an argument, or 0 if not.
112 int argumentNumberFor(const Identifier
&);
114 void setIsNumericCompareFunction(bool isNumericCompareFunction
);
116 bool willResolveToArguments(const Identifier
&);
117 RegisterID
* uncheckedRegisterForArguments();
119 // Behaves as registerFor does, but ignores dynamic scope as
120 // dynamic scope should not interfere with const initialisation
121 RegisterID
* constRegisterFor(const Identifier
&);
123 // Searches the scope chain in an attempt to statically locate the requested
124 // property. Returns false if for any reason the property cannot be safely
125 // optimised at all. Otherwise it will return the index and depth of the
126 // VariableObject that defines the property. If the property cannot be found
127 // statically, depth will contain the depth of the scope chain where dynamic
128 // lookup must begin.
129 bool findScopedProperty(const Identifier
&, int& index
, size_t& depth
, bool forWriting
, bool& includesDynamicScopes
, JSObject
*& globalObject
);
131 // Returns the register storing "this"
132 RegisterID
* thisRegister() { return &m_thisRegister
; }
134 bool isLocal(const Identifier
&);
135 bool isLocalConstant(const Identifier
&);
137 // Returns the next available temporary register. Registers returned by
138 // newTemporary require a modified form of reference counting: any
139 // register with a refcount of 0 is considered "available", meaning that
140 // the next instruction may overwrite it.
141 RegisterID
* newTemporary();
143 RegisterID
* highestUsedRegister();
145 // The same as newTemporary(), but this function returns "suggestion" if
146 // "suggestion" is a temporary. This function is helpful in situations
147 // where you've put "suggestion" in a RefPtr, but you'd like to allow
148 // the next instruction to overwrite it anyway.
149 RegisterID
* newTemporaryOr(RegisterID
* suggestion
) { return suggestion
->isTemporary() ? suggestion
: newTemporary(); }
151 // Functions for handling of dst register
153 RegisterID
* ignoredResult() { return &m_ignoredResultRegister
; }
155 // Returns a place to write intermediate values of an operation
156 // which reuses dst if it is safe to do so.
157 RegisterID
* tempDestination(RegisterID
* dst
)
159 return (dst
&& dst
!= ignoredResult() && dst
->isTemporary()) ? dst
: newTemporary();
162 // Returns the place to write the final output of an operation.
163 RegisterID
* finalDestination(RegisterID
* originalDst
, RegisterID
* tempDst
= 0)
165 if (originalDst
&& originalDst
!= ignoredResult())
167 ASSERT(tempDst
!= ignoredResult());
168 if (tempDst
&& tempDst
->isTemporary())
170 return newTemporary();
173 // Returns the place to write the final output of an operation.
174 RegisterID
* finalDestinationOrIgnored(RegisterID
* originalDst
, RegisterID
* tempDst
= 0)
178 ASSERT(tempDst
!= ignoredResult());
179 if (tempDst
&& tempDst
->isTemporary())
181 return newTemporary();
184 RegisterID
* destinationForAssignResult(RegisterID
* dst
)
186 if (dst
&& dst
!= ignoredResult() && m_codeBlock
->needsFullScopeChain())
187 return dst
->isTemporary() ? dst
: newTemporary();
191 // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
192 RegisterID
* moveToDestinationIfNeeded(RegisterID
* dst
, RegisterID
* src
)
194 return dst
== ignoredResult() ? 0 : (dst
&& dst
!= src
) ? emitMove(dst
, src
) : src
;
197 PassRefPtr
<LabelScope
> newLabelScope(LabelScope::Type
, const Identifier
* = 0);
198 PassRefPtr
<Label
> newLabel();
200 // The emitNode functions are just syntactic sugar for calling
201 // Node::emitCode. These functions accept a 0 for the register,
202 // meaning that the node should allocate a register, or ignoredResult(),
203 // meaning that the node need not put the result in a register.
204 // Other emit functions do not accept 0 or ignoredResult().
205 RegisterID
* emitNode(RegisterID
* dst
, Node
* n
)
207 // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
208 ASSERT(!dst
|| dst
== ignoredResult() || !dst
->isTemporary() || dst
->refCount());
209 addLineInfo(n
->lineNo());
210 return m_stack
.recursionCheck()
211 ? n
->emitBytecode(*this, dst
)
212 : emitThrowExpressionTooDeepException();
215 RegisterID
* emitNode(Node
* n
)
217 return emitNode(0, n
);
220 void emitNodeInConditionContext(ExpressionNode
* n
, Label
* trueTarget
, Label
* falseTarget
, bool fallThroughMeansTrue
)
222 addLineInfo(n
->lineNo());
223 if (m_stack
.recursionCheck())
224 n
->emitBytecodeInConditionContext(*this, trueTarget
, falseTarget
, fallThroughMeansTrue
);
226 emitThrowExpressionTooDeepException();
229 void emitExpressionInfo(unsigned divot
, unsigned startOffset
, unsigned endOffset
)
231 if (!m_shouldEmitRichSourceInfo
)
234 divot
-= m_codeBlock
->sourceOffset();
235 if (divot
> ExpressionRangeInfo::MaxDivot
) {
236 // Overflow has occurred, we can only give line number info for errors for this region
240 } else if (startOffset
> ExpressionRangeInfo::MaxOffset
) {
241 // If the start offset is out of bounds we clear both offsets
242 // so we only get the divot marker. Error message will have to be reduced
243 // to line and column number.
246 } else if (endOffset
> ExpressionRangeInfo::MaxOffset
) {
247 // The end offset is only used for additional context, and is much more likely
248 // to overflow (eg. function call arguments) so we are willing to drop it without
249 // dropping the rest of the range.
253 ExpressionRangeInfo info
;
254 info
.instructionOffset
= instructions().size();
255 info
.divotPoint
= divot
;
256 info
.startOffset
= startOffset
;
257 info
.endOffset
= endOffset
;
258 m_codeBlock
->addExpressionInfo(info
);
261 ALWAYS_INLINE
bool leftHandSideNeedsCopy(bool rightHasAssignments
, bool rightIsPure
)
263 return (m_codeType
!= FunctionCode
|| m_codeBlock
->needsFullScopeChain() || rightHasAssignments
) && !rightIsPure
;
266 ALWAYS_INLINE PassRefPtr
<RegisterID
> emitNodeForLeftHandSide(ExpressionNode
* n
, bool rightHasAssignments
, bool rightIsPure
)
268 if (leftHandSideNeedsCopy(rightHasAssignments
, rightIsPure
)) {
269 PassRefPtr
<RegisterID
> dst
= newTemporary();
270 emitNode(dst
.get(), n
);
274 return PassRefPtr
<RegisterID
>(emitNode(n
));
277 RegisterID
* emitLoad(RegisterID
* dst
, bool);
278 RegisterID
* emitLoad(RegisterID
* dst
, double);
279 RegisterID
* emitLoad(RegisterID
* dst
, const Identifier
&);
280 RegisterID
* emitLoad(RegisterID
* dst
, JSValue
);
282 RegisterID
* emitUnaryOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src
);
283 RegisterID
* emitBinaryOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
, OperandTypes
);
284 RegisterID
* emitEqualityOp(OpcodeID
, RegisterID
* dst
, RegisterID
* src1
, RegisterID
* src2
);
285 RegisterID
* emitUnaryNoDstOp(OpcodeID
, RegisterID
* src
);
287 RegisterID
* emitNewObject(RegisterID
* dst
);
288 RegisterID
* emitNewArray(RegisterID
* dst
, ElementNode
*, unsigned length
); // stops at first elision
290 RegisterID
* emitNewFunction(RegisterID
* dst
, FunctionBodyNode
* body
);
291 RegisterID
* emitLazyNewFunction(RegisterID
* dst
, FunctionBodyNode
* body
);
292 RegisterID
* emitNewFunctionInternal(RegisterID
* dst
, unsigned index
, bool shouldNullCheck
);
293 RegisterID
* emitNewFunctionExpression(RegisterID
* dst
, FuncExprNode
* func
);
294 RegisterID
* emitNewRegExp(RegisterID
* dst
, RegExp
*);
296 RegisterID
* emitMove(RegisterID
* dst
, RegisterID
* src
);
298 RegisterID
* emitToJSNumber(RegisterID
* dst
, RegisterID
* src
) { return emitUnaryOp(op_to_jsnumber
, dst
, src
); }
299 RegisterID
* emitPreInc(RegisterID
* srcDst
);
300 RegisterID
* emitPreDec(RegisterID
* srcDst
);
301 RegisterID
* emitPostInc(RegisterID
* dst
, RegisterID
* srcDst
);
302 RegisterID
* emitPostDec(RegisterID
* dst
, RegisterID
* srcDst
);
304 void emitCheckHasInstance(RegisterID
* base
);
305 RegisterID
* emitInstanceOf(RegisterID
* dst
, RegisterID
* value
, RegisterID
* base
, RegisterID
* basePrototype
);
306 RegisterID
* emitTypeOf(RegisterID
* dst
, RegisterID
* src
) { return emitUnaryOp(op_typeof
, dst
, src
); }
307 RegisterID
* emitIn(RegisterID
* dst
, RegisterID
* property
, RegisterID
* base
) { return emitBinaryOp(op_in
, dst
, property
, base
, OperandTypes()); }
309 RegisterID
* emitResolve(RegisterID
* dst
, const Identifier
& property
);
310 RegisterID
* emitGetScopedVar(RegisterID
* dst
, size_t skip
, int index
, JSValue globalObject
);
311 RegisterID
* emitPutScopedVar(size_t skip
, int index
, RegisterID
* value
, JSValue globalObject
);
313 RegisterID
* emitResolveBase(RegisterID
* dst
, const Identifier
& property
);
314 RegisterID
* emitResolveBaseForPut(RegisterID
* dst
, const Identifier
& property
);
315 RegisterID
* emitResolveWithBase(RegisterID
* baseDst
, RegisterID
* propDst
, const Identifier
& property
);
317 void emitMethodCheck();
319 RegisterID
* emitGetById(RegisterID
* dst
, RegisterID
* base
, const Identifier
& property
);
320 RegisterID
* emitGetArgumentsLength(RegisterID
* dst
, RegisterID
* base
);
321 RegisterID
* emitPutById(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
322 RegisterID
* emitDirectPutById(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
323 RegisterID
* emitDeleteById(RegisterID
* dst
, RegisterID
* base
, const Identifier
&);
324 RegisterID
* emitGetByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
);
325 RegisterID
* emitGetArgumentByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
);
326 RegisterID
* emitPutByVal(RegisterID
* base
, RegisterID
* property
, RegisterID
* value
);
327 RegisterID
* emitDeleteByVal(RegisterID
* dst
, RegisterID
* base
, RegisterID
* property
);
328 RegisterID
* emitPutByIndex(RegisterID
* base
, unsigned index
, RegisterID
* value
);
329 RegisterID
* emitPutGetter(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
330 RegisterID
* emitPutSetter(RegisterID
* base
, const Identifier
& property
, RegisterID
* value
);
332 RegisterID
* emitCall(RegisterID
* dst
, RegisterID
* func
, CallArguments
&, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
333 RegisterID
* emitCallEval(RegisterID
* dst
, RegisterID
* func
, CallArguments
&, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
334 RegisterID
* emitCallVarargs(RegisterID
* dst
, RegisterID
* func
, RegisterID
* thisRegister
, RegisterID
* argCount
, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
335 RegisterID
* emitLoadVarargs(RegisterID
* argCountDst
, RegisterID
* thisRegister
, RegisterID
* args
);
337 RegisterID
* emitReturn(RegisterID
* src
);
338 RegisterID
* emitEnd(RegisterID
* src
) { return emitUnaryNoDstOp(op_end
, src
); }
340 RegisterID
* emitConstruct(RegisterID
* dst
, RegisterID
* func
, CallArguments
&, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
341 RegisterID
* emitStrcat(RegisterID
* dst
, RegisterID
* src
, int count
);
342 void emitToPrimitive(RegisterID
* dst
, RegisterID
* src
);
344 PassRefPtr
<Label
> emitLabel(Label
*);
345 PassRefPtr
<Label
> emitJump(Label
* target
);
346 PassRefPtr
<Label
> emitJumpIfTrue(RegisterID
* cond
, Label
* target
);
347 PassRefPtr
<Label
> emitJumpIfFalse(RegisterID
* cond
, Label
* target
);
348 PassRefPtr
<Label
> emitJumpIfNotFunctionCall(RegisterID
* cond
, Label
* target
);
349 PassRefPtr
<Label
> emitJumpIfNotFunctionApply(RegisterID
* cond
, Label
* target
);
350 PassRefPtr
<Label
> emitJumpScopes(Label
* target
, int targetScopeDepth
);
352 PassRefPtr
<Label
> emitJumpSubroutine(RegisterID
* retAddrDst
, Label
*);
353 void emitSubroutineReturn(RegisterID
* retAddrSrc
);
355 RegisterID
* emitGetPropertyNames(RegisterID
* dst
, RegisterID
* base
, RegisterID
* i
, RegisterID
* size
, Label
* breakTarget
);
356 RegisterID
* emitNextPropertyName(RegisterID
* dst
, RegisterID
* base
, RegisterID
* i
, RegisterID
* size
, RegisterID
* iter
, Label
* target
);
358 RegisterID
* emitCatch(RegisterID
*, Label
* start
, Label
* end
);
359 void emitThrow(RegisterID
* exc
)
361 m_usesExceptions
= true;
362 emitUnaryNoDstOp(op_throw
, exc
);
365 void emitThrowReferenceError(const UString
& message
);
367 void emitPushNewScope(RegisterID
* dst
, const Identifier
& property
, RegisterID
* value
);
369 RegisterID
* emitPushScope(RegisterID
* scope
);
372 void emitDebugHook(DebugHookID
, int firstLine
, int lastLine
);
374 int scopeDepth() { return m_dynamicScopeDepth
+ m_finallyDepth
; }
375 bool hasFinaliser() { return m_finallyDepth
!= 0; }
377 void pushFinallyContext(Label
* target
, RegisterID
* returnAddrDst
);
378 void popFinallyContext();
380 void pushOptimisedForIn(RegisterID
* expectedBase
, RegisterID
* iter
, RegisterID
* index
, RegisterID
* propertyRegister
)
382 ForInContext context
= { expectedBase
, iter
, index
, propertyRegister
};
383 m_forInContextStack
.append(context
);
386 void popOptimisedForIn()
388 m_forInContextStack
.removeLast();
391 LabelScope
* breakTarget(const Identifier
&);
392 LabelScope
* continueTarget(const Identifier
&);
394 void beginSwitch(RegisterID
*, SwitchInfo::SwitchType
);
395 void endSwitch(uint32_t clauseCount
, RefPtr
<Label
>*, ExpressionNode
**, Label
* defaultLabel
, int32_t min
, int32_t range
);
397 CodeType
codeType() const { return m_codeType
; }
399 bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks
; }
401 bool isStrictMode() const { return m_codeBlock
->isStrictMode(); }
404 void emitOpcode(OpcodeID
);
405 void retrieveLastBinaryOp(int& dstIndex
, int& src1Index
, int& src2Index
);
406 void retrieveLastUnaryOp(int& dstIndex
, int& srcIndex
);
407 ALWAYS_INLINE
void rewindBinaryOp();
408 ALWAYS_INLINE
void rewindUnaryOp();
410 PassRefPtr
<Label
> emitComplexJumpScopes(Label
* target
, ControlFlowContext
* topScope
, ControlFlowContext
* bottomScope
);
412 typedef HashMap
<EncodedJSValue
, unsigned, EncodedJSValueHash
, EncodedJSValueHashTraits
> JSValueMap
;
414 struct IdentifierMapIndexHashTraits
{
415 typedef int TraitType
;
416 typedef IdentifierMapIndexHashTraits StorageTraits
;
417 static int emptyValue() { return std::numeric_limits
<int>::max(); }
418 static const bool emptyValueIsZero
= false;
419 static const bool needsDestruction
= false;
420 static const bool needsRef
= false;
423 typedef HashMap
<RefPtr
<StringImpl
>, int, IdentifierRepHash
, HashTraits
<RefPtr
<StringImpl
> >, IdentifierMapIndexHashTraits
> IdentifierMap
;
424 typedef HashMap
<double, JSValue
> NumberMap
;
425 typedef HashMap
<StringImpl
*, JSString
*, IdentifierRepHash
> IdentifierStringMap
;
427 RegisterID
* emitCall(OpcodeID
, RegisterID
* dst
, RegisterID
* func
, CallArguments
&, unsigned divot
, unsigned startOffset
, unsigned endOffset
);
429 RegisterID
* newRegister();
431 // Adds a var slot and maps it to the name ident in symbolTable().
432 RegisterID
* addVar(const Identifier
& ident
, bool isConstant
)
435 addVar(ident
, isConstant
, local
);
439 // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
440 bool addVar(const Identifier
&, bool isConstant
, RegisterID
*&);
442 // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
445 ++m_codeBlock
->m_numVars
;
446 return newRegister();
449 // Returns the RegisterID corresponding to ident.
450 RegisterID
* addGlobalVar(const Identifier
& ident
, bool isConstant
)
453 addGlobalVar(ident
, isConstant
, local
);
456 // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
457 bool addGlobalVar(const Identifier
&, bool isConstant
, RegisterID
*&);
459 void addParameter(const Identifier
&, int parameterIndex
);
461 void preserveLastVar();
462 bool shouldAvoidResolveGlobal();
464 RegisterID
& registerFor(int index
)
467 return m_calleeRegisters
[index
];
469 if (m_parameters
.size()) {
470 ASSERT(!m_globals
.size());
471 return m_parameters
[index
+ m_parameters
.size() + RegisterFile::CallFrameHeaderSize
];
474 return m_globals
[-index
- 1];
477 unsigned addConstant(const Identifier
&);
478 RegisterID
* addConstantValue(JSValue
);
479 unsigned addRegExp(RegExp
*);
481 unsigned addConstantBuffer(unsigned length
);
483 FunctionExecutable
* makeFunction(ExecState
* exec
, FunctionBodyNode
* body
)
485 return FunctionExecutable::create(exec
, body
->ident(), body
->source(), body
->usesArguments(), body
->parameters(), body
->isStrictMode(), body
->lineNo(), body
->lastLine());
488 FunctionExecutable
* makeFunction(JSGlobalData
* globalData
, FunctionBodyNode
* body
)
490 return FunctionExecutable::create(globalData
, body
->ident(), body
->source(), body
->usesArguments(), body
->parameters(), body
->isStrictMode(), body
->lineNo(), body
->lastLine());
493 JSString
* addStringConstant(const Identifier
&);
495 void addLineInfo(unsigned lineNo
)
497 #if !ENABLE(OPCODE_SAMPLING)
498 if (m_shouldEmitRichSourceInfo
)
500 m_codeBlock
->addLineInfo(instructions().size(), lineNo
);
503 RegisterID
* emitInitLazyRegister(RegisterID
*);
505 Vector
<Instruction
>& instructions() { return m_codeBlock
->instructions(); }
506 SymbolTable
& symbolTable() { return *m_symbolTable
; }
508 bool shouldOptimizeLocals() { return (m_codeType
!= EvalCode
) && !m_dynamicScopeDepth
; }
509 bool canOptimizeNonLocals() { return (m_codeType
== FunctionCode
) && !m_dynamicScopeDepth
&& !m_codeBlock
->usesEval(); }
511 RegisterID
* emitThrowExpressionTooDeepException();
513 void createArgumentsIfNecessary();
514 void createActivationIfNecessary();
515 RegisterID
* createLazyRegisterIfNecessary(RegisterID
*);
517 bool m_shouldEmitDebugHooks
;
518 bool m_shouldEmitProfileHooks
;
519 bool m_shouldEmitRichSourceInfo
;
521 Strong
<ScopeChainNode
> m_scopeChain
;
522 SymbolTable
* m_symbolTable
;
524 ScopeNode
* m_scopeNode
;
525 CodeBlock
* m_codeBlock
;
527 // Some of these objects keep pointers to one another. They are arranged
528 // to ensure a sane destruction order that avoids references to freed memory.
529 HashSet
<RefPtr
<StringImpl
>, IdentifierRepHash
> m_functions
;
530 RegisterID m_ignoredResultRegister
;
531 RegisterID m_thisRegister
;
532 RegisterID
* m_activationRegister
;
533 SegmentedVector
<RegisterID
, 32> m_constantPoolRegisters
;
534 SegmentedVector
<RegisterID
, 32> m_calleeRegisters
;
535 SegmentedVector
<RegisterID
, 32> m_parameters
;
536 SegmentedVector
<RegisterID
, 32> m_globals
;
537 SegmentedVector
<Label
, 32> m_labels
;
538 SegmentedVector
<LabelScope
, 8> m_labelScopes
;
539 RefPtr
<RegisterID
> m_lastVar
;
541 int m_dynamicScopeDepth
;
542 int m_baseScopeDepth
;
545 Vector
<ControlFlowContext
> m_scopeContextStack
;
546 Vector
<SwitchInfo
> m_switchContextStack
;
547 Vector
<ForInContext
> m_forInContextStack
;
549 int m_nextGlobalIndex
;
550 int m_firstConstantIndex
;
551 int m_nextConstantOffset
;
552 unsigned m_globalConstantIndex
;
554 int m_globalVarStorageOffset
;
556 bool m_hasCreatedActivation
;
557 int m_firstLazyFunction
;
558 int m_lastLazyFunction
;
559 HashMap
<unsigned int, FunctionBodyNode
*, WTF::IntHash
<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits
<unsigned int> > m_lazyFunctions
;
560 typedef HashMap
<FunctionBodyNode
*, unsigned> FunctionOffsetMap
;
561 FunctionOffsetMap m_functionOffsets
;
564 IdentifierMap m_identifierMap
;
565 JSValueMap m_jsValueMap
;
566 NumberMap m_numberMap
;
567 IdentifierStringMap m_stringMap
;
569 JSGlobalData
* m_globalData
;
571 OpcodeID m_lastOpcodeID
;
573 size_t m_lastOpcodePosition
;
578 bool m_usesExceptions
;
579 bool m_expressionTooDeep
;
583 #endif // BytecodeGenerator_h