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

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

2009-05-21 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

op_method_check

Optimize method calls, by caching specific function values within the Structure.
The new opcode is used almost like an x86 opcode prefix byte to optimize op_get_by_id,
where the property access is being used to read a function to be passed to op-call (i.e.
'foo.bar();'). This patch modifies the Structure class such that when a property is
put to an object for the first time we will check if the value is a function. If it is,
we will cache the function value on the Structure. A Structure in such a state guarantees
that not only does a property with the given identifier exist on the object, but also that
its value is unchanged. Upon any further attempt to put a property with the same identifier
(but a different value) to the object, it will transition back to a normal Structure (where
it will guarantee the presence but not the value of the property).

op_method_check makes use of the new information made available by the Structure, by
augmenting the functionality of op_get_by_id. Upon generating a FunctionCallDotNode a
check will be emitted prior to the property access reading the function value, and the JIT
will generate an extra (initially unlinked but patchable) set of checks prior to the regular
JIT code for get_by_id. The new code will do inline structure and prototype structure check
(unlike a regular get_by_id, which can only handle 'self' accesses inline), and then performs
an immediate load of the function value, rather than using memory accesses to load the value
from the obejct's property storage array. If the method check fails it will revert, or if
the access is polymorphic, the op_get_by_id will continue to operate - and optimize itself -
just as any other regular op_get_by_id would.

~2.5% on v8-tests, due to a ~9% progression on richards.

  • API/JSCallbackObjectFunctions.h: (JSC::::put): (JSC::::staticFunctionGetter):
  • API/JSObjectRef.cpp: (JSObjectMakeConstructor):
  • JavaScriptCore.exp:
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::differenceBetween):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::moveWithPatch):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • bytecode/CodeBlock.h: (JSC::getMethodCallLinkInfoReturnLocation): (JSC::CodeBlock::getMethodCallLinkInfo): (JSC::CodeBlock::addMethodCallLinkInfos): (JSC::CodeBlock::methodCallLinkInfo):
  • bytecode/Opcode.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitMethodCheck):
  • bytecompiler/BytecodeGenerator.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileSlowCases): (JSC::JIT::privateCompile):
  • jit/JIT.h: (JSC::MethodCallCompilationInfo::MethodCallCompilationInfo):
  • jit/JITOpcodes.cpp:
  • jit/JITPropertyAccess.cpp: (JSC::JIT::emit_op_method_check): (JSC::JIT::emitSlow_op_method_check): (JSC::JIT::emit_op_get_by_id): (JSC::JIT::emitSlow_op_get_by_id): (JSC::JIT::emit_op_put_by_id): (JSC::JIT::emitSlow_op_put_by_id): (JSC::JIT::compileGetByIdHotPath): (JSC::JIT::compileGetByIdSlowCase): (JSC::JIT::patchMethodCallProto):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_get_by_id_method_check): (JSC::JITStubs::cti_op_get_by_id_method_check_second):
  • jit/JITStubs.h:
  • jsc.cpp: (GlobalObject::GlobalObject):
  • parser/Nodes.cpp: (JSC::FunctionCallDotNode::emitBytecode):
  • runtime/Arguments.cpp: (JSC::Arguments::put):
  • runtime/ArrayConstructor.cpp: (JSC::ArrayConstructor::ArrayConstructor):
  • runtime/BooleanConstructor.cpp: (JSC::BooleanConstructor::BooleanConstructor):
  • runtime/DateConstructor.cpp: (JSC::DateConstructor::DateConstructor):
  • runtime/ErrorConstructor.cpp: (JSC::ErrorConstructor::ErrorConstructor): (JSC::constructError):
  • runtime/ErrorPrototype.cpp: (JSC::ErrorPrototype::ErrorPrototype):
  • runtime/FunctionConstructor.cpp: (JSC::FunctionConstructor::FunctionConstructor):
  • runtime/FunctionPrototype.cpp: (JSC::FunctionPrototype::FunctionPrototype):
  • runtime/InternalFunction.cpp: (JSC::InternalFunction::InternalFunction):
  • runtime/JSActivation.cpp: (JSC::JSActivation::put): (JSC::JSActivation::putWithAttributes):
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::JSByteArray):
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction): (JSC::JSFunction::getOwnPropertySlot):
  • runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::putWithAttributes): (JSC::JSGlobalObject::reset): (JSC::JSGlobalObject::mark):
  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): (JSC::JSGlobalObject::methodCallDummy):
  • runtime/JSObject.cpp: (JSC::JSObject::put): (JSC::JSObject::putWithAttributes): (JSC::JSObject::deleteProperty): (JSC::JSObject::defineGetter): (JSC::JSObject::defineSetter): (JSC::JSObject::getPropertyAttributes): (JSC::JSObject::getPropertySpecificFunction): (JSC::JSObject::putDirectFunction): (JSC::JSObject::putDirectFunctionWithoutTransition):
  • runtime/JSObject.h: (JSC::getJSFunction): (JSC::JSObject::getDirectLocation): (JSC::JSObject::putDirect): (JSC::JSObject::putDirectWithoutTransition):
  • runtime/LiteralParser.cpp: (JSC::LiteralParser::parseObject):
  • runtime/Lookup.cpp: (JSC::setUpStaticFunctionSlot):
  • runtime/Lookup.h: (JSC::lookupPut):
  • runtime/MathObject.cpp: (JSC::MathObject::MathObject):
  • runtime/NativeErrorConstructor.cpp: (JSC::NativeErrorConstructor::NativeErrorConstructor): (JSC::NativeErrorConstructor::construct):
  • runtime/NativeErrorPrototype.cpp: (JSC::NativeErrorPrototype::NativeErrorPrototype):
  • runtime/NumberConstructor.cpp: (JSC::NumberConstructor::NumberConstructor):
  • runtime/ObjectConstructor.cpp: (JSC::ObjectConstructor::ObjectConstructor):
  • runtime/PropertyMapHashTable.h: (JSC::PropertyMapEntry::PropertyMapEntry):
  • runtime/PrototypeFunction.cpp: (JSC::PrototypeFunction::PrototypeFunction):
  • runtime/PutPropertySlot.h: (JSC::PutPropertySlot::): (JSC::PutPropertySlot::PutPropertySlot): (JSC::PutPropertySlot::setNewProperty): (JSC::PutPropertySlot::setDespecifyFunctionProperty): (JSC::PutPropertySlot::isCacheable): (JSC::PutPropertySlot::cachedOffset):
  • runtime/RegExpConstructor.cpp: (JSC::RegExpConstructor::RegExpConstructor):
  • runtime/StringConstructor.cpp: (JSC::StringConstructor::StringConstructor):
  • runtime/StringPrototype.cpp: (JSC::StringPrototype::StringPrototype):
  • runtime/Structure.cpp: (JSC::Structure::Structure): (JSC::Structure::~Structure): (JSC::Structure::materializePropertyMap): (JSC::Structure::addPropertyTransitionToExistingStructure): (JSC::Structure::addPropertyTransition): (JSC::Structure::changeFunctionTransition): (JSC::Structure::addPropertyWithoutTransition): (JSC::Structure::get): (JSC::Structure::despecifyFunction): (JSC::Structure::put): (JSC::Structure::remove):
  • runtime/Structure.h: (JSC::Structure::get): (JSC::Structure::specificFunction):
  • runtime/StructureTransitionTable.h: (JSC::StructureTransitionTableHashTraits::emptyValue):
  • wtf/Platform.h:
File size: 23.3 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 MacroAssembler::CodeLocationLabel nativeCode;
63#endif
64 };
65
66 struct ExpressionRangeInfo {
67 enum {
68 MaxOffset = (1 << 7) - 1,
69 MaxDivot = (1 << 25) - 1
70 };
71 uint32_t instructionOffset : 25;
72 uint32_t divotPoint : 25;
73 uint32_t startOffset : 7;
74 uint32_t endOffset : 7;
75 };
76
77 struct LineInfo {
78 uint32_t instructionOffset;
79 int32_t lineNumber;
80 };
81
82 // Both op_construct and op_instanceof require a use of op_get_by_id to get
83 // the prototype property from an object. The exception messages for exceptions
84 // thrown by these instances op_get_by_id need to reflect this.
85 struct GetByIdExceptionInfo {
86 unsigned bytecodeOffset : 31;
87 bool isOpConstruct : 1;
88 };
89
90#if ENABLE(JIT)
91 struct CallLinkInfo {
92 CallLinkInfo()
93 : callee(0)
94 {
95 }
96
97 unsigned bytecodeIndex;
98 MacroAssembler::CodeLocationNearCall callReturnLocation;
99 MacroAssembler::CodeLocationDataLabelPtr hotPathBegin;
100 MacroAssembler::CodeLocationNearCall hotPathOther;
101 MacroAssembler::CodeLocationLabel coldPathOther;
102 CodeBlock* callee;
103 unsigned position;
104
105 void setUnlinked() { callee = 0; }
106 bool isLinked() { return callee; }
107 };
108
109 struct MethodCallLinkInfo {
110 MethodCallLinkInfo()
111 : cachedStructure(0)
112 {
113 }
114
115 MacroAssembler::CodeLocationCall callReturnLocation;
116 MacroAssembler::CodeLocationDataLabelPtr structureLabel;
117 Structure* cachedStructure;
118 };
119
120 struct FunctionRegisterInfo {
121 FunctionRegisterInfo(unsigned bytecodeOffset, int functionRegisterIndex)
122 : bytecodeOffset(bytecodeOffset)
123 , functionRegisterIndex(functionRegisterIndex)
124 {
125 }
126
127 unsigned bytecodeOffset;
128 int functionRegisterIndex;
129 };
130
131 struct GlobalResolveInfo {
132 GlobalResolveInfo(unsigned bytecodeOffset)
133 : structure(0)
134 , offset(0)
135 , bytecodeOffset(bytecodeOffset)
136 {
137 }
138
139 Structure* structure;
140 unsigned offset;
141 unsigned bytecodeOffset;
142 };
143
144 // This structure is used to map from a call return location
145 // (given as an offset in bytes into the JIT code) back to
146 // the bytecode index of the corresponding bytecode operation.
147 // This is then used to look up the corresponding handler.
148 struct CallReturnOffsetToBytecodeIndex {
149 CallReturnOffsetToBytecodeIndex(unsigned callReturnOffset, unsigned bytecodeIndex)
150 : callReturnOffset(callReturnOffset)
151 , bytecodeIndex(bytecodeIndex)
152 {
153 }
154
155 unsigned callReturnOffset;
156 unsigned bytecodeIndex;
157 };
158
159 // valueAtPosition helpers for the binaryChop algorithm below.
160
161 inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo)
162 {
163 return structureStubInfo->callReturnLocation.calleeReturnAddressValue();
164 }
165
166 inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
167 {
168 return callLinkInfo->callReturnLocation.calleeReturnAddressValue();
169 }
170
171 inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo)
172 {
173 return methodCallLinkInfo->callReturnLocation.calleeReturnAddressValue();
174 }
175
176 inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc)
177 {
178 return pc->callReturnOffset;
179 }
180
181 // Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
182 // compares result with key (KeyTypes should be comparable with '--', '<', '>').
183 // Optimized for cases where the array contains the key, checked by assertions.
184 template<typename ArrayType, typename KeyType, KeyType(*valueAtPosition)(ArrayType*)>
185 inline ArrayType* binaryChop(ArrayType* array, size_t size, KeyType key)
186 {
187 // The array must contain at least one element (pre-condition, array does conatin key).
188 // If the array only contains one element, no need to do the comparison.
189 while (size > 1) {
190 // Pick an element to check, half way through the array, and read the value.
191 int pos = (size - 1) >> 1;
192 KeyType val = valueAtPosition(&array[pos]);
193
194 // If the key matches, success!
195 if (val == key)
196 return &array[pos];
197 // The item we are looking for is smaller than the item being check; reduce the value of 'size',
198 // chopping off the right hand half of the array.
199 else if (key < val)
200 size = pos;
201 // Discard all values in the left hand half of the array, up to and including the item at pos.
202 else {
203 size -= (pos + 1);
204 array += (pos + 1);
205 }
206
207 // 'size' should never reach zero.
208 ASSERT(size);
209 }
210
211 // If we reach this point we've chopped down to one element, no need to check it matches
212 ASSERT(size == 1);
213 ASSERT(key == valueAtPosition(&array[0]));
214 return &array[0];
215 }
216#endif
217
218 class CodeBlock {
219 friend class JIT;
220 public:
221 CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
222 ~CodeBlock();
223
224 void mark();
225 void refStructures(Instruction* vPC) const;
226 void derefStructures(Instruction* vPC) const;
227#if ENABLE(JIT)
228 void unlinkCallers();
229#endif
230
231 static void dumpStatistics();
232
233#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
234 void dump(ExecState*) const;
235 void printStructures(const Instruction*) const;
236 void printStructure(const char* name, const Instruction*, int operand) const;
237#endif
238
239 inline bool isKnownNotImmediate(int index)
240 {
241 if (index == m_thisRegister)
242 return true;
243
244 if (isConstantRegisterIndex(index))
245 return getConstant(index).isCell();
246
247 return false;
248 }
249
250 ALWAYS_INLINE bool isConstantRegisterIndex(int index)
251 {
252 return index >= m_numVars && index < m_numVars + m_numConstants;
253 }
254
255 ALWAYS_INLINE JSValue getConstant(int index)
256 {
257 return m_constantRegisters[index - m_numVars].jsValue();
258 }
259
260 ALWAYS_INLINE bool isTemporaryRegisterIndex(int index)
261 {
262 return index >= m_numVars + m_numConstants;
263 }
264
265 HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset);
266 int lineNumberForBytecodeOffset(CallFrame*, unsigned bytecodeOffset);
267 int expressionRangeForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset);
268 bool getByIdExceptionInfoForBytecodeOffset(CallFrame*, unsigned bytecodeOffset, OpcodeID&);
269
270#if ENABLE(JIT)
271 void addCaller(CallLinkInfo* caller)
272 {
273 caller->callee = this;
274 caller->position = m_linkedCallerList.size();
275 m_linkedCallerList.append(caller);
276 }
277
278 void removeCaller(CallLinkInfo* caller)
279 {
280 unsigned pos = caller->position;
281 unsigned lastPos = m_linkedCallerList.size() - 1;
282
283 if (pos != lastPos) {
284 m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
285 m_linkedCallerList[pos]->position = pos;
286 }
287 m_linkedCallerList.shrink(lastPos);
288 }
289
290 StructureStubInfo& getStubInfo(void* returnAddress)
291 {
292 return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
293 }
294
295 CallLinkInfo& getCallLinkInfo(void* returnAddress)
296 {
297 return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
298 }
299
300 MethodCallLinkInfo& getMethodCallLinkInfo(void* returnAddress)
301 {
302 return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress));
303 }
304
305 unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC)
306 {
307 reparseForExceptionInfoIfNecessary(callFrame);
308 return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(m_exceptionInfo->m_callReturnIndexVector.begin(), m_exceptionInfo->m_callReturnIndexVector.size(), ownerNode()->generatedJITCode().offsetOf(nativePC))->bytecodeIndex;
309 }
310
311 bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex);
312#endif
313
314 void setIsNumericCompareFunction(bool isNumericCompareFunction) { m_isNumericCompareFunction = isNumericCompareFunction; }
315 bool isNumericCompareFunction() { return m_isNumericCompareFunction; }
316
317 Vector<Instruction>& instructions() { return m_instructions; }
318#ifndef NDEBUG
319 void setInstructionCount(unsigned instructionCount) { m_instructionCount = instructionCount; }
320#endif
321
322#if ENABLE(JIT)
323 void setJITCode(JITCode);
324 ExecutablePool* executablePool() { return ownerNode()->getExecutablePool(); }
325#endif
326
327 ScopeNode* ownerNode() const { return m_ownerNode; }
328
329 void setGlobalData(JSGlobalData* globalData) { m_globalData = globalData; }
330
331 void setThisRegister(int thisRegister) { m_thisRegister = thisRegister; }
332 int thisRegister() const { return m_thisRegister; }
333
334 void setNeedsFullScopeChain(bool needsFullScopeChain) { m_needsFullScopeChain = needsFullScopeChain; }
335 bool needsFullScopeChain() const { return m_needsFullScopeChain; }
336 void setUsesEval(bool usesEval) { m_usesEval = usesEval; }
337 bool usesEval() const { return m_usesEval; }
338 void setUsesArguments(bool usesArguments) { m_usesArguments = usesArguments; }
339 bool usesArguments() const { return m_usesArguments; }
340
341 CodeType codeType() const { return m_codeType; }
342
343 SourceProvider* source() const { return m_source.get(); }
344 unsigned sourceOffset() const { return m_sourceOffset; }
345
346 size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
347 void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
348 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
349 unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
350
351#if !ENABLE(JIT)
352 void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
353 void addGlobalResolveInstruction(unsigned globalResolveInstruction) { m_globalResolveInstructions.append(globalResolveInstruction); }
354 bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset);
355#else
356 size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
357 void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
358 StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
359
360 void addGlobalResolveInfo(unsigned globalResolveInstruction) { m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); }
361 GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
362 bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset);
363
364 size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
365 void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
366 CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
367
368 void addMethodCallLinkInfos(unsigned n) { m_methodCallLinkInfos.grow(n); }
369 MethodCallLinkInfo& methodCallLinkInfo(int index) { return m_methodCallLinkInfos[index]; }
370
371 void addFunctionRegisterInfo(unsigned bytecodeOffset, int functionIndex) { createRareDataIfNecessary(); m_rareData->m_functionRegisterInfos.append(FunctionRegisterInfo(bytecodeOffset, functionIndex)); }
372#endif
373
374 // Exception handling support
375
376 size_t numberOfExceptionHandlers() const { return m_rareData ? m_rareData->m_exceptionHandlers.size() : 0; }
377 void addExceptionHandler(const HandlerInfo& hanler) { createRareDataIfNecessary(); return m_rareData->m_exceptionHandlers.append(hanler); }
378 HandlerInfo& exceptionHandler(int index) { ASSERT(m_rareData); return m_rareData->m_exceptionHandlers[index]; }
379
380 bool hasExceptionInfo() const { return m_exceptionInfo; }
381 void clearExceptionInfo() { m_exceptionInfo.clear(); }
382
383 void addExpressionInfo(const ExpressionRangeInfo& expressionInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_expressionInfo.append(expressionInfo); }
384 void addGetByIdExceptionInfo(const GetByIdExceptionInfo& info) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_getByIdExceptionInfo.append(info); }
385
386 size_t numberOfLineInfos() const { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.size(); }
387 void addLineInfo(const LineInfo& lineInfo) { ASSERT(m_exceptionInfo); m_exceptionInfo->m_lineInfo.append(lineInfo); }
388 LineInfo& lastLineInfo() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_lineInfo.last(); }
389
390#if ENABLE(JIT)
391 Vector<CallReturnOffsetToBytecodeIndex>& callReturnIndexVector() { ASSERT(m_exceptionInfo); return m_exceptionInfo->m_callReturnIndexVector; }
392#endif
393
394 // Constant Pool
395
396 size_t numberOfIdentifiers() const { return m_identifiers.size(); }
397 void addIdentifier(const Identifier& i) { return m_identifiers.append(i); }
398 Identifier& identifier(int index) { return m_identifiers[index]; }
399
400 size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); }
401 void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); }
402 Register& constantRegister(int index) { return m_constantRegisters[index]; }
403
404 unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; }
405 FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); }
406
407 unsigned addFunction(FuncDeclNode* n) { createRareDataIfNecessary(); unsigned size = m_rareData->m_functions.size(); m_rareData->m_functions.append(n); return size; }
408 FuncDeclNode* function(int index) const { ASSERT(m_rareData); return m_rareData->m_functions[index].get(); }
409
410 bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); }
411
412 unsigned addUnexpectedConstant(JSValue v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; }
413 JSValue unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; }
414
415 unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; }
416 RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); }
417
418
419 // Jump Tables
420
421 size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; }
422 SimpleJumpTable& addImmediateSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_immediateSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_immediateSwitchJumpTables.last(); }
423 SimpleJumpTable& immediateSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_immediateSwitchJumpTables[tableIndex]; }
424
425 size_t numberOfCharacterSwitchJumpTables() const { return m_rareData ? m_rareData->m_characterSwitchJumpTables.size() : 0; }
426 SimpleJumpTable& addCharacterSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_characterSwitchJumpTables.append(SimpleJumpTable()); return m_rareData->m_characterSwitchJumpTables.last(); }
427 SimpleJumpTable& characterSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_characterSwitchJumpTables[tableIndex]; }
428
429 size_t numberOfStringSwitchJumpTables() const { return m_rareData ? m_rareData->m_stringSwitchJumpTables.size() : 0; }
430 StringJumpTable& addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData->m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData->m_stringSwitchJumpTables.last(); }
431 StringJumpTable& stringSwitchJumpTable(int tableIndex) { ASSERT(m_rareData); return m_rareData->m_stringSwitchJumpTables[tableIndex]; }
432
433
434 SymbolTable& symbolTable() { return m_symbolTable; }
435
436 EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; }
437
438 void shrinkToFit();
439
440 // FIXME: Make these remaining members private.
441
442 int m_numCalleeRegisters;
443 // NOTE: numConstants holds the number of constant registers allocated
444 // by the code generator, not the number of constant registers used.
445 // (Duplicate constants are uniqued during code generation, and spare
446 // constant registers may be allocated.)
447 int m_numConstants;
448 int m_numVars;
449 int m_numParameters;
450
451 private:
452#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
453 void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
454#endif
455
456 void reparseForExceptionInfoIfNecessary(CallFrame*);
457
458 void createRareDataIfNecessary()
459 {
460 if (!m_rareData)
461 m_rareData.set(new RareData);
462 }
463
464 ScopeNode* m_ownerNode;
465 JSGlobalData* m_globalData;
466
467 Vector<Instruction> m_instructions;
468#ifndef NDEBUG
469 unsigned m_instructionCount;
470#endif
471
472 int m_thisRegister;
473
474 bool m_needsFullScopeChain;
475 bool m_usesEval;
476 bool m_usesArguments;
477 bool m_isNumericCompareFunction;
478
479 CodeType m_codeType;
480
481 RefPtr<SourceProvider> m_source;
482 unsigned m_sourceOffset;
483
484#if !ENABLE(JIT)
485 Vector<unsigned> m_propertyAccessInstructions;
486 Vector<unsigned> m_globalResolveInstructions;
487#else
488 Vector<StructureStubInfo> m_structureStubInfos;
489 Vector<GlobalResolveInfo> m_globalResolveInfos;
490 Vector<CallLinkInfo> m_callLinkInfos;
491 Vector<MethodCallLinkInfo> m_methodCallLinkInfos;
492 Vector<CallLinkInfo*> m_linkedCallerList;
493#endif
494
495 Vector<unsigned> m_jumpTargets;
496
497 // Constant Pool
498 Vector<Identifier> m_identifiers;
499 Vector<Register> m_constantRegisters;
500 Vector<RefPtr<FuncExprNode> > m_functionExpressions;
501
502 SymbolTable m_symbolTable;
503
504 struct ExceptionInfo {
505 Vector<ExpressionRangeInfo> m_expressionInfo;
506 Vector<LineInfo> m_lineInfo;
507 Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo;
508
509#if ENABLE(JIT)
510 Vector<CallReturnOffsetToBytecodeIndex> m_callReturnIndexVector;
511#endif
512 };
513 OwnPtr<ExceptionInfo> m_exceptionInfo;
514
515 struct RareData {
516 Vector<HandlerInfo> m_exceptionHandlers;
517
518 // Rare Constants
519 Vector<RefPtr<FuncDeclNode> > m_functions;
520 Vector<JSValue> m_unexpectedConstants;
521 Vector<RefPtr<RegExp> > m_regexps;
522
523 // Jump Tables
524 Vector<SimpleJumpTable> m_immediateSwitchJumpTables;
525 Vector<SimpleJumpTable> m_characterSwitchJumpTables;
526 Vector<StringJumpTable> m_stringSwitchJumpTables;
527
528 EvalCodeCache m_evalCodeCache;
529
530#if ENABLE(JIT)
531 Vector<FunctionRegisterInfo> m_functionRegisterInfos;
532#endif
533 };
534 OwnPtr<RareData> m_rareData;
535 };
536
537 // Program code is not marked by any function, so we make the global object
538 // responsible for marking it.
539
540 class ProgramCodeBlock : public CodeBlock {
541 public:
542 ProgramCodeBlock(ScopeNode* ownerNode, CodeType codeType, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider)
543 : CodeBlock(ownerNode, codeType, sourceProvider, 0)
544 , m_globalObject(globalObject)
545 {
546 m_globalObject->codeBlocks().add(this);
547 }
548
549 ~ProgramCodeBlock()
550 {
551 if (m_globalObject)
552 m_globalObject->codeBlocks().remove(this);
553 }
554
555 void clearGlobalObject() { m_globalObject = 0; }
556
557 private:
558 JSGlobalObject* m_globalObject; // For program and eval nodes, the global object that marks the constant pool.
559 };
560
561 class EvalCodeBlock : public ProgramCodeBlock {
562 public:
563 EvalCodeBlock(ScopeNode* ownerNode, JSGlobalObject* globalObject, PassRefPtr<SourceProvider> sourceProvider, int baseScopeDepth)
564 : ProgramCodeBlock(ownerNode, EvalCode, globalObject, sourceProvider)
565 , m_baseScopeDepth(baseScopeDepth)
566 {
567 }
568
569 int baseScopeDepth() const { return m_baseScopeDepth; }
570
571 private:
572 int m_baseScopeDepth;
573 };
574
575} // namespace JSC
576
577#endif // CodeBlock_h
Note: See TracBrowser for help on using the repository browser.