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 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 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 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 175 void FunctionExecutable::markAggregate(MarkStack& markStack) 176 { 177 if (m_codeBlock) 178 m_codeBlock->markAggregate(markStack); 179 } 180 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 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 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 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 266 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