JavaScriptCore/runtime/Executable.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2009, 2010 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(ExecState* exec, const SourceCode& source)
       
    49     : ScriptExecutable(exec, source)
       
    50 {
       
    51 }
       
    52 
       
    53 EvalExecutable::~EvalExecutable()
       
    54 {
       
    55 }
       
    56 
       
    57 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
       
    58     : ScriptExecutable(exec, source)
       
    59 {
       
    60 }
       
    61 
       
    62 ProgramExecutable::~ProgramExecutable()
       
    63 {
       
    64 }
       
    65 
       
    66 FunctionExecutable::FunctionExecutable(JSGlobalData* globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
       
    67     : ScriptExecutable(globalData, source)
       
    68     , m_numVariables(0)
       
    69     , m_forceUsesArguments(forceUsesArguments)
       
    70     , m_parameters(parameters)
       
    71     , m_name(name)
       
    72     , m_symbolTable(0)
       
    73 {
       
    74     m_firstLine = firstLine;
       
    75     m_lastLine = lastLine;
       
    76 }
       
    77 
       
    78 FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, int firstLine, int lastLine)
       
    79     : ScriptExecutable(exec, source)
       
    80     , m_numVariables(0)
       
    81     , m_forceUsesArguments(forceUsesArguments)
       
    82     , m_parameters(parameters)
       
    83     , m_name(name)
       
    84     , m_symbolTable(0)
       
    85 {
       
    86     m_firstLine = firstLine;
       
    87     m_lastLine = lastLine;
       
    88 }
       
    89 
       
    90 FunctionExecutable::~FunctionExecutable()
       
    91 {
       
    92 }
       
    93 
       
    94 JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
       
    95 {
       
    96     JSObject* exception = 0;
       
    97     JSGlobalData* globalData = &exec->globalData();
       
    98     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
       
    99     RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
       
   100     if (!evalNode) {
       
   101         ASSERT(exception);
       
   102         return exception;
       
   103     }
       
   104     recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
       
   105 
       
   106     ScopeChain scopeChain(scopeChainNode);
       
   107     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   108 
       
   109     ASSERT(!m_evalCodeBlock);
       
   110     m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth()));
       
   111     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), globalObject->debugger(), scopeChain, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get())));
       
   112     generator->generate();
       
   113     
       
   114     evalNode->destroyData();
       
   115 
       
   116 #if ENABLE(JIT)
       
   117     if (exec->globalData().canUseJIT()) {
       
   118         m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get());
       
   119 #if !ENABLE(OPCODE_SAMPLING)
       
   120         if (!BytecodeGenerator::dumpsGeneratedCode())
       
   121             m_evalCodeBlock->discardBytecode();
       
   122 #endif
       
   123     }
       
   124 #endif
       
   125 
       
   126     return 0;
       
   127 }
       
   128 
       
   129 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
       
   130 {
       
   131     JSObject* exception = 0;
       
   132     JSGlobalData* globalData = &exec->globalData();
       
   133     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
       
   134     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
       
   135     if (programNode)
       
   136         return 0;
       
   137     ASSERT(exception);
       
   138     return exception;
       
   139 }
       
   140 
       
   141 JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
       
   142 {
       
   143     ASSERT(!m_programCodeBlock);
       
   144 
       
   145     JSObject* exception = 0;
       
   146     JSGlobalData* globalData = &exec->globalData();
       
   147     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
       
   148     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
       
   149     if (!programNode) {
       
   150         ASSERT(exception);
       
   151         return exception;
       
   152     }
       
   153     recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine());
       
   154 
       
   155     ScopeChain scopeChain(scopeChainNode);
       
   156     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   157     
       
   158     m_programCodeBlock = adoptPtr(new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider()));
       
   159     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock.get())));
       
   160     generator->generate();
       
   161 
       
   162     programNode->destroyData();
       
   163 
       
   164 #if ENABLE(JIT)
       
   165     if (exec->globalData().canUseJIT()) {
       
   166         m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock.get());
       
   167 #if !ENABLE(OPCODE_SAMPLING)
       
   168         if (!BytecodeGenerator::dumpsGeneratedCode())
       
   169             m_programCodeBlock->discardBytecode();
       
   170 #endif
       
   171     }
       
   172 #endif
       
   173 
       
   174    return 0;
       
   175 }
       
   176 
       
   177 JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
       
   178 {
       
   179     JSObject* exception = 0;
       
   180     JSGlobalData* globalData = scopeChainNode->globalData;
       
   181     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception);
       
   182     if (!body) {
       
   183         ASSERT(exception);
       
   184         return exception;
       
   185     }
       
   186     if (m_forceUsesArguments)
       
   187         body->setUsesArguments();
       
   188     body->finishParsing(m_parameters, m_name);
       
   189     recordParse(body->features(), body->lineNo(), body->lastLine());
       
   190 
       
   191     ScopeChain scopeChain(scopeChainNode);
       
   192     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   193 
       
   194     ASSERT(!m_codeBlockForCall);
       
   195     m_codeBlockForCall = adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), false));
       
   196     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForCall->symbolTable(), m_codeBlockForCall.get())));
       
   197     generator->generate();
       
   198     m_numParametersForCall = m_codeBlockForCall->m_numParameters;
       
   199     ASSERT(m_numParametersForCall);
       
   200     m_numVariables = m_codeBlockForCall->m_numVars;
       
   201     m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
       
   202 
       
   203     body->destroyData();
       
   204 
       
   205 #if ENABLE(JIT)
       
   206     if (exec->globalData().canUseJIT()) {
       
   207         m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall.get(), &m_jitCodeForCallWithArityCheck);
       
   208 #if !ENABLE(OPCODE_SAMPLING)
       
   209         if (!BytecodeGenerator::dumpsGeneratedCode())
       
   210             m_codeBlockForCall->discardBytecode();
       
   211 #endif
       
   212     }
       
   213 #endif
       
   214 
       
   215     return 0;
       
   216 }
       
   217 
       
   218 JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
       
   219 {
       
   220     JSObject* exception = 0;
       
   221     JSGlobalData* globalData = scopeChainNode->globalData;
       
   222     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception);
       
   223     if (!body) {
       
   224         ASSERT(exception);
       
   225         return exception;
       
   226     }
       
   227     if (m_forceUsesArguments)
       
   228         body->setUsesArguments();
       
   229     body->finishParsing(m_parameters, m_name);
       
   230     recordParse(body->features(), body->lineNo(), body->lastLine());
       
   231 
       
   232     ScopeChain scopeChain(scopeChainNode);
       
   233     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   234 
       
   235     ASSERT(!m_codeBlockForConstruct);
       
   236     m_codeBlockForConstruct = adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), true));
       
   237     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(body.get(), globalObject->debugger(), scopeChain, m_codeBlockForConstruct->symbolTable(), m_codeBlockForConstruct.get())));
       
   238     generator->generate();
       
   239     m_numParametersForConstruct = m_codeBlockForConstruct->m_numParameters;
       
   240     ASSERT(m_numParametersForConstruct);
       
   241     m_numVariables = m_codeBlockForConstruct->m_numVars;
       
   242     m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
       
   243 
       
   244     body->destroyData();
       
   245 
       
   246 #if ENABLE(JIT)
       
   247     if (exec->globalData().canUseJIT()) {
       
   248         m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, m_codeBlockForConstruct.get(), &m_jitCodeForConstructWithArityCheck);
       
   249 #if !ENABLE(OPCODE_SAMPLING)
       
   250         if (!BytecodeGenerator::dumpsGeneratedCode())
       
   251             m_codeBlockForConstruct->discardBytecode();
       
   252 #endif
       
   253     }
       
   254 #endif
       
   255 
       
   256     return 0;
       
   257 }
       
   258 
       
   259 void FunctionExecutable::markAggregate(MarkStack& markStack)
       
   260 {
       
   261     if (m_codeBlockForCall)
       
   262         m_codeBlockForCall->markAggregate(markStack);
       
   263     if (m_codeBlockForConstruct)
       
   264         m_codeBlockForConstruct->markAggregate(markStack);
       
   265 }
       
   266 
       
   267 PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
       
   268 {
       
   269     JSObject* exception = 0;
       
   270     RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, &exception);
       
   271     if (!newFunctionBody)
       
   272         return PassOwnPtr<ExceptionInfo>();
       
   273     if (m_forceUsesArguments)
       
   274         newFunctionBody->setUsesArguments();
       
   275     newFunctionBody->finishParsing(m_parameters, m_name);
       
   276 
       
   277     ScopeChain scopeChain(scopeChainNode);
       
   278     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   279 
       
   280     OwnPtr<CodeBlock> newCodeBlock(adoptPtr(new FunctionCodeBlock(this, FunctionCode, source().provider(), source().startOffset(), codeBlock->m_isConstructor)));
       
   281     globalData->functionCodeBlockBeingReparsed = newCodeBlock.get();
       
   282 
       
   283     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(newFunctionBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())));
       
   284     generator->setRegeneratingForExceptionInfo(static_cast<FunctionCodeBlock*>(codeBlock));
       
   285     generator->generate();
       
   286 
       
   287     ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
       
   288 
       
   289 #if ENABLE(JIT)
       
   290     if (globalData->canUseJIT()) {
       
   291         JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
       
   292         ASSERT(codeBlock->m_isConstructor ? newJITCode.size() == generatedJITCodeForConstruct().size() : newJITCode.size() == generatedJITCodeForCall().size());
       
   293     }
       
   294 #endif
       
   295 
       
   296     globalData->functionCodeBlockBeingReparsed = 0;
       
   297 
       
   298     return newCodeBlock->extractExceptionInfo();
       
   299 }
       
   300 
       
   301 PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
       
   302 {
       
   303     JSObject* exception = 0;
       
   304     RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, &exception);
       
   305     if (!newEvalBody)
       
   306         return PassOwnPtr<ExceptionInfo>();
       
   307 
       
   308     ScopeChain scopeChain(scopeChainNode);
       
   309     JSGlobalObject* globalObject = scopeChain.globalObject();
       
   310 
       
   311     OwnPtr<EvalCodeBlock> newCodeBlock(adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChain.localDepth())));
       
   312 
       
   313     OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(newEvalBody.get(), globalObject->debugger(), scopeChain, newCodeBlock->symbolTable(), newCodeBlock.get())));
       
   314     generator->setRegeneratingForExceptionInfo(static_cast<EvalCodeBlock*>(codeBlock));
       
   315     generator->generate();
       
   316 
       
   317     ASSERT(newCodeBlock->instructionCount() == codeBlock->instructionCount());
       
   318 
       
   319 #if ENABLE(JIT)
       
   320     if (globalData->canUseJIT()) {
       
   321         JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
       
   322         ASSERT(newJITCode.size() == generatedJITCodeForCall().size());
       
   323     }
       
   324 #endif
       
   325 
       
   326     return newCodeBlock->extractExceptionInfo();
       
   327 }
       
   328 
       
   329 void FunctionExecutable::recompile(ExecState*)
       
   330 {
       
   331     m_codeBlockForCall.clear();
       
   332     m_codeBlockForConstruct.clear();
       
   333     m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;
       
   334     m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;
       
   335 #if ENABLE(JIT)
       
   336     m_jitCodeForCall = JITCode();
       
   337     m_jitCodeForConstruct = JITCode();
       
   338 #endif
       
   339 }
       
   340 
       
   341 PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
       
   342 {
       
   343     JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
       
   344     RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, exception);
       
   345     if (!program) {
       
   346         ASSERT(*exception);
       
   347         return 0;
       
   348     }
       
   349 
       
   350     // Uses of this function that would not result in a single function expression are invalid.
       
   351     StatementNode* exprStatement = program->singleStatement();
       
   352     ASSERT(exprStatement);
       
   353     ASSERT(exprStatement->isExprStatement());
       
   354     ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
       
   355     ASSERT(funcExpr);
       
   356     ASSERT(funcExpr->isFuncExprNode());
       
   357     FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
       
   358     ASSERT(body);
       
   359 
       
   360     return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
       
   361 }
       
   362 
       
   363 UString FunctionExecutable::paramString() const
       
   364 {
       
   365     FunctionParameters& parameters = *m_parameters;
       
   366     StringBuilder builder;
       
   367     for (size_t pos = 0; pos < parameters.size(); ++pos) {
       
   368         if (!builder.isEmpty())
       
   369             builder.append(", ");
       
   370         builder.append(parameters[pos].ustring());
       
   371     }
       
   372     return builder.build();
       
   373 }
       
   374 
       
   375 PassOwnPtr<ExceptionInfo> ProgramExecutable::reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*)
       
   376 {
       
   377     // CodeBlocks for program code are transient and therefore do not gain from from throwing out their exception information.
       
   378     return PassOwnPtr<ExceptionInfo>();
       
   379 }
       
   380 
       
   381 }