]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Executable.cpp
JavaScriptCore-721.26.tar.gz
[apple/javascriptcore.git] / runtime / Executable.cpp
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
36 namespace JSC {
37
38 #if ENABLE(JIT)
39 NativeExecutable::~NativeExecutable()
40 {
41 }
42 #endif
43
44 VPtrHackExecutable::~VPtrHackExecutable()
45 {
46 }
47
48 EvalExecutable::~EvalExecutable()
49 {
50 delete m_evalCodeBlock;
51 }
52
53 ProgramExecutable::~ProgramExecutable()
54 {
55 delete m_programCodeBlock;
56 }
57
58 FunctionExecutable::~FunctionExecutable()
59 {
60 delete m_codeBlock;
61 }
62
63 JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
64 {
65 int errLine;
66 UString errMsg;
67 RefPtr<EvalNode> evalNode = exec->globalData().parser->parse<EvalNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
68 if (!evalNode)
69 return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
70 recordParse(evalNode->features(), evalNode->lineNo(), 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
84 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
85 {
86 int errLine;
87 UString errMsg;
88 RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
89 if (!programNode)
90 return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
91 return 0;
92 }
93
94 JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
95 {
96 int errLine;
97 UString errMsg;
98 RefPtr<ProgramNode> programNode = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), exec->lexicalGlobalObject()->debugger(), exec, m_source, &errLine, &errMsg);
99 if (!programNode)
100 return Error::create(exec, SyntaxError, errMsg, errLine, m_source.provider()->asID(), m_source.provider()->url());
101 recordParse(programNode->features(), programNode->lineNo(), 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
115 void FunctionExecutable::compile(ExecState*, ScopeChainNode* scopeChainNode)
116 {
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());
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
140 void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
141 {
142 #if ENABLE(INTERPRETER)
143 ASSERT(scopeChainNode->globalData->canUseJIT());
144 #endif
145 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
146 m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
147
148 #if !ENABLE(OPCODE_SAMPLING)
149 if (!BytecodeGenerator::dumpsGeneratedCode())
150 codeBlock->discardBytecode();
151 #endif
152 }
153
154 void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
155 {
156 #if ENABLE(INTERPRETER)
157 ASSERT(scopeChainNode->globalData->canUseJIT());
158 #endif
159 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
160 m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
161
162 #if !ENABLE(OPCODE_SAMPLING)
163 if (!BytecodeGenerator::dumpsGeneratedCode())
164 codeBlock->discardBytecode();
165 #endif
166 }
167
168 void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
169 {
170 #if ENABLE(INTERPRETER)
171 ASSERT(scopeChainNode->globalData->canUseJIT());
172 #endif
173 CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
174 m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
175
176 #if !ENABLE(OPCODE_SAMPLING)
177 if (!BytecodeGenerator::dumpsGeneratedCode())
178 codeBlock->discardBytecode();
179 #endif
180 }
181
182 #endif
183
184 void FunctionExecutable::markAggregate(MarkStack& markStack)
185 {
186 if (m_codeBlock)
187 m_codeBlock->markAggregate(markStack);
188 }
189
190 ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
191 {
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);
196
197 ScopeChain scopeChain(scopeChainNode);
198 JSGlobalObject* globalObject = scopeChain.globalObject();
199
200 OwnPtr<CodeBlock> newCodeBlock(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset()));
201 globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
202
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();
206
207 ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
208
209 #if ENABLE(JIT)
210 #if ENABLE(INTERPRETER)
211 if (globalData->canUseJIT())
212 #endif
213 {
214 JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
215 ASSERT(newJITCode.size() == generatedJITCode().size());
216 }
217 #endif
218
219 globalData->functionCodeBlockBeingReparsed = 0;
220
221 return newCodeBlock->extractExceptionInfo();
222 }
223
224 ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
225 {
226 RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
227
228 ScopeChain scopeChain(scopeChainNode);
229 JSGlobalObject* globalObject = scopeChain.globalObject();
230
231 OwnPtr<EvalCodeBlock> newCodeBlock(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
232
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();
236
237 ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
238
239 #if ENABLE(JIT)
240 #if ENABLE(INTERPRETER)
241 if (globalData->canUseJIT())
242 #endif
243 {
244 JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), generatedJITCode().start());
245 ASSERT(newJITCode.size() == generatedJITCode().size());
246 }
247 #endif
248
249 return newCodeBlock->extractExceptionInfo();
250 }
251
252 void FunctionExecutable::recompile()
253 {
254 delete m_codeBlock;
255 m_codeBlock = 0;
256 m_numParameters = NUM_PARAMETERS_NOT_COMPILED;
257 #if ENABLE(JIT)
258 m_jitCode = JITCode();
259 #endif
260 }
261
262 PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
263 {
264 RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg);
265 if (!program)
266 return 0;
267
268 StatementNode* exprStatement = program->singleStatement();
269 ASSERT(exprStatement);
270 ASSERT(exprStatement->isExprStatement());
271 if (!exprStatement || !exprStatement->isExprStatement())
272 return 0;
273
274 ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
275 ASSERT(funcExpr);
276 ASSERT(funcExpr->isFuncExprNode());
277 if (!funcExpr || !funcExpr->isFuncExprNode())
278 return 0;
279
280 FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
281 ASSERT(body);
282 return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
283 }
284
285 UString FunctionExecutable::paramString() const
286 {
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());
293 }
294 return builder.build();
295 }
296
297 };
298
299