class ExecState;
class JSValue;
+ // ECMA 11.9.3
bool equal(ExecState*, JSValue*, JSValue*);
+ bool equalSlowCase(ExecState*, JSValue*, JSValue*);
+
+ ALWAYS_INLINE bool equalSlowCaseInline(ExecState* exec, JSValue* v1, JSValue* v2)
+ {
+ ASSERT(!JSImmediate::areBothImmediateNumbers(v1, v2));
+
+ do {
+ if (v1->isNumber() && v2->isNumber())
+ return v1->uncheckedGetNumber() == v2->uncheckedGetNumber();
+
+ bool s1 = v1->isString();
+ bool s2 = v2->isString();
+ if (s1 && s2)
+ return static_cast<JSString*>(v1)->value() == static_cast<JSString*>(v2)->value();
+
+ if (v1->isUndefinedOrNull()) {
+ if (v2->isUndefinedOrNull())
+ return true;
+ if (JSImmediate::isImmediate(v2))
+ return false;
+ return v2->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
+ }
+
+ if (v2->isUndefinedOrNull()) {
+ if (JSImmediate::isImmediate(v1))
+ return false;
+ return v1->asCell()->structureID()->typeInfo().masqueradesAsUndefined();
+ }
+
+ if (v1->isObject()) {
+ if (v2->isObject())
+ return v1 == v2;
+ JSValue* p1 = v1->toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v1 = p1;
+ if (JSImmediate::areBothImmediateNumbers(v1, v2))
+ return v1 == v2;
+ continue;
+ }
+
+ if (v2->isObject()) {
+ JSValue* p2 = v2->toPrimitive(exec);
+ if (exec->hadException())
+ return false;
+ v2 = p2;
+ if (JSImmediate::areBothImmediateNumbers(v1, v2))
+ return v1 == v2;
+ continue;
+ }
+
+ if (s1 || s2) {
+ double d1 = v1->toNumber(exec);
+ double d2 = v2->toNumber(exec);
+ return d1 == d2;
+ }
+
+ if (v1->isBoolean()) {
+ if (v2->isNumber())
+ return static_cast<double>(v1->getBoolean()) == v2->uncheckedGetNumber();
+ } else if (v2->isBoolean()) {
+ if (v1->isNumber())
+ return v1->uncheckedGetNumber() == static_cast<double>(v2->getBoolean());
+ }
+
+ return v1 == v2;
+ } while (true);
+ }
+
+
bool strictEqual(JSValue*, JSValue*);
bool strictEqualSlowCase(JSValue*, JSValue*);