Commit 7c11a048 authored by ggaren@apple.com's avatar ggaren@apple.com

2008-07-01 Geoffrey Garen <ggaren@apple.com>

        Reviewed by Oliver Hunt.
        
        Removed and/or reordered exception checks in array-style a[n] access.
        
        SunSpider says 1.4% faster.

        * VM/Machine.cpp:
        (KJS::Machine::privateExecute): No need to check for exceptions before
        calling toString, toNumber and/or get. If the call ends up being observable
        through toString, valueOf, or a getter, we short-circuit it there, instead.
        In the op_del_by_val case, I removed the incorrect comment without actually
        removing the code, since I didn't want to tempt the GCC fates!

        * kjs/JSObject.cpp:
        (KJS::callDefaultValueFunction): Added exception check to prevent
        toString and valueOf functions from observing execution after an exception
        has been thrown. This removes some of the burden of exception checking
        from the machine.

        (KJS::JSObject::defaultValue): Removed redundant exception check here.

        * kjs/PropertySlot.cpp:
        (KJS::PropertySlot::functionGetter): Added exception check to prevent
        getter functions from observing execution after an exception has been
        thrown. This removes some of the burden of exception checking from the
        machine.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@34945 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 095b136f
2008-07-01 Geoffrey Garen <ggaren@apple.com>
Reviewed by Oliver Hunt.
Removed and/or reordered exception checks in array-style a[n] access.
SunSpider says 1.4% faster.
* VM/Machine.cpp:
(KJS::Machine::privateExecute): No need to check for exceptions before
calling toString, toNumber and/or get. If the call ends up being observable
through toString, valueOf, or a getter, we short-circuit it there, instead.
In the op_del_by_val case, I removed the incorrect comment without actually
removing the code, since I didn't want to tempt the GCC fates!
* kjs/JSObject.cpp:
(KJS::callDefaultValueFunction): Added exception check to prevent
toString and valueOf functions from observing execution after an exception
has been thrown. This removes some of the burden of exception checking
from the machine.
(KJS::JSObject::defaultValue): Removed redundant exception check here.
* kjs/PropertySlot.cpp:
(KJS::PropertySlot::functionGetter): Added exception check to prevent
getter functions from observing execution after an exception has been
thrown. This removes some of the burden of exception checking from the
machine.
2008-07-01 Geoffrey Garen <ggaren@apple.com>
Reviewed by Oliver Hunt.
......@@ -1838,17 +1838,8 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
if (LIKELY(isUInt32))
result = baseValue->get(exec, i);
else {
JSObject* baseObj = baseValue->toObject(exec); // may throw
Identifier property;
if (subscript->isObject()) {
VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
property = Identifier(exec, subscript->toString(exec));
} else
property = Identifier(exec, subscript->toString(exec));
VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a getter after an exception is thrown
result = baseObj->get(exec, property);
Identifier property(exec, subscript->toString(exec));
result = baseValue->get(exec, property);
}
VM_CHECK_EXCEPTION();
......@@ -1880,17 +1871,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
if (LIKELY(isUInt32))
baseValue->put(exec, i, r[value].u.jsValue);
else {
JSObject* baseObj = baseValue->toObject(exec);
Identifier property;
if (subscript->isObject()) {
VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
property = Identifier(exec, subscript->toString(exec));
} else
property = Identifier(exec, subscript->toString(exec));
VM_CHECK_EXCEPTION(); // This check is needed to prevent us from incorrectly calling a setter after an exception is thrown
baseObj->put(exec, property, r[value].u.jsValue);
Identifier property(exec, subscript->toString(exec));
if (!exec->hadException()) // Don't put to an object if toString threw an exception.
baseValue->put(exec, property, r[value].u.jsValue);
}
VM_CHECK_EXCEPTION();
......@@ -1917,7 +1900,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
if (subscript->getUInt32(i))
result = jsBoolean(baseObj->deleteProperty(exec, i));
else {
VM_CHECK_EXCEPTION(); // If toObject threw, we must not call toString, which may execute arbitrary code
VM_CHECK_EXCEPTION();
Identifier property(exec, subscript->toString(exec));
VM_CHECK_EXCEPTION();
result = jsBoolean(baseObj->deleteProperty(exec, property));
......
......@@ -226,7 +226,13 @@ static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JS
CallData callData;
CallType callType = function->getCallData(callData);
if (callType == CallTypeNone)
return 0;
return exec->exception();
// Prevent "toString" and "valueOf" from observing execution if an exception
// is pending.
if (exec->hadException())
return exec->exception();
JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
ASSERT(result->type() != GetterSetterType);
if (exec->hadException())
......@@ -246,12 +252,6 @@ bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& res
// ECMA 8.6.2.6
JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
{
// We need this check to guard against the case where this object is rhs of
// a binary expression where lhs threw an exception in its conversion to
// primitive.
if (exec->hadException())
return exec->exception();
// Must call toString first for Date objects.
if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
......
......@@ -36,6 +36,10 @@ JSValue* PropertySlot::undefinedGetter(ExecState*, const Identifier&, const Prop
JSValue* PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
// Prevent getter functions from observing execution if an exception is pending.
if (exec->hadException())
return exec->exception();
CallData callData;
CallType callType = slot.m_data.getterFunc->getCallData(callData);
if (callType == CallTypeNative)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment