• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
~NativeExecutable()39 NativeExecutable::~NativeExecutable()
40 {
41 }
42 #endif
43 
~VPtrHackExecutable()44 VPtrHackExecutable::~VPtrHackExecutable()
45 {
46 }
47 
~EvalExecutable()48 EvalExecutable::~EvalExecutable()
49 {
50     delete m_evalCodeBlock;
51 }
52 
~ProgramExecutable()53 ProgramExecutable::~ProgramExecutable()
54 {
55     delete m_programCodeBlock;
56 }
57 
~FunctionExecutable()58 FunctionExecutable::~FunctionExecutable()
59 {
60     delete m_codeBlock;
61 }
62 
compile(ExecState * exec,ScopeChainNode * scopeChainNode)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 
checkSyntax(ExecState * exec)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 
compile(ExecState * exec,ScopeChainNode * scopeChainNode)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 
compile(ExecState *,ScopeChainNode * scopeChainNode)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 
generateJITCode(ExecState * exec,ScopeChainNode * scopeChainNode)140 void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
141 {
142     CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
143     m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
144 
145 #if !ENABLE(OPCODE_SAMPLING)
146     if (!BytecodeGenerator::dumpsGeneratedCode())
147         codeBlock->discardBytecode();
148 #endif
149 }
150 
generateJITCode(ExecState * exec,ScopeChainNode * scopeChainNode)151 void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
152 {
153     CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
154     m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
155 
156 #if !ENABLE(OPCODE_SAMPLING)
157     if (!BytecodeGenerator::dumpsGeneratedCode())
158         codeBlock->discardBytecode();
159 #endif
160 }
161 
generateJITCode(ExecState * exec,ScopeChainNode * scopeChainNode)162 void FunctionExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
163 {
164     CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
165     m_jitCode = JIT::compile(scopeChainNode->globalData, codeBlock);
166 
167 #if !ENABLE(OPCODE_SAMPLING)
168     if (!BytecodeGenerator::dumpsGeneratedCode())
169         codeBlock->discardBytecode();
170 #endif
171 }
172 
173 #endif
174 
markAggregate(MarkStack & markStack)175 void FunctionExecutable::markAggregate(MarkStack& markStack)
176 {
177     if (m_codeBlock)
178         m_codeBlock->markAggregate(markStack);
179 }
180 
reparseExceptionInfo(JSGlobalData * globalData,ScopeChainNode * scopeChainNode,CodeBlock * codeBlock)181 ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
182 {
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);
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, newCodeBlock.get());
202     ASSERT(newJITCode.size() == generatedJITCode().size());
203 #endif
204 
205     globalData->functionCodeBlockBeingReparsed = 0;
206 
207     return newCodeBlock->extractExceptionInfo();
208 }
209 
reparseExceptionInfo(JSGlobalData * globalData,ScopeChainNode * scopeChainNode,CodeBlock * codeBlock)210 ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
211 {
212     RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 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, newCodeBlock.get());
227     ASSERT(newJITCode.size() == generatedJITCode().size());
228 #endif
229 
230     return newCodeBlock->extractExceptionInfo();
231 }
232 
recompile(ExecState *)233 void 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 
fromGlobalCode(const Identifier & functionName,ExecState * exec,Debugger * debugger,const SourceCode & source,int * errLine,UString * errMsg)243 PassRefPtr<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>(&exec->globalData(), debugger, 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(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
264 }
265 
paramString() const266 UString 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(", ");
273         builder.append(parameters[pos].ustring());
274     }
275     return builder.build();
276 }
277 
278 };
279 
280 
281