Add tracking of endColumn for Executables.
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.h
1 /*
2  * Copyright (C) 2012, 2013 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef UnlinkedCodeBlock_h
27 #define UnlinkedCodeBlock_h
28
29 #include "BytecodeConventions.h"
30 #include "CodeSpecializationKind.h"
31 #include "CodeType.h"
32 #include "ExpressionRangeInfo.h"
33 #include "Identifier.h"
34 #include "JSCell.h"
35 #include "JSString.h"
36 #include "LineInfo.h"
37 #include "ParserModes.h"
38 #include "RegExp.h"
39 #include "SpecialPointer.h"
40 #include "SymbolTable.h"
41 #include "VirtualRegister.h"
42
43 #include <wtf/Compression.h>
44 #include <wtf/RefCountedArray.h>
45 #include <wtf/Vector.h>
46
47 namespace JSC {
48
49 class Debugger;
50 class FunctionBodyNode;
51 class FunctionExecutable;
52 class FunctionParameters;
53 class JSScope;
54 struct ParserError;
55 class ScriptExecutable;
56 class SourceCode;
57 class SourceProvider;
58 class SharedSymbolTable;
59 class UnlinkedCodeBlock;
60 class UnlinkedFunctionCodeBlock;
61
62 typedef unsigned UnlinkedValueProfile;
63 typedef unsigned UnlinkedArrayProfile;
64 typedef unsigned UnlinkedArrayAllocationProfile;
65 typedef unsigned UnlinkedObjectAllocationProfile;
66 typedef unsigned UnlinkedLLIntCallLinkInfo;
67
68 struct ExecutableInfo {
69     ExecutableInfo(bool needsActivation, bool usesEval, bool isStrictMode, bool isConstructor)
70         : m_needsActivation(needsActivation)
71         , m_usesEval(usesEval)
72         , m_isStrictMode(isStrictMode)
73         , m_isConstructor(isConstructor)
74     {
75     }
76     bool m_needsActivation;
77     bool m_usesEval;
78     bool m_isStrictMode;
79     bool m_isConstructor;
80 };
81
82 class UnlinkedFunctionExecutable : public JSCell {
83 public:
84     friend class CodeCache;
85     typedef JSCell Base;
86     static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, bool isFromGlobalCode = false)
87     {
88         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, isFromGlobalCode);
89         instance->finishCreation(*vm);
90         return instance;
91     }
92
93     const Identifier& name() const { return m_name; }
94     const Identifier& inferredName() const { return m_inferredName; }
95     JSString* nameValue() const { return m_nameValue.get(); }
96     SharedSymbolTable* symbolTable(CodeSpecializationKind kind)
97     {
98         return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
99     }
100     size_t parameterCount() const;
101     bool isInStrictContext() const { return m_isInStrictContext; }
102     FunctionNameIsInScopeToggle functionNameIsInScopeToggle() const { return m_functionNameIsInScopeToggle; }
103
104     unsigned firstLineOffset() const { return m_firstLineOffset; }
105     unsigned lineCount() const { return m_lineCount; }
106     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
107     unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
108     unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
109     unsigned startOffset() const { return m_startOffset; }
110     unsigned sourceLength() { return m_sourceLength; }
111
112     String paramString() const;
113
114     UnlinkedFunctionCodeBlock* codeBlockFor(VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, ParserError&);
115
116     static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
117
118     FunctionExecutable* link(VM&, const SourceCode&, size_t lineOffset, size_t sourceOffset);
119
120     void clearCodeForRecompilation()
121     {
122         m_symbolTableForCall.clear();
123         m_symbolTableForConstruct.clear();
124         m_codeBlockForCall.clear();
125         m_codeBlockForConstruct.clear();
126     }
127
128     FunctionParameters* parameters() { return m_parameters.get(); }
129
130     void recordParse(CodeFeatures features, bool hasCapturedVariables)
131     {
132         m_features = features;
133         m_hasCapturedVariables = hasCapturedVariables;
134     }
135
136     bool forceUsesArguments() const { return m_forceUsesArguments; }
137
138     CodeFeatures features() const { return m_features; }
139     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
140
141     static const bool needsDestruction = true;
142     static const bool hasImmortalStructure = true;
143     static void destroy(JSCell*);
144
145 private:
146     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, bool isFromGlobalCode);
147     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
148     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
149
150     unsigned m_numCapturedVariables : 29;
151     bool m_forceUsesArguments : 1;
152     bool m_isInStrictContext : 1;
153     bool m_hasCapturedVariables : 1;
154     bool m_isFromGlobalCode : 1;
155
156     Identifier m_name;
157     Identifier m_inferredName;
158     WriteBarrier<JSString> m_nameValue;
159     WriteBarrier<SharedSymbolTable> m_symbolTableForCall;
160     WriteBarrier<SharedSymbolTable> m_symbolTableForConstruct;
161     RefPtr<FunctionParameters> m_parameters;
162     unsigned m_firstLineOffset;
163     unsigned m_lineCount;
164     unsigned m_unlinkedFunctionNameStart;
165     unsigned m_unlinkedBodyStartColumn;
166     unsigned m_unlinkedBodyEndColumn;
167     unsigned m_startOffset;
168     unsigned m_sourceLength;
169
170     CodeFeatures m_features;
171
172     FunctionNameIsInScopeToggle m_functionNameIsInScopeToggle;
173
174 protected:
175     void finishCreation(VM& vm)
176     {
177         Base::finishCreation(vm);
178         m_nameValue.set(vm, this, jsString(&vm, name().string()));
179     }
180
181     static void visitChildren(JSCell*, SlotVisitor&);
182
183 public:
184     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
185     {
186         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
187     }
188
189     static const unsigned StructureFlags = OverridesVisitChildren | JSCell::StructureFlags;
190
191     DECLARE_EXPORT_INFO;
192 };
193
194 struct UnlinkedStringJumpTable {
195     typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
196     StringOffsetTable offsetTable;
197
198     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
199     {
200         StringOffsetTable::const_iterator end = offsetTable.end();
201         StringOffsetTable::const_iterator loc = offsetTable.find(value);
202         if (loc == end)
203             return defaultOffset;
204         return loc->value;
205     }
206
207 };
208
209 struct UnlinkedSimpleJumpTable {
210     Vector<int32_t> branchOffsets;
211     int32_t min;
212
213     int32_t offsetForValue(int32_t value, int32_t defaultOffset);
214     void add(int32_t key, int32_t offset)
215     {
216         if (!branchOffsets[key])
217             branchOffsets[key] = offset;
218     }
219 };
220
221 struct UnlinkedHandlerInfo {
222     uint32_t start;
223     uint32_t end;
224     uint32_t target;
225     uint32_t scopeDepth;
226 };
227
228 struct UnlinkedInstruction {
229     UnlinkedInstruction() { u.operand = 0; }
230     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
231     UnlinkedInstruction(int operand) { u.operand = operand; }
232     union {
233         OpcodeID opcode;
234         int32_t operand;
235     } u;
236 };
237
238 class UnlinkedCodeBlock : public JSCell {
239 public:
240     typedef JSCell Base;
241     static const bool needsDestruction = true;
242     static const bool hasImmortalStructure = true;
243
244     enum { CallFunction, ApplyFunction };
245
246     bool isConstructor() const { return m_isConstructor; }
247     bool isStrictMode() const { return m_isStrictMode; }
248     bool usesEval() const { return m_usesEval; }
249
250     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
251     void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
252
253     void addExpressionInfo(unsigned instructionOffset, int divot,
254         int startOffset, int endOffset, unsigned line, unsigned column);
255
256     bool hasExpressionInfo() { return m_expressionInfo.size(); }
257
258     // Special registers
259     void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
260     void setActivationRegister(VirtualRegister activationRegister) { m_activationRegister = activationRegister; }
261
262     void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; }
263     bool usesArguments() const { return m_argumentsRegister.isValid(); }
264     VirtualRegister argumentsRegister() const { return m_argumentsRegister; }
265
266
267     bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
268     void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
269     VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
270
271     // Parameter information
272     void setNumParameters(int newValue) { m_numParameters = newValue; }
273     void addParameter() { m_numParameters++; }
274     unsigned numParameters() const { return m_numParameters; }
275
276     unsigned addRegExp(RegExp* r)
277     {
278         createRareDataIfNecessary();
279         unsigned size = m_rareData->m_regexps.size();
280         m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
281         return size;
282     }
283     unsigned numberOfRegExps() const
284     {
285         if (!m_rareData)
286             return 0;
287         return m_rareData->m_regexps.size();
288     }
289     RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
290
291     // Constant Pools
292
293     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
294     void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
295     const Identifier& identifier(int index) const { return m_identifiers[index]; }
296     const Vector<Identifier>& identifiers() const { return m_identifiers; }
297
298     size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
299     unsigned addConstant(JSValue v)
300     {
301         unsigned result = m_constantRegisters.size();
302         m_constantRegisters.append(WriteBarrier<Unknown>());
303         m_constantRegisters.last().set(*m_vm, this, v);
304         return result;
305     }
306     unsigned addOrFindConstant(JSValue);
307     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
308     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
309     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
310     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
311
312     // Jumps
313     size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
314     void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
315     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
316     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
317
318     void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
319     bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
320
321     void shrinkToFit()
322     {
323         m_jumpTargets.shrinkToFit();
324         m_identifiers.shrinkToFit();
325         m_constantRegisters.shrinkToFit();
326         m_functionDecls.shrinkToFit();
327         m_functionExprs.shrinkToFit();
328         m_propertyAccessInstructions.shrinkToFit();
329         m_expressionInfo.shrinkToFit();
330
331 #if ENABLE(BYTECODE_COMMENTS)
332         m_bytecodeComments.shrinkToFit();
333 #endif
334         if (m_rareData) {
335             m_rareData->m_exceptionHandlers.shrinkToFit();
336             m_rareData->m_regexps.shrinkToFit();
337             m_rareData->m_constantBuffers.shrinkToFit();
338             m_rareData->m_switchJumpTables.shrinkToFit();
339             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
340             m_rareData->m_expressionInfoFatPositions.shrinkToFit();
341         }
342     }
343
344     unsigned numberOfInstructions() const { return m_unlinkedInstructions.size(); }
345     RefCountedArray<UnlinkedInstruction>& instructions() { return m_unlinkedInstructions; }
346     const RefCountedArray<UnlinkedInstruction>& instructions() const { return m_unlinkedInstructions; }
347
348     int m_numVars;
349     int m_numCapturedVars;
350     int m_numCalleeRegisters;
351
352     // Jump Tables
353
354     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
355     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
356     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
357
358     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
359     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
360     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
361
362     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
363     {
364         unsigned size = m_functionDecls.size();
365         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
366         m_functionDecls.last().set(*m_vm, this, n);
367         return size;
368     }
369     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
370     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
371     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
372     {
373         unsigned size = m_functionExprs.size();
374         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
375         m_functionExprs.last().set(*m_vm, this, n);
376         return size;
377     }
378     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
379     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
380
381     // Exception handling support
382     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
383     void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
384     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
385
386     SharedSymbolTable* symbolTable() const { return m_symbolTable.get(); }
387
388     VM* vm() const { return m_vm; }
389
390     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
391     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
392     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
393     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
394     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
395     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
396     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
397     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
398
399     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
400     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
401
402     CodeType codeType() const { return m_codeType; }
403
404     VirtualRegister thisRegister() const { return m_thisRegister; }
405     VirtualRegister activationRegister() const { return m_activationRegister; }
406
407
408     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
409     {
410         m_propertyAccessInstructions.append(propertyAccessInstruction);
411     }
412
413     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
414     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
415
416     typedef Vector<JSValue> ConstantBuffer;
417
418     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
419     unsigned addConstantBuffer(unsigned length)
420     {
421         createRareDataIfNecessary();
422         unsigned size = m_rareData->m_constantBuffers.size();
423         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
424         return size;
425     }
426
427     const ConstantBuffer& constantBuffer(unsigned index) const
428     {
429         ASSERT(m_rareData);
430         return m_rareData->m_constantBuffers[index];
431     }
432
433     ConstantBuffer& constantBuffer(unsigned index)
434     {
435         ASSERT(m_rareData);
436         return m_rareData->m_constantBuffers[index];
437     }
438
439     bool hasRareData() const { return m_rareData; }
440
441     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
442
443     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
444         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
445
446     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
447     {
448         m_features = features;
449         m_hasCapturedVariables = hasCapturedVariables;
450         m_firstLine = firstLine;
451         m_lineCount = lineCount;
452         // For the UnlinkedCodeBlock, startColumn is always 0.
453         m_endColumn = endColumn;
454     }
455
456     CodeFeatures codeFeatures() const { return m_features; }
457     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
458     unsigned firstLine() const { return m_firstLine; }
459     unsigned lineCount() const { return m_lineCount; }
460     ALWAYS_INLINE unsigned startColumn() const { return 0; }
461     unsigned endColumn() const { return m_endColumn; }
462
463 protected:
464     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
465     ~UnlinkedCodeBlock();
466
467     void finishCreation(VM& vm)
468     {
469         Base::finishCreation(vm);
470         if (codeType() == GlobalCode)
471             return;
472         m_symbolTable.set(vm, this, SharedSymbolTable::create(vm));
473     }
474
475 private:
476
477     void createRareDataIfNecessary()
478     {
479         if (!m_rareData)
480             m_rareData = adoptPtr(new RareData);
481     }
482
483     RefCountedArray<UnlinkedInstruction> m_unlinkedInstructions;
484
485     int m_numParameters;
486     VM* m_vm;
487
488     VirtualRegister m_thisRegister;
489     VirtualRegister m_argumentsRegister;
490     VirtualRegister m_activationRegister;
491     VirtualRegister m_globalObjectRegister;
492
493     bool m_needsFullScopeChain : 1;
494     bool m_usesEval : 1;
495     bool m_isNumericCompareFunction : 1;
496     bool m_isStrictMode : 1;
497     bool m_isConstructor : 1;
498     bool m_hasCapturedVariables : 1;
499     unsigned m_firstLine;
500     unsigned m_lineCount;
501     unsigned m_endColumn;
502
503     CodeFeatures m_features;
504     CodeType m_codeType;
505
506     Vector<unsigned> m_jumpTargets;
507
508     // Constant Pools
509     Vector<Identifier> m_identifiers;
510     Vector<WriteBarrier<Unknown>> m_constantRegisters;
511     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
512     FunctionExpressionVector m_functionDecls;
513     FunctionExpressionVector m_functionExprs;
514
515     WriteBarrier<SharedSymbolTable> m_symbolTable;
516
517     Vector<unsigned> m_propertyAccessInstructions;
518
519 #if ENABLE(BYTECODE_COMMENTS)
520     Vector<Comment>  m_bytecodeComments;
521     size_t m_bytecodeCommentIterator;
522 #endif
523
524     unsigned m_arrayProfileCount;
525     unsigned m_arrayAllocationProfileCount;
526     unsigned m_objectAllocationProfileCount;
527     unsigned m_valueProfileCount;
528     unsigned m_llintCallLinkInfoCount;
529
530 public:
531     struct RareData {
532         WTF_MAKE_FAST_ALLOCATED;
533     public:
534         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
535
536         // Rare Constants
537         Vector<WriteBarrier<RegExp>> m_regexps;
538
539         // Buffers used for large array literals
540         Vector<ConstantBuffer> m_constantBuffers;
541
542         // Jump Tables
543         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
544         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
545
546         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
547     };
548
549 private:
550     OwnPtr<RareData> m_rareData;
551     Vector<ExpressionRangeInfo> m_expressionInfo;
552
553 protected:
554
555     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
556     static void visitChildren(JSCell*, SlotVisitor&);
557
558 public:
559     DECLARE_INFO;
560 };
561
562 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
563 public:
564     typedef UnlinkedCodeBlock Base;
565
566 protected:
567     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
568         : Base(vm, structure, codeType, info)
569     {
570     }
571
572     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
573
574     DECLARE_INFO;
575 };
576
577 class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
578 private:
579     friend class CodeCache;
580     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
581     {
582         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
583         instance->finishCreation(*vm);
584         return instance;
585     }
586
587 public:
588     typedef UnlinkedGlobalCodeBlock Base;
589     static void destroy(JSCell*);
590
591     void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
592     {
593         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
594     }
595
596     void addVariableDeclaration(const Identifier& name, bool isConstant)
597     {
598         m_varDeclarations.append(std::make_pair(name, isConstant));
599     }
600
601     typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
602     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
603
604     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
605     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
606
607     static void visitChildren(JSCell*, SlotVisitor&);
608
609 private:
610     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
611         : Base(vm, structure, GlobalCode, info)
612     {
613     }
614
615     VariableDeclations m_varDeclarations;
616     FunctionDeclations m_functionDeclarations;
617
618 public:
619     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
620     {
621         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
622     }
623
624     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
625
626     DECLARE_INFO;
627 };
628
629 class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
630 private:
631     friend class CodeCache;
632
633     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
634     {
635         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
636         instance->finishCreation(*vm);
637         return instance;
638     }
639
640 public:
641     typedef UnlinkedGlobalCodeBlock Base;
642     static void destroy(JSCell*);
643
644     const Identifier& variable(unsigned index) { return m_variables[index]; }
645     unsigned numVariables() { return m_variables.size(); }
646     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
647     {
648         ASSERT(m_variables.isEmpty());
649         m_variables.swap(variables);
650     }
651
652 private:
653     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
654         : Base(vm, structure, EvalCode, info)
655     {
656     }
657
658     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
659
660 public:
661     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
662     {
663         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
664     }
665
666     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
667
668     DECLARE_INFO;
669 };
670
671 class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
672 public:
673     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
674     {
675         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
676         instance->finishCreation(*vm);
677         return instance;
678     }
679
680     typedef UnlinkedCodeBlock Base;
681     static void destroy(JSCell*);
682
683 private:
684     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
685         : Base(vm, structure, codeType, info)
686     {
687     }
688     
689 public:
690     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
691     {
692         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
693     }
694
695     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
696
697     DECLARE_INFO;
698 };
699
700 }
701
702 #endif // UnlinkedCodeBlock_h