source: webkit/trunk/JavaScriptCore/VM/CodeBlock.h@ 36727

Last change on this file since 36727 was 36418, checked in by [email protected], 17 years ago

2008-09-14 Maciej Stachowiak <[email protected]>

Reviewed by Cameron Zwarich.


  • split the "prototype" lookup for hasInstance into opcode stream so it can be cached


~5% speedup on v8 earley-boyer test

  • API/JSCallbackObject.h: Add a parameter for the pre-looked-up prototype.
  • API/JSCallbackObjectFunctions.h: (JSC::::hasInstance): Ditto.
  • API/JSValueRef.cpp: (JSValueIsInstanceOfConstructor): Look up and pass in prototype.
  • JavaScriptCore.exp:
  • VM/CTI.cpp: (JSC::CTI::privateCompileMainPass): Pass along prototype.
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump): Print third arg.
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitInstanceOf): Implement this, now that there is a third argument.
  • VM/CodeGenerator.h:
  • VM/Machine.cpp: (JSC::Machine::privateExecute): Pass along the prototype. (JSC::Machine::cti_op_instanceof): ditto
  • kjs/JSObject.cpp: (JSC::JSObject::hasInstance): Expect to get a pre-looked-up prototype.
  • kjs/JSObject.h:
  • kjs/nodes.cpp: (JSC::InstanceOfNode::emitCode): Emit a get_by_id of the prototype property and pass that register to instanceof.
  • kjs/nodes.h:
File size: 10.3 KB
Line 
1/*
2 * Copyright (C) 2008 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 "Instruction.h"
34#include "JSGlobalObject.h"
35#include "nodes.h"
36#include "Parser.h"
37#include "SourceRange.h"
38#include "ustring.h"
39#include <wtf/RefPtr.h>
40#include <wtf/Vector.h>
41
42namespace JSC {
43
44 class ExecState;
45
46 static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); }
47
48 struct HandlerInfo {
49 uint32_t start;
50 uint32_t end;
51 uint32_t target;
52 uint32_t scopeDepth;
53 void* nativeCode;
54 };
55
56 struct ExpressionRangeInfo {
57 enum {
58 MaxOffset = (1 << 7) - 1,
59 MaxDivot = (1 << 25) - 1
60 };
61 uint32_t instructionOffset : 25;
62 uint32_t divotPoint : 25;
63 uint32_t startOffset : 7;
64 uint32_t endOffset : 7;
65 };
66
67 struct LineInfo {
68 uint32_t instructionOffset;
69 int32_t lineNumber;
70 };
71
72 struct OffsetLocation {
73 int32_t branchOffset;
74#if ENABLE(CTI)
75 void* ctiOffset;
76#endif
77 };
78
79 struct StructureStubInfo {
80 StructureStubInfo(unsigned opcodeIndex)
81 : opcodeIndex(opcodeIndex)
82 , stubRoutine(0)
83 , callReturnLocation(0)
84 , hotPathBegin(0)
85 {
86 }
87
88 unsigned opcodeIndex;
89 void* stubRoutine;
90 void* callReturnLocation;
91 void* hotPathBegin;
92 };
93
94 struct StringJumpTable {
95 typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable;
96 StringOffsetTable offsetTable;
97#if ENABLE(CTI)
98 void* ctiDefault; // FIXME: it should not be necessary to store this.
99#endif
100
101 inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset)
102 {
103 StringOffsetTable::const_iterator end = offsetTable.end();
104 StringOffsetTable::const_iterator loc = offsetTable.find(value);
105 if (loc == end)
106 return defaultOffset;
107 return loc->second.branchOffset;
108 }
109
110#if ENABLE(CTI)
111 inline void* ctiForValue(UString::Rep* value)
112 {
113 StringOffsetTable::const_iterator end = offsetTable.end();
114 StringOffsetTable::const_iterator loc = offsetTable.find(value);
115 if (loc == end)
116 return ctiDefault;
117 return loc->second.ctiOffset;
118 }
119#endif
120 };
121
122 struct SimpleJumpTable {
123 // FIXME: The two Vectors can be combind into one Vector<OffsetLocation>
124 Vector<int32_t> branchOffsets;
125 int32_t min;
126#if ENABLE(CTI)
127 Vector<void*> ctiOffsets;
128 void* ctiDefault;
129#endif
130
131 int32_t offsetForValue(int32_t value, int32_t defaultOffset);
132 void add(int32_t key, int32_t offset)
133 {
134 if (!branchOffsets[key])
135 branchOffsets[key] = offset;
136 }
137
138#if ENABLE(CTI)
139 inline void* ctiForValue(int32_t value)
140 {
141 if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size())
142 return ctiOffsets[value - min];
143 return ctiDefault;
144 }
145#endif
146 };
147
148 class EvalCodeCache {
149 public:
150 PassRefPtr<EvalNode> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue*& exceptionValue)
151 {
152 RefPtr<EvalNode> evalNode;
153
154 if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
155 evalNode = cacheMap.get(evalSource.rep());
156
157 if (!evalNode) {
158 int sourceId;
159 int errLine;
160 UString errMsg;
161
162 evalNode = exec->parser()->parse<EvalNode>(exec, UString(), 1, UStringSourceProvider::create(evalSource), &sourceId, &errLine, &errMsg);
163 if (evalNode) {
164 if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject() && cacheMap.size() < maxCacheEntries)
165 cacheMap.set(evalSource.rep(), evalNode);
166 } else {
167 exceptionValue = Error::create(exec, SyntaxError, errMsg, errLine, sourceId, NULL);
168 return 0;
169 }
170 }
171
172 return evalNode.release();
173 }
174
175 private:
176 static const int maxCacheableSourceLength = 256;
177 static const int maxCacheEntries = 64;
178
179 HashMap<RefPtr<UString::Rep>, RefPtr<EvalNode> > cacheMap;
180 };
181
182 struct CodeBlock {
183 CodeBlock(ScopeNode* ownerNode_, CodeType codeType_, PassRefPtr<SourceProvider> source_, unsigned sourceOffset_)
184 : ownerNode(ownerNode_)
185 , globalData(0)
186#if ENABLE(CTI)
187 , ctiCode(0)
188#endif
189 , numTemporaries(0)
190 , numVars(0)
191 , numParameters(0)
192 , numLocals(0)
193 , needsFullScopeChain(ownerNode_->usesEval() || ownerNode_->needsClosure())
194 , usesEval(ownerNode_->usesEval())
195 , codeType(codeType_)
196 , source(source_)
197 , sourceOffset(sourceOffset_)
198 {
199 }
200
201 ~CodeBlock();
202
203#if !defined(NDEBUG) || ENABLE_SAMPLING_TOOL
204 void dump(ExecState*) const;
205 void printStructureIDs(const Instruction*) const;
206 void printStructureID(const char* name, const Instruction*, int operand) const;
207#endif
208 int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
209 int lineNumberForVPC(const Instruction* vPC);
210 bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);
211 void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);
212
213 void mark();
214 void refStructureIDs(Instruction* vPC) const;
215 void derefStructureIDs(Instruction* vPC) const;
216
217 StructureStubInfo& getStubInfo(void* returnAddress)
218 {
219 // FIXME: would a binary chop be faster here?
220 for (unsigned i = 0; i < structureIDInstructions.size(); ++i) {
221 if (structureIDInstructions[i].callReturnLocation == returnAddress)
222 return structureIDInstructions[i];
223 }
224
225 ASSERT_NOT_REACHED();
226 // keep the compiler happy.
227 static StructureStubInfo duff(0);
228 return duff;
229 }
230
231 ScopeNode* ownerNode;
232 JSGlobalData* globalData;
233#if ENABLE(CTI)
234 void* ctiCode;
235#endif
236
237 int numConstants;
238 int numTemporaries;
239 int numVars;
240 int numParameters;
241 int numLocals;
242 int thisRegister;
243 bool needsFullScopeChain;
244 bool usesEval;
245 CodeType codeType;
246 RefPtr<SourceProvider> source;
247 unsigned sourceOffset;
248
249 Vector<Instruction> instructions;
250 Vector<StructureStubInfo> structureIDInstructions;
251
252 // Constant pool
253 Vector<Identifier> identifiers;
254 Vector<RefPtr<FuncDeclNode> > functions;
255 Vector<RefPtr<FuncExprNode> > functionExpressions;
256 Vector<Register> constantRegisters;
257 Vector<JSValue*> unexpectedConstants;
258 Vector<RefPtr<RegExp> > regexps;
259 Vector<HandlerInfo> exceptionHandlers;
260 Vector<ExpressionRangeInfo> expressionInfo;
261 Vector<LineInfo> lineInfo;
262
263 Vector<SimpleJumpTable> immediateSwitchJumpTables;
264 Vector<SimpleJumpTable> characterSwitchJumpTables;
265 Vector<StringJumpTable> stringSwitchJumpTables;
266
267 HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > labels;
268
269#if ENABLE(CTI)
270 HashMap<void*, unsigned> ctiReturnAddressVPCMap;
271#endif
272
273 EvalCodeCache evalCodeCache;
274
275 private:
276#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
277 void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
278#endif
279
280 };
281
282 // Program code is not marked by any function, so we make the global object
283 // responsible for marking it.
284
285 struct ProgramCodeBlock : public CodeBlock {
286 ProgramCodeBlock(ScopeNode* ownerNode_, CodeType codeType_, JSGlobalObject* globalObject_, PassRefPtr<SourceProvider> source_)
287 : CodeBlock(ownerNode_, codeType_, source_, 0)
288 , globalObject(globalObject_)
289 {
290 globalObject->codeBlocks().add(this);
291 }
292
293 ~ProgramCodeBlock()
294 {
295 if (globalObject)
296 globalObject->codeBlocks().remove(this);
297 }
298
299 JSGlobalObject* globalObject; // For program and eval nodes, the global object that marks the constant pool.
300 };
301
302 struct EvalCodeBlock : public ProgramCodeBlock {
303 EvalCodeBlock(ScopeNode* ownerNode_, JSGlobalObject* globalObject_, PassRefPtr<SourceProvider> source_)
304 : ProgramCodeBlock(ownerNode_, EvalCode, globalObject_, source_)
305 {
306 }
307 };
308
309} // namespace JSC
310
311#endif // CodeBlock_h
Note: See TracBrowser for help on using the repository browser.