source: webkit/trunk/JavaScriptCore/runtime/Executable.h@ 58286

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

2010-04-26 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

Need to support more efficient dispatch of lightweight builtins
https://bugs.webkit.org/show_bug.cgi?id=38155

The problem with calling lightweight builtins is that marshalling
the call from the nitro calling convention to the system calling
convention is very expensive relative to the cost of the actually
evaluating the function. To work around this problem this patch
adds the ability to define a custom thunk for a builtin.

This allows us to use high performance custom implementations of
the common and sensible versions of simple builtins. This patch
includes a simple (use of which is currently hardcoded) thunk for
charCodeAt.

This adds a JSInterfaceJIT subclass called SpecializedThunkJIT
that has helper functions to remove (or at least reduce) the need
to have separate thunk implementations for each JSValue encoding.

  • create_hash_table: Add thunk generation callbacks to the hash tables, currently we hardcode the script to only support charCodeAt
  • jit/JITStubCall.h:
  • jit/JITStubs.cpp: (JSC::JITThunks::~JITThunks): (JSC::JITThunks::specializedThunk):
  • jit/JITStubs.h:
  • jit/SpecializedThunkJIT.h: Added. (JSC::SpecializedThunkJIT::SpecializedThunkJIT): (JSC::SpecializedThunkJIT::loadCellArgument): (JSC::SpecializedThunkJIT::loadJSStringArgument): (JSC::SpecializedThunkJIT::loadInt32Argument): (JSC::SpecializedThunkJIT::appendFailure): (JSC::SpecializedThunkJIT::returnInt32): (JSC::SpecializedThunkJIT::finalize): (JSC::SpecializedThunkJIT::argumentToVirtualRegister): (JSC::SpecializedThunkJIT::tagReturnAsInt32):
  • jit/ThunkGenerators.cpp: Added. (JSC::ThunkHelpers::stringImplDataOffset): (JSC::ThunkHelpers::jsStringLengthOffset): (JSC::ThunkHelpers::jsStringValueOffset): (JSC::charCodeAtThunkGenerator):
  • jit/ThunkGenerators.h: Added.
  • runtime/Executable.h: (JSC::NativeExecutable::NativeExecutable):
  • runtime/JSFunction.cpp: (JSC::JSFunction::JSFunction):
  • runtime/JSFunction.h:
  • runtime/JSGlobalData.h: (JSC::JSGlobalData::getThunk):
  • runtime/JSString.h: (JSC::):
  • runtime/JSValue.h: Protect some of the JSVALUE32 and JSVALUE32_64 only constants and function behind appropriate USE() guards to make it harder to use the wrong flags for the target build.
  • runtime/Lookup.cpp: (JSC::HashTable::createTable): (JSC::setUpStaticFunctionSlot):
  • runtime/Lookup.h: (JSC::HashEntry::initialize): (JSC::HashEntry::generator): (JSC::HashEntry::): Make the lookup tables use a specialized thunkGenerator if present
  • wtf/text/StringImpl.h:

2010-04-26 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

Need to support more efficient dispatch of lightweight builtins
https://bugs.webkit.org/show_bug.cgi?id=38155

Update bindings generation to include new thunk generator field
in the property map hash tables.

  • bindings/scripts/CodeGeneratorJS.pm:
File size: 11.5 KB
Line 
1/*
2 * Copyright (C) 2009 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 Executable_h
27#define Executable_h
28
29#include "JSFunction.h"
30#include "Interpreter.h"
31#include "Nodes.h"
32#include "SamplingTool.h"
33
34namespace JSC {
35
36 class CodeBlock;
37 class Debugger;
38 class EvalCodeBlock;
39 class ProgramCodeBlock;
40 class ScopeChainNode;
41
42 struct ExceptionInfo;
43
44 class ExecutableBase : public RefCounted<ExecutableBase> {
45 friend class JIT;
46
47 protected:
48 static const int NUM_PARAMETERS_IS_HOST = 0;
49 static const int NUM_PARAMETERS_NOT_COMPILED = -1;
50
51 public:
52 ExecutableBase(int numParameters)
53 : m_numParameters(numParameters)
54 {
55 }
56
57 virtual ~ExecutableBase() {}
58
59 bool isHostFunction() const { return m_numParameters == NUM_PARAMETERS_IS_HOST; }
60
61 protected:
62 int m_numParameters;
63
64#if ENABLE(JIT)
65 public:
66 JITCode& generatedJITCode()
67 {
68 ASSERT(m_jitCode);
69 return m_jitCode;
70 }
71
72 ExecutablePool* getExecutablePool()
73 {
74 return m_jitCode.getExecutablePool();
75 }
76
77 protected:
78 JITCode m_jitCode;
79#endif
80 };
81
82#if ENABLE(JIT)
83 class NativeExecutable : public ExecutableBase {
84 public:
85 NativeExecutable(ExecState* exec)
86 : ExecutableBase(NUM_PARAMETERS_IS_HOST)
87 {
88 m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk()));
89 }
90 NativeExecutable(JITCode thunk)
91 : ExecutableBase(NUM_PARAMETERS_IS_HOST)
92 {
93 m_jitCode = thunk;
94 }
95
96 ~NativeExecutable();
97 };
98#endif
99
100 class VPtrHackExecutable : public ExecutableBase {
101 public:
102 VPtrHackExecutable()
103 : ExecutableBase(NUM_PARAMETERS_IS_HOST)
104 {
105 }
106
107 ~VPtrHackExecutable();
108 };
109
110 class ScriptExecutable : public ExecutableBase {
111 public:
112 ScriptExecutable(JSGlobalData* globalData, const SourceCode& source)
113 : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
114 , m_source(source)
115 , m_features(0)
116 {
117#if ENABLE(CODEBLOCK_SAMPLING)
118 if (SamplingTool* sampler = globalData->interpreter->sampler())
119 sampler->notifyOfScope(this);
120#else
121 UNUSED_PARAM(globalData);
122#endif
123 }
124
125 ScriptExecutable(ExecState* exec, const SourceCode& source)
126 : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED)
127 , m_source(source)
128 , m_features(0)
129 {
130#if ENABLE(CODEBLOCK_SAMPLING)
131 if (SamplingTool* sampler = exec->globalData().interpreter->sampler())
132 sampler->notifyOfScope(this);
133#else
134 UNUSED_PARAM(exec);
135#endif
136 }
137
138 const SourceCode& source() { return m_source; }
139 intptr_t sourceID() const { return m_source.provider()->asID(); }
140 const UString& sourceURL() const { return m_source.provider()->url(); }
141 int lineNo() const { return m_firstLine; }
142 int lastLine() const { return m_lastLine; }
143
144 bool usesEval() const { return m_features & EvalFeature; }
145 bool usesArguments() const { return m_features & ArgumentsFeature; }
146 bool needsActivation() const { return m_features & (EvalFeature | ClosureFeature | WithFeature | CatchFeature); }
147
148 virtual ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) = 0;
149
150 protected:
151 void recordParse(CodeFeatures features, int firstLine, int lastLine)
152 {
153 m_features = features;
154 m_firstLine = firstLine;
155 m_lastLine = lastLine;
156 }
157
158 SourceCode m_source;
159 CodeFeatures m_features;
160 int m_firstLine;
161 int m_lastLine;
162 };
163
164 class EvalExecutable : public ScriptExecutable {
165 public:
166
167 ~EvalExecutable();
168
169 EvalCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
170 {
171 if (!m_evalCodeBlock) {
172 JSObject* error = compile(exec, scopeChainNode);
173 ASSERT_UNUSED(!error, error);
174 }
175 return *m_evalCodeBlock;
176 }
177
178 JSObject* compile(ExecState*, ScopeChainNode*);
179
180 ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
181 static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); }
182
183 private:
184 EvalExecutable(ExecState* exec, const SourceCode& source)
185 : ScriptExecutable(exec, source)
186 , m_evalCodeBlock(0)
187 {
188 }
189 EvalCodeBlock* m_evalCodeBlock;
190
191#if ENABLE(JIT)
192 public:
193 JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
194 {
195 if (!m_jitCode)
196 generateJITCode(exec, scopeChainNode);
197 return m_jitCode;
198 }
199
200 private:
201 void generateJITCode(ExecState*, ScopeChainNode*);
202#endif
203 };
204
205 class ProgramExecutable : public ScriptExecutable {
206 public:
207 static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source)
208 {
209 return adoptRef(new ProgramExecutable(exec, source));
210 }
211
212 ~ProgramExecutable();
213
214 ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
215 {
216 if (!m_programCodeBlock) {
217 JSObject* error = compile(exec, scopeChainNode);
218 ASSERT_UNUSED(!error, error);
219 }
220 return *m_programCodeBlock;
221 }
222
223 JSObject* checkSyntax(ExecState*);
224 JSObject* compile(ExecState*, ScopeChainNode*);
225
226 // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
227 ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; }
228
229 private:
230 ProgramExecutable(ExecState* exec, const SourceCode& source)
231 : ScriptExecutable(exec, source)
232 , m_programCodeBlock(0)
233 {
234 }
235 ProgramCodeBlock* m_programCodeBlock;
236
237#if ENABLE(JIT)
238 public:
239 JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
240 {
241 if (!m_jitCode)
242 generateJITCode(exec, scopeChainNode);
243 return m_jitCode;
244 }
245
246 private:
247 void generateJITCode(ExecState*, ScopeChainNode*);
248#endif
249 };
250
251 class FunctionExecutable : public ScriptExecutable {
252 friend class JIT;
253 public:
254 static PassRefPtr<FunctionExecutable> create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
255 {
256 return adoptRef(new FunctionExecutable(exec, name, source, forceUsesArguments, parameters, firstLine, lastLine));
257 }
258
259 static PassRefPtr<FunctionExecutable> create(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
260 {
261 return adoptRef(new FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, firstLine, lastLine));
262 }
263
264 ~FunctionExecutable();
265
266 JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain)
267 {
268 return new (exec) JSFunction(exec, this, scopeChain);
269 }
270
271 CodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode)
272 {
273 ASSERT(scopeChainNode);
274 if (!m_codeBlock)
275 compile(exec, scopeChainNode);
276 return *m_codeBlock;
277 }
278
279 bool isGenerated() const
280 {
281 return m_codeBlock;
282 }
283
284 CodeBlock& generatedBytecode()
285 {
286 ASSERT(m_codeBlock);
287 return *m_codeBlock;
288 }
289
290 const Identifier& name() { return m_name; }
291 size_t parameterCount() const { return m_parameters->size(); }
292 size_t variableCount() const { return m_numVariables; }
293 UString paramString() const;
294
295 void recompile(ExecState*);
296 ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*);
297 void markAggregate(MarkStack& markStack);
298 static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, int* errLine = 0, UString* errMsg = 0);
299
300 private:
301 FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
302 : ScriptExecutable(globalData, source)
303 , m_forceUsesArguments(forceUsesArguments)
304 , m_parameters(parameters)
305 , m_codeBlock(0)
306 , m_name(name)
307 , m_numVariables(0)
308 {
309 m_firstLine = firstLine;
310 m_lastLine = lastLine;
311 }
312
313 FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
314 : ScriptExecutable(exec, source)
315 , m_forceUsesArguments(forceUsesArguments)
316 , m_parameters(parameters)
317 , m_codeBlock(0)
318 , m_name(name)
319 , m_numVariables(0)
320 {
321 m_firstLine = firstLine;
322 m_lastLine = lastLine;
323 }
324
325 void compile(ExecState*, ScopeChainNode*);
326
327 bool m_forceUsesArguments;
328 RefPtr<FunctionParameters> m_parameters;
329 CodeBlock* m_codeBlock;
330 Identifier m_name;
331 size_t m_numVariables;
332
333#if ENABLE(JIT)
334 public:
335 JITCode& jitCode(ExecState* exec, ScopeChainNode* scopeChainNode)
336 {
337 if (!m_jitCode)
338 generateJITCode(exec, scopeChainNode);
339 return m_jitCode;
340 }
341
342 private:
343 void generateJITCode(ExecState*, ScopeChainNode*);
344#endif
345 };
346
347 inline FunctionExecutable* JSFunction::jsExecutable() const
348 {
349 ASSERT(!isHostFunctionNonInline());
350 return static_cast<FunctionExecutable*>(m_executable.get());
351 }
352
353 inline bool JSFunction::isHostFunction() const
354 {
355 ASSERT(m_executable);
356 return m_executable->isHostFunction();
357 }
358
359}
360
361#endif
Note: See TracBrowser for help on using the repository browser.