[runtime] Replace the EQUALS builtin with proper Object::Equals.
authorbmeurer <bmeurer@chromium.org>
Tue, 15 Sep 2015 13:14:36 +0000 (06:14 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 15 Sep 2015 13:14:44 +0000 (13:14 +0000)
Move the implementation of the Abstract Equality Comparison to the
runtime and thereby remove the EQUALS dispatcher builtin. Also remove
the various runtime entry points that were only used to support the
EQUALS builtin.

Now the Abstract Equality Comparison is also using the correct
ToPrimitive implementation, which properly supports @@toPrimitive.

CQ_INCLUDE_TRYBOTS=tryserver.v8:v8_linux_layout_dbg,v8_linux_nosnap_dbg
R=mstarzinger@chromium.org
BUG=v8:4307
LOG=n

Review URL: https://codereview.chromium.org/1337993005

Cr-Commit-Position: refs/heads/master@{#30747}

16 files changed:
src/api.cc
src/arm/code-stubs-arm.cc
src/arm64/code-stubs-arm64.cc
src/contexts.h
src/ia32/code-stubs-ia32.cc
src/mips/code-stubs-mips.cc
src/mips64/code-stubs-mips64.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/runtime.js
src/runtime/runtime-numbers.cc
src/runtime/runtime-object.cc
src/runtime/runtime-simd.cc
src/runtime/runtime.h
src/x64/code-stubs-x64.cc

index 8cceb65..1b5d428 100644 (file)
@@ -3365,21 +3365,7 @@ Local<Uint32> Value::ToArrayIndex() const {
 Maybe<bool> Value::Equals(Local<Context> context, Local<Value> that) const {
   auto self = Utils::OpenHandle(this);
   auto other = Utils::OpenHandle(*that);
-  if (self->IsSmi() && other->IsSmi()) {
-    return Just(self->Number() == other->Number());
-  }
-  if (self->IsJSObject() && other->IsJSObject()) {
-    return Just(*self == *other);
-  }
-  PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Value::Equals()", bool);
-  i::Handle<i::Object> args[] = { other };
-  i::Handle<i::JSFunction> fun = isolate->equals_builtin();
-  i::Handle<i::Object> result;
-  has_pending_exception =
-      !i::Execution::Call(isolate, fun, self, arraysize(args), args)
-           .ToHandle(&result);
-  RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
-  return Just(*result == i::Smi::FromInt(i::EQUAL));
+  return i::Object::Equals(self, other);
 }
 
 
index 907bdac..f6b08bd 100644 (file)
@@ -681,26 +681,22 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
   __ Push(lhs, rhs);
   // Figure out which native to call and setup the arguments.
-  if (cc == eq && strict()) {
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+  if (cc == eq) {
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int context_index;
-    if (cc == eq) {
-      context_index = Context::EQUALS_BUILTIN_INDEX;
+    int context_index = is_strong(strength())
+                            ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                            : Context::COMPARE_BUILTIN_INDEX;
+    int ncr;  // NaN compare result
+    if (cc == lt || cc == le) {
+      ncr = GREATER;
     } else {
-      context_index = is_strong(strength())
-                          ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                          : Context::COMPARE_BUILTIN_INDEX;
-      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);
+      DCHECK(cc == gt || cc == ge);  // remaining cases
+      ncr = LESS;
     }
+    __ 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.
index 98dbb9c..cc198b8 100644 (file)
@@ -652,26 +652,22 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
   __ Push(lhs, rhs);
   // Figure out which native to call and setup the arguments.
-  if (cond == eq && strict()) {
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+  if (cond == eq) {
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int context_index;
-    if (cond == eq) {
-      context_index = Context::EQUALS_BUILTIN_INDEX;
+    int context_index = is_strong(strength())
+                            ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                            : Context::COMPARE_BUILTIN_INDEX;
+    int ncr;  // NaN compare result
+    if ((cond == lt) || (cond == le)) {
+      ncr = GREATER;
     } else {
-      context_index = is_strong(strength())
-                          ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                          : Context::COMPARE_BUILTIN_INDEX;
-      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);
+      DCHECK((cond == gt) || (cond == ge));  // remaining cases
+      ncr = LESS;
     }
+    __ Mov(x10, Smi::FromInt(ncr));
+    __ Push(x10);
 
     // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
     // tagged as a small integer.
index dd5e1ad..70e6ccf 100644 (file)
@@ -96,7 +96,6 @@ enum BindingFlags {
   V(COMPARE_STRONG_BUILTIN_INDEX, JSFunction, compare_strong_builtin) \
   V(CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, JSFunction,               \
     concat_iterable_to_array_builtin)                                 \
-  V(EQUALS_BUILTIN_INDEX, JSFunction, equals_builtin)                 \
   V(REFLECT_APPLY_PREPARE_BUILTIN_INDEX, JSFunction,                  \
     reflect_apply_prepare_builtin)                                    \
   V(REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, JSFunction,              \
index 4fcdabc..b9dc33f 100644 (file)
@@ -1867,19 +1867,15 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
   __ push(eax);
 
   // Figure out which native to call and setup the arguments.
-  if (cc == equal && strict()) {
+  if (cc == equal) {
     __ push(ecx);
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int native_context_index;
-    if (cc == equal) {
-      native_context_index = Context::EQUALS_BUILTIN_INDEX;
-    } else {
-      native_context_index = is_strong(strength())
-                                 ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                                 : Context::COMPARE_BUILTIN_INDEX;
-      __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
-    }
+    int native_context_index = is_strong(strength())
+                                   ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                                   : Context::COMPARE_BUILTIN_INDEX;
+    __ push(Immediate(Smi::FromInt(NegativeComparisonResult(cc))));
 
     // Restore return address on the stack.
     __ push(ecx);
index 955a87e..76a577c 100644 (file)
@@ -727,26 +727,22 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
   // a1 (rhs) second.
   __ Push(lhs, rhs);
   // Figure out which native to call and setup the arguments.
-  if (cc == eq && strict()) {
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+  if (cc == eq) {
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int context_index;
-    if (cc == eq) {
-      context_index = Context::EQUALS_BUILTIN_INDEX;
+    int context_index = is_strong(strength())
+                            ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                            : Context::COMPARE_BUILTIN_INDEX;
+    int ncr;  // NaN compare result.
+    if (cc == lt || cc == le) {
+      ncr = GREATER;
     } else {
-      context_index = is_strong(strength())
-                          ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                          : Context::COMPARE_BUILTIN_INDEX;
-      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);
+      DCHECK(cc == gt || cc == ge);  // Remaining cases.
+      ncr = LESS;
     }
+    __ 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.
index f2e751a..187f912 100644 (file)
@@ -722,26 +722,22 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
   // a1 (rhs) second.
   __ Push(lhs, rhs);
   // Figure out which native to call and setup the arguments.
-  if (cc == eq && strict()) {
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+  if (cc == eq) {
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int context_index;
-    if (cc == eq) {
-      context_index = Context::EQUALS_BUILTIN_INDEX;
+    int context_index = is_strong(strength())
+                            ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                            : Context::COMPARE_BUILTIN_INDEX;
+    int ncr;  // NaN compare result.
+    if (cc == lt || cc == le) {
+      ncr = GREATER;
     } else {
-      context_index = is_strong(strength())
-                          ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                          : Context::COMPARE_BUILTIN_INDEX;
-      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);
+      DCHECK(cc == gt || cc == ge);  // Remaining cases.
+      ncr = LESS;
     }
+    __ 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.
index f37671b..9790208 100644 (file)
@@ -1082,11 +1082,11 @@ bool Object::IsArgumentsMarker() const {
 }
 
 
-double Object::Number() {
+double Object::Number() const {
   DCHECK(IsNumber());
   return IsSmi()
-    ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
-    : reinterpret_cast<HeapNumber*>(this)->value();
+             ? static_cast<double>(reinterpret_cast<const Smi*>(this)->value())
+             : reinterpret_cast<const HeapNumber*>(this)->value();
 }
 
 
@@ -1567,6 +1567,12 @@ bool Simd128Value::Equals(Simd128Value* that) {
 }
 
 
+// static
+bool Simd128Value::Equals(Handle<Simd128Value> one, Handle<Simd128Value> two) {
+  return one->Equals(*two);
+}
+
+
 #define SIMD128_VALUE_EQUALS(TYPE, Type, type, lane_count, lane_type) \
   bool Type::Equals(Type* that) {                                     \
     for (int lane = 0; lane < lane_count; ++lane) {                   \
@@ -2053,6 +2059,12 @@ void Oddball::set_kind(byte value) {
 }
 
 
+// static
+Handle<Object> Oddball::ToNumber(Handle<Oddball> input) {
+  return handle(input->to_number(), input->GetIsolate());
+}
+
+
 ACCESSORS(Cell, value, Object, kValueOffset)
 ACCESSORS(PropertyCell, dependent_code, DependentCode, kDependentCodeOffset)
 ACCESSORS(PropertyCell, property_details_raw, Object, kDetailsOffset)
index edb7ee2..a642df0 100644 (file)
@@ -98,13 +98,13 @@ MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
     if (input->IsNumber()) {
       return input;
     }
-    Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
-    if (input->IsOddball()) {
-      return handle(Handle<Oddball>::cast(input)->to_number(), isolate);
-    }
     if (input->IsString()) {
       return String::ToNumber(Handle<String>::cast(input));
     }
+    if (input->IsOddball()) {
+      return Oddball::ToNumber(Handle<Oddball>::cast(input));
+    }
+    Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
     if (input->IsSymbol()) {
       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
                       Object);
@@ -159,13 +159,114 @@ bool Object::BooleanValue() {
 }
 
 
+namespace {
+
+// TODO(bmeurer): Maybe we should introduce a marker interface Number,
+// where we put all these methods at some point?
+bool NumberEquals(double x, double y) {
+  // Must check explicitly for NaN's on Windows, but -0 works fine.
+  if (std::isnan(x)) return false;
+  if (std::isnan(y)) return false;
+  return x == y;
+}
+
+
+bool NumberEquals(const Object* x, const Object* y) {
+  return NumberEquals(x->Number(), y->Number());
+}
+
+
+bool NumberEquals(Handle<Object> x, Handle<Object> y) {
+  return NumberEquals(*x, *y);
+}
+
+}  // namespace
+
+
+// static
+Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
+  while (true) {
+    if (x->IsNumber()) {
+      if (y->IsNumber()) {
+        return Just(NumberEquals(x, y));
+      } else if (y->IsBoolean()) {
+        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
+      } else if (y->IsString()) {
+        return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
+      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
+        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
+                 .ToHandle(&y)) {
+          return Nothing<bool>();
+        }
+      } else {
+        return Just(false);
+      }
+    } else if (x->IsString()) {
+      if (y->IsString()) {
+        return Just(
+            String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
+      } else if (y->IsNumber()) {
+        x = String::ToNumber(Handle<String>::cast(x));
+        return Just(NumberEquals(x, y));
+      } else if (y->IsBoolean()) {
+        x = String::ToNumber(Handle<String>::cast(x));
+        return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
+      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
+        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
+                 .ToHandle(&y)) {
+          return Nothing<bool>();
+        }
+      } else {
+        return Just(false);
+      }
+    } else if (x->IsBoolean()) {
+      if (y->IsOddball()) {
+        return Just(x.is_identical_to(y));
+      } else if (y->IsNumber()) {
+        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
+      } else if (y->IsString()) {
+        y = String::ToNumber(Handle<String>::cast(y));
+        return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
+      } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
+        if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
+                 .ToHandle(&y)) {
+          return Nothing<bool>();
+        }
+        x = Oddball::ToNumber(Handle<Oddball>::cast(x));
+      } else {
+        return Just(false);
+      }
+    } else if (x->IsSymbol()) {
+      return Just(x.is_identical_to(y));
+    } else if (x->IsSimd128Value()) {
+      if (!y->IsSimd128Value()) return Just(false);
+      return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
+                                       Handle<Simd128Value>::cast(y)));
+    } else if (x->IsJSReceiver() && !x->IsUndetectableObject()) {
+      if (y->IsJSReceiver()) {
+        return Just(x.is_identical_to(y));
+      } else if (y->IsNull() || y->IsSimd128Value() || y->IsSymbol() ||
+                 y->IsUndefined()) {
+        return Just(false);
+      } else if (y->IsBoolean()) {
+        y = Oddball::ToNumber(Handle<Oddball>::cast(y));
+      }
+      if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x)).ToHandle(&x)) {
+        return Nothing<bool>();
+      }
+    } else {
+      return Just(
+          (x->IsNull() || x->IsUndefined() || x->IsUndetectableObject()) &&
+          (y->IsNull() || y->IsUndefined() || y->IsUndetectableObject()));
+    }
+  }
+}
+
+
 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);
+    return NumberEquals(this, that);
   } else if (this->IsString()) {
     if (!that->IsString()) return false;
     return String::cast(this)->Equals(String::cast(that));
index 9797f04..9e773c0 100644 (file)
@@ -1048,7 +1048,7 @@ class Object {
   INLINE(bool IsFiller() const);
 
   // Extract the number.
-  inline double Number();
+  inline double Number() const;
   INLINE(bool IsNaN() const);
   INLINE(bool IsMinusZero() const);
   bool ToInt32(int32_t* value);
@@ -1083,6 +1083,9 @@ class Object {
 
   bool BooleanValue();                                      // ECMA-262 9.2.
 
+  // ES6 section 7.2.12 Abstract Equality Comparison
+  MUST_USE_RESULT static Maybe<bool> Equals(Handle<Object> x, Handle<Object> y);
+
   // ES6 section 7.2.13 Strict Equality Comparison
   bool StrictEquals(Object* that);
 
@@ -1657,6 +1660,7 @@ class Simd128Value : public HeapObject {
 
   // Equality operations.
   inline bool Equals(Simd128Value* that);
+  static inline bool Equals(Handle<Simd128Value> one, Handle<Simd128Value> two);
 
   // Checks that another instance is bit-wise equal.
   bool BitwiseEquals(const Simd128Value* other) const;
@@ -9102,6 +9106,9 @@ class Oddball: public HeapObject {
   inline byte kind() const;
   inline void set_kind(byte kind);
 
+  // ES6 section 7.1.3 ToNumber for Boolean, Null, Undefined.
+  MUST_USE_RESULT static inline Handle<Object> ToNumber(Handle<Oddball> input);
+
   DECLARE_CAST(Oddball)
 
   // Dispatched behavior.
index 6df7faa..fcb9471 100644 (file)
@@ -42,68 +42,6 @@ var isConcatSpreadableSymbol =
 -----------------------------------
 */
 
-// ECMA-262 Section 11.9.3.
-function EQUALS(y) {
-  if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y);
-  var x = this;
-
-  while (true) {
-    if (IS_NUMBER(x)) {
-      while (true) {
-        if (IS_NUMBER(y)) return %NumberEquals(x, y);
-        if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
-        if (!IS_SPEC_OBJECT(y)) {
-          if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1;  // not equal
-          // String or boolean.
-          return %NumberEquals(x, %to_number_fun(y));
-        }
-        y = %to_primitive(y, NO_HINT);
-      }
-    } else if (IS_STRING(x)) {
-      while (true) {
-        if (IS_STRING(y)) return %StringEquals(x, y);
-        if (IS_NUMBER(y)) return %NumberEquals(%to_number_fun(x), y);
-        if (IS_BOOLEAN(y)) {
-          return %NumberEquals(%to_number_fun(x), %to_number_fun(y));
-        }
-        if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
-        if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1;  // not equal
-        y = %to_primitive(y, NO_HINT);
-      }
-    } else if (IS_SYMBOL(x)) {
-      if (IS_SYMBOL(y)) return %_ObjectEquals(x, y) ? 0 : 1;
-      return 1; // not equal
-    } else if (IS_BOOLEAN(x)) {
-      if (IS_BOOLEAN(y)) return %_ObjectEquals(x, y) ? 0 : 1;
-      if (IS_NULL_OR_UNDEFINED(y)) return 1;
-      if (IS_NUMBER(y)) return %NumberEquals(%to_number_fun(x), y);
-      if (IS_STRING(y)) {
-        return %NumberEquals(%to_number_fun(x), %to_number_fun(y));
-      }
-      if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) return 1;  // not equal
-      // y is object.
-      x = %to_number_fun(x);
-      y = %to_primitive(y, NO_HINT);
-    } 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.
-      if (IS_SPEC_OBJECT(y)) return %_ObjectEquals(x, y) ? 0 : 1;
-      if (IS_NULL_OR_UNDEFINED(y)) return 1;  // not equal
-      if (IS_BOOLEAN(y)) {
-        y = %to_number_fun(y);
-      } else if (IS_SYMBOL(y) || IS_SIMD_VALUE(y)) {
-        return 1;  // not equal
-      }
-      x = %to_primitive(x, NO_HINT);
-    }
-  }
-}
-
-
 // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as
 // the result when either (or both) the operands are NaN.
 function COMPARE(x, ncr) {
@@ -498,7 +436,6 @@ $toString = ToString;
   "compare_builtin", COMPARE,
   "compare_strong_builtin", COMPARE_STRONG,
   "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
-  "equals_builtin", EQUALS,
   "reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
   "reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
 ]);
index 75c8065..bcdd89f 100644 (file)
@@ -11,8 +11,7 @@
 
 
 #ifndef _STLP_VENDOR_CSTD
-// STLPort doesn't import fpclassify and isless into the std namespace.
-using std::fpclassify;
+// STLPort doesn't import isless into the std namespace.
 using std::isless;
 #endif
 
@@ -233,25 +232,6 @@ RUNTIME_FUNCTION(Runtime_NumberImul) {
 }
 
 
-RUNTIME_FUNCTION(Runtime_NumberEquals) {
-  SealHandleScope shs(isolate);
-  DCHECK(args.length() == 2);
-
-  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
-  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
-  if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
-  if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
-  if (x == y) return Smi::FromInt(EQUAL);
-  Object* result;
-  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
-    result = Smi::FromInt(EQUAL);
-  } else {
-    result = Smi::FromInt(NOT_EQUAL);
-  }
-  return result;
-}
-
-
 RUNTIME_FUNCTION(Runtime_NumberCompare) {
   SealHandleScope shs(isolate);
   DCHECK(args.length() == 3);
@@ -362,5 +342,6 @@ RUNTIME_FUNCTION(Runtime_GetRootNaN) {
   DCHECK(args.length() == 0);
   return isolate->heap()->nan_value();
 }
+
 }  // namespace internal
 }  // namespace v8
index 75d09a8..0c6f813 100644 (file)
@@ -1478,6 +1478,18 @@ RUNTIME_FUNCTION(Runtime_ToName) {
 }
 
 
+RUNTIME_FUNCTION(Runtime_Equals) {
+  HandleScope scope(isolate);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
+  CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
+  Maybe<bool> result = Object::Equals(x, y);
+  if (!result.IsJust()) return isolate->heap()->exception();
+  // TODO(bmeurer): Change this at some point to return true/false instead.
+  return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
+}
+
+
 RUNTIME_FUNCTION(Runtime_StrictEquals) {
   SealHandleScope scope(isolate);
   DCHECK_EQ(2, args.length());
index 7ec9737..bed866f 100644 (file)
@@ -172,23 +172,6 @@ RUNTIME_FUNCTION(Runtime_IsSimdValue) {
 }
 
 
-RUNTIME_FUNCTION(Runtime_SimdToObject) {
-  HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(Simd128Value, value, 0);
-  return *Object::ToObject(isolate, value).ToHandleChecked();
-}
-
-
-RUNTIME_FUNCTION(Runtime_SimdEquals) {
-  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);
-}
-
-
 RUNTIME_FUNCTION(Runtime_SimdSameValue) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 2);
index 2b437da..4774073 100644 (file)
@@ -407,7 +407,6 @@ namespace internal {
   F(NumberToIntegerMapMinusZero, 1, 1) \
   F(NumberToSmi, 1, 1)                 \
   F(NumberImul, 2, 1)                  \
-  F(NumberEquals, 2, 1)                \
   F(NumberCompare, 3, 1)               \
   F(SmiLexicographicCompare, 2, 1)     \
   F(MaxSmi, 0, 1)                      \
@@ -480,6 +479,7 @@ namespace internal {
   F(ToNumber, 1, 1)                                  \
   F(ToString, 1, 1)                                  \
   F(ToName, 1, 1)                                    \
+  F(Equals, 2, 1)                                    \
   F(StrictEquals, 2, 1)                              \
   F(InstanceOf, 2, 1)                                \
   F(HasInPrototypeChain, 2, 1)                       \
@@ -576,8 +576,6 @@ namespace internal {
 
 #define FOR_EACH_INTRINSIC_SIMD(F)             \
   F(IsSimdValue, 1, 1)                         \
-  F(SimdToObject, 1, 1)                        \
-  F(SimdEquals, 2, 1)                          \
   F(SimdSameValue, 2, 1)                       \
   F(SimdSameValueZero, 2, 1)                   \
   F(CreateFloat32x4, 4, 1)                     \
index ff8d4be..7000e1d 100644 (file)
@@ -1734,20 +1734,15 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
   __ Push(rax);
 
   // Figure out which native to call and setup the arguments.
-  if (cc == equal && strict()) {
+  if (cc == equal) {
     __ PushReturnAddressFrom(rcx);
-    __ TailCallRuntime(Runtime::kStrictEquals, 2, 1);
+    __ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
+                       1);
   } else {
-    int context_index;
-    if (cc == equal) {
-      context_index = Context::EQUALS_BUILTIN_INDEX;
-    } else {
-      context_index = is_strong(strength())
-                          ? Context::COMPARE_STRONG_BUILTIN_INDEX
-                          : Context::COMPARE_BUILTIN_INDEX;
-      __ Push(Smi::FromInt(NegativeComparisonResult(cc)));
-    }
-
+    int context_index = is_strong(strength())
+                            ? Context::COMPARE_STRONG_BUILTIN_INDEX
+                            : Context::COMPARE_BUILTIN_INDEX;
+    __ Push(Smi::FromInt(NegativeComparisonResult(cc)));
     __ PushReturnAddressFrom(rcx);
 
     // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)