bool Value::StrictEquals(Local<Value> that) const {
- i::Handle<i::Object> obj = Utils::OpenHandle(this);
- i::Handle<i::Object> 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<i::String>::cast(obj),
- i::Handle<i::String>::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);
}
__ 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);
__ 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);
// 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) \
__ 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);
// 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);
// 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);
}
+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)
}
+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()) {
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<JSReceiver> ToObject(Isolate* isolate,
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.
\
DECLARE_PRINTER(Type) \
\
+ inline bool Equals(Type* that); \
+ \
private: \
DISALLOW_IMPLICIT_CONSTRUCTORS(Type); \
};
__ 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);
} 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.
}
}
-// 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.
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
}
-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; }
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);
}
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) \
__ 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);
__ 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);