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.
27 #include "Executable.h"
29 #include "BytecodeGenerator.h"
30 #include "CodeBlock.h"
33 #include "StringBuilder.h"
39 NativeExecutable::~NativeExecutable()
44 VPtrHackExecutable::~VPtrHackExecutable()
48 EvalExecutable::~EvalExecutable()
50 delete m_evalCodeBlock
;
53 ProgramExecutable::~ProgramExecutable()
55 delete m_programCodeBlock
;
58 FunctionExecutable::~FunctionExecutable()
63 JSObject
* EvalExecutable::compile(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
67 RefPtr
<EvalNode
> evalNode
= exec
->globalData().parser
->parse
<EvalNode
>(&exec
->globalData(), exec
->lexicalGlobalObject()->debugger(), exec
, m_source
, &errLine
, &errMsg
);
69 return Error::create(exec
, SyntaxError
, errMsg
, errLine
, m_source
.provider()->asID(), m_source
.provider()->url());
70 recordParse(evalNode
->features(), evalNode
->lineNo(), evalNode
->lastLine());
72 ScopeChain
scopeChain(scopeChainNode
);
73 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
75 ASSERT(!m_evalCodeBlock
);
76 m_evalCodeBlock
= new EvalCodeBlock(this, globalObject
, source().provider(), scopeChain
.localDepth());
77 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(evalNode
.get(), globalObject
->debugger(), scopeChain
, m_evalCodeBlock
->symbolTable(), m_evalCodeBlock
));
78 generator
->generate();
80 evalNode
->destroyData();
84 JSObject
* ProgramExecutable::checkSyntax(ExecState
* exec
)
88 RefPtr
<ProgramNode
> programNode
= exec
->globalData().parser
->parse
<ProgramNode
>(&exec
->globalData(), exec
->lexicalGlobalObject()->debugger(), exec
, m_source
, &errLine
, &errMsg
);
90 return Error::create(exec
, SyntaxError
, errMsg
, errLine
, m_source
.provider()->asID(), m_source
.provider()->url());
94 JSObject
* ProgramExecutable::compile(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
98 RefPtr
<ProgramNode
> programNode
= exec
->globalData().parser
->parse
<ProgramNode
>(&exec
->globalData(), exec
->lexicalGlobalObject()->debugger(), exec
, m_source
, &errLine
, &errMsg
);
100 return Error::create(exec
, SyntaxError
, errMsg
, errLine
, m_source
.provider()->asID(), m_source
.provider()->url());
101 recordParse(programNode
->features(), programNode
->lineNo(), programNode
->lastLine());
103 ScopeChain
scopeChain(scopeChainNode
);
104 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
106 ASSERT(!m_programCodeBlock
);
107 m_programCodeBlock
= new ProgramCodeBlock(this, GlobalCode
, globalObject
, source().provider());
108 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(programNode
.get(), globalObject
->debugger(), scopeChain
, &globalObject
->symbolTable(), m_programCodeBlock
));
109 generator
->generate();
111 programNode
->destroyData();
115 void FunctionExecutable::compile(ExecState
*, ScopeChainNode
* scopeChainNode
)
117 JSGlobalData
* globalData
= scopeChainNode
->globalData
;
118 RefPtr
<FunctionBodyNode
> body
= globalData
->parser
->parse
<FunctionBodyNode
>(globalData
, 0, 0, m_source
);
119 if (m_forceUsesArguments
)
120 body
->setUsesArguments();
121 body
->finishParsing(m_parameters
, m_name
);
122 recordParse(body
->features(), body
->lineNo(), body
->lastLine());
124 ScopeChain
scopeChain(scopeChainNode
);
125 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
127 ASSERT(!m_codeBlock
);
128 m_codeBlock
= new FunctionCodeBlock(this, FunctionCode
, source().provider(), source().startOffset());
129 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(body
.get(), globalObject
->debugger(), scopeChain
, m_codeBlock
->symbolTable(), m_codeBlock
));
130 generator
->generate();
131 m_numParameters
= m_codeBlock
->m_numParameters
;
132 ASSERT(m_numParameters
);
133 m_numVariables
= m_codeBlock
->m_numVars
;
140 void EvalExecutable::generateJITCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
142 #if ENABLE(INTERPRETER)
143 ASSERT(scopeChainNode
->globalData
->canUseJIT());
145 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
146 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
148 #if !ENABLE(OPCODE_SAMPLING)
149 if (!BytecodeGenerator::dumpsGeneratedCode())
150 codeBlock
->discardBytecode();
154 void ProgramExecutable::generateJITCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
156 #if ENABLE(INTERPRETER)
157 ASSERT(scopeChainNode
->globalData
->canUseJIT());
159 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
160 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
162 #if !ENABLE(OPCODE_SAMPLING)
163 if (!BytecodeGenerator::dumpsGeneratedCode())
164 codeBlock
->discardBytecode();
168 void FunctionExecutable::generateJITCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
170 #if ENABLE(INTERPRETER)
171 ASSERT(scopeChainNode
->globalData
->canUseJIT());
173 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
174 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
176 #if !ENABLE(OPCODE_SAMPLING)
177 if (!BytecodeGenerator::dumpsGeneratedCode())
178 codeBlock
->discardBytecode();
184 void FunctionExecutable::markAggregate(MarkStack
& markStack
)
187 m_codeBlock
->markAggregate(markStack
);
190 ExceptionInfo
* FunctionExecutable::reparseExceptionInfo(JSGlobalData
* globalData
, ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlock
)
192 RefPtr
<FunctionBodyNode
> newFunctionBody
= globalData
->parser
->parse
<FunctionBodyNode
>(globalData
, 0, 0, m_source
);
193 if (m_forceUsesArguments
)
194 newFunctionBody
->setUsesArguments();
195 newFunctionBody
->finishParsing(m_parameters
, m_name
);
197 ScopeChain
scopeChain(scopeChainNode
);
198 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
200 OwnPtr
<CodeBlock
> newCodeBlock(new FunctionCodeBlock(this, FunctionCode
, source().provider(), source().startOffset()));
201 globalData
->functionCodeBlockBeingReparsed
= newCodeBlock
.get();
203 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(newFunctionBody
.get(), globalObject
->debugger(), scopeChain
, newCodeBlock
->symbolTable(), newCodeBlock
.get()));
204 generator
->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock
*>(codeBlock
));
205 generator
->generate();
207 ASSERT(newCodeBlock
->instructionCount() == codeBlock
->instructionCount());
210 #if ENABLE(INTERPRETER)
211 if (globalData
->canUseJIT())
214 JITCode newJITCode
= JIT::compile(globalData
, newCodeBlock
.get());
215 ASSERT(newJITCode
.size() == generatedJITCode().size());
219 globalData
->functionCodeBlockBeingReparsed
= 0;
221 return newCodeBlock
->extractExceptionInfo();
224 ExceptionInfo
* EvalExecutable::reparseExceptionInfo(JSGlobalData
* globalData
, ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlock
)
226 RefPtr
<EvalNode
> newEvalBody
= globalData
->parser
->parse
<EvalNode
>(globalData
, 0, 0, m_source
);
228 ScopeChain
scopeChain(scopeChainNode
);
229 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
231 OwnPtr
<EvalCodeBlock
> newCodeBlock(new EvalCodeBlock(this, globalObject
, source().provider(), scopeChain
.localDepth()));
233 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(newEvalBody
.get(), globalObject
->debugger(), scopeChain
, newCodeBlock
->symbolTable(), newCodeBlock
.get()));
234 generator
->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock
*>(codeBlock
));
235 generator
->generate();
237 ASSERT(newCodeBlock
->instructionCount() == codeBlock
->instructionCount());
240 #if ENABLE(INTERPRETER)
241 if (globalData
->canUseJIT())
244 JITCode newJITCode
= JIT::compile(globalData
, newCodeBlock
.get());
245 ASSERT(newJITCode
.size() == generatedJITCode().size());
249 return newCodeBlock
->extractExceptionInfo();
252 void FunctionExecutable::recompile(ExecState
*)
256 m_numParameters
= NUM_PARAMETERS_NOT_COMPILED
;
258 m_jitCode
= JITCode();
262 PassRefPtr
<FunctionExecutable
> FunctionExecutable::fromGlobalCode(const Identifier
& functionName
, ExecState
* exec
, Debugger
* debugger
, const SourceCode
& source
, int* errLine
, UString
* errMsg
)
264 RefPtr
<ProgramNode
> program
= exec
->globalData().parser
->parse
<ProgramNode
>(&exec
->globalData(), debugger
, exec
, source
, errLine
, errMsg
);
268 StatementNode
* exprStatement
= program
->singleStatement();
269 ASSERT(exprStatement
);
270 ASSERT(exprStatement
->isExprStatement());
271 if (!exprStatement
|| !exprStatement
->isExprStatement())
274 ExpressionNode
* funcExpr
= static_cast<ExprStatementNode
*>(exprStatement
)->expr();
276 ASSERT(funcExpr
->isFuncExprNode());
277 if (!funcExpr
|| !funcExpr
->isFuncExprNode())
280 FunctionBodyNode
* body
= static_cast<FuncExprNode
*>(funcExpr
)->body();
282 return FunctionExecutable::create(&exec
->globalData(), functionName
, body
->source(), body
->usesArguments(), body
->parameters(), body
->lineNo(), body
->lastLine());
285 UString
FunctionExecutable::paramString() const
287 FunctionParameters
& parameters
= *m_parameters
;
288 StringBuilder builder
;
289 for (size_t pos
= 0; pos
< parameters
.size(); ++pos
) {
290 if (!builder
.isEmpty())
291 builder
.append(", ");
292 builder
.append(parameters
[pos
].ustring());
294 return builder
.build();