2 * Copyright (C) 2009 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "JSFunction.h"
30 #include "Interpreter.h"
32 #include "SamplingTool.h"
39 class ProgramCodeBlock
;
44 class ExecutableBase
: public RefCounted
<ExecutableBase
> {
48 static const int NUM_PARAMETERS_IS_HOST
= 0;
49 static const int NUM_PARAMETERS_NOT_COMPILED
= -1;
52 ExecutableBase(int numParameters
)
53 : m_numParameters(numParameters
)
57 virtual ~ExecutableBase() {}
59 bool isHostFunction() const { return m_numParameters
== NUM_PARAMETERS_IS_HOST
; }
66 JITCode
& generatedJITCode()
72 ExecutablePool
* getExecutablePool()
74 return m_jitCode
.getExecutablePool();
83 class NativeExecutable
: public ExecutableBase
{
85 NativeExecutable(JITCode thunk
)
86 : ExecutableBase(NUM_PARAMETERS_IS_HOST
)
95 class VPtrHackExecutable
: public ExecutableBase
{
98 : ExecutableBase(NUM_PARAMETERS_IS_HOST
)
102 ~VPtrHackExecutable();
105 class ScriptExecutable
: public ExecutableBase
{
107 ScriptExecutable(JSGlobalData
* globalData
, const SourceCode
& source
)
108 : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED
)
112 #if ENABLE(CODEBLOCK_SAMPLING)
113 if (SamplingTool
* sampler
= globalData
->interpreter
->sampler())
114 sampler
->notifyOfScope(this);
116 UNUSED_PARAM(globalData
);
120 ScriptExecutable(ExecState
* exec
, const SourceCode
& source
)
121 : ExecutableBase(NUM_PARAMETERS_NOT_COMPILED
)
125 #if ENABLE(CODEBLOCK_SAMPLING)
126 if (SamplingTool
* sampler
= exec
->globalData().interpreter
->sampler())
127 sampler
->notifyOfScope(this);
133 const SourceCode
& source() { return m_source
; }
134 intptr_t sourceID() const { return m_source
.provider()->asID(); }
135 const UString
& sourceURL() const { return m_source
.provider()->url(); }
136 int lineNo() const { return m_firstLine
; }
137 int lastLine() const { return m_lastLine
; }
139 bool usesEval() const { return m_features
& EvalFeature
; }
140 bool usesArguments() const { return m_features
& ArgumentsFeature
; }
141 bool needsActivation() const { return m_features
& (EvalFeature
| ClosureFeature
| WithFeature
| CatchFeature
); }
143 virtual ExceptionInfo
* reparseExceptionInfo(JSGlobalData
*, ScopeChainNode
*, CodeBlock
*) = 0;
146 void recordParse(CodeFeatures features
, int firstLine
, int lastLine
)
148 m_features
= features
;
149 m_firstLine
= firstLine
;
150 m_lastLine
= lastLine
;
154 CodeFeatures m_features
;
159 class EvalExecutable
: public ScriptExecutable
{
164 EvalCodeBlock
& bytecode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
166 if (!m_evalCodeBlock
) {
167 JSObject
* error
= compile(exec
, scopeChainNode
);
168 ASSERT_UNUSED(!error
, error
);
170 return *m_evalCodeBlock
;
173 JSObject
* compile(ExecState
*, ScopeChainNode
*);
175 ExceptionInfo
* reparseExceptionInfo(JSGlobalData
*, ScopeChainNode
*, CodeBlock
*);
176 static PassRefPtr
<EvalExecutable
> create(ExecState
* exec
, const SourceCode
& source
) { return adoptRef(new EvalExecutable(exec
, source
)); }
179 EvalExecutable(ExecState
* exec
, const SourceCode
& source
)
180 : ScriptExecutable(exec
, source
)
184 EvalCodeBlock
* m_evalCodeBlock
;
188 JITCode
& jitCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
191 generateJITCode(exec
, scopeChainNode
);
196 void generateJITCode(ExecState
*, ScopeChainNode
*);
200 class ProgramExecutable
: public ScriptExecutable
{
202 static PassRefPtr
<ProgramExecutable
> create(ExecState
* exec
, const SourceCode
& source
)
204 return adoptRef(new ProgramExecutable(exec
, source
));
207 ~ProgramExecutable();
209 ProgramCodeBlock
& bytecode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
211 if (!m_programCodeBlock
) {
212 JSObject
* error
= compile(exec
, scopeChainNode
);
213 ASSERT_UNUSED(!error
, error
);
215 return *m_programCodeBlock
;
218 JSObject
* checkSyntax(ExecState
*);
219 JSObject
* compile(ExecState
*, ScopeChainNode
*);
221 // CodeBlocks for program code are transient and therefore do not gain from from throwing out there exception information.
222 ExceptionInfo
* reparseExceptionInfo(JSGlobalData
*, ScopeChainNode
*, CodeBlock
*) { ASSERT_NOT_REACHED(); return 0; }
225 ProgramExecutable(ExecState
* exec
, const SourceCode
& source
)
226 : ScriptExecutable(exec
, source
)
227 , m_programCodeBlock(0)
230 ProgramCodeBlock
* m_programCodeBlock
;
234 JITCode
& jitCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
237 generateJITCode(exec
, scopeChainNode
);
242 void generateJITCode(ExecState
*, ScopeChainNode
*);
246 class FunctionExecutable
: public ScriptExecutable
{
249 static PassRefPtr
<FunctionExecutable
> create(ExecState
* exec
, const Identifier
& name
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, int firstLine
, int lastLine
)
251 return adoptRef(new FunctionExecutable(exec
, name
, source
, forceUsesArguments
, parameters
, firstLine
, lastLine
));
254 static PassRefPtr
<FunctionExecutable
> create(JSGlobalData
* globalData
, const Identifier
& name
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, int firstLine
, int lastLine
)
256 return adoptRef(new FunctionExecutable(globalData
, name
, source
, forceUsesArguments
, parameters
, firstLine
, lastLine
));
259 ~FunctionExecutable();
261 JSFunction
* make(ExecState
* exec
, ScopeChainNode
* scopeChain
)
263 return new (exec
) JSFunction(exec
, this, scopeChain
);
266 CodeBlock
& bytecode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
268 ASSERT(scopeChainNode
);
270 compile(exec
, scopeChainNode
);
274 bool isGenerated() const
279 CodeBlock
& generatedBytecode()
285 const Identifier
& name() { return m_name
; }
286 size_t parameterCount() const { return m_parameters
->size(); }
287 unsigned variableCount() const { return m_numVariables
; }
288 UString
paramString() const;
290 void recompile(ExecState
*);
291 ExceptionInfo
* reparseExceptionInfo(JSGlobalData
*, ScopeChainNode
*, CodeBlock
*);
292 void markAggregate(MarkStack
& markStack
);
293 static PassRefPtr
<FunctionExecutable
> fromGlobalCode(const Identifier
&, ExecState
*, Debugger
*, const SourceCode
&, int* errLine
= 0, UString
* errMsg
= 0);
296 FunctionExecutable(JSGlobalData
* globalData
, const Identifier
& name
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, int firstLine
, int lastLine
)
297 : ScriptExecutable(globalData
, source
)
299 , m_forceUsesArguments(forceUsesArguments
)
300 , m_parameters(parameters
)
304 m_firstLine
= firstLine
;
305 m_lastLine
= lastLine
;
308 FunctionExecutable(ExecState
* exec
, const Identifier
& name
, const SourceCode
& source
, bool forceUsesArguments
, FunctionParameters
* parameters
, int firstLine
, int lastLine
)
309 : ScriptExecutable(exec
, source
)
311 , m_forceUsesArguments(forceUsesArguments
)
312 , m_parameters(parameters
)
316 m_firstLine
= firstLine
;
317 m_lastLine
= lastLine
;
320 void compile(ExecState
*, ScopeChainNode
*);
322 unsigned m_numVariables
: 31;
323 bool m_forceUsesArguments
: 1;
325 RefPtr
<FunctionParameters
> m_parameters
;
326 CodeBlock
* m_codeBlock
;
331 JITCode
& jitCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
334 generateJITCode(exec
, scopeChainNode
);
339 void generateJITCode(ExecState
*, ScopeChainNode
*);
343 inline FunctionExecutable
* JSFunction::jsExecutable() const
345 ASSERT(!isHostFunctionNonInline());
346 return static_cast<FunctionExecutable
*>(m_executable
.get());
349 inline bool JSFunction::isHostFunction() const
351 ASSERT(m_executable
);
352 return m_executable
->isHostFunction();