Ignore:
Timestamp:
Jul 13, 2010, 5:27:13 PM (15 years ago)
Author:
[email protected]
Message:

Bug 42207 - Clean up interface to compile executables, always check for exceptions

Reviewed by Oliver Hunt.

Presently interface to compile executable is inconsistent between eval/program and
function code, and is error prone in allowing a caller to byte compile without JIT
compiling an executable (we rely on all executables with codeblocks having JIT code).
Unify on an interface where all compilation is performed by a single compile (with
ForCall|ForConstruct variants) method, and make all clients check for errors.

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::unwindCallFrame):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::privateExecute):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • parser/Parser.h:

(JSC::Parser::isFunctionBodyNode):
(JSC::Parser::parse):

  • runtime/ArrayPrototype.cpp:

(JSC::isNumericCompareFunction):

  • runtime/ExceptionHelpers.cpp:

(JSC::createStackOverflowError):

  • runtime/ExceptionHelpers.h:
  • runtime/Executable.cpp:

(JSC::EvalExecutable::compileInternal):
(JSC::ProgramExecutable::checkSyntax):
(JSC::ProgramExecutable::compileInternal):
(JSC::FunctionExecutable::compileForCallInternal):
(JSC::FunctionExecutable::compileForConstructInternal):
(JSC::FunctionExecutable::reparseExceptionInfo):
(JSC::EvalExecutable::reparseExceptionInfo):
(JSC::FunctionExecutable::fromGlobalCode):

  • runtime/Executable.h:

(JSC::EvalExecutable::compile):
(JSC::EvalExecutable::generatedBytecode):
(JSC::EvalExecutable::generatedJITCode):
(JSC::ProgramExecutable::compile):
(JSC::ProgramExecutable::generatedBytecode):
(JSC::ProgramExecutable::generatedJITCode):
(JSC::FunctionExecutable::generatedBytecode):
(JSC::FunctionExecutable::compileForCall):
(JSC::FunctionExecutable::compileForConstruct):
(JSC::FunctionExecutable::generatedJITCodeForConstructWithArityCheck):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunction):

  • runtime/JSActivation.cpp:

(JSC::JSActivation::argumentsGetter):

  • runtime/JSGlobalData.h:

(JSC::JSGlobalData::canUseJIT):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/Executable.cpp

    r62677 r63267  
    6262}
    6363
    64 JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
    65 {
    66     int errLine;
    67     UString errMsg;
     64JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
     65{
     66    JSObject* exception = 0;
    6867    JSGlobalData* globalData = &exec->globalData();
    6968    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    70     RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
    71     if (!evalNode)
    72         return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);
     69    RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
     70    if (!evalNode) {
     71        ASSERT(exception);
     72        return exception;
     73    }
    7374    recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
    7475
     
    8283   
    8384    evalNode->destroyData();
     85
     86#if ENABLE(JIT)
     87    if (exec->globalData().canUseJIT()) {
     88        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock);
     89#if !ENABLE(OPCODE_SAMPLING)
     90        if (!BytecodeGenerator::dumpsGeneratedCode())
     91            m_evalCodeBlock->discardBytecode();
     92#endif
     93    }
     94#endif
     95
    8496    return 0;
    8597}
     
    8799JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
    88100{
    89     int errLine;
    90     UString errMsg;
     101    JSObject* exception = 0;
    91102    JSGlobalData* globalData = &exec->globalData();
    92103    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    93     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
    94     if (!programNode)
    95         return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);
    96     return 0;
    97 }
    98 
    99 JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
    100 {
    101     int errLine;
    102     UString errMsg;
     104    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
     105    if (programNode)
     106        return 0;
     107    ASSERT(exception);
     108    return exception;
     109}
     110
     111JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
     112{
     113    ASSERT(!m_programCodeBlock);
     114
     115    JSObject* exception = 0;
    103116    JSGlobalData* globalData = &exec->globalData();
    104117    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
    105     RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
    106     if (!programNode)
    107         return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);
     118    RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
     119    if (!programNode) {
     120        ASSERT(exception);
     121        return exception;
     122    }
    108123    recordParse(programNode->features(), programNode->lineNo(), programNode->lastLine());
    109124
     
    111126    JSGlobalObject* globalObject = scopeChain.globalObject();
    112127   
    113     ASSERT(!m_programCodeBlock);
    114128    m_programCodeBlock = new ProgramCodeBlock(this, GlobalCode, globalObject, source().provider());
    115129    OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(programNode.get(), globalObject->debugger(), scopeChain, &globalObject->symbolTable(), m_programCodeBlock)));
     
    117131
    118132    programNode->destroyData();
    119     return 0;
    120 }
    121 
    122 bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)
    123 {
     133
     134#if ENABLE(JIT)
     135    if (exec->globalData().canUseJIT()) {
     136        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_programCodeBlock);
     137#if !ENABLE(OPCODE_SAMPLING)
     138        if (!BytecodeGenerator::dumpsGeneratedCode())
     139            m_programCodeBlock->discardBytecode();
     140#endif
     141    }
     142#endif
     143
     144   return 0;
     145}
     146
     147JSObject* FunctionExecutable::compileForCallInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
     148{
     149    JSObject* exception = 0;
    124150    JSGlobalData* globalData = scopeChainNode->globalData;
    125     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
    126     if (!body)
    127         return false;
     151    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception);
     152    if (!body) {
     153        ASSERT(exception);
     154        return exception;
     155    }
    128156    if (m_forceUsesArguments)
    129157        body->setUsesArguments();
     
    144172
    145173    body->destroyData();
    146     return true;
    147 }
    148 
    149 bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode)
    150 {
     174
     175#if ENABLE(JIT)
     176    if (exec->globalData().canUseJIT()) {
     177        m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_codeBlockForCall, &m_jitCodeForCallWithArityCheck);
     178#if !ENABLE(OPCODE_SAMPLING)
     179        if (!BytecodeGenerator::dumpsGeneratedCode())
     180            m_codeBlockForCall->discardBytecode();
     181#endif
     182    }
     183#endif
     184
     185    return 0;
     186}
     187
     188JSObject* FunctionExecutable::compileForConstructInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
     189{
     190    JSObject* exception = 0;
    151191    JSGlobalData* globalData = scopeChainNode->globalData;
    152     RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
    153     if (!body)
    154         return false;
     192    RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, exec->lexicalGlobalObject(), 0, 0, m_source, &exception);
     193    if (!body) {
     194        ASSERT(exception);
     195        return exception;
     196    }
    155197    if (m_forceUsesArguments)
    156198        body->setUsesArguments();
     
    171213
    172214    body->destroyData();
    173     return true;
    174 }
    175 
    176 #if ENABLE(JIT)
    177 
    178 void EvalExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
    179 {
    180 #if ENABLE(INTERPRETER)
    181     ASSERT(exec->globalData().canUseJIT());
    182 #endif
    183     CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
    184     m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock);
    185 
     215
     216#if ENABLE(JIT)
     217    if (exec->globalData().canUseJIT()) {
     218        m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, m_codeBlockForConstruct, &m_jitCodeForConstructWithArityCheck);
    186219#if !ENABLE(OPCODE_SAMPLING)
    187     if (!BytecodeGenerator::dumpsGeneratedCode())
    188         codeBlock->discardBytecode();
    189 #endif
    190 }
    191 
    192 void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeChainNode)
    193 {
    194 #if ENABLE(INTERPRETER)
    195     ASSERT(exec->globalData().canUseJIT());
    196 #endif
    197     CodeBlock* codeBlock = &bytecode(exec, scopeChainNode);
    198     m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock);
    199 
    200 #if !ENABLE(OPCODE_SAMPLING)
    201     if (!BytecodeGenerator::dumpsGeneratedCode())
    202         codeBlock->discardBytecode();
    203 #endif
    204 }
    205 
    206 void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
    207 {
    208 #if ENABLE(INTERPRETER)
    209     ASSERT(exec->globalData().canUseJIT());
    210 #endif
    211     CodeBlock* codeBlock = bytecodeForCall(exec, scopeChainNode);
    212     m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForCallWithArityCheck);
    213 
    214 #if !ENABLE(OPCODE_SAMPLING)
    215     if (!BytecodeGenerator::dumpsGeneratedCode())
    216         codeBlock->discardBytecode();
    217 #endif
    218 }
    219 
    220 void FunctionExecutable::generateJITCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
    221 {
    222 #if ENABLE(INTERPRETER)
    223     ASSERT(exec->globalData().canUseJIT());
    224 #endif
    225     CodeBlock* codeBlock = bytecodeForConstruct(exec, scopeChainNode);
    226     m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForConstructWithArityCheck);
    227 
    228 #if !ENABLE(OPCODE_SAMPLING)
    229     if (!BytecodeGenerator::dumpsGeneratedCode())
    230         codeBlock->discardBytecode();
    231 #endif
    232 }
    233 
    234 #endif
     220        if (!BytecodeGenerator::dumpsGeneratedCode())
     221            m_codeBlockForConstruct->discardBytecode();
     222#endif
     223    }
     224#endif
     225
     226    return 0;
     227}
    235228
    236229void FunctionExecutable::markAggregate(MarkStack& markStack)
     
    244237PassOwnPtr<ExceptionInfo> FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
    245238{
    246     RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
     239    JSObject* exception = 0;
     240    RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, 0, m_source, &exception);
    247241    if (!newFunctionBody)
    248242        return PassOwnPtr<ExceptionInfo>();
     
    264258
    265259#if ENABLE(JIT)
    266 #if ENABLE(INTERPRETER)
    267     if (globalData->canUseJIT())
    268 #endif
    269     {
     260    if (globalData->canUseJIT()) {
    270261        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
    271262        ASSERT(codeBlock->m_isConstructor ? newJITCode.size() == generatedJITCodeForConstruct().size() : newJITCode.size() == generatedJITCodeForCall().size());
     
    280271PassOwnPtr<ExceptionInfo> EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
    281272{
    282     RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
     273    JSObject* exception = 0;
     274    RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, 0, m_source, &exception);
    283275    if (!newEvalBody)
    284276        return PassOwnPtr<ExceptionInfo>();
     
    296288
    297289#if ENABLE(JIT)
    298 #if ENABLE(INTERPRETER)
    299     if (globalData->canUseJIT())
    300 #endif
    301     {
     290    if (globalData->canUseJIT()) {
    302291        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
    303292        ASSERT(newJITCode.size() == generatedJITCodeForCall().size());
     
    322311}
    323312
    324 PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, int* errLine, UString* errMsg)
    325 {
    326     RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), debugger, exec, source, errLine, errMsg);
    327     if (!program)
     313PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifier& functionName, ExecState* exec, Debugger* debugger, const SourceCode& source, JSObject** exception)
     314{
     315    JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
     316    RefPtr<ProgramNode> program = exec->globalData().parser->parse<ProgramNode>(&exec->globalData(), lexicalGlobalObject, debugger, exec, source, exception);
     317    if (!program) {
     318        ASSERT(*exception);
    328319        return 0;
    329 
     320    }
     321
     322    // Uses of this function that would not result in a single function expression are invalid.
    330323    StatementNode* exprStatement = program->singleStatement();
    331324    ASSERT(exprStatement);
    332325    ASSERT(exprStatement->isExprStatement());
    333     if (!exprStatement || !exprStatement->isExprStatement())
    334         return 0;
    335 
    336326    ExpressionNode* funcExpr = static_cast<ExprStatementNode*>(exprStatement)->expr();
    337327    ASSERT(funcExpr);
    338328    ASSERT(funcExpr->isFuncExprNode());
    339     if (!funcExpr || !funcExpr->isFuncExprNode())
    340         return 0;
    341 
    342329    FunctionBodyNode* body = static_cast<FuncExprNode*>(funcExpr)->body();
    343330    ASSERT(body);
     331
    344332    return FunctionExecutable::create(&exec->globalData(), functionName, body->source(), body->usesArguments(), body->parameters(), body->lineNo(), body->lastLine());
    345333}
Note: See TracChangeset for help on using the changeset viewer.