Commit 4674e190 authored by darin@apple.com's avatar darin@apple.com

JavaScriptCore:

2008-06-03  Darin Adler  <darin@apple.com>

        Reviewed by Geoff.

        - https://bugs.webkit.org/show_bug.cgi?id=19269
          speed up SunSpider by eliminating the toObject call for most get/put/delete

        Makes standalone SunSpider 1.025x as fast as before.

        The getOwnPropertySlot virtual function now takes care of the toObject call
        for get. Similarly, the put function (and later deleteProperty) does the
        same for those operations. To do this, the virtual functions were moved from
        the JSObject class to the JSCell class. Also, since the caller no longer knows
        the identity of the "original object", which is used by JavaScript-function
        based getters, changed the PropertySlot class so the original object is
        already stored in the slot when getOwnPropertySlot is called, if the caller
        intends to call getValue.

        This affected the old interpreter code enough that the easiest thing for me
        was to just delete it. While I am not certain the mysterious slowdown is not
        still occurring, the net change is definitely a significant speedup.

        * JavaScriptCore.exp: Updated.

        * VM/Machine.cpp: Moved the UNLIKELY macro into AlwaysInline.h.
        (KJS::resolve): Set up the originalObject in the PropertySlot before
        calling getPropertySlot. Also removed the originalObject argument from
        getValue.
        (KJS::resolve_skip): Ditto.
        (KJS::resolveBaseAndProperty): Ditto.
        (KJS::resolveBaseAndFunc): Ditto.
        (KJS::Machine::privateExecute): Removed the toObject calls from the get and
        put functions where possible, instead calling directly with JSValue and letting
        the JSValue and JSCell calls handle toObject. Same for toThisObject.

        * kjs/ExecState.h: Removed OldInterpreterExecState.

        * API/JSBase.cpp: Updated includes.

        * kjs/LocalStorageEntry.h: Removed contents. Later we can remove the file too.

        * kjs/array_instance.cpp:
        (KJS::ArrayInstance::lengthGetter): Removed originalObject argumet.
        (KJS::ArrayInstance::inlineGetOwnPropertySlot): Don't pass a base value to
        setValueSlot. Also use UNLIKELY around the "getting elements past the end of
        the array" code path; less common than successfully getting an element.

        * kjs/array_object.cpp:
        (KJS::getProperty): Initialize the PropertySlot with the original object.
        Don't pass the original object to the get function.
        (KJS::arrayProtoFuncFilter): Ditto.
        (KJS::arrayProtoFuncMap): Ditto.
        (KJS::arrayProtoFuncEvery): Ditto.
        (KJS::arrayProtoFuncForEach): Ditto.
        (KJS::arrayProtoFuncSome): Ditto.

        * kjs/function_object.cpp:
        (KJS::FunctionObjectImp::construct): Removed an obsolete comment.

        * kjs/grammar.y: Eliminated support for some of the node types that were
        used to optimize executing from the syntax tree.

        * kjs/internal.cpp:
        (KJS::StringImp::toThisObject): Added. Same as toObject.
        (KJS::NumberImp::toThisObject): Ditto.
        (KJS::GetterSetterImp::getOwnPropertySlot): Added. Not reached.
        (KJS::GetterSetterImp::put): Ditto.
        (KJS::GetterSetterImp::toThisObject): Ditto.

        * kjs/internal.h: Added toThisObject to NumberImp for speed.

        * kjs/lexer.cpp:
        (KJS::Lexer::shift): Changed shift to just do a single character, to unroll
        the loop and especially to make the one character case faster.
        (KJS::Lexer::setCode): Call shift multiple times instead of passing a number.
        (KJS::Lexer::lex): Ditto.
        (KJS::Lexer::matchPunctuator): Ditto. Also removed unneeded elses after returns.
        (KJS::Lexer::scanRegExp): Ditto.
        * kjs/lexer.h: Removed the count argument from shift.

        * kjs/math_object.cpp:
        (KJS::mathProtoFuncPow): Call jsNaN instead of jsNumber(NaN).

        * kjs/nodes.cpp: Removed some of the things needed only for the pre-SquirrelFish
        execution model.
        (KJS::ForNode::emitCode): Handle cases where some expressions are missing by
        not emitting any code at all. The old way was to emit code for "true", but
        this is an unnecessary remnant of the old way of doing things.

        * kjs/nodes.h: Removed some of the things needed only for the pre-SquirrelFish
        execution model.

        * kjs/object.cpp:
        (KJS::JSObject::fillGetterPropertySlot): Changed to only pass in the getter
        function. The old code passed in a base, but it was never used when
        actually getting the property; the toThisObject call was pointless. Also
        changed to not pass a base for setUndefined.

        * kjs/object.h: Added the new JSCell operations to GetterSetterImp.
        Never called.
        (KJS::JSObject::get): Initialize the object in the PropertySlot and don't
        pass it in getValue.
        (KJS::JSObject::getOwnPropertySlotForWrite): Removed the base argument
        in calls to setValueSlot.
        (KJS::JSObject::getOwnPropertySlot): Ditto.
        (KJS::JSValue::get): Added. Here because it calls through to JSObject.
        A version of JSObject::get that also handles the other types of JSValue
        by creating the appropriate wrapper. Saves the virtual call to toObject.
        (KJS::JSValue::put): Ditto.
        (KJS::JSValue::deleteProperty): Ditto.

        * kjs/property_slot.cpp:
        (KJS::PropertySlot::undefinedGetter): Removed the originalObject argument.
        (KJS::PropertySlot::ungettableGetter): Ditto.
        (KJS::PropertySlot::functionGetter): Ditto. Use the value in the base
        as the "this" object, which will be set to the original object by the new
        PropertySlot initialization code. Also call toThisObject. The old code did
        not do this, but needed to so we can properly handle the activation object
        like the other similar code paths.

        * kjs/property_slot.h:
        (KJS::PropertySlot::PropertySlot): Added a constructor that takes a base
        object. In debug builds, set the base to 0 if you don't pass one.
        (KJS::PropertySlot::getValue): Don't take or pass the originalObject.
        (KJS::PropertySlot::setValueSlot): Don't take a base object, and clear the
        base object in debug builds.
        (KJS::PropertySlot::setGetterSlot): Ditto.
        (KJS::PropertySlot::setUndefined): Ditto.
        (KJS::PropertySlot::setUngettable): Ditto.
        (KJS::PropertySlot::slotBase): Assert that a base object is present.
        This will fire if someone actually calls the get function without having
        passed in a base object and the getter needs it.
        (KJS::PropertySlot::setBase): Added. Used by the code that implements
        toObject so it can supply the original object after the fact.
        (KJS::PropertySlot::clearBase): Added. Clears the base, but is debug-only
        code because it's an error to fetch the base if you don't have a guarantee
        it was set.

        * API/JSCallbackObject.h:
        * API/JSCallbackObjectFunctions.h:
        (KJS::JSCallbackObject::cachedValueGetter):
        (KJS::JSCallbackObject::staticValueGetter):
        (KJS::JSCallbackObject::staticFunctionGetter):
        (KJS::JSCallbackObject::callbackGetter):
        * kjs/JSActivation.cpp:
        (KJS::JSActivation::getOwnPropertySlot):
        (KJS::JSActivation::argumentsGetter):
        * kjs/JSActivation.h:
        * kjs/JSVariableObject.h:
        (KJS::JSVariableObject::symbolTableGet):
        * kjs/array_instance.h:
        * kjs/function.cpp:
        (KJS::FunctionImp::argumentsGetter):
        (KJS::FunctionImp::callerGetter):
        (KJS::FunctionImp::lengthGetter):
        (KJS::Arguments::mappedIndexGetter):
        * kjs/function.h:
        * kjs/lookup.h:
        (KJS::staticFunctionGetter):
        (KJS::staticValueGetter):
        * kjs/string_object.cpp:
        (KJS::StringInstance::lengthGetter):
        (KJS::StringInstance::indexGetter):
        (KJS::stringInstanceNumericPropertyGetter):
        * kjs/string_object.h:
        Removed originalObject arguments from getters. Don't pass base values to
        the various PropertySlot functions that no longer take them.

        * kjs/value.cpp:
        (KJS::JSCell::getOwnPropertySlot): Added. Calls toObject and then sets the slot.
        This function has to always return true, because the caller can't walk the prototype
        chain. Because of that, we do a getPropertySlot, not getOwnPropertySlot, which works
        for the caller. This is private, only called by getOwnPropertySlotInternal.
        (KJS::JSCell::put): Added. Calls toObject and then put.
        (KJS::JSCell::toThisObject): Added. Calls toObject.

        * kjs/value.h: Added get, put, and toThisObject to both JSValue
        and JSCell. These take care of the toObject operation without an additional virtual
        function call, and so make the common "already an object" case faster.

        * wtf/AlwaysInline.h: Moved the UNLIKELY macro here for now. Maybe we can find a
        better place later, or rename this header.

JavaScriptGlue:

2008-06-03  Darin Adler  <darin@apple.com>

        - update for JavaScriptCore changes for https://bugs.webkit.org/show_bug.cgi?id=19269
          speed up SunSpider by eliminating the toObject call for most get/put/delete

        * UserObjectImp.cpp:
        (UserObjectImp::userObjectGetter): Removed originalObject argument.
        * UserObjectImp.h: Ditto.

WebCore:

2008-06-03  Justin Garcia  <justin.garcia@apple.com>

        Reviewed by John.

        <rdar://problem/5763082> GMail: Hang when removing indent from nested list
        <rdar://problem/5775449> In Gmail and GoogleDocs, a hang occurs when I attempt to apply a list style to a large selection of text
        <rdar://problem/5937624> 9D32: Hang in Safari. Using 100% of processor

        * editing/InsertListCommand.cpp:
        (WebCore::InsertListCommand::modifyRange): doApply() may operate on and remove 
        the last paragraph of the selection from the document if it's in the same list 
        item as startOfCurrentParagraph.  Return early to avoid an infinite loop and 
        because there is no more work to be done.  Added a FIXME (<rdar://problem/5983974>)
        about the incorrect endingSelection()s.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@34355 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent aed9c451
......@@ -78,10 +78,10 @@ public:
private:
void init(ExecState*);
static JSValue* cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
static JSValue* staticValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
static JSValue* staticFunctionGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot);
static JSValue* callbackGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
static JSValue* cachedValueGetter(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* staticValueGetter(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&);
static JSValue* callbackGetter(ExecState*, const Identifier&, const PropertySlot&);
void* m_privateData;
JSClassRef m_class;
......
......@@ -427,7 +427,7 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const
}
template <class Base>
JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, const Identifier&, const PropertySlot& slot)
{
JSValue* v = slot.slotBase();
ASSERT(v);
......@@ -435,7 +435,7 @@ JSValue* JSCallbackObject<Base>::cachedValueGetter(ExecState*, JSObject*, const
}
template <class Base>
JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
......@@ -456,15 +456,15 @@ JSValue* JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSObject*, c
}
template <class Base>
JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
// Check for cached or override property.
PropertySlot slot2;
PropertySlot slot2(thisObj);
if (thisObj->Base::getOwnPropertySlot(exec, propertyName, slot2))
return slot2.getValue(exec, thisObj, propertyName);
return slot2.getValue(exec, propertyName);
for (JSClassRef jsClass = thisObj->m_class; jsClass; jsClass = jsClass->parentClass) {
if (OpaqueJSClass::StaticFunctionsTable* staticFunctions = jsClass->staticFunctions) {
......@@ -482,7 +482,7 @@ JSValue* JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSObject*
}
template <class Base>
JSValue* JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
JSValue* JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)
{
ASSERT(slot.slotBase()->inherits(&JSCallbackObject::info));
JSCallbackObject* thisObj = static_cast<JSCallbackObject*>(slot.slotBase());
......
2008-06-03 Darin Adler <darin@apple.com>
Reviewed by Geoff.
- https://bugs.webkit.org/show_bug.cgi?id=19269
speed up SunSpider by eliminating the toObject call for most get/put/delete
Makes standalone SunSpider 1.025x as fast as before.
The getOwnPropertySlot virtual function now takes care of the toObject call
for get. Similarly, the put function (and later deleteProperty) does the
same for those operations. To do this, the virtual functions were moved from
the JSObject class to the JSCell class. Also, since the caller no longer knows
the identity of the "original object", which is used by JavaScript-function
based getters, changed the PropertySlot class so the original object is
already stored in the slot when getOwnPropertySlot is called, if the caller
intends to call getValue.
This affected the old interpreter code enough that the easiest thing for me
was to just delete it. While I am not certain the mysterious slowdown is not
still occurring, the net change is definitely a significant speedup.
* JavaScriptCore.exp: Updated.
* VM/Machine.cpp: Moved the UNLIKELY macro into AlwaysInline.h.
(KJS::resolve): Set up the originalObject in the PropertySlot before
calling getPropertySlot. Also removed the originalObject argument from
getValue.
(KJS::resolve_skip): Ditto.
(KJS::resolveBaseAndProperty): Ditto.
(KJS::resolveBaseAndFunc): Ditto.
(KJS::Machine::privateExecute): Removed the toObject calls from the get and
put functions where possible, instead calling directly with JSValue and letting
the JSValue and JSCell calls handle toObject. Same for toThisObject.
* kjs/ExecState.h: Removed OldInterpreterExecState.
* API/JSBase.cpp: Updated includes.
* kjs/LocalStorageEntry.h: Removed contents. Later we can remove the file too.
* kjs/array_instance.cpp:
(KJS::ArrayInstance::lengthGetter): Removed originalObject argumet.
(KJS::ArrayInstance::inlineGetOwnPropertySlot): Don't pass a base value to
setValueSlot. Also use UNLIKELY around the "getting elements past the end of
the array" code path; less common than successfully getting an element.
* kjs/array_object.cpp:
(KJS::getProperty): Initialize the PropertySlot with the original object.
Don't pass the original object to the get function.
(KJS::arrayProtoFuncFilter): Ditto.
(KJS::arrayProtoFuncMap): Ditto.
(KJS::arrayProtoFuncEvery): Ditto.
(KJS::arrayProtoFuncForEach): Ditto.
(KJS::arrayProtoFuncSome): Ditto.
* kjs/function_object.cpp:
(KJS::FunctionObjectImp::construct): Removed an obsolete comment.
* kjs/grammar.y: Eliminated support for some of the node types that were
used to optimize executing from the syntax tree.
* kjs/internal.cpp:
(KJS::StringImp::toThisObject): Added. Same as toObject.
(KJS::NumberImp::toThisObject): Ditto.
(KJS::GetterSetterImp::getOwnPropertySlot): Added. Not reached.
(KJS::GetterSetterImp::put): Ditto.
(KJS::GetterSetterImp::toThisObject): Ditto.
* kjs/internal.h: Added toThisObject to NumberImp for speed.
* kjs/lexer.cpp:
(KJS::Lexer::shift): Changed shift to just do a single character, to unroll
the loop and especially to make the one character case faster.
(KJS::Lexer::setCode): Call shift multiple times instead of passing a number.
(KJS::Lexer::lex): Ditto.
(KJS::Lexer::matchPunctuator): Ditto. Also removed unneeded elses after returns.
(KJS::Lexer::scanRegExp): Ditto.
* kjs/lexer.h: Removed the count argument from shift.
* kjs/math_object.cpp:
(KJS::mathProtoFuncPow): Call jsNaN instead of jsNumber(NaN).
* kjs/nodes.cpp: Removed some of the things needed only for the pre-SquirrelFish
execution model.
(KJS::ForNode::emitCode): Handle cases where some expressions are missing by
not emitting any code at all. The old way was to emit code for "true", but
this is an unnecessary remnant of the old way of doing things.
* kjs/nodes.h: Removed some of the things needed only for the pre-SquirrelFish
execution model.
* kjs/object.cpp:
(KJS::JSObject::fillGetterPropertySlot): Changed to only pass in the getter
function. The old code passed in a base, but it was never used when
actually getting the property; the toThisObject call was pointless. Also
changed to not pass a base for setUndefined.
* kjs/object.h: Added the new JSCell operations to GetterSetterImp.
Never called.
(KJS::JSObject::get): Initialize the object in the PropertySlot and don't
pass it in getValue.
(KJS::JSObject::getOwnPropertySlotForWrite): Removed the base argument
in calls to setValueSlot.
(KJS::JSObject::getOwnPropertySlot): Ditto.
(KJS::JSValue::get): Added. Here because it calls through to JSObject.
A version of JSObject::get that also handles the other types of JSValue
by creating the appropriate wrapper. Saves the virtual call to toObject.
(KJS::JSValue::put): Ditto.
(KJS::JSValue::deleteProperty): Ditto.
* kjs/property_slot.cpp:
(KJS::PropertySlot::undefinedGetter): Removed the originalObject argument.
(KJS::PropertySlot::ungettableGetter): Ditto.
(KJS::PropertySlot::functionGetter): Ditto. Use the value in the base
as the "this" object, which will be set to the original object by the new
PropertySlot initialization code. Also call toThisObject. The old code did
not do this, but needed to so we can properly handle the activation object
like the other similar code paths.
* kjs/property_slot.h:
(KJS::PropertySlot::PropertySlot): Added a constructor that takes a base
object. In debug builds, set the base to 0 if you don't pass one.
(KJS::PropertySlot::getValue): Don't take or pass the originalObject.
(KJS::PropertySlot::setValueSlot): Don't take a base object, and clear the
base object in debug builds.
(KJS::PropertySlot::setGetterSlot): Ditto.
(KJS::PropertySlot::setUndefined): Ditto.
(KJS::PropertySlot::setUngettable): Ditto.
(KJS::PropertySlot::slotBase): Assert that a base object is present.
This will fire if someone actually calls the get function without having
passed in a base object and the getter needs it.
(KJS::PropertySlot::setBase): Added. Used by the code that implements
toObject so it can supply the original object after the fact.
(KJS::PropertySlot::clearBase): Added. Clears the base, but is debug-only
code because it's an error to fetch the base if you don't have a guarantee
it was set.
* API/JSCallbackObject.h:
* API/JSCallbackObjectFunctions.h:
(KJS::JSCallbackObject::cachedValueGetter):
(KJS::JSCallbackObject::staticValueGetter):
(KJS::JSCallbackObject::staticFunctionGetter):
(KJS::JSCallbackObject::callbackGetter):
* kjs/JSActivation.cpp:
(KJS::JSActivation::getOwnPropertySlot):
(KJS::JSActivation::argumentsGetter):
* kjs/JSActivation.h:
* kjs/JSVariableObject.h:
(KJS::JSVariableObject::symbolTableGet):
* kjs/array_instance.h:
* kjs/function.cpp:
(KJS::FunctionImp::argumentsGetter):
(KJS::FunctionImp::callerGetter):
(KJS::FunctionImp::lengthGetter):
(KJS::Arguments::mappedIndexGetter):
* kjs/function.h:
* kjs/lookup.h:
(KJS::staticFunctionGetter):
(KJS::staticValueGetter):
* kjs/string_object.cpp:
(KJS::StringInstance::lengthGetter):
(KJS::StringInstance::indexGetter):
(KJS::stringInstanceNumericPropertyGetter):
* kjs/string_object.h:
Removed originalObject arguments from getters. Don't pass base values to
the various PropertySlot functions that no longer take them.
* kjs/value.cpp:
(KJS::JSCell::getOwnPropertySlot): Added. Calls toObject and then sets the slot.
This function has to always return true, because the caller can't walk the prototype
chain. Because of that, we do a getPropertySlot, not getOwnPropertySlot, which works
for the caller. This is private, only called by getOwnPropertySlotInternal.
(KJS::JSCell::put): Added. Calls toObject and then put.
(KJS::JSCell::toThisObject): Added. Calls toObject.
* kjs/value.h: Added get, put, and toThisObject to both JSValue
and JSCell. These take care of the toObject operation without an additional virtual
function call, and so make the common "already an object" case faster.
* wtf/AlwaysInline.h: Moved the UNLIKELY macro here for now. Maybe we can find a
better place later, or rename this header.
2008-06-03 Oliver Hunt <oliver@apple.com>
Reviewed by Tim.
......
......@@ -108,7 +108,7 @@ __ZN3KJS11PropertyMap3putERKNS_10IdentifierEPNS_7JSValueEjb
__ZN3KJS11PropertyMap5clearEv
__ZN3KJS11PropertyMapD1Ev
__ZN3KJS12DateInstance4infoE
__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateEPNS_8JSObjectERKNS_10IdentifierERKS0_
__ZN3KJS12PropertySlot15undefinedGetterEPNS_9ExecStateERKNS_10IdentifierERKS0_
__ZN3KJS12RegisterFile14addGlobalSlotsEm
__ZN3KJS13ArrayInstance4infoE
__ZN3KJS13CodeGenerator21setDumpsGeneratedCodeEb
......@@ -151,6 +151,10 @@ __ZN3KJS4List15expandAndAppendEPNS_7JSValueE
__ZN3KJS4List7markSetEv
__ZN3KJS6JSCell11getCallDataERNS_8CallDataE
__ZN3KJS6JSCell16getConstructDataERNS_13ConstructDataE
__ZN3KJS6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
__ZN3KJS6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
__ZN3KJS6JSCell3putEPNS_9ExecStateERKNS_10IdentifierEPNS_7JSValueE
__ZN3KJS6JSCell3putEPNS_9ExecStateEjPNS_7JSValueE
__ZN3KJS6JSCell9getObjectEv
__ZN3KJS6JSCellnwEm
__ZN3KJS6JSLock12DropAllLocksC1Ev
......@@ -261,6 +265,7 @@ __ZNK3KJS17DebuggerCallFrame8evaluateERKNS_7UStringERPNS_7JSValueE
__ZNK3KJS19InternalFunctionImp21implementsHasInstanceEv
__ZNK3KJS4List8getSliceEiRS0_
__ZNK3KJS4Node8toStringEv
__ZNK3KJS6JSCell12toThisObjectEPNS_9ExecStateE
__ZNK3KJS6JSCell17getTruncatedInt32ERi
__ZNK3KJS6JSCell18getTruncatedUInt32ERj
__ZNK3KJS6JSCell9getNumberERd
......
......@@ -49,13 +49,6 @@
#include "operations.h"
#include "regexp_object.h"
#if COMPILER(GCC)
#define UNLIKELY(x) \
__builtin_expect ((x), 0)
#else
#define UNLIKELY(x) x
#endif
namespace KJS {
#if HAVE(COMPUTED_GOTO)
......@@ -209,12 +202,12 @@ static bool NEVER_INLINE resolve(ExecState* exec, Instruction* vPC, Register* r,
ScopeChainIterator end = scopeChain->end();
ASSERT(iter != end);
PropertySlot slot;
Identifier& ident = codeBlock->identifiers[property];
do {
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(exec, ident, slot)) {
JSValue* result = slot.getValue(exec, o, ident);
JSValue* result = slot.getValue(exec, ident);
exceptionValue = exec->exception();
if (exceptionValue)
return false;
......@@ -239,12 +232,12 @@ static bool NEVER_INLINE resolve_skip(ExecState* exec, Instruction* vPC, Registe
++iter;
ASSERT(iter != end);
}
PropertySlot slot;
Identifier& ident = codeBlock->identifiers[property];
do {
JSObject* o = *iter;
PropertySlot slot(o);
if (o->getPropertySlot(exec, ident, slot)) {
JSValue* result = slot.getValue(exec, o, ident);
JSValue* result = slot.getValue(exec, ident);
exceptionValue = exec->exception();
if (exceptionValue)
return false;
......@@ -294,13 +287,13 @@ static bool NEVER_INLINE resolveBaseAndProperty(ExecState* exec, Instruction* vP
ASSERT(iter != end);
PropertySlot slot;
Identifier& ident = codeBlock->identifiers[property];
JSObject* base;
do {
base = *iter;
PropertySlot slot(base);
if (base->getPropertySlot(exec, ident, slot)) {
JSValue* result = slot.getValue(exec, base, ident);
JSValue* result = slot.getValue(exec, ident);
exceptionValue = exec->exception();
if (exceptionValue)
return false;
......@@ -328,11 +321,11 @@ static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, R
ASSERT(iter != end);
PropertySlot slot;
Identifier& ident = codeBlock->identifiers[property];
JSObject* base;
do {
base = *iter;
PropertySlot slot(base);
if (base->getPropertySlot(exec, ident, slot)) {
// ECMA 11.2.3 says that if we hit an activation the this value should be null.
// However, section 10.2.3 says that in the case where the value provided
......@@ -342,7 +335,7 @@ static bool NEVER_INLINE resolveBaseAndFunc(ExecState* exec, Instruction* vPC, R
// that in host objects you always get a valid object for this.
// We also handle wrapper substitution for the global object at the same time.
JSObject* thisObj = base->toThisObject(exec);
JSValue* result = slot.getValue(exec, base, ident);
JSValue* result = slot.getValue(exec, ident);
exceptionValue = exec->exception();
if (exceptionValue)
return false;
......@@ -1684,10 +1677,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
#ifndef NDEBUG
int registerOffset = r - (*registerBase);
#endif
JSObject* baseObj = r[base].u.jsValue->toObject(exec);
Identifier& ident = codeBlock->identifiers[property];
JSValue *result = baseObj->get(exec, ident);
JSValue *result = r[base].u.jsValue->get(exec, ident);
ASSERT(registerOffset == (r - (*registerBase)));
VM_CHECK_EXCEPTION();
r[dst].u.jsValue = result;
......@@ -1709,11 +1701,9 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
#ifndef NDEBUG
int registerOffset = r - (*registerBase);
#endif
JSObject* baseObj = r[base].u.jsValue->toObject(exec);
Identifier& ident = codeBlock->identifiers[property];
baseObj->put(exec, ident, r[value].u.jsValue);
r[base].u.jsValue->put(exec, ident, r[value].u.jsValue);
ASSERT(registerOffset == (r - (*registerBase)));
VM_CHECK_EXCEPTION();
......@@ -1753,14 +1743,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
int base = (++vPC)->u.operand;
int property = (++vPC)->u.operand;
JSObject* baseObj = r[base].u.jsValue->toObject(exec); // may throw
JSValue* baseValue = r[base].u.jsValue;
JSValue* subscript = r[property].u.jsValue;
JSValue* result;
uint32_t i;
if (subscript->getUInt32(i))
result = baseObj->get(exec, i);
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
......@@ -1792,14 +1784,16 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
int property = (++vPC)->u.operand;
int value = (++vPC)->u.operand;
JSObject* baseObj = r[base].u.jsValue->toObject(exec);
JSValue* baseValue = r[base].u.jsValue;
JSValue* subscript = r[property].u.jsValue;
uint32_t i;
if (subscript->getUInt32(i))
baseObj->put(exec, i, r[value].u.jsValue);
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
......@@ -1989,7 +1983,7 @@ JSValue* Machine::privateExecute(ExecutionFlag flag, ExecState* exec, RegisterFi
// this instruction as a normal function call, supplying the proper 'this'
// value.
vPC -= 5;
r[thisVal].u.jsValue = baseVal->toObject(exec)->toThisObject(exec);
r[thisVal].u.jsValue = baseVal->toThisObject(exec);
#if HAVE(COMPUTED_GOTO)
// Hack around gcc performance quirk by performing an indirect goto
......
......@@ -104,8 +104,8 @@ namespace KJS {
static const HashTable* stringTable(ExecState* exec) { return exec->m_perThreadData->stringTable; }
private:
// Default constructor required for OldInterpreterExecState with gcc 3.
ExecState() {};
// Default constructor required for gcc 3.
ExecState() { }
ExecState(ExecState*, Machine*, RegisterFile*, ScopeChainNode*, int callFrameOffset);
......@@ -126,109 +126,7 @@ namespace KJS {
int m_callFrameOffset; // A negative offset indicates a non-function scope.
};
// This code is now defunct:
enum CodeType { GlobalCode, EvalCode, FunctionCode };
class OldInterpreterExecState : public ExecState {
public:
void pushSwitch() { m_switchDepth++; }
void popSwitch() { m_switchDepth--; }
bool inSwitch() const { return (m_switchDepth > 0); }
// These are only valid right after calling execute().
ComplType completionType() const { return m_completionType; }
const Identifier& breakOrContinueTarget() const
{
ASSERT(m_completionType == Break || m_completionType == Continue);
return *m_breakOrContinueTarget;
}
// Only for use in the implementation of execute().
void setCompletionType(ComplType type)
{
ASSERT(type != Break);
ASSERT(type != Continue);
m_completionType = type;
}
JSValue* setNormalCompletion()
{
ASSERT(!hadException());
m_completionType = Normal;
return 0;
}
JSValue* setNormalCompletion(JSValue* value)
{
ASSERT(!hadException());
m_completionType = Normal;
return value;
}
JSValue* setBreakCompletion(const Identifier* target)
{
ASSERT(!hadException());
m_completionType = Break;
m_breakOrContinueTarget = target;
return 0;
}
JSValue* setContinueCompletion(const Identifier* target)
{
ASSERT(!hadException());
m_completionType = Continue;
m_breakOrContinueTarget = target;
return 0;
}
JSValue* setReturnValueCompletion(JSValue* returnValue)
{
ASSERT(!hadException());
ASSERT(returnValue);
m_completionType = ReturnValue;
return returnValue;
}
JSValue* setThrowCompletion(JSValue* exception)
{
ASSERT(!hadException());
ASSERT(exception);
m_completionType = Throw;
return exception;
}
JSValue* setInterruptedCompletion()
{
ASSERT(!hadException());
m_completionType = Interrupted;
return 0;
}
CodeType codeType() { return m_codeType; }
void pushIteration() { m_iterationDepth++; }
void popIteration() { m_iterationDepth--; }
bool inIteration() const { return (m_iterationDepth > 0); }
LabelStack& seenLabels() { return m_labelStack; }
void pushScope(JSObject* s) { m_scopeChain.push(s); }
void popScope() { m_scopeChain.pop(); }
JSVariableObject* variableObject() const { ASSERT_NOT_REACHED(); return m_variableObject; }
void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
ExecState* callingExecState() { return m_callingExec; }
ScopeNode* scopeNode() { return m_scopeNode; }
const List* arguments() const { return m_arguments; }
FunctionImp* function() const { return m_function; }
LocalStorage& localStorage() { ASSERT_NOT_REACHED(); return *(LocalStorage*)0; }
void setLocalStorage(LocalStorage*) { ASSERT_NOT_REACHED(); }
ScopeChain& scopeChain() { return m_scopeChain; }
JSObject* thisValue() const { return m_thisValue; }
ComplType m_completionType;
const Identifier* m_breakOrContinueTarget;
int m_switchDepth;
CodeType m_codeType;
int m_iterationDepth;
LabelStack m_labelStack;
ScopeChainNode m_inlineScopeChainNode;
ScopeChain m_scopeChain;
JSVariableObject* m_variableObject;
ScopeNode* m_scopeNode;
const List* m_arguments;
FunctionImp* m_function;
ExecState* m_callingExec;
JSObject* m_thisValue;
};
} // namespace KJS
......
......@@ -74,7 +74,7 @@ bool JSActivation::getOwnPropertySlot(ExecState* exec, const Identifier& propert
return true;
if (JSValue** location = getDirectLocation(propertyName)) {
slot.setValueSlot(this, location);
slot.setValueSlot(location);
return true;
}
......@@ -160,7 +160,7 @@ bool JSActivation::isDynamicScope() const
return d()->functionBody->usesEval();
}
JSValue* JSActivation::argumentsGetter(ExecState* exec, JSObject*, const Identifier&, const PropertySlot& slot)
JSValue* JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
{
JSActivation* thisObj = static_cast<JSActivation*>(slot.slotBase());
if (!thisObj->d()->argumentsObject)
......
......@@ -76,7 +76,7 @@ namespace KJS {
JSObject* argumentsObject;
};
static JSValue* argumentsGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
static JSValue* argumentsGetter(ExecState*, const Identifier&, const PropertySlot&);
NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
NEVER_INLINE JSObject* createArgumentsObject(ExecState*);
......
......@@ -100,7 +100,7 @@ namespace KJS {
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
if (!entry.isEmpty()) {
slot.setValueSlot(this, &valueAt(entry.getIndex()));
slot.setValueSlot(&valueAt(entry.getIndex()));
return true;
}
return false;
......@@ -110,7 +110,7 @@ namespace KJS {
{
SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
if (!entry.isEmpty()) {
slot.setValueSlot(this, &valueAt(entry.getIndex()));
slot.setValueSlot(&valueAt(entry.getIndex()));
slotIsWriteable = !entry.isReadOnly();
return true;
}
......
......@@ -130,7 +130,7 @@ JSValue* ArrayInstance::getItem(unsigned i) const
return value ? value : jsUndefined();
}
JSValue* ArrayInstance::lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)
JSValue* ArrayInstance::lengthGetter(ExecState*, const Identifier&, const PropertySlot& slot)
{
return jsNumber(static_cast<ArrayInstance*>(slot.slotBase())->m_length);
}
......@@ -139,7 +139,7 @@ ALWAYS_INLINE bool ArrayInstance::inlineGetOwnPropertySlot(ExecState* exec, unsi
{
ArrayStorage* storage = m_storage;
if (i >= m_length) {
if (UNLIKELY(i >= m_length)) {
if (i > maxArrayIndex)
return getOwnPropertySlot(exec, Identifier::from(i), slot);
return false;
......@@ -148,14 +148,14 @@ ALWAYS_INLINE bool ArrayInstance::inlineGetOwnPropertySlot(ExecState* exec, unsi
if (i < m_vectorLength) {
JSValue*& valueSlot = storage->m_vector[i];
if (valueSlot) {
slot.setValueSlot(this, &valueSlot);
slot.setValueSlot(&valueSlot);
return true;
}
} else if (SparseArrayValueMap* map = storage->m_sparseValueMap) {
if (i >= sparseArrayCutoff) {
SparseArrayValueMap::iterator it = map->find(i);
if (it != map->end()) {
slot.setValueSlot(this, &it->second);
slot.setValueSlot(&it->second);
return true;
}
}
......
......@@ -58,7 +58,7 @@ namespace KJS {
void setLazyCreationData(void*);
private:
static JSValue* lengthGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
static JSValue* lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
bool inlineGetOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
void setLength(unsigned);
......
......@@ -82,10 +82,10 @@ bool ArrayPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& prope