22e50804ad48060c0f7f6c1e6bcf2e54fdd01fe9
[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, bool isBuiltinFunction)
70         : m_needsActivation(needsActivation)
71         , m_usesEval(usesEval)
72         , m_isStrictMode(isStrictMode)
73         , m_isConstructor(isConstructor)
74         , m_isBuiltinFunction(isBuiltinFunction)
75     {
76     }
77     bool m_needsActivation : 1;
78     bool m_usesEval : 1;
79     bool m_isStrictMode : 1;
80     bool m_isConstructor : 1;
81     bool m_isBuiltinFunction : 1;
82 };
83
84 enum UnlinkedFunctionKind {
85     UnlinkedNormalFunction,
86     UnlinkedBuiltinFunction,
87 };
88
89 class UnlinkedFunctionExecutable : public JSCell {
90 public:
91     friend class BuiltinExecutables;
92     friend class CodeCache;
93     friend class VM;
94     typedef JSCell Base;
95     static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionBodyNode* node, UnlinkedFunctionKind unlinkedFunctionKind)
96     {
97         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind);
98         instance->finishCreation(*vm);
99         return instance;
100     }
101
102     const Identifier& name() const { return m_name; }
103     const Identifier& inferredName() const { return m_inferredName; }
104     JSString* nameValue() const { return m_nameValue.get(); }
105     SymbolTable* symbolTable(CodeSpecializationKind kind)
106     {
107         return (kind == CodeForCall) ? m_symbolTableForCall.get() : m_symbolTableForConstruct.get();
108     }
109     size_t parameterCount() const;
110     bool isInStrictContext() const { return m_isInStrictContext; }
111     FunctionMode functionMode() const { return m_functionMode; }
112     JSParserStrictness toStrictness() const
113     {
114         if (m_isBuiltinFunction)
115             return JSParseBuiltin;
116         if (m_isInStrictContext)
117             return JSParseStrict;
118         return JSParseNormal;
119     }
120
121     unsigned firstLineOffset() const { return m_firstLineOffset; }
122     unsigned lineCount() const { return m_lineCount; }
123     unsigned unlinkedFunctionNameStart() const { return m_unlinkedFunctionNameStart; }
124     unsigned unlinkedBodyStartColumn() const { return m_unlinkedBodyStartColumn; }
125     unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
126     unsigned startOffset() const { return m_startOffset; }
127     unsigned sourceLength() { return m_sourceLength; }
128     unsigned typeProfilingStartOffset() const { return m_typeProfilingStartOffset; }
129     unsigned typeProfilingEndOffset() const { return m_typeProfilingEndOffset; }
130
131     String paramString() const;
132
133     UnlinkedFunctionCodeBlock* codeBlockFor(VM&, const SourceCode&, CodeSpecializationKind, DebuggerMode, ProfilerMode, bool bodyIncludesBraces, ParserError&);
134
135     static UnlinkedFunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
136
137     FunctionExecutable* link(VM&, const SourceCode&, size_t lineOffset);
138
139     void clearCodeForRecompilation()
140     {
141         m_symbolTableForCall.clear();
142         m_symbolTableForConstruct.clear();
143         m_codeBlockForCall.clear();
144         m_codeBlockForConstruct.clear();
145     }
146
147     FunctionParameters* parameters() { return m_parameters.get(); }
148
149     void recordParse(CodeFeatures features, bool hasCapturedVariables)
150     {
151         m_features = features;
152         m_hasCapturedVariables = hasCapturedVariables;
153     }
154
155     bool forceUsesArguments() const { return m_forceUsesArguments; }
156
157     CodeFeatures features() const { return m_features; }
158     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
159
160     static const bool needsDestruction = true;
161     static const bool hasImmortalStructure = true;
162     static void destroy(JSCell*);
163
164     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
165
166 private:
167     UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionBodyNode*, UnlinkedFunctionKind);
168     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForCall;
169     WriteBarrier<UnlinkedFunctionCodeBlock> m_codeBlockForConstruct;
170
171     unsigned m_numCapturedVariables : 29;
172     bool m_forceUsesArguments : 1;
173     bool m_isInStrictContext : 1;
174     bool m_hasCapturedVariables : 1;
175     bool m_isBuiltinFunction : 1;
176
177     Identifier m_name;
178     Identifier m_inferredName;
179     WriteBarrier<JSString> m_nameValue;
180     WriteBarrier<SymbolTable> m_symbolTableForCall;
181     WriteBarrier<SymbolTable> m_symbolTableForConstruct;
182     RefPtr<FunctionParameters> m_parameters;
183     unsigned m_firstLineOffset;
184     unsigned m_lineCount;
185     unsigned m_unlinkedFunctionNameStart;
186     unsigned m_unlinkedBodyStartColumn;
187     unsigned m_unlinkedBodyEndColumn;
188     unsigned m_startOffset;
189     unsigned m_sourceLength;
190     unsigned m_typeProfilingStartOffset;
191     unsigned m_typeProfilingEndOffset;
192
193     CodeFeatures m_features;
194
195     FunctionMode m_functionMode;
196
197 protected:
198     void finishCreation(VM& vm)
199     {
200         Base::finishCreation(vm);
201         m_nameValue.set(vm, this, jsString(&vm, name().string()));
202     }
203
204     static void visitChildren(JSCell*, SlotVisitor&);
205
206 public:
207     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
208     {
209         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionExecutableType, StructureFlags), info());
210     }
211
212     static const unsigned StructureFlags = StructureIsImmortal | JSCell::StructureFlags;
213
214     DECLARE_EXPORT_INFO;
215 };
216
217 struct UnlinkedStringJumpTable {
218     typedef HashMap<RefPtr<StringImpl>, int32_t> StringOffsetTable;
219     StringOffsetTable offsetTable;
220
221     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
222     {
223         StringOffsetTable::const_iterator end = offsetTable.end();
224         StringOffsetTable::const_iterator loc = offsetTable.find(value);
225         if (loc == end)
226             return defaultOffset;
227         return loc->value;
228     }
229
230 };
231
232 struct UnlinkedSimpleJumpTable {
233     Vector<int32_t> branchOffsets;
234     int32_t min;
235
236     int32_t offsetForValue(int32_t value, int32_t defaultOffset);
237     void add(int32_t key, int32_t offset)
238     {
239         if (!branchOffsets[key])
240             branchOffsets[key] = offset;
241     }
242 };
243
244 struct UnlinkedHandlerInfo {
245     uint32_t start;
246     uint32_t end;
247     uint32_t target;
248     uint32_t scopeDepth;
249 };
250
251 struct UnlinkedInstruction {
252     UnlinkedInstruction() { u.operand = 0; }
253     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
254     UnlinkedInstruction(int operand) { u.operand = operand; }
255     union {
256         OpcodeID opcode;
257         int32_t operand;
258         unsigned index;
259     } u;
260 };
261
262 class UnlinkedCodeBlock : public JSCell {
263 public:
264     typedef JSCell Base;
265     static const bool needsDestruction = true;
266     static const bool hasImmortalStructure = true;
267
268     enum { CallFunction, ApplyFunction };
269
270     bool isConstructor() const { return m_isConstructor; }
271     bool isStrictMode() const { return m_isStrictMode; }
272     bool usesEval() const { return m_usesEval; }
273
274     bool needsFullScopeChain() const { return m_needsFullScopeChain; }
275
276     void addExpressionInfo(unsigned instructionOffset, int divot,
277         int startOffset, int endOffset, unsigned line, unsigned column);
278
279     void addTypeProfilerExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
280
281     bool hasExpressionInfo() { return m_expressionInfo.size(); }
282
283     // Special registers
284     void setThisRegister(VirtualRegister thisRegister) { m_thisRegister = thisRegister; }
285     void setActivationRegister(VirtualRegister activationRegister) { m_activationRegister = activationRegister; }
286
287     void setArgumentsRegister(VirtualRegister argumentsRegister) { m_argumentsRegister = argumentsRegister; }
288     bool usesArguments() const { return m_argumentsRegister.isValid(); }
289     VirtualRegister argumentsRegister() const { return m_argumentsRegister; }
290
291
292     bool usesGlobalObject() const { return m_globalObjectRegister.isValid(); }
293     void setGlobalObjectRegister(VirtualRegister globalObjectRegister) { m_globalObjectRegister = globalObjectRegister; }
294     VirtualRegister globalObjectRegister() const { return m_globalObjectRegister; }
295
296     // Parameter information
297     void setNumParameters(int newValue) { m_numParameters = newValue; }
298     void addParameter() { m_numParameters++; }
299     unsigned numParameters() const { return m_numParameters; }
300
301     unsigned addRegExp(RegExp* r)
302     {
303         createRareDataIfNecessary();
304         unsigned size = m_rareData->m_regexps.size();
305         m_rareData->m_regexps.append(WriteBarrier<RegExp>(*m_vm, this, r));
306         return size;
307     }
308     unsigned numberOfRegExps() const
309     {
310         if (!m_rareData)
311             return 0;
312         return m_rareData->m_regexps.size();
313     }
314     RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
315
316     // Constant Pools
317
318     size_t numberOfIdentifiers() const { return m_identifiers.size(); }
319     void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
320     const Identifier& identifier(int index) const { return m_identifiers[index]; }
321     const Vector<Identifier>& identifiers() const { return m_identifiers; }
322
323     size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
324     unsigned addConstant(JSValue v)
325     {
326         unsigned result = m_constantRegisters.size();
327         m_constantRegisters.append(WriteBarrier<Unknown>());
328         m_constantRegisters.last().set(*m_vm, this, v);
329         return result;
330     }
331     unsigned addOrFindConstant(JSValue);
332     const Vector<WriteBarrier<Unknown>>& constantRegisters() { return m_constantRegisters; }
333     const WriteBarrier<Unknown>& constantRegister(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
334     ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; }
335     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
336
337     // Jumps
338     size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
339     void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
340     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
341     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
342
343     void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
344     bool isNumericCompareFunction() const { return m_isNumericCompareFunction; }
345
346     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
347     
348     void shrinkToFit()
349     {
350         m_jumpTargets.shrinkToFit();
351         m_identifiers.shrinkToFit();
352         m_constantRegisters.shrinkToFit();
353         m_functionDecls.shrinkToFit();
354         m_functionExprs.shrinkToFit();
355         m_propertyAccessInstructions.shrinkToFit();
356         m_expressionInfo.shrinkToFit();
357
358 #if ENABLE(BYTECODE_COMMENTS)
359         m_bytecodeComments.shrinkToFit();
360 #endif
361         if (m_rareData) {
362             m_rareData->m_exceptionHandlers.shrinkToFit();
363             m_rareData->m_regexps.shrinkToFit();
364             m_rareData->m_constantBuffers.shrinkToFit();
365             m_rareData->m_switchJumpTables.shrinkToFit();
366             m_rareData->m_stringSwitchJumpTables.shrinkToFit();
367             m_rareData->m_expressionInfoFatPositions.shrinkToFit();
368         }
369     }
370
371     void setInstructions(std::unique_ptr<UnlinkedInstructionStream>);
372     const UnlinkedInstructionStream& instructions() const;
373
374     int m_numVars;
375     int m_numCapturedVars;
376     int m_numCalleeRegisters;
377
378     // Jump Tables
379
380     size_t numberOfSwitchJumpTables() const { return m_rareData ? m_rareData->m_switchJumpTables.size() : 0; }
381     UnlinkedSimpleJumpTable& addSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_switchJumpTables.append(UnlinkedSimpleJumpTable()); return m_rareData->m_switchJumpTables.last(); }
382     UnlinkedSimpleJumpTable& switchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_switchJumpTables[tableIndex]; }
383
384     size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
385     UnlinkedStringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(UnlinkedStringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
386     UnlinkedStringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
387
388     unsigned addFunctionDecl(UnlinkedFunctionExecutable* n)
389     {
390         unsigned size = m_functionDecls.size();
391         m_functionDecls.append(WriteBarrier<UnlinkedFunctionExecutable>());
392         m_functionDecls.last().set(*m_vm, this, n);
393         return size;
394     }
395     UnlinkedFunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); }
396     size_t numberOfFunctionDecls() { return m_functionDecls.size(); }
397     unsigned addFunctionExpr(UnlinkedFunctionExecutable* n)
398     {
399         unsigned size = m_functionExprs.size();
400         m_functionExprs.append(WriteBarrier<UnlinkedFunctionExecutable>());
401         m_functionExprs.last().set(*m_vm, this, n);
402         return size;
403     }
404     UnlinkedFunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); }
405     size_t numberOfFunctionExprs() { return m_functionExprs.size(); }
406
407     // Exception handling support
408     size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
409     void addExceptionHandler(const UnlinkedHandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
410     UnlinkedHandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
411
412     SymbolTable* symbolTable() const { return m_symbolTable.get(); }
413     void setSymbolTable(SymbolTable* table) { m_symbolTable.set(*m_vm, this, table); }
414
415     VM* vm() const { return m_vm; }
416
417     UnlinkedArrayProfile addArrayProfile() { return m_arrayProfileCount++; }
418     unsigned numberOfArrayProfiles() { return m_arrayProfileCount; }
419     UnlinkedArrayAllocationProfile addArrayAllocationProfile() { return m_arrayAllocationProfileCount++; }
420     unsigned numberOfArrayAllocationProfiles() { return m_arrayAllocationProfileCount; }
421     UnlinkedObjectAllocationProfile addObjectAllocationProfile() { return m_objectAllocationProfileCount++; }
422     unsigned numberOfObjectAllocationProfiles() { return m_objectAllocationProfileCount; }
423     UnlinkedValueProfile addValueProfile() { return m_valueProfileCount++; }
424     unsigned numberOfValueProfiles() { return m_valueProfileCount; }
425
426     UnlinkedLLIntCallLinkInfo addLLIntCallLinkInfo() { return m_llintCallLinkInfoCount++; }
427     unsigned numberOfLLintCallLinkInfos() { return m_llintCallLinkInfoCount; }
428
429     CodeType codeType() const { return m_codeType; }
430
431     VirtualRegister thisRegister() const { return m_thisRegister; }
432     VirtualRegister activationRegister() const { return m_activationRegister; }
433     bool hasActivationRegister() const { return m_activationRegister.isValid(); }
434
435     void addPropertyAccessInstruction(unsigned propertyAccessInstruction)
436     {
437         m_propertyAccessInstructions.append(propertyAccessInstruction);
438     }
439
440     size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
441     const Vector<unsigned>& propertyAccessInstructions() const { return m_propertyAccessInstructions; }
442
443     typedef Vector<JSValue> ConstantBuffer;
444
445     size_t constantBufferCount() { ASSERT(m_rareData); return m_rareData->m_constantBuffers.size(); }
446     unsigned addConstantBuffer(unsigned length)
447     {
448         createRareDataIfNecessary();
449         unsigned size = m_rareData->m_constantBuffers.size();
450         m_rareData->m_constantBuffers.append(Vector<JSValue>(length));
451         return size;
452     }
453
454     const ConstantBuffer& constantBuffer(unsigned index) const
455     {
456         ASSERT(m_rareData);
457         return m_rareData->m_constantBuffers[index];
458     }
459
460     ConstantBuffer& constantBuffer(unsigned index)
461     {
462         ASSERT(m_rareData);
463         return m_rareData->m_constantBuffers[index];
464     }
465
466     bool hasRareData() const { return m_rareData; }
467
468     int lineNumberForBytecodeOffset(unsigned bytecodeOffset);
469
470     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
471         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
472
473     bool typeProfilerExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
474
475     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
476     {
477         m_features = features;
478         m_hasCapturedVariables = hasCapturedVariables;
479         m_firstLine = firstLine;
480         m_lineCount = lineCount;
481         // For the UnlinkedCodeBlock, startColumn is always 0.
482         m_endColumn = endColumn;
483     }
484
485     CodeFeatures codeFeatures() const { return m_features; }
486     bool hasCapturedVariables() const { return m_hasCapturedVariables; }
487     unsigned firstLine() const { return m_firstLine; }
488     unsigned lineCount() const { return m_lineCount; }
489     ALWAYS_INLINE unsigned startColumn() const { return 0; }
490     unsigned endColumn() const { return m_endColumn; }
491
492     void dumpExpressionRangeInfo(); // For debugging purpose only.
493
494 protected:
495     UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&);
496     ~UnlinkedCodeBlock();
497
498     void finishCreation(VM& vm)
499     {
500         Base::finishCreation(vm);
501         if (codeType() == GlobalCode)
502             return;
503         m_symbolTable.set(vm, this, SymbolTable::create(vm));
504     }
505
506 private:
507
508     void createRareDataIfNecessary()
509     {
510         if (!m_rareData)
511             m_rareData = adoptPtr(new RareData);
512     }
513
514     void getLineAndColumn(ExpressionRangeInfo&, unsigned& line, unsigned& column);
515
516     std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
517
518     int m_numParameters;
519     VM* m_vm;
520
521     VirtualRegister m_thisRegister;
522     VirtualRegister m_argumentsRegister;
523     VirtualRegister m_activationRegister;
524     VirtualRegister m_globalObjectRegister;
525
526     bool m_needsFullScopeChain : 1;
527     bool m_usesEval : 1;
528     bool m_isNumericCompareFunction : 1;
529     bool m_isStrictMode : 1;
530     bool m_isConstructor : 1;
531     bool m_hasCapturedVariables : 1;
532     bool m_isBuiltinFunction : 1;
533     unsigned m_firstLine;
534     unsigned m_lineCount;
535     unsigned m_endColumn;
536
537     CodeFeatures m_features;
538     CodeType m_codeType;
539
540     Vector<unsigned> m_jumpTargets;
541
542     // Constant Pools
543     Vector<Identifier> m_identifiers;
544     Vector<WriteBarrier<Unknown>> m_constantRegisters;
545     typedef Vector<WriteBarrier<UnlinkedFunctionExecutable>> FunctionExpressionVector;
546     FunctionExpressionVector m_functionDecls;
547     FunctionExpressionVector m_functionExprs;
548
549     WriteBarrier<SymbolTable> m_symbolTable;
550
551     Vector<unsigned> m_propertyAccessInstructions;
552
553 #if ENABLE(BYTECODE_COMMENTS)
554     Vector<Comment>  m_bytecodeComments;
555     size_t m_bytecodeCommentIterator;
556 #endif
557
558     unsigned m_arrayProfileCount;
559     unsigned m_arrayAllocationProfileCount;
560     unsigned m_objectAllocationProfileCount;
561     unsigned m_valueProfileCount;
562     unsigned m_llintCallLinkInfoCount;
563
564 public:
565     struct RareData {
566         WTF_MAKE_FAST_ALLOCATED;
567     public:
568         Vector<UnlinkedHandlerInfo> m_exceptionHandlers;
569
570         // Rare Constants
571         Vector<WriteBarrier<RegExp>> m_regexps;
572
573         // Buffers used for large array literals
574         Vector<ConstantBuffer> m_constantBuffers;
575
576         // Jump Tables
577         Vector<UnlinkedSimpleJumpTable> m_switchJumpTables;
578         Vector<UnlinkedStringJumpTable> m_stringSwitchJumpTables;
579
580         Vector<ExpressionRangeInfo::FatPosition> m_expressionInfoFatPositions;
581     };
582
583 private:
584     OwnPtr<RareData> m_rareData;
585     Vector<ExpressionRangeInfo> m_expressionInfo;
586     struct TypeProfilerExpressionRange {
587         unsigned m_startDivot;
588         unsigned m_endDivot;
589     };
590     HashMap<unsigned, TypeProfilerExpressionRange> m_typeProfilerInfoMap;
591
592 protected:
593
594     static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
595     static void visitChildren(JSCell*, SlotVisitor&);
596
597 public:
598     DECLARE_INFO;
599 };
600
601 class UnlinkedGlobalCodeBlock : public UnlinkedCodeBlock {
602 public:
603     typedef UnlinkedCodeBlock Base;
604
605 protected:
606     UnlinkedGlobalCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
607         : Base(vm, structure, codeType, info)
608     {
609     }
610
611     DECLARE_INFO;
612 };
613
614 class UnlinkedProgramCodeBlock : public UnlinkedGlobalCodeBlock {
615 private:
616     friend class CodeCache;
617     static UnlinkedProgramCodeBlock* create(VM* vm, const ExecutableInfo& info)
618     {
619         UnlinkedProgramCodeBlock* instance = new (NotNull, allocateCell<UnlinkedProgramCodeBlock>(vm->heap)) UnlinkedProgramCodeBlock(vm, vm->unlinkedProgramCodeBlockStructure.get(), info);
620         instance->finishCreation(*vm);
621         return instance;
622     }
623
624 public:
625     typedef UnlinkedGlobalCodeBlock Base;
626     static void destroy(JSCell*);
627
628     void addFunctionDeclaration(VM& vm, const Identifier& name, UnlinkedFunctionExecutable* functionExecutable)
629     {
630         m_functionDeclarations.append(std::make_pair(name, WriteBarrier<UnlinkedFunctionExecutable>(vm, this, functionExecutable)));
631     }
632
633     void addVariableDeclaration(const Identifier& name, bool isConstant)
634     {
635         m_varDeclarations.append(std::make_pair(name, isConstant));
636     }
637
638     typedef Vector<std::pair<Identifier, bool>> VariableDeclations;
639     typedef Vector<std::pair<Identifier, WriteBarrier<UnlinkedFunctionExecutable>> > FunctionDeclations;
640
641     const VariableDeclations& variableDeclarations() const { return m_varDeclarations; }
642     const FunctionDeclations& functionDeclarations() const { return m_functionDeclarations; }
643
644     static void visitChildren(JSCell*, SlotVisitor&);
645
646 private:
647     UnlinkedProgramCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
648         : Base(vm, structure, GlobalCode, info)
649     {
650     }
651
652     VariableDeclations m_varDeclarations;
653     FunctionDeclations m_functionDeclarations;
654
655 public:
656     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
657     {
658         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedProgramCodeBlockType, StructureFlags), info());
659     }
660
661     DECLARE_INFO;
662 };
663
664 class UnlinkedEvalCodeBlock : public UnlinkedGlobalCodeBlock {
665 private:
666     friend class CodeCache;
667
668     static UnlinkedEvalCodeBlock* create(VM* vm, const ExecutableInfo& info)
669     {
670         UnlinkedEvalCodeBlock* instance = new (NotNull, allocateCell<UnlinkedEvalCodeBlock>(vm->heap)) UnlinkedEvalCodeBlock(vm, vm->unlinkedEvalCodeBlockStructure.get(), info);
671         instance->finishCreation(*vm);
672         return instance;
673     }
674
675 public:
676     typedef UnlinkedGlobalCodeBlock Base;
677     static void destroy(JSCell*);
678
679     const Identifier& variable(unsigned index) { return m_variables[index]; }
680     unsigned numVariables() { return m_variables.size(); }
681     void adoptVariables(Vector<Identifier, 0, UnsafeVectorOverflow>& variables)
682     {
683         ASSERT(m_variables.isEmpty());
684         m_variables.swap(variables);
685     }
686
687 private:
688     UnlinkedEvalCodeBlock(VM* vm, Structure* structure, const ExecutableInfo& info)
689         : Base(vm, structure, EvalCode, info)
690     {
691     }
692
693     Vector<Identifier, 0, UnsafeVectorOverflow> m_variables;
694
695 public:
696     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
697     {
698         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedEvalCodeBlockType, StructureFlags), info());
699     }
700
701     DECLARE_INFO;
702 };
703
704 class UnlinkedFunctionCodeBlock : public UnlinkedCodeBlock {
705 public:
706     static UnlinkedFunctionCodeBlock* create(VM* vm, CodeType codeType, const ExecutableInfo& info)
707     {
708         UnlinkedFunctionCodeBlock* instance = new (NotNull, allocateCell<UnlinkedFunctionCodeBlock>(vm->heap)) UnlinkedFunctionCodeBlock(vm, vm->unlinkedFunctionCodeBlockStructure.get(), codeType, info);
709         instance->finishCreation(*vm);
710         return instance;
711     }
712
713     typedef UnlinkedCodeBlock Base;
714     static void destroy(JSCell*);
715
716 private:
717     UnlinkedFunctionCodeBlock(VM* vm, Structure* structure, CodeType codeType, const ExecutableInfo& info)
718         : Base(vm, structure, codeType, info)
719     {
720     }
721     
722 public:
723     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)
724     {
725         return Structure::create(vm, globalObject, proto, TypeInfo(UnlinkedFunctionCodeBlockType, StructureFlags), info());
726     }
727
728     DECLARE_INFO;
729 };
730
731 }
732
733 #endif // UnlinkedCodeBlock_h