diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/JavaScriptCore/interpreter/Interpreter.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-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.cpp | 116 |
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) |