source: webkit/trunk/JavaScriptCore/bytecode/CodeBlock.h@ 40813

Last change on this file since 40813 was 40813, checked in by [email protected], 16 years ago

2009-02-09 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Provide a class type for a generated block of JIT code.
Also changes the return address -> bytecode index map to
track the return addess as an unsigned offset into the code
instead of a ptrdiff_t in terms of voids - the latter is
equal to the actual offset / sizeof(void*), making it a
potentially lossy representation.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::PatchBuffer::returnAddressOffset):
  • assembler/X86Assembler.h: (JSC::X86Assembler::getCallReturnOffset):
  • bytecode/CodeBlock.h: (JSC::CallReturnOffsetToBytecodeIndex::CallReturnOffsetToBytecodeIndex): (JSC::getCallReturnOffset): (JSC::CodeBlock::getBytecodeIndex): (JSC::CodeBlock::jitCode): (JSC::CodeBlock::callReturnIndexVector):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::execute): (JSC::Interpreter::cti_vm_dontLazyLinkCall): (JSC::Interpreter::cti_vm_lazyLinkCall):
  • jit/JIT.cpp: (JSC::JIT::privateCompile):
  • jit/JIT.h: (JSC::):
  • jit/JITCall.cpp: (JSC::JIT::linkCall):
  • jit/JITCode.h: Added. (JSC::): (JSC::JITCode::JITCode): (JSC::JITCode::operator bool): (JSC::JITCode::addressForCall): (JSC::JITCode::offsetOf): (JSC::JITCode::execute):
File size: 22.6 KB
Line 
1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef CodeBlock_h
31#define CodeBlock_h
32
33#include "EvalCodeCache.h"
34#include "Instruction.h"
35#include "JITCode.h"
36#include "JSGlobalObject.h"
37#include "JumpTable.h"
38#include "Nodes.h"
39#include "RegExp.h"
40#include "UString.h"
41#include <wtf/RefPtr.h>
42#include <wtf/Vector.h>
43
44#if ENABLE(JIT)
45#include "StructureStubInfo.h"
46#endif
47
48namespace JSC {
49
50 class ExecState;
51
52 enum CodeType { GlobalCode, EvalCode, FunctionCode };
53
54 static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
55
56 struct HandlerInfo {
57 uint32_t start;
58 uint32_t end;
59 uint32_t target;
60 uint32_t scopeDepth;
61#if ENABLE(JIT)
62 void* nativeCode;
63#endif
64 };
65
66#if ENABLE(JIT)
67 // The code, and the associated pool from which it was allocated.
68 struct JITCodeRef {
69 JITCode code;
70#ifndef NDEBUG
71 unsigned codeSize;
72#endif
73 RefPtr<ExecutablePool> executablePool;
74
75 JITCodeRef()
76 : code(0)
77#ifndef NDEBUG
78 , codeSize(0)
79#endif
80 {
81 }
82
83 JITCodeRef(void* code, PassRefPtr<ExecutablePool> executablePool)
84 : code(code)
85#ifndef NDEBUG
86 , codeSize(0)
87#endif
88 , executablePool(executablePool)
89 {
90 }
91 };
92#endif
93
94 struct ExpressionRangeInfo {
95 enum {
96 MaxOffset = (1 << 7) - 1,
97 MaxDivot = (1 << 25) - 1
98 };
99 uint32_t instructionOffset : 25;
100 uint32_t divotPoint : 25;
101 uint32_t startOffset : 7;
102 uint32_t endOffset : 7;
103 };
104
105 struct LineInfo {
106 uint32_t instructionOffset;
107 int32_t lineNumber;
108 };
109
110 // Both op_construct and op_instanceof require a use of op_get_by_id to get
111 // the prototype property from an object. The exception messages for exceptions
112 // thrown by these instances op_get_by_id need to reflect this.
113 struct GetByIdExceptionInfo {
114 unsigned bytecodeOffset : 31;
115 bool isOpConstruct : 1;
116 };
117
118#if ENABLE(JIT)
119 struct CallLinkInfo {
120 CallLinkInfo()
121 : callReturnLocation(0)
122 , hotPathBegin(0)
123 , hotPathOther(0)
124 , coldPathOther(0)
125 , callee(0)
126 {
127 }
128
129 unsigned bytecodeIndex;
130 void* callReturnLocation;
131 void* hotPathBegin;
132 void* hotPathOther;
133 void* coldPathOther;
134 CodeBlock* callee;
135 unsigned position;
136
137 void setUnlinked() { callee = 0; }
138 bool isLinked() { return callee; }
139 };
140
141 struct FunctionRegisterInfo {
142 FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
143 : bytecodeOffset(bytecodeOffset)
144 , functionRegisterIndex(functionRegisterIndex)
145 {
146 }
147
148 unsigned bytecodeOffset;
149 int functionRegisterIndex;
150 };
151
152 struct GlobalResolveInfo {
153 GlobalResolveInfo(unsigned bytecodeOffset)
154 : structure(0)
155 , offset(0)
156 , bytecodeOffset(bytecodeOffset)
157 {
158 }
159
160 Structure* structure;
161 unsigned offset;
162 unsigned bytecodeOffset;
163 };
164
165 // This structure is used to map from a call return location
166 // (given as an offset in bytes into the JIT code) back to
167 // the bytecode index of the corresponding bytecode operation.
168 // This is then used to look up the corresponding handler.
169 struct CallReturnOffsetToBytecodeIndex {
170 CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset, unsigned bytecodeIndex)
171 : callReturnOffset(callReturnOffset)
172 , bytecodeIndex(bytecodeIndex)
173 {
174 }
175
176 unsigned callReturnOffset;
177 unsigned bytecodeIndex;
178 };
179
180 // valueAtPosition helpers for the binaryChop algorithm below.
181
182 inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
183 {
184 return structureStubInfo->callReturnLocation;
185 }
186
187 inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
188 {
189 return callLinkInfo->callReturnLocation;
190 }
191
192 inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc)
193 {
194 return pc->callReturnOffset;
195 }
196
197 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
198 // compares result with key (KeyTypes should be comparable with '--', '<', '>').
199 // Optimized for cases where the array contains the key, checked by assertions.
200 template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
201 inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
202 {
203 // The array must contain at least one element (pre-condition, array does conatin key).
204 // If the array only contains one element, no need to do the comparison.
205 while (size > 1) {
206 // Pick an element to check, half way through the array, and read the value.
207 int pos = (size - 1) >> 1;
208 KeyType val = valueAtPosition(&array[pos]);
209
210 // If the key matches, success!
211 if (val == key)
212 return &array[pos];
213 // The item we are looking for is smaller than the item being check; reduce the value of 'size',
214 // chopping off the right hand half of the array.
215 else if (key < val)
216 size = pos;
217 // Discard all values in the left hand half of the array, up to and including the item at pos.
218 else {
219 size -= (pos + 1);
220 array += (pos + 1);
221 }
222
223 // 'size' should never reach zero.
224 ASSERT(size);
225 }
226
227 // If we reach this point we've chopped down to one element, no need to check it matches
228 ASSERT(size == 1);
229 ASSERT(key == valueAtPosition(&array[0]));
230 return &array[0];
231 }
232#endif
233
234 class CodeBlock {
235 friend class JIT;
236 public:
237 CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
238 ~CodeBlock();
239
240 void mark();
241 void refStructures(Instruction* vPC) const;
242 void derefStructures(Instruction* vPC) const;
243#if ENABLE(JIT)
244 void unlinkCallers();
245#endif
246
247 static void dumpStatistics();
248
249#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
250 void dump(ExecState*) const;
251 void printStructures(const Instruction*) const;
252 void printStructure(const char* name, const Instruction*, int operand) const;
253#endif
254
255 inline bool isKnownNotImmediate(int index)
256 {
257 if (index == m_thisRegister)
258 return true;
259
260 if (isConstantRegisterIndex(index))
261 return getConstant(index).isCell();
262
263 return false;
264 }
265
266 ALWAYS_INLINE bool isConstantRegisterIndex(int index)
267 {
268 return index >= m_numVars && index < m_numVars + m_numConstants;
269 }
270
271 ALWAYS_INLINE JSValuePtr getConstant(int index)
272 {
273 return m_constantRegisters[index - m_numVars].getJSValue();
274 }
275
276 ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)
277 {
278 return index >= m_numVars + m_numConstants;
279 }
280
281 HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
282 int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
283 int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
284 bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
285
286#if ENABLE(JIT)
287 void addCaller(CallLinkInfo* caller)
288 {
289 caller->callee = this;
290 caller->position = m_linkedCallerList.size();
291 m_linkedCallerList.append(caller);
292 }
293
294 void removeCaller(CallLinkInfo* caller)
295 {
296 unsigned pos = caller->position;
297 unsigned lastPos = m_linkedCallerList.size() - 1;
298
299 if (pos != lastPos) {
300 m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
301 m_linkedCallerList[pos]->position = pos;
302 }
303 m_linkedCallerList.shrink(lastPos);
304 }
305
306 StructureStubInfo& getStubInfo(void* returnAddress)
307 {
308 return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
309 }
310
311 CallLinkInfo& getCallLinkInfo(void* returnAddress)
312 {
313 return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
314 }
315
316 unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC)
317 {
318 reparseForExceptionInfoIfNecessary(callFrame);
319 return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(m_exceptionInfo->m_callReturnIndexVector.begin(), m_exceptionInfo->m_callReturnIndexVector.size(), m_jitCode.code.offsetOf(nativePC))->bytecodeIndex;
320 }
321
322 bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
323#endif
324
325 Vector<Instruction>& instructions() { return m_instructions; }
326#ifndef NDEBUG
327 void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
328#endif
329
330#if ENABLE(JIT)
331 void setJITCode(JITCodeRef& jitCode);
332 JITCode jitCode() { return m_jitCode.code; }
333 ExecutablePool* executablePool() { return m_jitCode.executablePool.get(); }
334#endif
335
336 ScopeNode* ownerNode() const { return m_ownerNode; }
337
338 void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
339
340 void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
341 int thisRegister() const { return m_thisRegister; }
342
343 void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
344 bool needsFullScopeChain() const { return m_needsFullScopeChain; }
345 void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
346 bool usesEval() const { return m_usesEval; }
347 void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
348 bool usesArguments() const { return m_usesArguments; }
349
350 CodeType codeType() const { return m_codeType; }
351
352 SourceProvider* source() const { return m_source.get(); }
353 unsigned sourceOffset() const { return m_sourceOffset; }
354
355 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
356 void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
357 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
358 unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
359
360#if !ENABLE(JIT)
361 void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
362 void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
363 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
364#else
365 size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
366 void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
367 StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
368
369 void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); }
370 GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
371 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
372
373 size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
374 void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
375 CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
376
377 void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
378#endif
379
380 // Exception handling support
381
382 size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
383 void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
384 HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
385
386 bool hasExceptionInfo() const { return m_exceptionInfo; }
387 void clearExceptionInfo() { m_exceptionInfo.clear(); }
388
389 void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
390 void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
391
392 size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
393 void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
394 LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); }
395
396#if ENABLE(JIT)
397 Vector<CallReturnOffsetToBytecodeIndex>& callReturnIndexVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_callReturnIndexVector; }
398#endif
399
400 // Constant Pool
401
402 size_t numberOfIdentifiers() const { return m_identifiers.size(); }
403 void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
404 Identifier& identifier(int index) { return m_identifiers[index]; }
405
406 size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
407 void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
408 Register& constantRegister(int index) { return m_constantRegisters[index]; }
409
410 unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
411 FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
412
413 unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; }
414 FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); }
415
416 bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); }
417
418 unsigned addUnexpectedConstant(JSValuePtr v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; }
419 JSValuePtr unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; }
420
421 unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
422 RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
423
424
425 // Jump Tables
426
427 size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
428 SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
429 SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
430
431 size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
432 SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
433 SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
434
435 size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
436 StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
437 StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
438
439
440 SymbolTable& symbolTable() { return m_symbolTable; }
441
442 EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
443
444 void shrinkToFit();
445
446 // FIXME: Make these remaining members private.
447
448 int m_numCalleeRegisters;
449 // NOTE: numConstants holds the number of constant registers allocated
450 // by the code generator, not the number of constant registers used.
451 // (Duplicate constants are uniqued during code generation, and spare
452 // constant registers may be allocated.)
453 int m_numConstants;
454 int m_numVars;
455 int m_numParameters;
456
457 private:
458#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
459 void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
460#endif
461
462 void reparseForExceptionInfoIfNecessary(CallFrame*);
463
464 void createRareDataIfNecessary()
465 {
466 if (!m_rareData)
467 m_rareData.set(new RareData);
468 }
469
470 ScopeNode* m_ownerNode;
471 JSGlobalData* m_globalData;
472
473 Vector<Instruction> m_instructions;
474#ifndef NDEBUG
475 unsigned m_instructionCount;
476#endif
477#if ENABLE(JIT)
478 JITCodeRef m_jitCode;
479#endif
480
481 int m_thisRegister;
482
483 bool m_needsFullScopeChain;
484 bool m_usesEval;
485 bool m_usesArguments;
486
487 CodeType m_codeType;
488
489 RefPtr<SourceProvider> m_source;
490 unsigned m_sourceOffset;
491
492#if !ENABLE(JIT)
493 Vector<unsigned> m_propertyAccessInstructions;
494 Vector<unsigned> m_globalResolveInstructions;
495#else
496 Vector<StructureStubInfo> m_structureStubInfos;
497 Vector<GlobalResolveInfo> m_globalResolveInfos;
498 Vector<CallLinkInfo> m_callLinkInfos;
499 Vector<CallLinkInfo*> m_linkedCallerList;
500#endif
501
502 Vector<unsigned> m_jumpTargets;
503
504 // Constant Pool
505 Vector<Identifier> m_identifiers;
506 Vector<Register> m_constantRegisters;
507 Vector<RefPtr<FuncExprNode> > m_functionExpressions;
508
509 SymbolTable m_symbolTable;
510
511 struct ExceptionInfo {
512 Vector<ExpressionRangeInfo> m_expressionInfo;
513 Vector<LineInfo> m_lineInfo;
514 Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
515
516#if ENABLE(JIT)
517 Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
518#endif
519 };
520 OwnPtr<ExceptionInfo> m_exceptionInfo;
521
522 struct RareData {
523 Vector<HandlerInfo> m_exceptionHandlers;
524
525 // Rare Constants
526 Vector<RefPtr<FuncDeclNode> > m_functions;
527 Vector<JSValuePtr> m_unexpectedConstants;
528 Vector<RefPtr<RegExp> > m_regexps;
529
530 // Jump Tables
531 Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
532 Vector<SimpleJumpTable> m_characterSwitchJumpTables;
533 Vector<StringJumpTable> m_stringSwitchJumpTables;
534
535 EvalCodeCache m_evalCodeCache;
536
537#if ENABLE(JIT)
538 Vector<FunctionRegisterInfo> m_functionRegisterInfos;
539#endif
540 };
541 OwnPtr<RareData> m_rareData;
542 };
543
544 // Program code is not marked by any function, so we make the global object
545 // responsible for marking it.
546
547 class ProgramCodeBlock : public CodeBlock {
548 public:
549 ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
550 : CodeBlock(ownerNode, codeType, sourceProvider, 0)
551 , m_globalObject(globalObject)
552 {
553 m_globalObject->codeBlocks().add(this);
554 }
555
556 ~ProgramCodeBlock()
557 {
558 if (m_globalObject)
559 m_globalObject->codeBlocks().remove(this);
560 }
561
562 void clearGlobalObject() { m_globalObject = 0; }
563
564 private:
565 JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
566 };
567
568 class EvalCodeBlock : public ProgramCodeBlock {
569 public:
570 EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
571 : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
572 , m_baseScopeDepth(baseScopeDepth)
573 {
574 }
575
576 int baseScopeDepth() const { return m_baseScopeDepth; }
577
578 private:
579 int m_baseScopeDepth;
580 };
581
582} // namespace JSC
583
584#endif // CodeBlock_h
Note: See TracBrowser for help on using the repository browser.