Reviewed by Sam Weinig.
- optimize op_jtrue, op_loop_if_true and op_not in various ways
https://bugs.webkit.org/show_bug.cgi?id=21404
1) Make JSValue::toBoolean nonvirtual and completely inline by
making use of the StructureID type field.
2) Make JSValue::toBoolean not take an ExecState; doesn't need it.
3) Make op_not, op_loop_if_true and op_jtrue not read the
ExecState (toBoolean doesn't need it any more) and not check
exceptions (toBoolean can't throw).
* API/JSValueRef.cpp:
(JSValueToBoolean):
* JavaScriptCore.exp:
* VM/CodeBlock.cpp:
(JSC::CodeBlock::dump):
* VM/Machine.cpp:
(JSC::Machine::privateExecute):
(JSC::Machine::cti_op_loop_if_true):
(JSC::Machine::cti_op_not):
(JSC::Machine::cti_op_jtrue):
* kjs/ArrayPrototype.cpp:
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncSome):
* kjs/BooleanConstructor.cpp:
(JSC::constructBoolean):
(JSC::callBooleanConstructor):
* kjs/GetterSetter.h:
* kjs/JSCell.h:
(JSC::JSValue::toBoolean):
* kjs/JSNumberCell.cpp:
* kjs/JSNumberCell.h:
(JSC::JSNumberCell::toBoolean):
* kjs/JSObject.cpp:
* kjs/JSObject.h:
(JSC::JSObject::toBoolean):
(JSC::JSCell::toBoolean):
* kjs/JSString.cpp:
* kjs/JSString.h:
(JSC::JSString::toBoolean):
* kjs/JSValue.h:
* kjs/RegExpConstructor.cpp:
(JSC::setRegExpConstructorMultiline):
* kjs/RegExpObject.cpp:
(JSC::RegExpObject::match):
* kjs/RegExpPrototype.cpp:
(JSC::regExpProtoFuncToString):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@37333
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
return toRef(jsString(exec, string->ustring()));
}
-bool JSValueToBoolean(JSContextRef ctx, JSValueRef value)
+bool JSValueToBoolean(JSContextRef, JSValueRef value)
{
- ExecState* exec = toJS(ctx);
- JSValue* jsValue = toJS(value);
- return jsValue->toBoolean(exec);
+ return toJS(value)->toBoolean();
}
double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception)
+2008-10-06 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ - optimize op_jtrue, op_loop_if_true and op_not in various ways
+ https://bugs.webkit.org/show_bug.cgi?id=21404
+
+ 1) Make JSValue::toBoolean nonvirtual and completely inline by
+ making use of the StructureID type field.
+
+ 2) Make JSValue::toBoolean not take an ExecState; doesn't need it.
+
+ 3) Make op_not, op_loop_if_true and op_jtrue not read the
+ ExecState (toBoolean doesn't need it any more) and not check
+ exceptions (toBoolean can't throw).
+
+ * API/JSValueRef.cpp:
+ (JSValueToBoolean):
+ * JavaScriptCore.exp:
+ * VM/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * VM/Machine.cpp:
+ (JSC::Machine::privateExecute):
+ (JSC::Machine::cti_op_loop_if_true):
+ (JSC::Machine::cti_op_not):
+ (JSC::Machine::cti_op_jtrue):
+ * kjs/ArrayPrototype.cpp:
+ (JSC::arrayProtoFuncFilter):
+ (JSC::arrayProtoFuncEvery):
+ (JSC::arrayProtoFuncSome):
+ * kjs/BooleanConstructor.cpp:
+ (JSC::constructBoolean):
+ (JSC::callBooleanConstructor):
+ * kjs/GetterSetter.h:
+ * kjs/JSCell.h:
+ (JSC::JSValue::toBoolean):
+ * kjs/JSNumberCell.cpp:
+ * kjs/JSNumberCell.h:
+ (JSC::JSNumberCell::toBoolean):
+ * kjs/JSObject.cpp:
+ * kjs/JSObject.h:
+ (JSC::JSObject::toBoolean):
+ (JSC::JSCell::toBoolean):
+ * kjs/JSString.cpp:
+ * kjs/JSString.h:
+ (JSC::JSString::toBoolean):
+ * kjs/JSValue.h:
+ * kjs/RegExpConstructor.cpp:
+ (JSC::setRegExpConstructorMultiline):
+ * kjs/RegExpObject.cpp:
+ (JSC::RegExpObject::match):
+ * kjs/RegExpPrototype.cpp:
+ (JSC::regExpProtoFuncToString):
+
2008-10-06 Ariya Hidayat <ariya.hidayat@trolltech.com>
Reviewed by Simon.
__ZNK3JSC8JSObject8toObjectEPNS_9ExecStateE
__ZNK3JSC8JSObject8toStringEPNS_9ExecStateE
__ZNK3JSC8JSObject9classNameEv
-__ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE
__ZNK3JSC9CodeBlock17derefStructureIDsEPNS_11InstructionE
__ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE
__ZNK3WTF8Collator7collateEPKtmS2_m
break;
}
case op_tear_off_activation: {
- int r0 = (++it)->u.operand;
- printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
+ printf("[%4d] tear_off_activation\n", location);
break;
}
case op_tear_off_arguments: {
- int r0 = (++it)->u.operand;
- printf("[%4d] tear_off_arguments\t %s\n", location, registerName(r0).c_str());
+ printf("[%4d] tear_off_arguments\n", location);
break;
}
case op_ret: {
*/
int dst = (++vPC)->u.operand;
int src = (++vPC)->u.operand;
- JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean(exec));
- VM_CHECK_EXCEPTION();
+ JSValue* result = jsBoolean(!r[src].jsValue(exec)->toBoolean());
r[dst] = result;
++vPC;
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (r[cond].jsValue(exec)->toBoolean(exec)) {
+ if (r[cond].jsValue(exec)->toBoolean()) {
vPC += target;
CHECK_FOR_TIMEOUT();
NEXT_OPCODE;
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (r[cond].jsValue(exec)->toBoolean(exec)) {
+ if (r[cond].jsValue(exec)->toBoolean()) {
vPC += target;
NEXT_OPCODE;
}
*/
int cond = (++vPC)->u.operand;
int target = (++vPC)->u.operand;
- if (!r[cond].jsValue(exec)->toBoolean(exec)) {
+ if (!r[cond].jsValue(exec)->toBoolean()) {
vPC += target;
NEXT_OPCODE;
}
{
JSValue* src1 = ARG_src1;
- ExecState* exec = ARG_exec;
-
- bool result = src1->toBoolean(exec);
- VM_CHECK_EXCEPTION_AT_END();
- return result;
+ return src1->toBoolean();
}
JSValue* Machine::cti_op_negate(CTI_ARGS)
JSValue* Machine::cti_op_not(CTI_ARGS)
{
- JSValue* src = ARG_src1;
-
- ExecState* exec = ARG_exec;
-
- JSValue* result = jsBoolean(!src->toBoolean(exec));
- VM_CHECK_EXCEPTION_AT_END();
- return result;
+ return jsBoolean(!ARG_src1->toBoolean());
}
int SFX_CALL Machine::cti_op_jtrue(CTI_ARGS)
{
- JSValue* src1 = ARG_src1;
-
- ExecState* exec = ARG_exec;
-
- bool result = src1->toBoolean(exec);
- VM_CHECK_EXCEPTION_AT_END();
- return result;
+ return ARG_src1->toBoolean();
}
JSValue* Machine::cti_op_post_inc(CTI_ARGS)
JSValue* result = call(exec, function, callType, callData, applyThis, eachArguments);
- if (result->toBoolean(exec))
+ if (result->toBoolean())
resultArray->put(exec, filterIndex++, v);
}
return resultArray;
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
- bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean();
if (!predicateResult) {
result = jsBoolean(false);
eachArguments.append(jsNumber(exec, k));
eachArguments.append(thisObj);
- bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean(exec);
+ bool predicateResult = call(exec, function, callType, callData, applyThis, eachArguments)->toBoolean();
if (predicateResult) {
result = jsBoolean(true);
JSObject* constructBoolean(ExecState* exec, const ArgList& args)
{
BooleanObject* obj = new (exec) BooleanObject(exec->lexicalGlobalObject()->booleanObjectStructure());
- obj->setInternalValue(jsBoolean(args.at(exec, 0)->toBoolean(exec)));
+ obj->setInternalValue(jsBoolean(args.at(exec, 0)->toBoolean()));
return obj;
}
// ECMA 15.6.1
static JSValue* callBooleanConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
{
- return jsBoolean(args.at(exec, 0)->toBoolean(exec));
+ return jsBoolean(args.at(exec, 0)->toBoolean());
}
CallType BooleanConstructor::getCallData(CallData& callData)
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState*) const;
+ bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
// Basic conversions.
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const = 0;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*&) = 0;
- virtual bool toBoolean(ExecState*) const = 0;
+ bool toBoolean() const;
virtual double toNumber(ExecState*) const = 0;
virtual UString toString(ExecState*) const = 0;
virtual JSObject* toObject(ExecState*) const = 0;
return asCell()->getPrimitiveNumber(exec, number, value);
}
- inline bool JSValue::toBoolean(ExecState* exec) const
+ inline bool JSValue::toBoolean() const
{
- return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean(exec);
+ return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : asCell()->toBoolean();
}
ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
return true;
}
-bool JSNumberCell::toBoolean(ExecState*) const
-{
- return m_value < 0.0 || m_value > 0.0; // false for NaN
-}
-
double JSNumberCell::toNumber(ExecState*) const
{
return m_value;
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState*) const;
+ bool toBoolean() const { return m_value < 0.0 || m_value > 0.0; /* false for NaN */ }
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
m_structureID->getEnumerablePropertyNames(exec, propertyNames, this);
}
-bool JSObject::toBoolean(ExecState*) const
-{
- return true;
-}
-
double JSObject::toNumber(ExecState* exec) const
{
JSValue* primitive = toPrimitive(exec, PreferNumber);
#include "CommonIdentifiers.h"
#include "ExecState.h"
#include "JSNumberCell.h"
+#include "JSString.h"
#include "PropertyMap.h"
#include "PropertySlot.h"
#include "PutPropertySlot.h"
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState*) const;
+ bool toBoolean() const { return true; }
virtual double toNumber(ExecState*) const;
virtual UString toString(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
return false;
}
+inline bool JSCell::toBoolean() const
+{
+ JSType type = structureID()->typeInfo().type();
+ if (type == NumberType)
+ return static_cast<const JSNumberCell*>(this)->toBoolean();
+ if (type == ObjectType)
+ return static_cast<const JSObject*>(this)->toBoolean();
+ ASSERT(type == StringType);
+ return static_cast<const JSString*>(this)->toBoolean();
+}
+
// this method is here to be after the inline declaration of JSCell::isObject
inline bool JSValue::isObject(const ClassInfo* classInfo) const
{
return false;
}
-bool JSString::toBoolean(ExecState*) const
-{
- return !m_value.isEmpty();
-}
-
double JSString::toNumber(ExecState*) const
{
return m_value.toDouble();
static PassRefPtr<StructureID> createStructureID(JSValue* proto) { return StructureID::create(proto, TypeInfo(StringType, NeedsThisConversion)); }
+ bool toBoolean() const { return !m_value.isEmpty(); }
+
private:
enum VPtrStealingHackType { VPtrStealingHack };
JSString(VPtrStealingHackType)
virtual JSValue* toPrimitive(ExecState*, PreferredPrimitiveType) const;
virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue*& value);
- virtual bool toBoolean(ExecState*) const;
virtual double toNumber(ExecState*) const;
virtual JSObject* toObject(ExecState*) const;
virtual UString toString(ExecState*) const;
JSValue* toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
bool getPrimitiveNumber(ExecState*, double& number, JSValue*&);
- bool toBoolean(ExecState*) const;
+ bool toBoolean() const;
// toNumber conversion is expected to be side effect free if an exception has
// been set in the ExecState already.
static_cast<RegExpConstructor*>(baseObject)->setInput(value->toString(exec));
}
-void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue* value)
+void setRegExpConstructorMultiline(ExecState*, JSObject* baseObject, JSValue* value)
{
- static_cast<RegExpConstructor*>(baseObject)->setMultiline(value->toBoolean(exec));
+ static_cast<RegExpConstructor*>(baseObject)->setMultiline(value->toBoolean());
}
// ECMA 15.10.4
}
}
- bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
+ bool global = get(exec, exec->propertyNames().global)->toBoolean();
int lastIndex = 0;
if (global) {
if (d->lastIndex < 0 || d->lastIndex > input.size()) {
UString result = "/" + static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().source)->toString(exec);
result.append('/');
- if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec))
+ if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().global)->toBoolean())
result.append('g');
- if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))
+ if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean())
result.append('i');
- if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec))
+ if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean())
result.append('m');
return jsNontrivialString(exec, result);
}