summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/interpreter/Interpreter.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-07 11:21:11 +0200
commit2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch)
tree988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/JavaScriptCore/interpreter/Interpreter.cpp
parentdd91e772430dc294e3bf478c119ef8d43c0a3358 (diff)
downloadqtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/JavaScriptCore/interpreter/Interpreter.cpp')
-rw-r--r--Source/JavaScriptCore/interpreter/Interpreter.cpp116
1 files changed, 59 insertions, 57 deletions
diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp
index a74d3de89..1cd5719ff 100644
--- a/Source/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp
@@ -45,7 +45,6 @@
#include "JSActivation.h"
#include "JSArray.h"
#include "JSBoundFunction.h"
-#include "JSByteArray.h"
#include "JSNotAnObject.h"
#include "JSPropertyNameIterator.h"
#include "LiteralParser.h"
@@ -65,6 +64,7 @@
#include <limits.h>
#include <stdio.h>
#include <wtf/Threading.h>
+#include <wtf/text/StringBuilder.h>
#if ENABLE(JIT)
#include "JIT.h"
@@ -421,7 +421,8 @@ JSValue eval(CallFrame* callFrame)
JSValue program = callFrame->argument(0);
if (!program.isString())
return program;
-
+
+ TopCallFrameSetter topCallFrame(callFrame->globalData(), callFrame);
UString programSource = asString(program)->value(callFrame);
if (callFrame->hadException())
return JSValue();
@@ -952,14 +953,14 @@ static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame)
return StackFrameGlobalCode;
}
-void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results)
+void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results)
{
- CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag()->trueCallFrameFromVMCode();
+ CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag();
if (!callFrame || callFrame == CallFrame::noCaller())
return;
+ int line = getLineNumberForCallFrame(globalData, callFrame);
- if (line == -1)
- line = getLineNumberForCallFrame(globalData, callFrame);
+ callFrame = callFrame->trueCallFrameFromVMCode();
while (callFrame && callFrame != CallFrame::noCaller()) {
UString sourceURL;
@@ -975,11 +976,46 @@ void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<Stack
}
}
+void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error)
+{
+ JSGlobalData* globalData = &callFrame->globalData();
+ ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec());
+ if (error->hasProperty(callFrame, globalData->propertyNames->stack))
+ return;
+
+ Vector<StackFrame> stackTrace;
+ getStackTrace(&callFrame->globalData(), stackTrace);
+
+ if (stackTrace.isEmpty())
+ return;
+
+ JSGlobalObject* globalObject = 0;
+ if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error))
+ globalObject = globalData->dynamicGlobalObject;
+ else
+ globalObject = error->globalObject();
+ StringBuilder builder;
+ for (unsigned i = 0; i < stackTrace.size(); i++) {
+ builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl()));
+ if (i != stackTrace.size() - 1)
+ builder.append('\n');
+ }
+
+ error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete);
+}
+
NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset)
{
CodeBlock* codeBlock = callFrame->codeBlock();
bool isInterrupt = false;
+ ASSERT(!exceptionValue.isEmpty());
+ ASSERT(!exceptionValue.isCell() || exceptionValue.asCell());
+ // This shouldn't be possible (hence the assertions), but we're already in the slowest of
+ // slow cases, so let's harden against it anyway to be safe.
+ if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
+ exceptionValue = jsNull();
+
// Set up the exception object
if (exceptionValue.isObject()) {
JSObject* exception = asObject(exceptionValue);
@@ -990,12 +1026,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
// Using hasExpressionInfo to imply we are interested in rich exception info.
if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) {
ASSERT(codeBlock->hasLineInfo());
-
// FIXME: should only really be adding these properties to VM generated exceptions,
// but the inspector currently requires these for all thrown objects.
- Vector<StackFrame> stackTrace;
- getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace);
- addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace);
+ addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source());
}
isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception);
@@ -1013,9 +1046,11 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV
if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) {
if (Profiler* profiler = *Profiler::enabledProfilerReference())
profiler->exceptionUnwind(callFrame);
+ callFrame->globalData().topCallFrame = callFrame;
return 0;
}
}
+ callFrame->globalData().topCallFrame = callFrame;
if (Profiler* profiler = *Profiler::enabledProfilerReference())
profiler->exceptionUnwind(callFrame);
@@ -1223,6 +1258,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
return checkedReturn(throwStackOverflowError(callFrame));
Register* oldEnd = m_registerFile.end();
+ ASSERT(callFrame->frameExtent() <= oldEnd || callFrame == callFrame->scopeChain()->globalObject->globalExec());
int argCount = 1 + args.size(); // implicit "this" parameter
size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize;
@@ -1514,7 +1550,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) {
ASSERT(node);
if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) {
- variableObject = static_cast<JSVariableObject*>(node->object.get());
+ variableObject = jsCast<JSVariableObject*>(node->object.get());
break;
}
}
@@ -1831,6 +1867,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
}
+ StructureChain* prototypeChain = structure->prototypeChain(callFrame);
switch (slot.cachedPropertyType()) {
case PropertySlot::Getter:
vPC[0] = getOpcode(op_get_by_id_getter_chain);
@@ -1846,7 +1883,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock*
break;
}
vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure);
- vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame));
+ vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain);
vPC[6] = count;
}
@@ -2352,7 +2389,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
int dst = vPC[1].u.operand;
JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
- if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
+ if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32());
else {
JSValue result = jsAdd(callFrame, src1, src2);
@@ -2371,7 +2408,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
int dst = vPC[1].u.operand;
JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
- if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow
+ if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32()) >> 15) // no overflow
callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32());
else {
JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame));
@@ -2439,7 +2476,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
int dst = vPC[1].u.operand;
JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue();
JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue();
- if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow
+ if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow
callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32());
else {
JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame));
@@ -2883,7 +2920,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
ASSERT_UNUSED(end, iter != end);
}
ASSERT((*iter)->isVariableObject());
- JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+ JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get());
callFrame->uncheckedR(dst) = scope->registerAt(index).get();
ASSERT(callFrame->r(dst).jsValue());
vPC += OPCODE_LENGTH(op_get_scoped_var);
@@ -2914,7 +2951,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi
}
ASSERT((*iter)->isVariableObject());
- JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get());
+ JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get());
ASSERT(callFrame->r(value).jsValue());
scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue());
vPC += OPCODE_LENGTH(op_put_scoped_var);
@@ -3738,8 +3775,6 @@ skip_id_custom_self:
result = jsArray->JSArray::get(callFrame, i);
} else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
result = asString(baseValue)->getIndex(callFrame, i);
- else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i))
- result = asByteArray(baseValue)->getIndex(callFrame, i);
else
result = baseValue.get(callFrame, i);
} else {
@@ -3778,15 +3813,6 @@ skip_id_custom_self:
jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue());
else
jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
- } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) {
- JSByteArray* jsByteArray = asByteArray(baseValue);
- JSValue jsValue = callFrame->r(value).jsValue();
- if (jsValue.isInt32())
- jsByteArray->setIndex(i, jsValue.asInt32());
- else if (jsValue.isDouble())
- jsByteArray->setIndex(i, jsValue.asDouble());
- else
- baseValue.putByIndex(callFrame, i, jsValue, codeBlock->isStrictMode());
} else
baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode());
} else {
@@ -4443,7 +4469,7 @@ skip_id_custom_self:
if (isHostFunction(funcVal, globalFuncEval)) {
CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
- newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scopeChain(), callFrame, argCount, asFunction(funcVal));
+ newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scopeChain(), callFrame, argCount, jsCast<JSFunction*>(funcVal));
JSValue result = eval(newCallFrame);
if ((exceptionValue = globalData->exception))
@@ -4496,7 +4522,7 @@ skip_id_custom_self:
goto vm_throw;
}
- callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+ callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v));
codeBlock = newCodeBlock;
ASSERT(codeBlock == callFrame->codeBlock());
*topCallFrameSlot = callFrame;
@@ -4574,7 +4600,7 @@ skip_id_custom_self:
goto vm_throw;
}
- newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, callFrame, argCount, asFunction(v));
+ newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, callFrame, argCount, jsCast<JSFunction*>(v));
codeBlock = newCodeBlock;
callFrame = newCallFrame;
ASSERT(codeBlock == callFrame->codeBlock());
@@ -4785,7 +4811,7 @@ skip_id_custom_self:
int thisRegister = vPC[1].u.operand;
int protoRegister = vPC[2].u.operand;
- JSFunction* constructor = asFunction(callFrame->callee());
+ JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee());
#if !ASSERT_DISABLED
ConstructData constructData;
ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS);
@@ -4895,7 +4921,7 @@ skip_id_custom_self:
goto vm_throw;
}
- callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v));
+ callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v));
codeBlock = newCodeBlock;
*topCallFrameSlot = callFrame;
vPC = newCodeBlock->instructions().begin();
@@ -5186,30 +5212,6 @@ skip_id_custom_self:
vPC++;
NEXT_INSTRUCTION();
}
- DEFINE_OPCODE(op_jsr) {
- /* jsr retAddrDst(r) target(offset)
-
- Places the address of the next instruction into the retAddrDst
- register and jumps to offset target from the current instruction.
- */
- int retAddrDst = vPC[1].u.operand;
- int target = vPC[2].u.operand;
- callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
-
- vPC += target;
- NEXT_INSTRUCTION();
- }
- DEFINE_OPCODE(op_sret) {
- /* sret retAddrSrc(r)
-
- Jumps to the address stored in the retAddrSrc register. This
- differs from op_jmp because the target address is stored in a
- register, not as an immediate.
- */
- int retAddrSrc = vPC[1].u.operand;
- vPC = callFrame->r(retAddrSrc).vPC();
- NEXT_INSTRUCTION();
- }
DEFINE_OPCODE(op_debug) {
/* debug debugHookID(n) firstLine(n) lastLine(n)