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