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

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

JavaScriptCore:

2008-10-01 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler and Cameron Zwarich.

Preliminary step toward dynamic recompilation: Standardized and
simplified the parsing interface.


The main goal in this patch is to make it easy to ask for a duplicate
compilation, and get back a duplicate result -- same source URL, same
debugger / profiler ID, same toString behavior, etc.


The basic unit of compilation and evaluation is now SourceCode, which
encompasses a SourceProvider, a range in that provider, and a starting
line number.

A SourceProvider now encompasses a source URL, and *is* a source ID,
since a pointer is a unique identifier.

  • API/JSBase.cpp: (JSEvaluateScript): (JSCheckScriptSyntax): Provide a SourceCode to the Interpreter, since other APIs are no longer supported.


  • VM/CodeBlock.h: (JSC::EvalCodeCache::get): Provide a SourceCode to the Interpreter, since other APIs are no longer supported. (JSC::CodeBlock::CodeBlock): ASSERT something that used to be ASSERTed by our caller -- this is a better bottleneck.
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::CodeGenerator): Updated for the fact that FunctionBodyNode's parameters are no longer a WTF::Vector.
  • kjs/Arguments.cpp: (JSC::Arguments::Arguments): ditto
  • kjs/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::evaluate): Provide a SourceCode to the Parser, since other APIs are no longer supported.
  • kjs/FunctionConstructor.cpp: (JSC::constructFunction): Provide a SourceCode to the Parser, since other APIs are no longer supported. Adopt FunctionBodyNode's new "finishParsing" API.
  • kjs/JSFunction.cpp: (JSC::JSFunction::lengthGetter): (JSC::JSFunction::getParameterName): Updated for the fact that FunctionBodyNode's parameters are no longer a wtf::Vector.
  • kjs/JSFunction.h: Nixed some cruft.
  • kjs/JSGlobalObjectFunctions.cpp: (JSC::globalFuncEval): Provide a SourceCode to the Parser, since other APIs are no longer supported.
  • kjs/Parser.cpp: (JSC::Parser::parse): Require a SourceCode argument, instead of a bunch of broken out parameters. Stop tracking sourceId as an integer, since we use the SourceProvider pointer for this now. Don't clamp the startingLineNumber, since SourceCode does that now.
  • kjs/Parser.h: (JSC::Parser::parse): Standardized the parsing interface to require a SourceCode.
  • kjs/Shell.cpp: (functionRun): (functionLoad): (prettyPrintScript): (runWithScripts): (runInteractive): Provide a SourceCode to the Interpreter, since other APIs are no longer supported.
  • kjs/SourceProvider.h: (JSC::SourceProvider::SourceProvider): (JSC::SourceProvider::url): (JSC::SourceProvider::asId): (JSC::UStringSourceProvider::create): (JSC::UStringSourceProvider::UStringSourceProvider): Added new responsibilities described above.
  • kjs/SourceRange.h: (JSC::SourceCode::SourceCode): (JSC::SourceCode::toString): (JSC::SourceCode::provider): (JSC::SourceCode::firstLine): (JSC::SourceCode::data): (JSC::SourceCode::length): Added new responsibilities described above. Renamed SourceRange to SourceCode, based on review feedback. Added a makeSource function for convenience.
  • kjs/debugger.h: Provide a SourceCode to the client, since other APIs are no longer supported.
  • kjs/grammar.y: Provide startingLineNumber when creating a SourceCode.
  • kjs/debugger.h: Treat sourceId as intptr_t to avoid loss of precision on 64bit platforms.
  • kjs/interpreter.cpp: (JSC::Interpreter::checkSyntax): (JSC::Interpreter::evaluate):
  • kjs/interpreter.h: Require a SourceCode instead of broken out arguments.
  • kjs/lexer.cpp: (JSC::Lexer::setCode):
  • kjs/lexer.h: (JSC::Lexer::sourceRange): Fold together the SourceProvider and line number into a SourceCode. Fixed a bug where the Lexer would accidentally keep alive the last SourceProvider forever.
  • kjs/nodes.cpp: (JSC::ScopeNode::ScopeNode): (JSC::ProgramNode::ProgramNode): (JSC::ProgramNode::create): (JSC::EvalNode::EvalNode): (JSC::EvalNode::generateCode): (JSC::EvalNode::create): (JSC::FunctionBodyNode::FunctionBodyNode): (JSC::FunctionBodyNode::finishParsing): (JSC::FunctionBodyNode::create): (JSC::FunctionBodyNode::generateCode): (JSC::ProgramNode::generateCode): (JSC::FunctionBodyNode::paramString):
  • kjs/nodes.h: (JSC::ScopeNode::): (JSC::ScopeNode::sourceId): (JSC::FunctionBodyNode::): (JSC::FunctionBodyNode::parameterCount): (JSC::FuncExprNode::): (JSC::FuncDeclNode::): Store a SourceCode in all ScopeNodes, since SourceCode is now responsible for tracking URL, ID, etc. Streamlined some ad hoc FunctionBodyNode fixups into a "finishParsing" function, to help make clear what you need to do in order to finish parsing a FunctionBodyNode.
  • wtf/Vector.h: (WTF::::releaseBuffer): Don't ASSERT that releaseBuffer() is only called when buffer is not 0, since FunctionBodyNode is more than happy to get back a 0 buffer, and other functions like RefPtr::release() allow for 0, too.

JavaScriptGlue:

2008-10-01 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler and Cameron Zwarich.

  • JSRun.cpp: (JSRun::Evaluate): (JSRun::CheckSyntax): Provide a SourceCode to the Interpreter, since other APIs are no longer supported.

WebCore:

2008-10-01 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler and Cameron Zwarich.

Updated for JavaScriptCore API changes: use a SourceCode instead of
broken out parameters; treat sourceId as intptr_t.

  • ForwardingHeaders/kjs/SourceRange.h: Copied from ForwardingHeaders/kjs/SourceProvider.h.
  • bindings/js/JSXMLHttpRequestCustom.cpp: (WebCore::JSXMLHttpRequest::send):
  • bindings/js/ScriptController.cpp: (WebCore::ScriptController::evaluate):
  • bindings/js/StringSourceProvider.h: (WebCore::StringSourceProvider::create): (WebCore::StringSourceProvider::StringSourceProvider):

(WebCore::makeSource): Added a makeSource function for convenience.

  • bindings/objc/WebScriptObject.mm: (-[WebScriptObject evaluateWebScript:]):
  • bridge/NP_jsobject.cpp: (_NPN_Evaluate):
  • bridge/jni/jni_jsobject.mm: (JavaJSObject::call): (JavaJSObject::eval): (JavaJSObject::getMember): (JavaJSObject::setMember): (JavaJSObject::removeMember):
  • bridge/jni/jni_runtime.h: (JSC::Bindings::JavaString::operator UString): Replaced the explicit ustring() function with an implicit operator because this class already holds a UString::rep.
  • page/Console.cpp: (WebCore::retrieveLastCaller): (WebCore::Console::trace):
  • page/InspectorController.cpp: (WebCore::jsStringRef): (WebCore::InspectorController::addBreakpoint): (WebCore::InspectorController::removeBreakpoint): (WebCore::InspectorController::didParseSource): (WebCore::InspectorController::failedToParseSource):
  • page/InspectorController.h:
  • page/JavaScriptCallFrame.cpp: (WebCore::JavaScriptCallFrame::JavaScriptCallFrame):
  • page/JavaScriptCallFrame.h: (WebCore::JavaScriptCallFrame::create): (WebCore::JavaScriptCallFrame::sourceIdentifier): (WebCore::JavaScriptCallFrame::update):
  • page/JavaScriptDebugListener.h:
  • page/JavaScriptDebugServer.cpp: (WebCore::JavaScriptDebugServer::addBreakpoint): (WebCore::JavaScriptDebugServer::removeBreakpoint): (WebCore::JavaScriptDebugServer::hasBreakpoint): (WebCore::dispatchDidParseSource): (WebCore::dispatchFailedToParseSource): (WebCore::JavaScriptDebugServer::sourceParsed): (WebCore::JavaScriptDebugServer::callEvent): (WebCore::JavaScriptDebugServer::atStatement): (WebCore::JavaScriptDebugServer::returnEvent): (WebCore::JavaScriptDebugServer::exception): (WebCore::JavaScriptDebugServer::willExecuteProgram): (WebCore::JavaScriptDebugServer::didExecuteProgram): (WebCore::JavaScriptDebugServer::didReachBreakpoint):
  • page/JavaScriptDebugServer.h:
  • page/inspector/ScriptsPanel.js: Renamed internal uses of sourceId and sourceIdentifier to sourceID.

WebKit/mac:

2008-10-01 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler and Cameron Zwarich.

Updated for JavaScriptCore API changes: use a SourceCode instead of
broken out parameters; treat sourceId as intptr_t.


We still treat sourceId as int in some cases because of DashCode. See
<rdar://problem/6263293> WebScriptDebugDelegate should use intptr_t for
sourceId, not int.

  • WebView/WebScriptDebugger.h:
  • WebView/WebScriptDebugger.mm: (toNSString): (WebScriptDebugger::sourceParsed): (WebScriptDebugger::callEvent): (WebScriptDebugger::atStatement): (WebScriptDebugger::returnEvent): (WebScriptDebugger::exception): (WebScriptDebugger::willExecuteProgram): (WebScriptDebugger::didExecuteProgram): (WebScriptDebugger::didReachBreakpoint):
File size: 10.5 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 errLine;
159 UString errMsg;
160
161 SourceCode source = makeSource(evalSource);
162 evalNode = exec->parser()->parse<EvalNode>(exec, source, &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, source.provider()->asID(), 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 , numCalleeRegisters(0)
190 , numConstants(0)
191 , numVars(0)
192 , numParameters(0)
193 , needsFullScopeChain(ownerNode_->usesEval() || ownerNode_->needsClosure())
194 , usesEval(ownerNode_->usesEval())
195 , codeType(codeType_)
196 , source(source_)
197 , sourceOffset(sourceOffset_)
198 {
199 ASSERT(source);
200 }
201
202 ~CodeBlock();
203
204#if !defined(NDEBUG) || ENABLE_SAMPLING_TOOL
205 void dump(ExecState*) const;
206 void printStructureIDs(const Instruction*) const;
207 void printStructureID(const char* name, const Instruction*, int operand) const;
208#endif
209 int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
210 int lineNumberForVPC(const Instruction* vPC);
211 bool getHandlerForVPC(const Instruction* vPC, Instruction*& target, int& scopeDepth);
212 void* nativeExceptionCodeForHandlerVPC(const Instruction* handlerVPC);
213
214 void mark();
215 void refStructureIDs(Instruction* vPC) const;
216 void derefStructureIDs(Instruction* vPC) const;
217
218 StructureStubInfo& getStubInfo(void* returnAddress)
219 {
220 // FIXME: would a binary chop be faster here?
221 for (unsigned i = 0; ; ++i) {
222 if (structureIDInstructions[i].callReturnLocation == returnAddress)
223 return structureIDInstructions[i];
224 }
225 }
226
227 ScopeNode* ownerNode;
228 JSGlobalData* globalData;
229#if ENABLE(CTI)
230 void* ctiCode;
231#endif
232
233 int numCalleeRegisters;
234
235 // NOTE: numConstants holds the number of constant registers allocated
236 // by the code generator, not the number of constant registers used.
237 // (Duplicate constants are uniqued during code generation, and spare
238 // constant registers may be allocated.)
239 int numConstants;
240 int numVars;
241 int numParameters;
242 int thisRegister;
243 bool needsFullScopeChain;
244 bool usesEval;
245 bool usesArguments;
246 CodeType codeType;
247 RefPtr<SourceProvider> source;
248 unsigned sourceOffset;
249
250 Vector<Instruction> instructions;
251 Vector<StructureStubInfo> structureIDInstructions;
252
253 // Constant pool
254 Vector<Identifier> identifiers;
255 Vector<RefPtr<FuncDeclNode> > functions;
256 Vector<RefPtr<FuncExprNode> > functionExpressions;
257 Vector<Register> constantRegisters;
258 Vector<JSValue*> unexpectedConstants;
259 Vector<RefPtr<RegExp> > regexps;
260 Vector<HandlerInfo> exceptionHandlers;
261 Vector<ExpressionRangeInfo> expressionInfo;
262 Vector<LineInfo> lineInfo;
263
264 Vector<SimpleJumpTable> immediateSwitchJumpTables;
265 Vector<SimpleJumpTable> characterSwitchJumpTables;
266 Vector<StringJumpTable> stringSwitchJumpTables;
267
268 HashSet<unsigned, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > labels;
269
270#if ENABLE(CTI)
271 HashMap<void*, unsigned> ctiReturnAddressVPCMap;
272#endif
273
274 EvalCodeCache evalCodeCache;
275
276 private:
277#if !defined(NDEBUG) || ENABLE(SAMPLING_TOOL)
278 void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
279#endif
280
281 };
282
283 // Program code is not marked by any function, so we make the global object
284 // responsible for marking it.
285
286 struct ProgramCodeBlock : public CodeBlock {
287 ProgramCodeBlock(ScopeNode* ownerNode_, CodeType codeType_, JSGlobalObject* globalObject_, PassRefPtr<SourceProvider> source_)
288 : CodeBlock(ownerNode_, codeType_, source_, 0)
289 , globalObject(globalObject_)
290 {
291 globalObject->codeBlocks().add(this);
292 }
293
294 ~ProgramCodeBlock()
295 {
296 if (globalObject)
297 globalObject->codeBlocks().remove(this);
298 }
299
300 JSGlobalObject* globalObject; // For program and eval nodes, the global object that marks the constant pool.
301 };
302
303 struct EvalCodeBlock : public ProgramCodeBlock {
304 EvalCodeBlock(ScopeNode* ownerNode_, JSGlobalObject* globalObject_, PassRefPtr<SourceProvider> source_)
305 : ProgramCodeBlock(ownerNode_, EvalCode, globalObject_, source_)
306 {
307 }
308 };
309
310} // namespace JSC
311
312#endif // CodeBlock_h
Note: See TracBrowser for help on using the repository browser.