7c091e1f16909ee3b6cf145a710044817849f6c4
[WebKit-https.git] / Source / JavaScriptCore / bytecode / UnlinkedCodeBlock.h
1 /*
2  * Copyright (C) 2012, 2013, 2014 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 "ParserModes.h"
37 #include "RegExp.h"
38 #include "SpecialPointer.h"
39 #include "SymbolTable.h"
40 #include "VirtualRegister.h"
41
42 #include <wtf/Compression.h>
43 #include <wtf/RefCountedArray.h>
44 #include <wtf/Vector.h>
45
46 namespace JSC {
47
48 class Debugger;
49 class FunctionBodyNode;
50 class FunctionExecutable;
51 class FunctionParameters;
52 class JSScope;
53 struct ParserError;
54 class ScriptExecutable;
55 class SourceCode;
56 class SourceProvider;
57 class SymbolTable;
58 class UnlinkedCodeBlock;
59 class UnlinkedFunctionCodeBlock;
60 class UnlinkedInstructionStream;
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     SymbolTable* 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     FunctionMode functionMode() const { return m_functionMode; }
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<SymbolTable> m_symbolTableForCall;
160     WriteBarrier<SymbolTable> 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     FunctionMode m_functionMode;
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         unsigned index;
236     } u;
237 };
238
239 class UnlinkedCodeBlock : public JSCell {
240 public:
241     typedef JSCell Base;
242     static const bool needsDestruction = true;
243     static const bool hasImmortalStructure = true;
244
245     enum { CallFunction, ApplyFunction };
246
247     bool isConstructor() const { return m_isConstructor; }
248     bool isStrictMode() const { return m_isStrictMode; }
249     bool usesEval() const { return m_usesEval; }
250
251     bool needsFullScopeChain() const { return m_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     void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
345     const UnlinkedInstructionStream& instructions() const;
346
347     int m_numVars;
348     int m_numCapturedVars;
349     int m_numCalleeRegisters;
350
351     // Jump Tables
352
353     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
354     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
355     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
356
357     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
358     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
359     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
360
361     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
362     {
363         unsigned size = m_functionDecls.size();
364         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
365         m_functionDecls.last().set(*m_vm, this, n);
366         return size;
367     }
368     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
369     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
370     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
371     {
372         unsigned size = m_functionExprs.size();
373         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
374         m_functionExprs.last().set(*m_vm, this, n);
375         return size;
376     }
377     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
378     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
379
380     // Exception handling support
381     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
382     void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
383     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
384
385     SymbolTable* symbolTable() const { return m_symbolTable.get(); }
386
387     VM* vm() const { return m_vm; }
388
389     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
390     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
391     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
392     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
393     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
394     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
395     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
396     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
397
398     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
399     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
400
401     CodeType codeType() const { return m_codeType; }
402
403     VirtualRegister thisRegister() const { return m_thisRegister; }
404     VirtualRegister activationRegister() const { return m_activationRegister; }
405     bool hasActivationRegister() const { return m_activationRegister.isValid(); }
406
407     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
408     {
409         m_propertyAccessInstructions.append(propertyAccessInstruction);
410     }
411
412     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
413     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
414
415     typedef Vector<JSValue> ConstantBuffer;
416
417     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
418     unsigned addConstantBuffer(unsigned length)
419     {
420         createRareDataIfNecessary();
421         unsigned size = m_rareData->m_constantBuffers.size();
422         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
423         return size;
424     }
425
426     const ConstantBuffer& constantBuffer(unsigned index) const
427     {
428         ASSERT(m_rareData);
429         return m_rareData->m_constantBuffers[index];
430     }
431
432     ConstantBuffer& constantBuffer(unsigned index)
433     {
434         ASSERT(m_rareData);
435         return m_rareData->m_constantBuffers[index];
436     }
437
438     bool hasRareData() const { return m_rareData; }
439
440     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
441
442     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
443         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
444
445     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
446     {
447         m_features = features;
448         m_hasCapturedVariables = hasCapturedVariables;
449         m_firstLine = firstLine;
450         m_lineCount = lineCount;
451         // For the UnlinkedCodeBlock, startColumn is always 0.
452         m_endColumn = endColumn;
453     }
454
455     CodeFeatures codeFeatures() const { return m_features; }
456     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
457     unsigned firstLine() const { return m_firstLine; }
458     unsigned lineCount() const { return m_lineCount; }
459     ALWAYS_INLINE unsigned startColumn() const { return 0; }
460     unsigned endColumn() const { return m_endColumn; }
461
462     void dumpExpressionRangeInfo(); // For debugging purpose only.
463
464 protected:
465     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
466     ~UnlinkedCodeBlock();
467
468     void finishCreation(VM& vm)
469     {
470         Base::finishCreation(vm);
471         if (codeType() == GlobalCode)
472             return;
473         m_symbolTable.set(vm, this, SymbolTable::create(vm));
474     }
475
476 private:
477
478     void createRareDataIfNecessary()
479     {
480         if (!m_rareData)
481             m_rareData = adoptPtr(new RareData);
482     }
483
484     void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
485
486     std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
487
488     int m_numParameters;
489     VM* m_vm;
490
491     VirtualRegister m_thisRegister;
492     VirtualRegister m_argumentsRegister;
493     VirtualRegister m_activationRegister;
494     VirtualRegister m_globalObjectRegister;
495
496     bool m_needsFullScopeChain : 1;
497     bool m_usesEval : 1;
498     bool m_isNumericCompareFunction : 1;
499     bool m_isStrictMode : 1;
500     bool m_isConstructor : 1;
501     bool m_hasCapturedVariables : 1;
502     unsigned m_firstLine;
503     unsigned m_lineCount;
504     unsigned m_endColumn;
505
506     CodeFeatures m_features;
507     CodeType m_codeType;
508
509     Vector<unsigned> m_jumpTargets;
510
511     // Constant Pools
512     Vector<Identifier> m_identifiers;
513     Vector<WriteBarrier<Unknown>> m_constantRegisters;
514     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
515     FunctionExpressionVector m_functionDecls;
516     FunctionExpressionVector m_functionExprs;
517
518     WriteBarrier<SymbolTable> m_symbolTable;
519
520     Vector<unsigned> m_propertyAccessInstructions;
521
522 #if ENABLE(BYTECODE_COMMENTS)
523     Vector<Comment>  m_bytecodeComments;
524     size_t m_bytecodeCommentIterator;
525 #endif
526
527     unsigned m_arrayProfileCount;
528     unsigned m_arrayAllocationProfileCount;
529     unsigned m_objectAllocationProfileCount;
530     unsigned m_valueProfileCount;
531     unsigned m_llintCallLinkInfoCount;
532
533 public:
534     struct RareData {
535         WTF_MAKE_FAST_ALLOCATED;
536     public:
537         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
538
539         // Rare Constants
540         Vector<WriteBarrier<RegExp>> m_regexps;
541
542         // Buffers used for large array literals
543         Vector<ConstantBuffer> m_constantBuffers;
544
545         // Jump Tables
546         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
547         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
548
549         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
550     };
551
552 private:
553     OwnPtr<RareData> m_rareData;
554     Vector<ExpressionRangeInfo> m_expressionInfo;
555
556 protected:
557
558     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
559     static void visitChildren(JSCell*, SlotVisitor&);
560
561 public:
562     DECLARE_INFO;
563 };
564
565 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
566 public:
567     typedef UnlinkedCodeBlock Base;
568
569 protected:
570     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
571         : Base(vm, structure, codeType, info)
572     {
573     }
574
575     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
576
577     DECLARE_INFO;
578 };
579
580 class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
581 private:
582     friend class CodeCache;
583     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
584     {
585         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
586         instance->finishCreation(*vm);
587         return instance;
588     }
589
590 public:
591     typedef UnlinkedGlobalCodeBlock Base;
592     static void destroy(JSCell*);
593
594     void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
595     {
596         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
597     }
598
599     void addVariableDeclaration(const Identifier& name, bool isConstant)
600     {
601         m_varDeclarations.append(std::make_pair(name, isConstant));
602     }
603
604     typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
605     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
606
607     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
608     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
609
610     static void visitChildren(JSCell*, SlotVisitor&);
611
612 private:
613     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
614         : Base(vm, structure, GlobalCode, info)
615     {
616     }
617
618     VariableDeclations m_varDeclarations;
619     FunctionDeclations m_functionDeclarations;
620
621 public:
622     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
623     {
624         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
625     }
626
627     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
628
629     DECLARE_INFO;
630 };
631
632 class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
633 private:
634     friend class CodeCache;
635
636     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
637     {
638         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
639         instance->finishCreation(*vm);
640         return instance;
641     }
642
643 public:
644     typedef UnlinkedGlobalCodeBlock Base;
645     static void destroy(JSCell*);
646
647     const Identifier& variable(unsigned index) { return m_variables[index]; }
648     unsigned numVariables() { return m_variables.size(); }
649     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
650     {
651         ASSERT(m_variables.isEmpty());
652         m_variables.swap(variables);
653     }
654
655 private:
656     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
657         : Base(vm, structure, EvalCode, info)
658     {
659     }
660
661     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
662
663 public:
664     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
665     {
666         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
667     }
668
669     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
670
671     DECLARE_INFO;
672 };
673
674 class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
675 public:
676     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
677     {
678         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
679         instance->finishCreation(*vm);
680         return instance;
681     }
682
683     typedef UnlinkedCodeBlock Base;
684     static void destroy(JSCell*);
685
686 private:
687     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
688         : Base(vm, structure, codeType, info)
689     {
690     }
691     
692 public:
693     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
694     {
695         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
696     }
697
698     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
699
700     DECLARE_INFO;
701 };
702
703 }
704
705 #endif // UnlinkedCodeBlock_h