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 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
143 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
145 #if !ENABLE(OPCODE_SAMPLING)
146 if (!BytecodeGenerator::dumpsGeneratedCode())
147 codeBlock
->discardBytecode();
151 void ProgramExecutable::generateJITCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
153 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
154 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
156 #if !ENABLE(OPCODE_SAMPLING)
157 if (!BytecodeGenerator::dumpsGeneratedCode())
158 codeBlock
->discardBytecode();
162 void FunctionExecutable::generateJITCode(ExecState
* exec
, ScopeChainNode
* scopeChainNode
)
164 CodeBlock
* codeBlock
= &bytecode(exec
, scopeChainNode
);
165 m_jitCode
= JIT::compile(scopeChainNode
->globalData
, codeBlock
);
167 #if !ENABLE(OPCODE_SAMPLING)
168 if (!BytecodeGenerator::dumpsGeneratedCode())
169 codeBlock
->discardBytecode();
175 void FunctionExecutable::markAggregate(MarkStack
& markStack
)
178 m_codeBlock
->markAggregate(markStack
);
181 ExceptionInfo
* FunctionExecutable::reparseExceptionInfo(JSGlobalData
* globalData
, ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlock
)
183 RefPtr
<FunctionBodyNode
> newFunctionBody
= globalData
->parser
->parse
<FunctionBodyNode
>(globalData
, 0, 0, m_source
);
184 if (m_forceUsesArguments
)
185 newFunctionBody
->setUsesArguments();
186 newFunctionBody
->finishParsing(m_parameters
, m_name
);
188 ScopeChain
scopeChain(scopeChainNode
);
189 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
191 OwnPtr
<CodeBlock
> newCodeBlock(new FunctionCodeBlock(this, FunctionCode
, source().provider(), source().startOffset()));
192 globalData
->functionCodeBlockBeingReparsed
= newCodeBlock
.get();
194 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(newFunctionBody
.get(), globalObject
->debugger(), scopeChain
, newCodeBlock
->symbolTable(), newCodeBlock
.get()));
195 generator
->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock
*>(codeBlock
));
196 generator
->generate();
198 ASSERT(newCodeBlock
->instructionCount() == codeBlock
->instructionCount());
201 JITCode newJITCode
= JIT::compile(globalData
, newCodeBlock
.get());
202 ASSERT(newJITCode
.size() == generatedJITCode().size());
205 globalData
->functionCodeBlockBeingReparsed
= 0;
207 return newCodeBlock
->extractExceptionInfo();
210 ExceptionInfo
* EvalExecutable::reparseExceptionInfo(JSGlobalData
* globalData
, ScopeChainNode
* scopeChainNode
, CodeBlock
* codeBlock
)
212 RefPtr
<EvalNode
> newEvalBody
= globalData
->parser
->parse
<EvalNode
>(globalData
, 0, 0, m_source
);
214 ScopeChain
scopeChain(scopeChainNode
);
215 JSGlobalObject
* globalObject
= scopeChain
.globalObject();
217 OwnPtr
<EvalCodeBlock
> newCodeBlock(new EvalCodeBlock(this, globalObject
, source().provider(), scopeChain
.localDepth()));
219 OwnPtr
<BytecodeGenerator
> generator(new BytecodeGenerator(newEvalBody
.get(), globalObject
->debugger(), scopeChain
, newCodeBlock
->symbolTable(), newCodeBlock
.get()));
220 generator
->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock
*>(codeBlock
));
221 generator
->generate();
223 ASSERT(newCodeBlock
->instructionCount() == codeBlock
->instructionCount());
226 JITCode newJITCode
= JIT::compile(globalData
, newCodeBlock
.get());
227 ASSERT(newJITCode
.size() == generatedJITCode().size());
230 return newCodeBlock
->extractExceptionInfo();
233 void FunctionExecutable::recompile(ExecState
*)
237 m_numParameters
= NUM_PARAMETERS_NOT_COMPILED
;
239 m_jitCode
= JITCode();
243 PassRefPtr
<FunctionExecutable
> FunctionExecutable::fromGlobalCode(const Identifier
& functionName
, ExecState
* exec
, Debugger
* debugger
, const SourceCode
& source
, int* errLine
, UString
* errMsg
)
245 RefPtr
<ProgramNode
> program
= exec
->globalData().parser
->parse
<ProgramNode
>(&exec
->globalData(), debugger
, exec
, source
, errLine
, errMsg
);
249 StatementNode
* exprStatement
= program
->singleStatement();
250 ASSERT(exprStatement
);
251 ASSERT(exprStatement
->isExprStatement());
252 if (!exprStatement
|| !exprStatement
->isExprStatement())
255 ExpressionNode
* funcExpr
= static_cast<ExprStatementNode
*>(exprStatement
)->expr();
257 ASSERT(funcExpr
->isFuncExprNode());
258 if (!funcExpr
|| !funcExpr
->isFuncExprNode())
261 FunctionBodyNode
* body
= static_cast<FuncExprNode
*>(funcExpr
)->body();
263 return FunctionExecutable::create(&exec
->globalData(), functionName
, body
->source(), body
->usesArguments(), body
->parameters(), body
->lineNo(), body
->lastLine());
266 UString
FunctionExecutable::paramString() const
268 FunctionParameters
& parameters
= *m_parameters
;
269 StringBuilder builder
;
270 for (size_t pos
= 0; pos
< parameters
.size(); ++pos
) {
271 if (!builder
.isEmpty())
272 builder
.append(", ");
273 builder
.append(parameters
[pos
].ustring());
275 return builder
.release();