Bug 48365 - Remove output parameters from JITStackFrame
Reviewed by Oliver Hunt.
The JIT stub functions presently use the stackframe to provide a couple of additional return values.
* In the case of uncaught exceptions the exception value is returned on the stackframe.exception property.
* In the case of caught exceptions the updated value for the callFrame register is returned on the stackframe.callFrame property.
Change exception returns such that exceptions are always returned on JSGlobalData::exception.
Change op_catch such that the new CallFrame value is returned from op_throw / vm_throw in regT0.
* JavaScriptCore.xcodeproj/project.pbxproj:
* debugger/Debugger.cpp:
(JSC::evaluateInGlobalCallFrame):
* debugger/DebuggerCallFrame.cpp:
(JSC::DebuggerCallFrame::evaluate):
* interpreter/CachedCall.h:
(JSC::CachedCall::CachedCall):
(JSC::CachedCall::call):
* interpreter/CallFrame.h:
(JSC::ExecState::exception):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::callEval):
(JSC::Interpreter::Interpreter):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::privateExecute):
* interpreter/Interpreter.h:
* jit/JITCode.h:
(JSC::JITCode::execute):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITStubs.cpp:
(JSC::ctiTrampoline):
(JSC::jitThrow):
(JSC::DEFINE_STUB_FUNCTION):
* jit/JITStubs.h:
* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncMap):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncForEach):
(JSC::arrayProtoFuncSome):
(JSC::arrayProtoFuncReduce):
(JSC::arrayProtoFuncReduceRight):
* runtime/CallData.cpp:
(JSC::call):
* runtime/Completion.cpp:
(JSC::evaluate):
* runtime/ConstructData.cpp:
(JSC::construct):
* runtime/ExceptionHelpers.cpp:
(JSC::createErrorForInvalidGlobalAssignment):
(JSC::throwOutOfMemoryError):
(JSC::throwStackOverflowError):
* runtime/ExceptionHelpers.h:
* runtime/JSArray.cpp:
(JSC::JSArray::sort):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncEval):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncReplace):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70703 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index f29a7a8..dfe4b1d 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,72 @@
+2010-10-27 Gavin Barraclough <barraclough@apple.com>
+
+ Reviewed by Oliver Hunt.
+
+ Bug 48365 - Remove output parameters from JITStackFrame
+
+ The JIT stub functions presently use the stackframe to provide a couple of additional return values.
+ * In the case of uncaught exceptions the exception value is returned on the stackframe.exception property.
+ * In the case of caught exceptions the updated value for the callFrame register is returned on the stackframe.callFrame property.
+
+ Change exception returns such that exceptions are always returned on JSGlobalData::exception.
+ Change op_catch such that the new CallFrame value is returned from op_throw / vm_throw in regT0.
+
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * debugger/Debugger.cpp:
+ (JSC::evaluateInGlobalCallFrame):
+ * debugger/DebuggerCallFrame.cpp:
+ (JSC::DebuggerCallFrame::evaluate):
+ * interpreter/CachedCall.h:
+ (JSC::CachedCall::CachedCall):
+ (JSC::CachedCall::call):
+ * interpreter/CallFrame.h:
+ (JSC::ExecState::exception):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::callEval):
+ (JSC::Interpreter::Interpreter):
+ (JSC::Interpreter::execute):
+ (JSC::Interpreter::executeCall):
+ (JSC::Interpreter::executeConstruct):
+ (JSC::Interpreter::prepareForRepeatCall):
+ (JSC::Interpreter::privateExecute):
+ * interpreter/Interpreter.h:
+ * jit/JITCode.h:
+ (JSC::JITCode::execute):
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_catch):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_catch):
+ * jit/JITStubs.cpp:
+ (JSC::ctiTrampoline):
+ (JSC::jitThrow):
+ (JSC::DEFINE_STUB_FUNCTION):
+ * jit/JITStubs.h:
+ * runtime/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncMap):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncForEach):
+ (JSC::arrayProtoFuncSome):
+ (JSC::arrayProtoFuncReduce):
+ (JSC::arrayProtoFuncReduceRight):
+ * runtime/CallData.cpp:
+ (JSC::call):
+ * runtime/Completion.cpp:
+ (JSC::evaluate):
+ * runtime/ConstructData.cpp:
+ (JSC::construct):
+ * runtime/ExceptionHelpers.cpp:
+ (JSC::createErrorForInvalidGlobalAssignment):
+ (JSC::throwOutOfMemoryError):
+ (JSC::throwStackOverflowError):
+ * runtime/ExceptionHelpers.h:
+ * runtime/JSArray.cpp:
+ (JSC::JSArray::sort):
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::globalFuncEval):
+ * runtime/StringPrototype.cpp:
+ (JSC::stringProtoFuncReplace):
+
2010-10-27 Gabor Loki <loki@webkit.org>
Reviewed by Oliver Hunt.
diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp
index 29b6eb2..472a03a 100644
--- a/JavaScriptCore/debugger/Debugger.cpp
+++ b/JavaScriptCore/debugger/Debugger.cpp
@@ -106,7 +106,14 @@
if (error)
return error;
- return globalObject->globalData().interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception);
+ JSGlobalData& globalData = globalObject->globalData();
+ JSValue result = globalData.interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain());
+ if (globalData.exception) {
+ exception = globalData.exception;
+ globalData.exception = JSValue();
+ }
+ ASSERT(result);
+ return result;
}
} // namespace JSC
diff --git a/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/JavaScriptCore/debugger/DebuggerCallFrame.cpp
index c98c7cc..a5897c59 100644
--- a/JavaScriptCore/debugger/DebuggerCallFrame.cpp
+++ b/JavaScriptCore/debugger/DebuggerCallFrame.cpp
@@ -93,7 +93,14 @@
if (error)
return error;
- return m_callFrame->scopeChain()->globalData->interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception);
+ JSGlobalData& globalData = m_callFrame->globalData();
+ JSValue result = globalData.interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain());
+ if (globalData.exception) {
+ exception = globalData.exception;
+ globalData.exception = JSValue();
+ }
+ ASSERT(result);
+ return result;
}
} // namespace JSC
diff --git a/JavaScriptCore/interpreter/CachedCall.h b/JavaScriptCore/interpreter/CachedCall.h
index eb48a03..dfbe658 100644
--- a/JavaScriptCore/interpreter/CachedCall.h
+++ b/JavaScriptCore/interpreter/CachedCall.h
@@ -34,21 +34,20 @@
namespace JSC {
class CachedCall : public Noncopyable {
public:
- CachedCall(CallFrame* callFrame, JSFunction* function, int argCount, JSValue* exception)
+ CachedCall(CallFrame* callFrame, JSFunction* function, int argCount)
: m_valid(false)
, m_interpreter(callFrame->interpreter())
- , m_exception(exception)
, m_globalObjectScope(callFrame, function->scope().globalObject())
{
ASSERT(!function->isHostFunction());
- m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node(), exception);
- m_valid = !*exception;
+ m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node());
+ m_valid = !callFrame->hadException();
}
JSValue call()
{
ASSERT(m_valid);
- return m_interpreter->execute(m_closure, m_exception);
+ return m_interpreter->execute(m_closure);
}
void setThis(JSValue v) { m_closure.setArgument(0, v); }
void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); }
@@ -69,7 +68,6 @@
private:
bool m_valid;
Interpreter* m_interpreter;
- JSValue* m_exception;
DynamicGlobalObjectScope m_globalObjectScope;
CallFrameClosure m_closure;
};
diff --git a/JavaScriptCore/interpreter/CallFrame.h b/JavaScriptCore/interpreter/CallFrame.h
index 67deb38..56709f3b 100644
--- a/JavaScriptCore/interpreter/CallFrame.h
+++ b/JavaScriptCore/interpreter/CallFrame.h
@@ -76,7 +76,6 @@
void clearException() { globalData().exception = JSValue(); }
JSValue exception() const { return globalData().exception; }
- JSValue* exceptionSlot() { return &globalData().exception; }
bool hadException() const { return globalData().exception; }
const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; }
diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index 61e5a70..29051bb 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -383,7 +383,7 @@
}
#endif
-NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue& exceptionValue)
+NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset)
{
if (argc < 2)
return jsUndefined();
@@ -407,13 +407,14 @@
}
ScopeChainNode* scopeChain = callFrame->scopeChain();
+ JSValue exceptionValue;
RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, codeBlock->isStrictMode(), programSource, scopeChain, exceptionValue);
- JSValue result = jsUndefined();
- if (eval)
- result = callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->r(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
+ ASSERT(!eval == exceptionValue);
+ if (UNLIKELY(!eval))
+ return throwError(callFrame, exceptionValue);
- return result;
+ return callFrame->globalData().interpreter->execute(eval.get(), callFrame, callFrame->r(codeBlock->thisRegister()).jsValue().toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain);
}
Interpreter::Interpreter()
@@ -421,7 +422,7 @@
, m_reentryDepth(0)
{
#if ENABLE(COMPUTED_GOTO_INTERPRETER)
- privateExecute(InitializeAndReturn, 0, 0, 0);
+ privateExecute(InitializeAndReturn, 0, 0);
for (int i = 0; i < numOpcodeIDs; ++i)
m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i));
@@ -701,30 +702,34 @@
return handler;
}
-JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj, JSValue* exception)
+static inline JSValue checkedReturn(JSValue returnValue)
+{
+ ASSERT(returnValue);
+ return returnValue;
+}
+
+static inline JSObject* checkedReturn(JSObject* returnValue)
+{
+ ASSERT(returnValue);
+ return returnValue;
+}
+
+JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, ScopeChainNode* scopeChain, JSObject* thisObj)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
- if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
- }
- }
+ if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+ return checkedReturn(throwStackOverflowError(callFrame));
JSObject* error = program->compile(callFrame, scopeChain);
- if (error) {
- *exception = error;
- return jsNull();
- }
+ if (error)
+ return checkedReturn(throwError(callFrame, error));
CodeBlock* codeBlock = &program->generatedBytecode();
Register* oldEnd = m_registerFile.end();
Register* newEnd = oldEnd + codeBlock->m_numParameters + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters;
- if (!m_registerFile.grow(newEnd)) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
- }
+ if (!m_registerFile.grow(newEnd))
+ return checkedReturn(throwStackOverflowError(callFrame));
JSGlobalObject* lastGlobalObject = m_registerFile.globalObject();
JSGlobalObject* globalObject = callFrame->dynamicGlobalObject();
@@ -751,10 +756,10 @@
m_reentryDepth++;
#if ENABLE(JIT)
if (callFrame->globalData().canUseJIT())
- result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+ result = program->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
else
#endif
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+ result = privateExecute(Normal, &m_registerFile, newCallFrame);
m_reentryDepth--;
}
@@ -767,28 +772,22 @@
m_registerFile.shrink(oldEnd);
- return result;
+ return checkedReturn(result);
}
-JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, JSValue* exception)
+JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
{
ASSERT(!callFrame->hadException());
- if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
- if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
- }
- }
+ if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+ return checkedReturn(throwStackOverflowError(callFrame));
Register* oldEnd = m_registerFile.end();
int argCount = 1 + args.size(); // implicit "this" parameter
size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
- if (!m_registerFile.grow(oldEnd + registerOffset)) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
- }
+ if (!m_registerFile.grow(oldEnd + registerOffset))
+ return checkedReturn(throwStackOverflowError(callFrame));
CallFrame* newCallFrame = CallFrame::create(oldEnd);
size_t dst = 0;
@@ -802,17 +801,15 @@
JSObject* compileError = callData.js.functionExecutable->compileForCall(callFrame, callDataScopeChain);
if (UNLIKELY(!!compileError)) {
- *exception = compileError;
m_registerFile.shrink(oldEnd);
- return jsNull();
+ return checkedReturn(throwError(callFrame, compileError));
}
CodeBlock* newCodeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
if (UNLIKELY(!newCallFrame)) {
- *exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
- return jsNull();
+ return checkedReturn(throwStackOverflowError(callFrame));
}
newCallFrame->init(newCodeBlock, 0, callDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, function);
@@ -830,10 +827,10 @@
m_reentryDepth++;
#if ENABLE(JIT)
if (callFrame->globalData().canUseJIT())
- result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData, exception);
+ result = callData.js.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, newCallFrame, callDataScopeChain->globalData);
else
#endif
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+ result = privateExecute(Normal, &m_registerFile, newCallFrame);
m_reentryDepth--;
}
@@ -841,7 +838,7 @@
(*profiler)->didExecute(newCallFrame, function);
m_registerFile.shrink(oldEnd);
- return result;
+ return checkedReturn(result);
}
ASSERT(callType == CallTypeHost);
@@ -865,28 +862,22 @@
(*profiler)->didExecute(newCallFrame, function);
m_registerFile.shrink(oldEnd);
- return result;
+ return checkedReturn(result);
}
-JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args, JSValue* exception)
+JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* constructor, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
{
ASSERT(!callFrame->hadException());
- if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
- if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return 0;
- }
- }
+ if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+ return checkedReturn(throwStackOverflowError(callFrame));
Register* oldEnd = m_registerFile.end();
int argCount = 1 + args.size(); // implicit "this" parameter
size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
- if (!m_registerFile.grow(oldEnd + registerOffset)) {
- *exception = createStackOverflowError(callFrame);
- return 0;
- }
+ if (!m_registerFile.grow(oldEnd + registerOffset))
+ return checkedReturn(throwStackOverflowError(callFrame));
CallFrame* newCallFrame = CallFrame::create(oldEnd);
size_t dst = 0;
@@ -899,17 +890,15 @@
JSObject* compileError = constructData.js.functionExecutable->compileForConstruct(callFrame, constructDataScopeChain);
if (UNLIKELY(!!compileError)) {
- *exception = compileError;
m_registerFile.shrink(oldEnd);
- return 0;
+ return checkedReturn(throwError(callFrame, compileError));
}
CodeBlock* newCodeBlock = &constructData.js.functionExecutable->generatedBytecodeForConstruct();
newCallFrame = slideRegisterWindowForCall(newCodeBlock, &m_registerFile, newCallFrame, registerOffset, argCount);
if (UNLIKELY(!newCallFrame)) {
- *exception = createStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
- return 0;
+ return checkedReturn(throwStackOverflowError(callFrame));
}
newCallFrame->init(newCodeBlock, 0, constructDataScopeChain, callFrame->addHostCallFrameFlag(), argCount, constructor);
@@ -927,10 +916,10 @@
m_reentryDepth++;
#if ENABLE(JIT)
if (callFrame->globalData().canUseJIT())
- result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData, exception);
+ result = constructData.js.functionExecutable->generatedJITCodeForConstruct().execute(&m_registerFile, newCallFrame, constructDataScopeChain->globalData);
else
#endif
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+ result = privateExecute(Normal, &m_registerFile, newCallFrame);
m_reentryDepth--;
}
@@ -941,7 +930,7 @@
if (callFrame->hadException())
return 0;
ASSERT(result.isObject());
- return asObject(result);
+ return checkedReturn(asObject(result));
}
ASSERT(constructType == ConstructTypeHost);
@@ -968,16 +957,16 @@
if (callFrame->hadException())
return 0;
ASSERT(result.isObject());
- return asObject(result);
+ return checkedReturn(asObject(result));
}
-CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain, JSValue* exception)
+CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionExecutable, CallFrame* callFrame, JSFunction* function, int argCount, ScopeChainNode* scopeChain)
{
ASSERT(!scopeChain->globalData->exception);
if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
+ throwStackOverflowError(callFrame);
return CallFrameClosure();
}
}
@@ -986,7 +975,7 @@
int argc = 1 + argCount; // implicit "this" parameter
if (!m_registerFile.grow(oldEnd + argc)) {
- *exception = createStackOverflowError(callFrame);
+ throwStackOverflowError(callFrame);
return CallFrameClosure();
}
@@ -997,7 +986,7 @@
JSObject* error = FunctionExecutable->compileForCall(callFrame, scopeChain);
if (error) {
- *exception = error;
+ throwError(callFrame, error);
m_registerFile.shrink(oldEnd);
return CallFrameClosure();
}
@@ -1005,7 +994,7 @@
newCallFrame = slideRegisterWindowForCall(codeBlock, &m_registerFile, newCallFrame, argc + RegisterFile::CallFrameHeaderSize, argc);
if (UNLIKELY(!newCallFrame)) {
- *exception = createStackOverflowError(callFrame);
+ throwStackOverflowError(callFrame);
m_registerFile.shrink(oldEnd);
return CallFrameClosure();
}
@@ -1014,7 +1003,7 @@
return result;
}
-JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception)
+JSValue Interpreter::execute(CallFrameClosure& closure)
{
closure.resetCallFrame();
Profiler** profiler = Profiler::enabledProfilerReference();
@@ -1030,20 +1019,20 @@
#if ENABLE(INTERPRETER)
if (closure.newCallFrame->globalData().canUseJIT())
#endif
- result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData, exception);
+ result = closure.functionExecutable->generatedJITCodeForCall().execute(&m_registerFile, closure.newCallFrame, closure.globalData);
#if ENABLE(INTERPRETER)
else
#endif
#endif
#if ENABLE(INTERPRETER)
- result = privateExecute(Normal, &m_registerFile, closure.newCallFrame, exception);
+ result = privateExecute(Normal, &m_registerFile, closure.newCallFrame);
#endif
m_reentryDepth--;
}
if (*profiler)
(*profiler)->didExecute(closure.oldCallFrame, closure.function);
- return result;
+ return checkedReturn(result);
}
void Interpreter::endRepeatCall(CallFrameClosure& closure)
@@ -1051,34 +1040,26 @@
m_registerFile.shrink(closure.oldEnd);
}
-JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain)
{
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);
+ if (UNLIKELY(!!compileError))
+ return checkedReturn(throwError(callFrame, compileError));
+ return execute(eval, callFrame, thisObj, m_registerFile.size() + eval->generatedBytecode().m_numParameters + RegisterFile::CallFrameHeaderSize, scopeChain);
}
-JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue* exception)
+JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain)
{
ASSERT(!scopeChain->globalData->exception);
- if (m_reentryDepth >= MaxSmallThreadReentryDepth) {
- if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
- *exception = createStackOverflowError(callFrame);
- return jsNull();
- }
- }
+ if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
+ return checkedReturn(throwStackOverflowError(callFrame));
DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject);
JSObject* compileError = eval->compile(callFrame, scopeChain);
- if (UNLIKELY(!!compileError)) {
- *exception = compileError;
- return jsNull();
- }
+ if (UNLIKELY(!!compileError))
+ return checkedReturn(throwError(callFrame, compileError));
EvalCodeBlock* codeBlock = &eval->generatedBytecode();
JSObject* variableObject;
@@ -1120,10 +1101,9 @@
Register* oldEnd = m_registerFile.end();
Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->m_numCalleeRegisters;
if (!m_registerFile.grow(newEnd)) {
- *exception = createStackOverflowError(callFrame);
if (pushedScope)
scopeChain->pop();
- return jsNull();
+ return checkedReturn(throwStackOverflowError(callFrame));
}
CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
@@ -1149,13 +1129,13 @@
#if ENABLE(INTERPRETER)
if (callFrame->globalData().canUseJIT())
#endif
- result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData, exception);
+ result = eval->generatedJITCode().execute(&m_registerFile, newCallFrame, scopeChain->globalData);
#if ENABLE(INTERPRETER)
else
#endif
#endif
#if ENABLE(INTERPRETER)
- result = privateExecute(Normal, &m_registerFile, newCallFrame, exception);
+ result = privateExecute(Normal, &m_registerFile, newCallFrame);
#endif
m_reentryDepth--;
}
@@ -1166,7 +1146,7 @@
m_registerFile.shrink(oldEnd);
if (pushedScope)
scopeChain->pop();
- return result;
+ return checkedReturn(result);
}
NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine)
@@ -1435,7 +1415,7 @@
#endif // ENABLE(INTERPRETER)
-JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame, JSValue* exception)
+JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFile, CallFrame* callFrame)
{
// One-time initialization of our address tables. We have to put this code
// here because our labels are only in scope inside this function.
@@ -1461,7 +1441,6 @@
#if !ENABLE(INTERPRETER)
UNUSED_PARAM(registerFile);
UNUSED_PARAM(callFrame);
- UNUSED_PARAM(exception);
return JSValue();
#else
@@ -3818,8 +3797,8 @@
JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
- JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
- if (exceptionValue)
+ JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset);
+ if (exceptionValue = globalData->exception)
goto vm_throw;
functionReturnValue = result;
@@ -4599,10 +4578,8 @@
exceptionValue = callFrame->r(ex).jsValue();
handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin(), true);
- if (!handler) {
- *exception = exceptionValue;
- return jsNull();
- }
+ if (!handler)
+ return throwError(callFrame, exceptionValue);
codeBlock = callFrame->codeBlock();
vPC = codeBlock->instructions().begin() + handler->target;
@@ -4769,10 +4746,8 @@
exceptionValue = createInterruptedExecutionException(globalData);
}
handler = throwException(callFrame, exceptionValue, vPC - codeBlock->instructions().begin(), false);
- if (!handler) {
- *exception = exceptionValue;
- return jsNull();
- }
+ if (!handler)
+ return throwError(callFrame, exceptionValue);
codeBlock = callFrame->codeBlock();
vPC = codeBlock->instructions().begin() + handler->target;
diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h
index 50f07b3..2bc403e 100644
--- a/JavaScriptCore/interpreter/Interpreter.h
+++ b/JavaScriptCore/interpreter/Interpreter.h
@@ -93,11 +93,11 @@
}
bool isOpcode(Opcode);
-
- JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj, JSValue* exception);
- JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&, JSValue* exception);
- JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&, JSValue* exception);
- JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain, JSValue* exception);
+
+ JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj);
+ JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&);
+ JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&);
+ JSValue execute(EvalExecutable* evalNode, CallFrame* exec, JSObject* thisObj, ScopeChainNode* scopeChain);
JSValue retrieveArguments(CallFrame*, JSFunction*) const;
JSValue retrieveCaller(CallFrame*, JSFunction*) const;
@@ -107,7 +107,7 @@
SamplingTool* sampler() { return m_sampler.get(); }
- NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue);
+ NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset);
NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool);
NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
@@ -117,11 +117,11 @@
private:
enum ExecutionFlag { Normal, InitializeAndReturn };
- CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*, JSValue* exception);
+ CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argCount, ScopeChainNode*);
void endRepeatCall(CallFrameClosure&);
- JSValue execute(CallFrameClosure&, JSValue* exception);
+ JSValue execute(CallFrameClosure&);
- JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue* exception);
+ JSValue execute(EvalExecutable*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*);
#if ENABLE(INTERPRETER)
NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue);
@@ -144,7 +144,7 @@
static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*);
- JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue* exception);
+ JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*);
void dumpCallFrame(CallFrame*);
void dumpRegisters(CallFrame*);
diff --git a/JavaScriptCore/jit/JITCode.h b/JavaScriptCore/jit/JITCode.h
index 5d889b5..7346fd5 100644
--- a/JavaScriptCore/jit/JITCode.h
+++ b/JavaScriptCore/jit/JITCode.h
@@ -72,9 +72,10 @@
}
// Execute the code!
- inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue* exception)
+ inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData)
{
- return JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
+ JSValue result = JSValue::decode(ctiTrampoline(m_ref.m_code.executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData));
+ return globalData->exception ? jsNull() : result;
}
void* start()
diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h
index 0fe9929..7611151 100644
--- a/JavaScriptCore/jit/JITInlineMethods.h
+++ b/JavaScriptCore/jit/JITInlineMethods.h
@@ -186,7 +186,7 @@
ALWAYS_INLINE void JIT::restoreArgumentReference()
{
move(stackPointerRegister, firstArgumentRegister);
- poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+ poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
}
ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp
index e77b8bc..1528b76 100644
--- a/JavaScriptCore/jit/JITOpcodes.cpp
+++ b/JavaScriptCore/jit/JITOpcodes.cpp
@@ -1064,7 +1064,10 @@
void JIT::emit_op_catch(Instruction* currentInstruction)
{
killLastResultRegister(); // FIXME: Implicitly treat op_catch as a labeled statement, and remove this line of code.
- peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
+ move(regT0, callFrameRegister);
+ peek(regT3, OBJECT_OFFSETOF(struct JITStackFrame, globalData) / sizeof(void*));
+ loadPtr(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception)), regT0);
+ storePtr(ImmPtr(JSValue::encode(JSValue())), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception)));
emitPutVirtualRegister(currentInstruction[1].u.operand);
}
@@ -1286,7 +1289,7 @@
void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
{
- peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
Jump noProfiler = branchTestPtr(Zero, Address(regT1));
JITStubCall stubCall(this, cti_op_profile_will_call);
@@ -1298,7 +1301,7 @@
void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
{
- peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
+ peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof(void*));
Jump noProfiler = branchTestPtr(Zero, Address(regT1));
JITStubCall stubCall(this, cti_op_profile_did_call);
diff --git a/JavaScriptCore/jit/JITOpcodes32_64.cpp b/JavaScriptCore/jit/JITOpcodes32_64.cpp
index 2259dfe..0a3d69d 100644
--- a/JavaScriptCore/jit/JITOpcodes32_64.cpp
+++ b/JavaScriptCore/jit/JITOpcodes32_64.cpp
@@ -1386,15 +1386,17 @@
void JIT::emit_op_catch(Instruction* currentInstruction)
{
- unsigned exception = currentInstruction[1].u.operand;
-
- // This opcode only executes after a return from cti_op_throw.
-
- // cti_op_throw may have taken us to a call frame further up the stack; reload
- // the call frame pointer to adjust.
- peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof(void*));
+ // cti_op_throw returns the callFrame for the handler.
+ move(regT0, callFrameRegister);
// Now store the exception returned by cti_op_throw.
+ loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(struct JITStackFrame, globalData)), regT3);
+ load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+ load32(Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+ store32(Imm32(JSValue().payload()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+ store32(Imm32(JSValue().tag()), Address(regT3, OBJECT_OFFSETOF(JSGlobalData, exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+
+ unsigned exception = currentInstruction[1].u.operand;
emitStore(exception, regT1, regT0);
map(m_bytecodeOffset + OPCODE_LENGTH(op_catch), exception, regT1, regT0);
}
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 0715328..50d84c6 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -147,12 +147,7 @@
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movl %esp, %ecx" "\n"
"call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
- "addl $0x3c, %esp" "\n"
- "popl %ebx" "\n"
- "popl %edi" "\n"
- "popl %esi" "\n"
- "popl %ebp" "\n"
- "ret" "\n"
+ "int3" "\n"
);
asm (
@@ -209,14 +204,7 @@
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movq %rsp, %rdi" "\n"
"call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
- "addq $0x48, %rsp" "\n"
- "popq %rbx" "\n"
- "popq %r15" "\n"
- "popq %r14" "\n"
- "popq %r13" "\n"
- "popq %r12" "\n"
- "popq %rbp" "\n"
- "ret" "\n"
+ "int3" "\n"
);
asm (
@@ -261,7 +249,7 @@
extern "C" {
- __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
+ __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
{
__asm {
push ebp;
@@ -373,12 +361,7 @@
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movl %esp, %ecx" "\n"
"call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
- "addl $0x1c, %esp" "\n"
- "popl %ebx" "\n"
- "popl %edi" "\n"
- "popl %esi" "\n"
- "popl %ebp" "\n"
- "ret" "\n"
+ "int3" "\n"
);
asm (
@@ -442,14 +425,7 @@
SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
"movq %rsp, %rdi" "\n"
"call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n"
- "addq $0x78, %rsp" "\n"
- "popq %rbx" "\n"
- "popq %r15" "\n"
- "popq %r14" "\n"
- "popq %r13" "\n"
- "popq %r12" "\n"
- "popq %rbp" "\n"
- "ret" "\n"
+ "int3" "\n"
);
asm (
@@ -508,7 +484,7 @@
extern "C" {
- __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*)
+ __declspec(naked) EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
{
__asm {
push ebp;
@@ -763,7 +739,7 @@
#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL)
-__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*)
+__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*)
{
ARM
stmdb sp!, {r1-r3}
@@ -1087,6 +1063,24 @@
} \
} while (0)
+struct ExceptionHandler {
+ void* catchRoutine;
+ CallFrame* callFrame;
+};
+static ExceptionHandler jitThrow(JSGlobalData* globalData, CallFrame* callFrame, JSValue exceptionValue, ReturnAddressPtr faultLocation, bool explicitThrow)
+{
+ ASSERT(exceptionValue);
+
+ unsigned vPCIndex = callFrame->codeBlock()->bytecodeOffset(callFrame, faultLocation);
+ globalData->exception = JSValue();
+ HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, explicitThrow); // This may update callFrame & exceptionValue!
+ globalData->exception = exceptionValue;
+
+ void* catchRoutine = handler ? handler->nativeCode.executableAddress() : FunctionPtr(ctiOpThrowNotCaught).value();
+ ASSERT(catchRoutine);
+ return (ExceptionHandler){ catchRoutine, callFrame };
+}
+
#if CPU(ARM_THUMB2)
#define DEFINE_STUB_FUNCTION(rtype, op) \
@@ -1380,18 +1374,21 @@
return timeoutChecker.ticksUntilNextCheck();
}
-DEFINE_STUB_FUNCTION(void, register_file_check)
+DEFINE_STUB_FUNCTION(void*, register_file_check)
{
STUB_INIT_STACK_FRAME(stackFrame);
+ CallFrame* callFrame = stackFrame.callFrame;
- if (LIKELY(stackFrame.registerFile->grow(&stackFrame.callFrame->registers()[stackFrame.callFrame->codeBlock()->m_numCalleeRegisters])))
- return;
+ if (UNLIKELY(!stackFrame.registerFile->grow(&callFrame->registers()[callFrame->codeBlock()->m_numCalleeRegisters]))) {
+ // Rewind to the previous call frame because op_call already optimistically
+ // moved the call frame forward.
+ CallFrame* oldCallFrame = callFrame->callerFrame();
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), ReturnAddressPtr(oldCallFrame->returnPC()), false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ callFrame = handler.callFrame;
+ }
- // Rewind to the previous call frame because op_call already optimistically
- // moved the call frame forward.
- CallFrame* oldCallFrame = stackFrame.callFrame->callerFrame();
- stackFrame.callFrame = oldCallFrame;
- throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS);
+ return callFrame;
}
DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq)
@@ -1994,9 +1991,9 @@
if (!stackFrame.registerFile->grow(newEnd)) {
// Rewind to the previous call frame because op_call already optimistically
// moved the call frame forward.
- stackFrame.callFrame = oldCallFrame;
- throwStackOverflowError(oldCallFrame, stackFrame.globalData, pc, STUB_RETURN_ADDRESS);
- return 0;
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
@@ -2009,9 +2006,9 @@
if (!stackFrame.registerFile->grow(newEnd)) {
// Rewind to the previous call frame because op_call already optimistically
// moved the call frame forward.
- stackFrame.callFrame = oldCallFrame;
- throwStackOverflowError(oldCallFrame, stackFrame.globalData, pc, STUB_RETURN_ADDRESS);
- return 0;
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
@@ -2053,9 +2050,9 @@
if (!stackFrame.registerFile->grow(newEnd)) {
// Rewind to the previous call frame because op_call already optimistically
// moved the call frame forward.
- stackFrame.callFrame = oldCallFrame;
- throwStackOverflowError(oldCallFrame, stackFrame.globalData, pc, STUB_RETURN_ADDRESS);
- return 0;
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
@@ -2068,9 +2065,9 @@
if (!stackFrame.registerFile->grow(newEnd)) {
// Rewind to the previous call frame because op_call already optimistically
// moved the call frame forward.
- stackFrame.callFrame = oldCallFrame;
- throwStackOverflowError(oldCallFrame, stackFrame.globalData, pc, STUB_RETURN_ADDRESS);
- return 0;
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, oldCallFrame, createStackOverflowError(oldCallFrame), pc, false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
@@ -2188,17 +2185,16 @@
throwStackOverflowError(previousCallFrame, stackFrame.globalData, callFrame->returnPC(), STUB_RETURN_ADDRESS);
VM_THROW_EXCEPTION();
}
+
callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(funcVal));
- stackFrame.callFrame = callFrame;
EncodedJSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
returnValue = callData.native.function(callFrame);
}
- stackFrame.callFrame = previousCallFrame;
- CHECK_FOR_EXCEPTION();
+ CHECK_FOR_EXCEPTION_AT_END();
return returnValue;
}
@@ -2336,16 +2332,14 @@
}
callFrame->init(0, static_cast<Instruction*>((STUB_RETURN_ADDRESS).value()), previousCallFrame->scopeChain(), previousCallFrame, argCount, asObject(constrVal));
- stackFrame.callFrame = callFrame;
EncodedJSValue returnValue;
{
SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
returnValue = constructData.native.function(callFrame);
}
- stackFrame.callFrame = previousCallFrame;
- CHECK_FOR_EXCEPTION();
+ CHECK_FOR_EXCEPTION_AT_END();
return returnValue;
}
@@ -3232,43 +3226,20 @@
JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject;
if (baseValue == globalObject && funcVal == globalObject->evalFunction()) {
- JSValue exceptionValue;
- JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
- if (UNLIKELY(exceptionValue)) {
- stackFrame.globalData->exception = exceptionValue;
- VM_THROW_EXCEPTION_AT_END();
- }
+ JSValue result = interpreter->callEval(callFrame, registerFile, argv, argCount, registerOffset);
+ CHECK_FOR_EXCEPTION_AT_END();
return JSValue::encode(result);
}
return JSValue::encode(JSValue());
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)
+DEFINE_STUB_FUNCTION(void*, op_throw)
{
STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
-
- unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS);
-
- JSValue exceptionValue = stackFrame.args[0].jsValue();
- ASSERT(exceptionValue);
-
- HandlerInfo* handler = stackFrame.globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, true);
-
- if (!handler) {
- *stackFrame.exception = exceptionValue;
- STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value());
- return JSValue::encode(jsNull());
- }
-
- stackFrame.callFrame = callFrame;
- void* catchRoutine = handler->nativeCode.executableAddress();
- ASSERT(catchRoutine);
- STUB_SET_RETURN_ADDRESS(catchRoutine);
- return JSValue::encode(exceptionValue);
+ ExceptionHandler handler = jitThrow(stackFrame.globalData, stackFrame.callFrame, stackFrame.args[0].jsValue(), STUB_RETURN_ADDRESS, true);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames)
@@ -3617,32 +3588,13 @@
stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine);
}
-DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw)
+DEFINE_STUB_FUNCTION(void*, vm_throw)
{
STUB_INIT_STACK_FRAME(stackFrame);
-
- CallFrame* callFrame = stackFrame.callFrame;
- CodeBlock* codeBlock = callFrame->codeBlock();
JSGlobalData* globalData = stackFrame.globalData;
-
- unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, globalData->exceptionLocation);
-
- JSValue exceptionValue = globalData->exception;
- ASSERT(exceptionValue);
- globalData->exception = JSValue();
-
- HandlerInfo* handler = globalData->interpreter->throwException(callFrame, exceptionValue, vPCIndex, false);
-
- if (!handler) {
- *stackFrame.exception = exceptionValue;
- return JSValue::encode(jsNull());
- }
-
- stackFrame.callFrame = callFrame;
- void* catchRoutine = handler->nativeCode.executableAddress();
- ASSERT(catchRoutine);
- STUB_SET_RETURN_ADDRESS(catchRoutine);
- return JSValue::encode(exceptionValue);
+ ExceptionHandler handler = jitThrow(globalData, stackFrame.callFrame, globalData->exception, globalData->exceptionLocation, false);
+ STUB_SET_RETURN_ADDRESS(handler.catchRoutine);
+ return handler.callFrame;
}
DEFINE_STUB_FUNCTION(EncodedJSValue, to_object)
diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h
index b91a074..c27ee52b 100644
--- a/JavaScriptCore/jit/JITStubs.h
+++ b/JavaScriptCore/jit/JITStubs.h
@@ -97,7 +97,7 @@
void* code;
RegisterFile* registerFile;
CallFrame* callFrame;
- JSValue* exception;
+ void* unused1;
Profiler** enabledProfilerReference;
JSGlobalData* globalData;
@@ -133,7 +133,7 @@
void* code;
RegisterFile* registerFile;
CallFrame* callFrame;
- JSValue* exception;
+ void* unused1;
Profiler** enabledProfilerReference;
JSGlobalData* globalData;
@@ -161,7 +161,7 @@
// These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved)
RegisterFile* registerFile;
CallFrame* callFrame;
- JSValue* exception;
+ void* unused1;
// These arguments passed on the stack.
Profiler** enabledProfilerReference;
@@ -189,7 +189,7 @@
RegisterFile* registerFile;
CallFrame* callFrame;
- JSValue* exception;
+ void* unused1;
// These arguments passed on the stack.
Profiler** enabledProfilerReference;
@@ -221,7 +221,7 @@
// These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved)
RegisterFile* registerFile;
CallFrame* callFrame;
- JSValue* exception;
+ void* unused1;
// These arguments passed on the stack.
Profiler** enabledProfilerReference;
@@ -252,7 +252,7 @@
extern "C" void ctiVMThrowTrampoline();
extern "C" void ctiOpThrowNotCaught();
- extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*);
+ extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*);
class JITThunks {
public:
@@ -348,13 +348,11 @@
EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
- EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION);
@@ -395,7 +393,6 @@
void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
- void JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION);
@@ -403,8 +400,11 @@
void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION);
+ void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
} // extern "C"
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 8a19f77..ab0c3d4 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -649,7 +649,7 @@
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
- CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ CachedCall cachedCall(exec, f, 3);
for (; k < length && !exec->hadException(); ++k) {
if (!array->canGetIndex(k))
break;
@@ -707,7 +707,7 @@
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
- CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ CachedCall cachedCall(exec, f, 3);
for (; k < length && !exec->hadException(); ++k) {
if (UNLIKELY(!array->canGetIndex(k)))
break;
@@ -764,7 +764,7 @@
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
- CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ CachedCall cachedCall(exec, f, 3);
for (; k < length && !exec->hadException(); ++k) {
if (UNLIKELY(!array->canGetIndex(k)))
break;
@@ -818,7 +818,7 @@
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
- CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ CachedCall cachedCall(exec, f, 3);
for (; k < length && !exec->hadException(); ++k) {
if (UNLIKELY(!array->canGetIndex(k)))
break;
@@ -865,7 +865,7 @@
if (callType == CallTypeJS && isJSArray(&exec->globalData(), thisObj)) {
JSFunction* f = asFunction(function);
JSArray* array = asArray(thisObj);
- CachedCall cachedCall(exec, f, 3, exec->exceptionSlot());
+ CachedCall cachedCall(exec, f, 3);
for (; k < length && !exec->hadException(); ++k) {
if (UNLIKELY(!array->canGetIndex(k)))
break;
@@ -935,7 +935,7 @@
}
if (callType == CallTypeJS && array) {
- CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+ CachedCall cachedCall(exec, asFunction(function), 4);
for (; i < length && !exec->hadException(); ++i) {
cachedCall.setThis(jsNull());
cachedCall.setArgument(0, rv);
@@ -1005,7 +1005,7 @@
}
if (callType == CallTypeJS && array) {
- CachedCall cachedCall(exec, asFunction(function), 4, exec->exceptionSlot());
+ CachedCall cachedCall(exec, asFunction(function), 4);
for (; i < length && !exec->hadException(); ++i) {
unsigned idx = length - i - 1;
cachedCall.setThis(jsNull());
diff --git a/JavaScriptCore/runtime/CallData.cpp b/JavaScriptCore/runtime/CallData.cpp
index 2b9302ae..018e2ca 100644
--- a/JavaScriptCore/runtime/CallData.cpp
+++ b/JavaScriptCore/runtime/CallData.cpp
@@ -35,7 +35,7 @@
JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
{
ASSERT(callType == CallTypeJS || callType == CallTypeHost);
- return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args, exec->exceptionSlot());
+ return exec->interpreter()->executeCall(exec, asObject(functionObject), callType, callData, thisValue, args);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/Completion.cpp b/JavaScriptCore/runtime/Completion.cpp
index 9af5171..eeb8b0d 100644
--- a/JavaScriptCore/runtime/Completion.cpp
+++ b/JavaScriptCore/runtime/Completion.cpp
@@ -59,10 +59,12 @@
JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec);
- JSValue exception;
- JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception);
+ JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj);
- if (exception) {
+ if (exec->hadException()) {
+ JSValue exception = exec->exception();
+ exec->clearException();
+
ComplType exceptionType = Throw;
if (exception.isObject())
exceptionType = asObject(exception)->exceptionType();
diff --git a/JavaScriptCore/runtime/ConstructData.cpp b/JavaScriptCore/runtime/ConstructData.cpp
index 0d27e25..5da2a91 100644
--- a/JavaScriptCore/runtime/ConstructData.cpp
+++ b/JavaScriptCore/runtime/ConstructData.cpp
@@ -36,7 +36,7 @@
JSObject* construct(ExecState* exec, JSValue constructorObject, ConstructType constructType, const ConstructData& constructData, const ArgList& args)
{
ASSERT(constructType == ConstructTypeJS || constructType == ConstructTypeHost);
- return exec->interpreter()->executeConstruct(exec, asObject(constructorObject), constructType, constructData, args, exec->exceptionSlot());
+ return exec->interpreter()->executeConstruct(exec, asObject(constructorObject), constructType, constructData, args);
}
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp
index a1e28d1..5fbaa18 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -187,14 +187,19 @@
return exception;
}
-JSValue throwOutOfMemoryError(ExecState* exec)
-{
- return throwError(exec, createError(exec, "Out of memory"));
-}
-
JSObject* createErrorForInvalidGlobalAssignment(ExecState* exec, const UString& propertyName)
{
return createReferenceError(exec, makeUString("Strict mode forbids implicit creation of global property '", propertyName, "'"));
}
+JSObject* throwOutOfMemoryError(ExecState* exec)
+{
+ return throwError(exec, createError(exec, "Out of memory"));
+}
+
+JSObject* throwStackOverflowError(ExecState* exec)
+{
+ return throwError(exec, createStackOverflowError(exec));
+}
+
} // namespace JSC
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h
index 9b6f1f2..a7b2ca7 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -53,9 +53,11 @@
JSObject* createNotAConstructorError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
JSValue createNotAFunctionError(ExecState*, JSValue, unsigned bytecodeOffset, CodeBlock*);
JSObject* createNotAnObjectError(ExecState*, JSNotAnObjectErrorStub*, unsigned bytecodeOffset, CodeBlock*);
- JSValue throwOutOfMemoryError(ExecState*);
JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&);
+ JSObject* throwOutOfMemoryError(ExecState*);
+ JSObject* throwStackOverflowError(ExecState*);
+
} // namespace JSC
#endif // ExceptionHelpers_h
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
index f9384ec..b8b92f4 100644
--- a/JavaScriptCore/runtime/JSArray.cpp
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -1085,7 +1085,7 @@
tree.abstractor().m_nodes.grow(nodeCount);
if (callType == CallTypeJS)
- tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2, exec->exceptionSlot()));
+ tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2));
if (!tree.abstractor().m_nodes.begin()) {
throwOutOfMemoryError(exec);
diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
index d146e87..284806e 100644
--- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
@@ -455,7 +455,7 @@
if (error)
return throwVMError(exec, error);
- return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()));
+ return JSValue::encode(exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()));
}
EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec)
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index f655c33..b5ea8fa 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -326,7 +326,7 @@
// reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
int argCount = reg->numSubpatterns() + 1 + 2;
JSFunction* func = asFunction(replacement);
- CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
+ CachedCall cachedCall(exec, func, argCount);
if (exec->hadException())
return JSValue::encode(jsNull());
while (true) {