Commit 40b4ad33 authored by barraclough@apple.com's avatar barraclough@apple.com

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):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@63267 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 59f8b820
2010-07-13 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
Bug 42207 - Clean up interface to compile executables, always check for exceptions
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):
2010-07-13 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org>
Reviewed by Oliver Hunt.
......
......@@ -547,18 +547,17 @@ NEVER_INLINE bool Interpreter::unwindCallFrame(CallFrame*& callFrame, JSValue ex
return false;
codeBlock = callerFrame->codeBlock();
#if ENABLE(JIT)
#if ENABLE(INTERPRETER)
#if ENABLE(JIT) && ENABLE(INTERPRETER)
if (callerFrame->globalData().canUseJIT())
#endif
bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
#if ENABLE(INTERPRETER)
else
bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
#endif
#elif ENABLE(JIT)
bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnPC());
#else
bytecodeOffset = codeBlock->bytecodeOffset(callerFrame, callFrame->returnVPC());
#endif
callFrame = callerFrame;
return true;
}
......@@ -660,11 +659,12 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
}
}
CodeBlock* codeBlock = &program->bytecode(callFrame, scopeChain);
if (!codeBlock) {
*exception = createStackOverflowError(callFrame);
JSObject* error = program->compile(callFrame, scopeChain);
if (error) {
*exception = error;
return jsNull();
}
CodeBlock* codeBlock = &program->generatedBytecode();
Register* oldEnd = m_registerFile.end();
Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
......@@ -697,17 +697,11 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S
m_reentryDepth++;
#if ENABLE(JIT)
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
result = program->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#if ENABLE(INTERPRETER)
result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
else
#endif
#endif
#if ENABLE(INTERPRETER)
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
m_reentryDepth--;
}
......@@ -752,12 +746,16 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
if (newCodeBlock)
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
else
newCallFrame = 0;
JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
if (UNLIKELY(!!compileError)) {
*exception = compileError;
m_registerFile.shrink(oldEnd);
return jsNull();
}
CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
......@@ -778,17 +776,11 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
m_reentryDepth++;
#if ENABLE(JIT)
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
result = callData.js.functionExecutable->jitCodeForCall(newCallFrame, callDataScopeChain).execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
#if ENABLE(INTERPRETER)
result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
else
#endif
#endif
#if ENABLE(INTERPRETER)
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
m_reentryDepth--;
}
......@@ -851,12 +843,16 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
if (constructType == ConstructTypeJS) {
ScopeChainNode* constructDataScopeChain = constructData.js.scopeChain;
CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, constructDataScopeChain);
if (newCodeBlock)
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
else
newCallFrame = 0;
JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
if (UNLIKELY(!!compileError)) {
*exception = compileError;
m_registerFile.shrink(oldEnd);
return 0;
}
CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
......@@ -877,17 +873,11 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
m_reentryDepth++;
#if ENABLE(JIT)
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
result = constructData.js.functionExecutable->jitCodeForConstruct(newCallFrame, constructDataScopeChain).execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
#if ENABLE(INTERPRETER)
result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
else
#endif
#endif
#if ENABLE(INTERPRETER)
result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
#endif
m_reentryDepth--;
}
......@@ -952,11 +942,15 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
for (int i = 0; i < argc; ++i)
newCallFrame->r(++dst) = jsUndefined();
CodeBlock* codeBlock = FunctionExecutable->bytecodeForCall(callFrame, scopeChain);
if (codeBlock)
newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
else
newCallFrame = 0;
JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
if (error) {
*exception = error;
m_registerFile.shrink(oldEnd);
return CallFrameClosure();
}
CodeBlock* codeBlock = &FunctionExecutable->generatedBytecodeForCall();
newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
if (UNLIKELY(!newCallFrame)) {
*exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
......@@ -964,12 +958,6 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE
}
// a 0 codeBlock indicates a built-in caller
newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag(), argc, function);
#if ENABLE(JIT)
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
FunctionExecutable->jitCodeForCall(newCallFrame, scopeChain);
#endif
CallFrameClosure result = { callFrame, newCallFrame, function, FunctionExecutable, scopeChain->globalData, oldEnd, scopeChain, codeBlock->m_numParameters, argc };
return result;
}
......@@ -1013,7 +1001,12 @@ void Interpreter::endRepeatCall(CallFrameClosure& closure)
JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
{
return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->bytecode(callFrame, scopeChain).m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
JSObject* compileError = eval->compile(callFrame, scopeChain);
if (UNLIKELY(!!compileError)) {
*exception = compileError;
return jsNull();
}
return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain, exception);
}
JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
......@@ -1029,11 +1022,12 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain);
if (!codeBlock) {
*exception = createStackOverflowError(callFrame);
JSObject* compileError = eval->compile(callFrame, scopeChain);
if (UNLIKELY(!!compileError)) {
*exception = compileError;
return jsNull();
}
EvalCodeBlock* codeBlock = &eval->generatedBytecode();
JSVariableObject* variableObject;
for (ScopeChainNode* node = scopeChain; ; node = node->next) {
......@@ -1096,7 +1090,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
result = eval->jitCode(newCallFrame, scopeChain).execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
#if ENABLE(INTERPRETER)
else
#endif
......@@ -3712,13 +3706,16 @@ skip_id_custom_self:
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
if (UNLIKELY(!!error)) {
exceptionValue = error;
goto vm_throw;
}
CallFrame* previousCallFrame = callFrame;
if (newCodeBlock)
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
else
callFrame = 0;
CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
......@@ -3870,19 +3867,22 @@ skip_id_custom_self:
if (callType == CallTypeJS) {
ScopeChainNode* callDataScopeChain = callData.js.scopeChain;
CodeBlock* newCodeBlock = callData.js.functionExecutable->bytecodeForCall(callFrame, callDataScopeChain);
JSObject* error = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
if (UNLIKELY(!!error)) {
exceptionValue = error;
goto vm_throw;
}
CallFrame* previousCallFrame = callFrame;
if (newCodeBlock)
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
else
callFrame = 0;
CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
goto vm_throw;
}
callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
codeBlock = newCodeBlock;
ASSERT(codeBlock == callFrame->codeBlock());
......@@ -4195,15 +4195,16 @@ skip_id_custom_self:
if (constructType == ConstructTypeJS) {
ScopeChainNode* callDataScopeChain = constructData.js.scopeChain;
CodeBlock* newCodeBlock = constructData.js.functionExecutable->bytecodeForConstruct(callFrame, callDataScopeChain);
CallFrame* previousCallFrame = callFrame;
if (newCodeBlock)
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
else
callFrame = 0;
JSObject* error = constructData.js.functionExecutable->compileForConstruct(callFrame, callDataScopeChain);
if (UNLIKELY(!!error)) {
exceptionValue = error;
goto vm_throw;
}
CallFrame* previousCallFrame = callFrame;
CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
if (UNLIKELY(!callFrame)) {
callFrame = previousCallFrame;
exceptionValue = createStackOverflowError(callFrame);
......
......@@ -1858,8 +1858,9 @@ DEFINE_STUB_FUNCTION(void*, op_call_jitCompile)
ASSERT(!function->isHostFunction());
FunctionExecutable* executable = function->jsExecutable();
ScopeChainNode* callDataScopeChain = function->scope().node();
if (!executable->tryJitCodeForCall(stackFrame.callFrame, callDataScopeChain)) {
stackFrame.callFrame->globalData().exception = createStackOverflowError(stackFrame.callFrame);
JSObject* error = executable->compileForCall(stackFrame.callFrame, callDataScopeChain);
if (error) {
stackFrame.callFrame->globalData().exception = error;
return 0;
}
return function;
......@@ -1878,8 +1879,9 @@ DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile)
ASSERT(!function->isHostFunction());
FunctionExecutable* executable = function->jsExecutable();
ScopeChainNode* callDataScopeChain = function->scope().node();
if (!executable->tryJitCodeForConstruct(stackFrame.callFrame, callDataScopeChain)) {
stackFrame.callFrame->globalData().exception = createStackOverflowError(stackFrame.callFrame);
JSObject* error = executable->compileForConstruct(stackFrame.callFrame, callDataScopeChain);
if (error) {
stackFrame.callFrame->globalData().exception = error;
return 0;
}
return function;
......@@ -2017,12 +2019,12 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkCall)
codePtr = executable->generatedJITCodeForCall().addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
codeBlock = functionExecutable->bytecodeForCall(stackFrame.callFrame, callee->scope().node());
if (!codeBlock) {
stackFrame.callFrame->globalData().exception = createStackOverflowError(callFrame);
JSObject* error = functionExecutable->compileForCall(callFrame, callee->scope().node());
if (error) {
callFrame->globalData().exception = createStackOverflowError(callFrame);
return 0;
}
functionExecutable->jitCodeForCall(callFrame, callee->scope().node());
codeBlock = &functionExecutable->generatedBytecodeForCall();
if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
codePtr = functionExecutable->generatedJITCodeForCall().addressForCall();
else
......@@ -2051,12 +2053,12 @@ DEFINE_STUB_FUNCTION(void*, vm_lazyLinkConstruct)
codePtr = executable->generatedJITCodeForConstruct().addressForCall();
else {
FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
codeBlock = functionExecutable->bytecodeForConstruct(stackFrame.callFrame, callee->scope().node());
if (!codeBlock) {
JSObject* error = functionExecutable->compileForConstruct(callFrame, callee->scope().node());
if (error) {
throwStackOverflowError(callFrame, stackFrame.globalData, ReturnAddressPtr(callFrame->returnPC()), STUB_RETURN_ADDRESS);
return 0;
}
functionExecutable->jitCodeForConstruct(callFrame, callee->scope().node());
codeBlock = &functionExecutable->generatedBytecodeForConstruct();
if (callFrame->argumentCountIncludingThis() == static_cast<size_t>(codeBlock->m_numParameters))
codePtr = functionExecutable->generatedJITCodeForConstruct().addressForCall();
else
......
......@@ -24,6 +24,7 @@
#define Parser_h
#include "Debugger.h"
#include "ExceptionHelpers.h"
#include "Executable.h"
#include "JSGlobalObject.h"
#include "Lexer.h"
......@@ -38,6 +39,7 @@
namespace JSC {
class FunctionBodyNode;
class ProgramNode;
class UString;
......@@ -46,7 +48,7 @@ namespace JSC {
class Parser : public Noncopyable {
public:
template <class ParsedNode>
PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, Debugger*, ExecState*, const SourceCode& source, int* errLine = 0, UString* errMsg = 0);
PassRefPtr<ParsedNode> parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger*, ExecState*, const SourceCode& source, JSObject** exception);
void didFinishParsing(SourceElements*, ParserArenaData<DeclarationStacks::VarStack>*,
ParserArenaData<DeclarationStacks::FunctionStack>*, CodeFeatures features, int lastLine, int numConstants);
......@@ -56,6 +58,10 @@ namespace JSC {
private:
void parse(JSGlobalData*, int* errLine, UString* errMsg);
// Used to determine type of error to report.
bool isFunctionBodyNode(ScopeNode*) { return false; }
bool isFunctionBodyNode(FunctionBodyNode*) { return true; }
ParserArena m_arena;
const SourceCode* m_source;
SourceElements* m_sourceElements;
......@@ -67,12 +73,16 @@ namespace JSC {
};
template <class ParsedNode>
PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, int* errLine, UString* errMsg)
PassRefPtr<ParsedNode> Parser::parse(JSGlobalData* globalData, JSGlobalObject* lexicalGlobalObject, Debugger* debugger, ExecState* debuggerExecState, const SourceCode& source, JSObject** exception)
{
ASSERT(exception && !*exception);
int errLine;
UString errMsg;
m_source = &source;
if (ParsedNode::scopeIsFunction)
globalData->lexer->setIsReparsing();
parse(globalData, errLine, errMsg);
parse(globalData, &errLine, &errMsg);
RefPtr<ParsedNode> result;
if (m_sourceElements) {
......@@ -84,6 +94,17 @@ namespace JSC {
m_features,
m_numConstants);
result->setLoc(m_source->firstLine(), m_lastLine);
} else if (lexicalGlobalObject) {
// We can never see a syntax error when reparsing a function, since we should have
// reported the error when parsing the containing program or eval code. So if we're
// parsing a function body node, we assume that what actually happened here is that
// we ran out of stack while parsing. If we see an error while parsing eval or program
// code we assume that it was a syntax error since running out of stack is much less
// likely, and we are currently unable to distinguish between the two cases.
if (isFunctionBodyNode(static_cast<ParsedNode*>(0)))
*exception = createStackOverflowError(lexicalGlobalObject);
else
*exception = addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, source);
}
m_arena.reset();
......@@ -94,7 +115,7 @@ namespace JSC {
m_funcDeclarations = 0;
if (debugger && !ParsedNode::scopeIsFunction)
debugger->sourceParsed(debuggerExecState, source, *errLine, *errMsg);
debugger->sourceParsed(debuggerExecState, source, errLine, errMsg);
return result.release();
}
......
......@@ -73,26 +73,13 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
if (callType != CallTypeJS)
return false;
#if ENABLE(JIT)
// If the JIT is enabled then we need to preserve the invariant that every
// function with a CodeBlock also has JIT code.
CodeBlock* codeBlock = 0;
#if ENABLE(INTERPRETER)
if (!exec->globalData().canUseJIT())
codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
else
#endif
{
callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain);
codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
}
#else
CodeBlock* codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
#endif
if (!codeBlock)
FunctionExecutable* executable = callData.js.functionExecutable;
JSObject* error = executable->compileForCall(exec, callData.js.scopeChain);
if (error)
return false;
return codeBlock->isNumericCompareFunction();
return executable->generatedBytecodeForCall().isNumericCompareFunction();
}
// ------------------------------ ArrayPrototype ----------------------------
......
......@@ -78,6 +78,11 @@ JSObject* createStackOverflowError(ExecState* exec)
return createRangeError(exec, "Maximum call stack size exceeded.");
}
JSObject* createStackOverflowError(JSGlobalObject* globalObject)
{
return createRangeError(globalObject, "Maximum call stack size exceeded.");
}
JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
{
int startOffset = 0;
......
......@@ -37,6 +37,7 @@ namespace JSC {
class ExecState;
class Identifier;
class JSGlobalData;
class JSGlobalObject;
class JSNotAnObjectErrorStub;
class JSObject;
class Node;
......@@ -45,6 +46,7 @@ namespace JSC {
JSValue createInterruptedExecutionException(JSGlobalData*);
JSValue createTerminatedExecutionException(JSGlobalData*);
JSObject* createStackOverflowError(ExecState*);
JSObject* createStackOverflowError(JSGlobalObject*);
JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
......
......@@ -61,15 +61,16 @@ FunctionExecutable::~FunctionExecutable()
delete m_codeBlockForConstruct;
}
JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
{
int errLine;
UString errMsg;
JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
if (!evalNode)
return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);
RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
if (!evalNode) {
ASSERT(exception);
return exception;
}
recordParse(evalNode->features(), evalNode->lineNo(), evalNode->lastLine());
ScopeChain scopeChain(scopeChainNode);
......@@ -81,50 +82,77 @@ JSObject* EvalExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNod
generator->generate();
evalNode->destroyData();
#if ENABLE(JIT)
if (exec->globalData().canUseJIT()) {
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock);
#if !ENABLE(OPCODE_SAMPLING)
if (!BytecodeGenerator::dumpsGeneratedCode())
m_evalCodeBlock->discardBytecode();
#endif
}
#endif
return 0;
}
JSObject* ProgramExecutable::checkSyntax(ExecState* exec)
{
int errLine;
UString errMsg;
JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
if (!programNode)
return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);
return 0;
RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, &exception);
if (programNode)
return 0;
ASSERT(exception);
return exception;
}
JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChainNode)
JSObject* ProgramExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode)
{
int errLine;
UString errMsg;
ASSERT(!m_programCodeBlock);
JSObject* exception = 0;
JSGlobalData* globalData = &exec->globalData();
JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
RefPtr<ProgramNode> programNode = globalData->parser->parse<ProgramNode>(globalData, lexicalGlobalObject->debugger(), exec, m_source, &errLine, &errMsg);
if (!programNode)
return addErrorInfo(globalData, createSyntaxError(lexicalGlobalObject, errMsg), errLine, m_source);