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#include "config.h"
27#include "Executable.h"
28
29#include "BytecodeGenerator.h"
30#include "CodeBlock.h"
31#include "JIT.h"
32#include "Parser.h"
33#include "StringBuilder.h"
34#include "Vector.h"
35
36namespace JSC {
37
38#if ENABLE(JIT)
39NativeExecutable::~NativeExecutable()
40{
41}
42#endif
43
44VPtrHackExecutable::~VPtrHackExecutable()
45{
46}
47
48EvalExecutable::~EvalExecutable()
49{
50 delete m_evalCodeBlock;
51}
52
53ProgramExecutable::~ProgramExecutable()
54{
55 delete m_programCodeBlock;
56}
57
58FunctionExecutable::~FunctionExecutable()
59{
60 delete m_codeBlock;
61}
62
63JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
64{
65 int errLine;
66 UString errMsg;
67 RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(globalData: &exec->globalData(), debugger: exec->lexicalGlobalObject()->debugger(), debuggerExecState: exec, source: m_source, errLine: &errLine, errMsg: &errMsg);
68 if (!evalNode)
69 return Error::create(exec, SyntaxError, message: errMsg, lineNumber: errLine, sourceID: m_source.provider()->asID(), sourceURL: m_source.provider()->url());
70 recordParse(features: evalNode->features(), firstLine: evalNode->lineNo(), lastLine: evalNode->lastLine());
71
72 ScopeChain scopeChain(scopeChainNode);
73 JSGlobalObject* globalObject = scopeChain.globalObject();
74
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();
79
80 evalNode->destroyData();
81 return 0;
82}
83
84JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
85{
86 int errLine;
87 UString errMsg;
88 RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(globalData: &exec->globalData(), debugger: exec->lexicalGlobalObject()->debugger(), debuggerExecState: exec, source: m_source, errLine: &errLine, errMsg: &errMsg);
89 if (!programNode)
90 return Error::create(exec, SyntaxError, message: errMsg, lineNumber: errLine, sourceID: m_source.provider()->asID(), sourceURL: m_source.provider()->url());
91 return 0;
92}
93
94JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
95{
96 int errLine;
97 UString errMsg;
98 RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(globalData: &exec->globalData(), debugger: exec->lexicalGlobalObject()->debugger(), debuggerExecState: exec, source: m_source, errLine: &errLine, errMsg: &errMsg);
99 if (!programNode)
100 return Error::create(exec, SyntaxError, message: errMsg, lineNumber: errLine, sourceID: m_source.provider()->asID(), sourceURL: m_source.provider()->url());
101 recordParse(features: programNode->features(), firstLine: programNode->lineNo(), lastLine: programNode->lastLine());
102
103 ScopeChain scopeChain(scopeChainNode);
104 JSGlobalObject* globalObject = scopeChain.globalObject();
105
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();
110
111 programNode->destroyData();
112 return 0;
113}
114
115void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode)
116{
117 JSGlobalData* globalData = scopeChainNode->globalData;
118 RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, debugger: 0, debuggerExecState: 0, source: m_source);
119 if (m_forceUsesArguments)
120 body->setUsesArguments();
121 body->finishParsing(m_parameters, m_name);
122 recordParse(features: body->features(), firstLine: body->lineNo(), lastLine: body->lastLine());
123
124 ScopeChain scopeChain(scopeChainNode);
125 JSGlobalObject* globalObject = scopeChain.globalObject();
126
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;
134
135 body->destroyData();
136}
137
138#if ENABLE(JIT)
139
140void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
141{
142 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
143 m_jitCode = JIT::compile(globalData: scopeChainNode->globalData, codeBlock);
144
145#if !ENABLE(OPCODE_SAMPLING)
146 if (!BytecodeGenerator::dumpsGeneratedCode())
147 codeBlock->discardBytecode();
148#endif
149}
150
151void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
152{
153 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
154 m_jitCode = JIT::compile(globalData: scopeChainNode->globalData, codeBlock);
155
156#if !ENABLE(OPCODE_SAMPLING)
157 if (!BytecodeGenerator::dumpsGeneratedCode())
158 codeBlock->discardBytecode();
159#endif
160}
161
162void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
163{
164 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
165 m_jitCode = JIT::compile(globalData: scopeChainNode->globalData, codeBlock);
166
167#if !ENABLE(OPCODE_SAMPLING)
168 if (!BytecodeGenerator::dumpsGeneratedCode())
169 codeBlock->discardBytecode();
170#endif
171}
172
173#endif
174
175void FunctionExecutable::markAggregate(MarkStack& markStack)
176{
177 if (m_codeBlock)
178 m_codeBlock->markAggregate(markStack);
179}
180
181ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
182{
183 RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, debugger: 0, debuggerExecState: 0, source: m_source);
184 if (m_forceUsesArguments)
185 newFunctionBody->setUsesArguments();
186 newFunctionBody->finishParsing(m_parameters, m_name);
187
188 ScopeChain scopeChain(scopeChainNode);
189 JSGlobalObject* globalObject = scopeChain.globalObject();
190
191 OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
192 globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
193
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();
197
198 ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
199
200#if ENABLE(JIT)
201 JITCode newJITCode = JIT::compile(globalData, codeBlock: newCodeBlock.get());
202 ASSERT(newJITCode.size() == generatedJITCode().size());
203#endif
204
205 globalData->functionCodeBlockBeingReparsed = 0;
206
207 return newCodeBlock->extractExceptionInfo();
208}
209
210ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
211{
212 RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, debugger: 0, debuggerExecState: 0, source: m_source);
213
214 ScopeChain scopeChain(scopeChainNode);
215 JSGlobalObject* globalObject = scopeChain.globalObject();
216
217 OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
218
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();
222
223 ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
224
225#if ENABLE(JIT)
226 JITCode newJITCode = JIT::compile(globalData, codeBlock: newCodeBlock.get());
227 ASSERT(newJITCode.size() == generatedJITCode().size());
228#endif
229
230 return newCodeBlock->extractExceptionInfo();
231}
232
233void FunctionExecutable::recompile(ExecState*)
234{
235 delete m_codeBlock;
236 m_codeBlock = 0;
237 m_numParameters = NUM_PARAMETERS_NOT_COMPILED;
238#if ENABLE(JIT)
239 m_jitCode = JITCode();
240#endif
241}
242
243PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
244{
245 RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(globalData: &exec->globalData(), debugger, debuggerExecState: exec, source, errLine, errMsg);
246 if (!program)
247 return 0;
248
249 StatementNode* exprStatement = program->singleStatement();
250 ASSERT(exprStatement);
251 ASSERT(exprStatement->isExprStatement());
252 if (!exprStatement || !exprStatement->isExprStatement())
253 return 0;
254
255 ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
256 ASSERT(funcExpr);
257 ASSERT(funcExpr->isFuncExprNode());
258 if (!funcExpr || !funcExpr->isFuncExprNode())
259 return 0;
260
261 FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
262 ASSERT(body);
263 return FunctionExecutable::create(globalData: &exec->globalData(), name: functionName, source: body->source(), forceUsesArguments: body->usesArguments(), parameters: body->parameters(), firstLine: body->lineNo(), lastLine: body->lastLine());
264}
265
266UString FunctionExecutable::paramString() const
267{
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(str: ", ");
273 builder.append(str: parameters[pos].ustring());
274 }
275 return builder.release();
276}
277
278};
279
280
281

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp