From: bmeurer Date: Mon, 17 Aug 2015 08:01:55 +0000 (-0700) Subject: [runtime] Unify and fix the strict equality comparison. X-Git-Tag: upstream/4.7.83~854 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9780ddeb9685c30cf64a337446b9a7413a3be64f;p=platform%2Fupstream%2Fv8.git [runtime] Unify and fix the strict equality comparison. Add Object::StrictEquals to unify the implementation of strict equality comparison in the runtime and the api (the api was already missing a case for SIMD). Now we (almost) have a single bottleneck for strict equality, we just need to reduce the amount of unnecessary complexity for the code stub. R=yangguo@chromium.org Review URL: https://codereview.chromium.org/1298603002 Cr-Commit-Position: refs/heads/master@{#30186} --- diff --git a/src/api.cc b/src/api.cc index 8fa2e2c30..46cac758f 100644 --- a/src/api.cc +++ b/src/api.cc @@ -3405,33 +3405,9 @@ bool Value::Equals(Local that) const { bool Value::StrictEquals(Local that) const { - i::Handle obj = Utils::OpenHandle(this); - i::Handle other = Utils::OpenHandle(*that); - if (obj->IsSmi()) { - return other->IsNumber() && obj->Number() == other->Number(); - } - i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate(); - LOG_API(isolate, "StrictEquals"); - // Must check HeapNumber first, since NaN !== NaN. - if (obj->IsHeapNumber()) { - if (!other->IsNumber()) return false; - double x = obj->Number(); - double y = other->Number(); - // Must check explicitly for NaN:s on Windows, but -0 works fine. - return x == y && !std::isnan(x) && !std::isnan(y); - } else if (*obj == *other) { // Also covers Booleans. - return true; - } else if (obj->IsSmi()) { - return other->IsNumber() && obj->Number() == other->Number(); - } else if (obj->IsString()) { - return other->IsString() && - i::String::Equals(i::Handle::cast(obj), - i::Handle::cast(other)); - } else if (obj->IsUndefined() || obj->IsUndetectableObject()) { - return other->IsUndefined() || other->IsUndetectableObject(); - } else { - return false; - } + auto self = Utils::OpenHandle(this); + auto other = Utils::OpenHandle(*that); + return self->StrictEquals(*other); } diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 5bd6c08ca..ffc821b16 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -681,26 +681,30 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ Push(lhs, rhs); // Figure out which native to call and setup the arguments. - Builtins::JavaScript native; - if (cc == eq) { - native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == eq && strict()) { + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - native = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - int ncr; // NaN compare result - if (cc == lt || cc == le) { - ncr = GREATER; + Builtins::JavaScript native; + if (cc == eq) { + native = Builtins::EQUALS; } else { - DCHECK(cc == gt || cc == ge); // remaining cases - ncr = LESS; + native = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + int ncr; // NaN compare result + if (cc == lt || cc == le) { + ncr = GREATER; + } else { + DCHECK(cc == gt || cc == ge); // remaining cases + ncr = LESS; + } + __ mov(r0, Operand(Smi::FromInt(ncr))); + __ push(r0); } - __ mov(r0, Operand(Smi::FromInt(ncr))); - __ push(r0); - } - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(native, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(native, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index 74ed8a29f..48a6e5c87 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -652,26 +652,30 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ Push(lhs, rhs); // Figure out which native to call and setup the arguments. - Builtins::JavaScript native; - if (cond == eq) { - native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cond == eq && strict()) { + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - native = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - int ncr; // NaN compare result - if ((cond == lt) || (cond == le)) { - ncr = GREATER; + Builtins::JavaScript native; + if (cond == eq) { + native = Builtins::EQUALS; } else { - DCHECK((cond == gt) || (cond == ge)); // remaining cases - ncr = LESS; + native = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + int ncr; // NaN compare result + if ((cond == lt) || (cond == le)) { + ncr = GREATER; + } else { + DCHECK((cond == gt) || (cond == ge)); // remaining cases + ncr = LESS; + } + __ Mov(x10, Smi::FromInt(ncr)); + __ Push(x10); } - __ Mov(x10, Smi::FromInt(ncr)); - __ Push(x10); - } - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(native, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(native, JUMP_FUNCTION); + } __ Bind(&miss); GenerateMiss(masm); diff --git a/src/builtins.h b/src/builtins.h index 6ec618ada..cf90aacf8 100644 --- a/src/builtins.h +++ b/src/builtins.h @@ -150,7 +150,6 @@ enum BuiltinExtraArguments { // Define list of builtins implemented in JavaScript. #define BUILTINS_LIST_JS(V) \ V(EQUALS, 1) \ - V(STRICT_EQUALS, 1) \ V(COMPARE, 2) \ V(COMPARE_STRONG, 2) \ V(ADD, 1) \ diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 6480e7483..dc8c517d9 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -1894,21 +1894,26 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ push(eax); // Figure out which native to call and setup the arguments. - Builtins::JavaScript builtin; - if (cc == equal) { - builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == equal && strict()) { + __ push(ecx); + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - builtin = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); - } + Builtins::JavaScript builtin; + if (cc == equal) { + builtin = Builtins::EQUALS; + } else { + builtin = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); + } - // Restore return address on the stack. - __ push(ecx); + // Restore return address on the stack. + __ push(ecx); - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(builtin, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(builtin, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 069611b6d..2fa084980 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -728,26 +728,30 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { // a1 (rhs) second. __ Push(lhs, rhs); // Figure out which native to call and setup the arguments. - Builtins::JavaScript native; - if (cc == eq) { - native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == eq && strict()) { + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - native = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - int ncr; // NaN compare result. - if (cc == lt || cc == le) { - ncr = GREATER; + Builtins::JavaScript native; + if (cc == eq) { + native = Builtins::EQUALS; } else { - DCHECK(cc == gt || cc == ge); // Remaining cases. - ncr = LESS; + native = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + int ncr; // NaN compare result. + if (cc == lt || cc == le) { + ncr = GREATER; + } else { + DCHECK(cc == gt || cc == ge); // Remaining cases. + ncr = LESS; + } + __ li(a0, Operand(Smi::FromInt(ncr))); + __ push(a0); } - __ li(a0, Operand(Smi::FromInt(ncr))); - __ push(a0); - } - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(native, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(native, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index f62b3547b..9a2802e7e 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -723,26 +723,30 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { // a1 (rhs) second. __ Push(lhs, rhs); // Figure out which native to call and setup the arguments. - Builtins::JavaScript native; - if (cc == eq) { - native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == eq && strict()) { + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - native = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - int ncr; // NaN compare result. - if (cc == lt || cc == le) { - ncr = GREATER; + Builtins::JavaScript native; + if (cc == eq) { + native = Builtins::EQUALS; } else { - DCHECK(cc == gt || cc == ge); // Remaining cases. - ncr = LESS; + native = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + int ncr; // NaN compare result. + if (cc == lt || cc == le) { + ncr = GREATER; + } else { + DCHECK(cc == gt || cc == ge); // Remaining cases. + ncr = LESS; + } + __ li(a0, Operand(Smi::FromInt(ncr))); + __ push(a0); } - __ li(a0, Operand(Smi::FromInt(ncr))); - __ push(a0); - } - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(native, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(native, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/objects-inl.h b/src/objects-inl.h index 1cb246b30..2afd802f5 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -1521,6 +1521,29 @@ int HeapNumber::get_sign() { } +bool Simd128Value::Equals(Simd128Value* that) { +#define SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \ + if (this->Is##Type()) { \ + if (!that->Is##Type()) return false; \ + return Type::cast(this)->Equals(Type::cast(that)); \ + } + SIMD128_TYPES(SIMD128_VALUE) +#undef SIMD128_VALUE + return false; +} + + +#define SIMD128_VALUE_EQUALS(TYPE, Type, type, lane_count, lane_type) \ + bool Type::Equals(Type* that) { \ + for (int lane = 0; lane < lane_count; ++lane) { \ + if (this->get_lane(lane) != that->get_lane(lane)) return false; \ + } \ + return true; \ + } +SIMD128_TYPES(SIMD128_VALUE_EQUALS) +#undef SIMD128_VALUE_EQUALS + + float Float32x4::get_lane(int lane) const { DCHECK(lane < 4 && lane >= 0); #if defined(V8_TARGET_LITTLE_ENDIAN) diff --git a/src/objects.cc b/src/objects.cc index 2cfc82df1..1f25a5d11 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -102,6 +102,24 @@ bool Object::BooleanValue() { } +bool Object::StrictEquals(Object* that) { + if (this->IsNumber()) { + if (!that->IsNumber()) return false; + double const x = this->Number(); + double const y = that->Number(); + // Must check explicitly for NaN:s on Windows, but -0 works fine. + return x == y && !std::isnan(x) && !std::isnan(y); + } else if (this->IsString()) { + if (!that->IsString()) return false; + return String::cast(this)->Equals(String::cast(that)); + } else if (this->IsSimd128Value()) { + if (!that->IsSimd128Value()) return false; + return Simd128Value::cast(this)->Equals(Simd128Value::cast(that)); + } + return this == that; +} + + bool Object::IsCallable() const { const Object* fun = this; while (fun->IsJSFunctionProxy()) { diff --git a/src/objects.h b/src/objects.h index c298cc86f..a19ac5d51 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1088,6 +1088,9 @@ class Object { bool BooleanValue(); // ECMA-262 9.2. + // ES6 section 7.2.13 Strict Equality Comparison + bool StrictEquals(Object* that); + // Convert to a JSObject if needed. // native_context is used when creating wrapper object. static inline MaybeHandle ToObject(Isolate* isolate, @@ -1593,6 +1596,9 @@ class Simd128Value : public HeapObject { DECLARE_PRINTER(Simd128Value) DECLARE_VERIFIER(Simd128Value) + // Equality operations. + inline bool Equals(Simd128Value* that); + // Checks that another instance is bit-wise equal. bool BitwiseEquals(const Simd128Value* other) const; // Computes a hash from the 128 bit value, viewed as 4 32-bit integers. @@ -1629,6 +1635,8 @@ class Simd128Value : public HeapObject { \ DECLARE_PRINTER(Type) \ \ + inline bool Equals(Type* that); \ + \ private: \ DISALLOW_IMPLICIT_CONSTRUCTORS(Type); \ }; diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc index b136b7dd2..303c85737 100644 --- a/src/ppc/code-stubs-ppc.cc +++ b/src/ppc/code-stubs-ppc.cc @@ -716,26 +716,30 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ Push(lhs, rhs); // Figure out which native to call and setup the arguments. - Builtins::JavaScript native; - if (cc == eq) { - native = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == eq && strict()) { + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - native = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - int ncr; // NaN compare result - if (cc == lt || cc == le) { - ncr = GREATER; + Builtins::JavaScript native; + if (cc == eq) { + native = Builtins::EQUALS; } else { - DCHECK(cc == gt || cc == ge); // remaining cases - ncr = LESS; + native = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + int ncr; // NaN compare result + if (cc == lt || cc == le) { + ncr = GREATER; + } else { + DCHECK(cc == gt || cc == ge); // remaining cases + ncr = LESS; + } + __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); + __ push(r3); } - __ LoadSmiLiteral(r3, Smi::FromInt(ncr)); - __ push(r3); - } - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(native, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(native, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/runtime.js b/src/runtime.js index 5683f8422..4de9c2997 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -127,6 +127,7 @@ EQUALS = function EQUALS(y) { } else if (IS_NULL_OR_UNDEFINED(x)) { return IS_NULL_OR_UNDEFINED(y) ? 0 : 1; } else if (IS_SIMD_VALUE(x)) { + if (!IS_SIMD_VALUE(y)) return 1; // not equal return %SimdEquals(x, y); } else { // x is an object. @@ -142,26 +143,6 @@ EQUALS = function EQUALS(y) { } } -// ECMA-262, section 11.9.4, page 56. -STRICT_EQUALS = function STRICT_EQUALS(x) { - if (IS_STRING(this)) { - if (!IS_STRING(x)) return 1; // not equal - return %StringEquals(this, x); - } - - if (IS_NUMBER(this)) { - if (!IS_NUMBER(x)) return 1; // not equal - return %NumberEquals(this, x); - } - - if (IS_SIMD_VALUE(this)) return %SimdEquals(this, x); - - // If anything else gets here, we just do simple identity check. - // Objects (including functions), null, undefined and booleans were - // checked in the CompareStub, so there should be nothing left. - return %_ObjectEquals(this, x) ? 0 : 1; -} - // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as // the result when either (or both) the operands are NaN. diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc index f0c83e0f2..624708714 100644 --- a/src/runtime/runtime-object.cc +++ b/src/runtime/runtime-object.cc @@ -1461,5 +1461,15 @@ RUNTIME_FUNCTION(Runtime_ToObject) { isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject)); } + +RUNTIME_FUNCTION(Runtime_StrictEquals) { + SealHandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_CHECKED(Object, x, 0); + CONVERT_ARG_CHECKED(Object, y, 1); + // TODO(bmeurer): Change this at some point to return true/false instead. + return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL); +} + } // namespace internal } // namespace v8 diff --git a/src/runtime/runtime-simd.cc b/src/runtime/runtime-simd.cc index bcf356702..ad337eaf1 100644 --- a/src/runtime/runtime-simd.cc +++ b/src/runtime/runtime-simd.cc @@ -48,14 +48,6 @@ int8_t ConvertNumber(double number) { } -bool Equals(Float32x4* a, Float32x4* b) { - for (int i = 0; i < 4; i++) { - if (a->get_lane(i) != b->get_lane(i)) return false; - } - return true; -} - - // TODO(bbudge): Make this consistent with SIMD instruction results. inline float RecipApprox(float a) { return 1.0f / a; } @@ -148,22 +140,11 @@ RUNTIME_FUNCTION(Runtime_SimdToObject) { RUNTIME_FUNCTION(Runtime_SimdEquals) { - HandleScope scope(isolate); - DCHECK(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(Simd128Value, a, 0); - bool result = false; - // args[1] is of unknown type. - if (args[1]->IsSimd128Value()) { - Simd128Value* b = Simd128Value::cast(args[1]); - if (a->map() == b->map()) { - if (a->IsFloat32x4()) { - result = Equals(Float32x4::cast(*a), Float32x4::cast(b)); - } else { - result = a->BitwiseEquals(b); - } - } - } - return Smi::FromInt(result ? EQUAL : NOT_EQUAL); + SealHandleScope scope(isolate); + DCHECK_EQ(2, args.length()); + CONVERT_ARG_CHECKED(Simd128Value, x, 0); + CONVERT_ARG_CHECKED(Simd128Value, y, 1); + return Smi::FromInt(x->Equals(y) ? EQUAL : NOT_EQUAL); } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 9ff0adae9..e145b2db0 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -492,7 +492,8 @@ namespace internal { F(ClassOf, 1, 1) \ F(DefineGetterPropertyUnchecked, 4, 1) \ F(DefineSetterPropertyUnchecked, 4, 1) \ - F(ToObject, 1, 1) + F(ToObject, 1, 1) \ + F(StrictEquals, 2, 1) #define FOR_EACH_INTRINSIC_OBSERVE(F) \ diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 29de1bdfa..5d999152e 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -1763,20 +1763,25 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ Push(rax); // Figure out which native to call and setup the arguments. - Builtins::JavaScript builtin; - if (cc == equal) { - builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == equal && strict()) { + __ PushReturnAddressFrom(rcx); + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - builtin = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - __ Push(Smi::FromInt(NegativeComparisonResult(cc))); - } + Builtins::JavaScript builtin; + if (cc == equal) { + builtin = Builtins::EQUALS; + } else { + builtin = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + __ Push(Smi::FromInt(NegativeComparisonResult(cc))); + } - __ PushReturnAddressFrom(rcx); + __ PushReturnAddressFrom(rcx); - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(builtin, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(builtin, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm); diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc index c7a6d23dc..cf2f0b3e0 100644 --- a/src/x87/code-stubs-x87.cc +++ b/src/x87/code-stubs-x87.cc @@ -1605,21 +1605,26 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) { __ push(eax); // Figure out which native to call and setup the arguments. - Builtins::JavaScript builtin; - if (cc == equal) { - builtin = strict() ? Builtins::STRICT_EQUALS : Builtins::EQUALS; + if (cc == equal && strict()) { + __ push(ecx); + __ TailCallRuntime(Runtime::kStrictEquals, 2, 1); } else { - builtin = - is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; - __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); - } + Builtins::JavaScript builtin; + if (cc == equal) { + builtin = Builtins::EQUALS; + } else { + builtin = + is_strong(strength()) ? Builtins::COMPARE_STRONG : Builtins::COMPARE; + __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc)))); + } - // Restore return address on the stack. - __ push(ecx); + // Restore return address on the stack. + __ push(ecx); - // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) - // tagged as a small integer. - __ InvokeBuiltin(builtin, JUMP_FUNCTION); + // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) + // tagged as a small integer. + __ InvokeBuiltin(builtin, JUMP_FUNCTION); + } __ bind(&miss); GenerateMiss(masm);