__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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;
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ InvokeBuiltin(context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ bind(&miss);
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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;
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ InvokeBuiltin(context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ Bind(&miss);
#define NATIVE_CONTEXT_JS_BUILTINS(V) \
V(APPLY_PREPARE_BUILTIN_INDEX, JSFunction, apply_prepare_builtin) \
- V(COMPARE_BUILTIN_INDEX, JSFunction, compare_builtin) \
- V(COMPARE_STRONG_BUILTIN_INDEX, JSFunction, compare_strong_builtin) \
V(CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, JSFunction, \
concat_iterable_to_array_builtin) \
V(REFLECT_APPLY_PREPARE_BUILTIN_INDEX, JSFunction, \
}
-void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(2, args->length());
-
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
-
- StringCompareStub stub(isolate());
- __ CallStub(&stub);
- context()->Plug(result_register());
-}
-
-
bool RecordStatementPosition(MacroAssembler* masm, int pos) {
if (pos == RelocInfo::kNoPosition) return false;
masm->positions_recorder()->RecordStatementPosition(pos);
F(StringCharCodeAt) \
F(StringAdd) \
F(SubString) \
- F(StringCompare) \
F(RegExpExec) \
F(RegExpConstructResult) \
F(NumberToString) \
}
-// Fast support for StringCompare.
-void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
- DCHECK_EQ(2, call->arguments()->length());
- CHECK_ALIVE(VisitExpressions(call->arguments()));
- PushArgumentsFromEnvironment(call->arguments()->length());
- HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
- return ast_context()->ReturnInstruction(result, call->id());
-}
-
-
void HOptimizedGraphBuilder::GenerateStringGetLength(CallRuntime* call) {
DCHECK(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
F(StringCharCodeAt) \
F(StringAdd) \
F(SubString) \
- F(StringCompare) \
F(RegExpExec) \
F(RegExpConstructResult) \
F(NumberToString) \
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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.
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ InvokeBuiltin(native_context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ bind(&miss);
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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;
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ InvokeBuiltin(context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ bind(&miss);
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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;
// Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
// tagged as a small integer.
- __ InvokeBuiltin(context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ bind(&miss);
}
+// static
+Maybe<bool> Object::GreaterThan(Handle<Object> x, Handle<Object> y,
+ Strength strength) {
+ Maybe<ComparisonResult> result = Compare(x, y, strength);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kGreaterThan:
+ return Just(true);
+ case ComparisonResult::kLessThan:
+ case ComparisonResult::kEqual:
+ case ComparisonResult::kUndefined:
+ return Just(false);
+ }
+ }
+ return Nothing<bool>();
+}
+
+
+// static
+Maybe<bool> Object::GreaterThanOrEqual(Handle<Object> x, Handle<Object> y,
+ Strength strength) {
+ Maybe<ComparisonResult> result = Compare(x, y, strength);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kEqual:
+ case ComparisonResult::kGreaterThan:
+ return Just(true);
+ case ComparisonResult::kLessThan:
+ case ComparisonResult::kUndefined:
+ return Just(false);
+ }
+ }
+ return Nothing<bool>();
+}
+
+
+// static
+Maybe<bool> Object::LessThan(Handle<Object> x, Handle<Object> y,
+ Strength strength) {
+ Maybe<ComparisonResult> result = Compare(x, y, strength);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kLessThan:
+ return Just(true);
+ case ComparisonResult::kEqual:
+ case ComparisonResult::kGreaterThan:
+ case ComparisonResult::kUndefined:
+ return Just(false);
+ }
+ }
+ return Nothing<bool>();
+}
+
+
+// static
+Maybe<bool> Object::LessThanOrEqual(Handle<Object> x, Handle<Object> y,
+ Strength strength) {
+ Maybe<ComparisonResult> result = Compare(x, y, strength);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kEqual:
+ case ComparisonResult::kLessThan:
+ return Just(true);
+ case ComparisonResult::kGreaterThan:
+ case ComparisonResult::kUndefined:
+ return Just(false);
+ }
+ }
+ return Nothing<bool>();
+}
+
+
MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
Handle<Name> name,
LanguageMode language_mode) {
#include "src/objects.h"
+#include <cmath>
#include <iomanip>
#include <sstream>
// TODO(bmeurer): Maybe we should introduce a marker interface Number,
// where we put all these methods at some point?
+ComparisonResult NumberCompare(double x, double y) {
+ if (std::isnan(x) || std::isnan(y)) {
+ return ComparisonResult::kUndefined;
+ } else if (x < y) {
+ return ComparisonResult::kLessThan;
+ } else if (x > y) {
+ return ComparisonResult::kGreaterThan;
+ } else {
+ return ComparisonResult::kEqual;
+ }
+}
+
+
bool NumberEquals(double x, double y) {
// Must check explicitly for NaN's on Windows, but -0 works fine.
if (std::isnan(x)) return false;
// static
+Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y,
+ Strength strength) {
+ if (!is_strong(strength)) {
+ // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
+ if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
+ !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
+ return Nothing<ComparisonResult>();
+ }
+ }
+ if (x->IsString() && y->IsString()) {
+ // ES6 section 7.2.11 Abstract Relational Comparison step 5.
+ return Just(
+ String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
+ }
+ // ES6 section 7.2.11 Abstract Relational Comparison step 6.
+ if (!is_strong(strength)) {
+ if (!Object::ToNumber(x).ToHandle(&x) ||
+ !Object::ToNumber(y).ToHandle(&y)) {
+ return Nothing<ComparisonResult>();
+ }
+ } else {
+ if (!x->IsNumber()) {
+ Isolate* const isolate = Handle<HeapObject>::cast(x)->GetIsolate();
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kStrongImplicitConversion));
+ return Nothing<ComparisonResult>();
+ } else if (!y->IsNumber()) {
+ Isolate* const isolate = Handle<HeapObject>::cast(y)->GetIsolate();
+ isolate->Throw(*isolate->factory()->NewTypeError(
+ MessageTemplate::kStrongImplicitConversion));
+ return Nothing<ComparisonResult>();
+ }
+ }
+ return Just(NumberCompare(x->Number(), y->Number()));
+}
+
+
+// static
Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
while (true) {
if (x->IsNumber()) {
}
+// static
+ComparisonResult String::Compare(Handle<String> x, Handle<String> y) {
+ // A few fast case tests before we flatten.
+ if (x.is_identical_to(y)) {
+ return ComparisonResult::kEqual;
+ } else if (y->length() == 0) {
+ return x->length() == 0 ? ComparisonResult::kEqual
+ : ComparisonResult::kGreaterThan;
+ } else if (x->length() == 0) {
+ return ComparisonResult::kLessThan;
+ }
+
+ int const d = x->Get(0) - y->Get(0);
+ if (d < 0) {
+ return ComparisonResult::kLessThan;
+ } else if (d > 0) {
+ return ComparisonResult::kGreaterThan;
+ }
+
+ // Slow case.
+ x = String::Flatten(x);
+ y = String::Flatten(y);
+
+ DisallowHeapAllocation no_gc;
+ ComparisonResult result = ComparisonResult::kEqual;
+ int prefix_length = x->length();
+ if (y->length() < prefix_length) {
+ prefix_length = y->length();
+ result = ComparisonResult::kGreaterThan;
+ } else if (y->length() > prefix_length) {
+ result = ComparisonResult::kLessThan;
+ }
+ int r;
+ String::FlatContent x_content = x->GetFlatContent();
+ String::FlatContent y_content = y->GetFlatContent();
+ if (x_content.IsOneByte()) {
+ Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
+ if (y_content.IsOneByte()) {
+ Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
+ r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
+ } else {
+ Vector<const uc16> y_chars = y_content.ToUC16Vector();
+ r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
+ }
+ } else {
+ Vector<const uc16> x_chars = x_content.ToUC16Vector();
+ if (y_content.IsOneByte()) {
+ Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
+ r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
+ } else {
+ Vector<const uc16> y_chars = y_content.ToUC16Vector();
+ r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
+ }
+ }
+ if (r < 0) {
+ result = ComparisonResult::kLessThan;
+ } else if (r > 0) {
+ result = ComparisonResult::kGreaterThan;
+ }
+ return result;
+}
+
+
bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
int slen = length();
// Can't check exact length equality, but we can check bounds.
};
+// TODO(bmeurer): Remove this in favor of the ComparisonResult below.
enum CompareResult {
LESS = -1,
EQUAL = 0,
};
+// Result of an abstract relational comparison of x and y, implemented according
+// to ES6 section 7.2.11 Abstract Relational Comparison.
+enum class ComparisonResult {
+ kLessThan, // x < y
+ kEqual, // x = y
+ kGreaterThan, // x > x
+ kUndefined // at least one of x or y was undefined or NaN
+};
+
+
#define DECL_BOOLEAN_ACCESSORS(name) \
inline bool name() const; \
inline void set_##name(bool value); \
bool BooleanValue(); // ECMA-262 9.2.
+ // ES6 section 7.2.11 Abstract Relational Comparison
+ MUST_USE_RESULT static Maybe<ComparisonResult> Compare(
+ Handle<Object> x, Handle<Object> y, Strength strength = Strength::WEAK);
+
// ES6 section 7.2.12 Abstract Equality Comparison
MUST_USE_RESULT static Maybe<bool> Equals(Handle<Object> x, Handle<Object> y);
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
Strength strength = Strength::WEAK);
+ // ES6 section 12.9 Relational Operators
+ MUST_USE_RESULT static inline Maybe<bool> GreaterThan(
+ Handle<Object> x, Handle<Object> y, Strength strength = Strength::WEAK);
+ MUST_USE_RESULT static inline Maybe<bool> GreaterThanOrEqual(
+ Handle<Object> x, Handle<Object> y, Strength strength = Strength::WEAK);
+ MUST_USE_RESULT static inline Maybe<bool> LessThan(
+ Handle<Object> x, Handle<Object> y, Strength strength = Strength::WEAK);
+ MUST_USE_RESULT static inline Maybe<bool> LessThanOrEqual(
+ Handle<Object> x, Handle<Object> y, Strength strength = Strength::WEAK);
+
// ES6 section 12.11 Binary Bitwise Operators
MUST_USE_RESULT static MaybeHandle<Object> BitwiseAnd(
Isolate* isolate, Handle<Object> lhs, Handle<Object> rhs,
// Requires: StringShape(this).IsIndirect() && this->IsFlat()
inline String* GetUnderlying();
+ // String relational comparison, implemented according to ES6 section 7.2.11
+ // Abstract Relational Comparison (step 5): The comparison of Strings uses a
+ // simple lexicographic ordering on sequences of code unit values. There is no
+ // attempt to use the more complex, semantically oriented definitions of
+ // character or string equality and collating order defined in the Unicode
+ // specification. Therefore String values that are canonically equal according
+ // to the Unicode standard could test as unequal. In effect this algorithm
+ // assumes that both Strings are already in normalized form. Also, note that
+ // for strings containing supplementary characters, lexicographic ordering on
+ // sequences of UTF-16 code unit values differs from that on sequences of code
+ // point values.
+ MUST_USE_RESULT static ComparisonResult Compare(Handle<String> x,
+ Handle<String> y);
+
// String equality operations.
inline bool Equals(String* other);
inline static bool Equals(Handle<String> one, Handle<String> two);
// ----------------------------------------------------------------------------
-/* -----------------------------------
-- - - C o m p a r i s o n - - -
------------------------------------
-*/
-
-// 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) {
- var left;
- var right;
- // Fast cases for string, numbers and undefined compares.
- if (IS_STRING(this)) {
- if (IS_STRING(x)) return %_StringCompare(this, x);
- if (IS_UNDEFINED(x)) return ncr;
- left = this;
- } else if (IS_NUMBER(this)) {
- if (IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
- if (IS_UNDEFINED(x)) return ncr;
- left = this;
- } else if (IS_UNDEFINED(this)) {
- if (!IS_UNDEFINED(x)) {
- %to_primitive(x, NUMBER_HINT);
- }
- return ncr;
- } else if (IS_UNDEFINED(x)) {
- %to_primitive(this, NUMBER_HINT);
- return ncr;
- } else {
- left = %to_primitive(this, NUMBER_HINT);
- }
-
- right = %to_primitive(x, NUMBER_HINT);
- if (IS_STRING(left) && IS_STRING(right)) {
- return %_StringCompare(left, right);
- } else {
- var left_number = %to_number_fun(left);
- var right_number = %to_number_fun(right);
- if (NUMBER_IS_NAN(left_number) || NUMBER_IS_NAN(right_number)) return ncr;
- return %NumberCompare(left_number, right_number, ncr);
- }
-}
-
-// Strong mode COMPARE throws if an implicit conversion would be performed
-function COMPARE_STRONG(x, ncr) {
- if (IS_STRING(this) && IS_STRING(x)) return %_StringCompare(this, x);
- if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberCompare(this, x, ncr);
-
- throw %make_type_error(kStrongImplicitConversion);
-}
-
-
/* -----------------------------
- - - H e l p e r s - - -
-----------------------------
%InstallToContext([
"apply_prepare_builtin", APPLY_PREPARE,
- "compare_builtin", COMPARE,
- "compare_strong_builtin", COMPARE_STRONG,
"concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY,
"reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
"reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
#include "src/bootstrapper.h"
#include "src/codegen.h"
-
-#ifndef _STLP_VENDOR_CSTD
-// STLPort doesn't import isless into the std namespace.
-using std::isless;
-#endif
-
namespace v8 {
namespace internal {
}
-RUNTIME_FUNCTION(Runtime_NumberCompare) {
- SealHandleScope shs(isolate);
- DCHECK(args.length() == 3);
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- CONVERT_DOUBLE_ARG_CHECKED(y, 1);
- CONVERT_ARG_HANDLE_CHECKED(Object, uncomparable_result, 2)
- if (std::isnan(x) || std::isnan(y)) return *uncomparable_result;
- if (x == y) return Smi::FromInt(EQUAL);
- if (isless(x, y)) return Smi::FromInt(LESS);
- return Smi::FromInt(GREATER);
-}
-
-
// Compare two Smis as if they were converted to strings and then
// compared lexicographically.
RUNTIME_FUNCTION(Runtime_SmiLexicographicCompare) {
}
+// TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
+// GreaterThan, etc. which return true or false.
+RUNTIME_FUNCTION(Runtime_Compare) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
+ Maybe<ComparisonResult> result = Object::Compare(x, y);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kLessThan:
+ return Smi::FromInt(LESS);
+ case ComparisonResult::kEqual:
+ return Smi::FromInt(EQUAL);
+ case ComparisonResult::kGreaterThan:
+ return Smi::FromInt(GREATER);
+ case ComparisonResult::kUndefined:
+ return *ncr;
+ }
+ UNREACHABLE();
+ }
+ return isolate->heap()->exception();
+}
+
+
+// TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
+// GreaterThan, etc. which return true or false.
+RUNTIME_FUNCTION(Runtime_Compare_Strong) {
+ HandleScope scope(isolate);
+ DCHECK_EQ(3, args.length());
+ CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
+ Maybe<ComparisonResult> result = Object::Compare(x, y, Strength::STRONG);
+ if (result.IsJust()) {
+ switch (result.FromJust()) {
+ case ComparisonResult::kLessThan:
+ return Smi::FromInt(LESS);
+ case ComparisonResult::kEqual:
+ return Smi::FromInt(EQUAL);
+ case ComparisonResult::kGreaterThan:
+ return Smi::FromInt(GREATER);
+ case ComparisonResult::kUndefined:
+ return *ncr;
+ }
+ UNREACHABLE();
+ }
+ return isolate->heap()->exception();
+}
+
+
RUNTIME_FUNCTION(Runtime_InstanceOf) {
// ECMA-262, section 11.8.6, page 54.
HandleScope shs(isolate);
RUNTIME_FUNCTION(Runtime_StringCompare) {
HandleScope handle_scope(isolate);
- DCHECK(args.length() == 2);
-
+ DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
-
isolate->counters()->string_compare_runtime()->Increment();
-
- // A few fast case tests before we flatten.
- if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
- if (y->length() == 0) {
- if (x->length() == 0) return Smi::FromInt(EQUAL);
- return Smi::FromInt(GREATER);
- } else if (x->length() == 0) {
- return Smi::FromInt(LESS);
- }
-
- int d = x->Get(0) - y->Get(0);
- if (d < 0)
- return Smi::FromInt(LESS);
- else if (d > 0)
- return Smi::FromInt(GREATER);
-
- // Slow case.
- x = String::Flatten(x);
- y = String::Flatten(y);
-
- DisallowHeapAllocation no_gc;
- Object* equal_prefix_result = Smi::FromInt(EQUAL);
- int prefix_length = x->length();
- if (y->length() < prefix_length) {
- prefix_length = y->length();
- equal_prefix_result = Smi::FromInt(GREATER);
- } else if (y->length() > prefix_length) {
- equal_prefix_result = Smi::FromInt(LESS);
- }
- int r;
- String::FlatContent x_content = x->GetFlatContent();
- String::FlatContent y_content = y->GetFlatContent();
- if (x_content.IsOneByte()) {
- Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
- if (y_content.IsOneByte()) {
- Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
- r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
- } else {
- Vector<const uc16> y_chars = y_content.ToUC16Vector();
- r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
- }
- } else {
- Vector<const uc16> x_chars = x_content.ToUC16Vector();
- if (y_content.IsOneByte()) {
- Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
- r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
- } else {
- Vector<const uc16> y_chars = y_content.ToUC16Vector();
- r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
- }
- }
- Object* result;
- if (r == 0) {
- result = equal_prefix_result;
- } else {
- result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
+ switch (String::Compare(x, y)) {
+ case ComparisonResult::kLessThan:
+ return Smi::FromInt(LESS);
+ case ComparisonResult::kEqual:
+ return Smi::FromInt(EQUAL);
+ case ComparisonResult::kGreaterThan:
+ return Smi::FromInt(GREATER);
+ case ComparisonResult::kUndefined:
+ break;
}
- return result;
+ UNREACHABLE();
+ return Smi::FromInt(0);
}
F(NumberToIntegerMapMinusZero, 1, 1) \
F(NumberToSmi, 1, 1) \
F(NumberImul, 2, 1) \
- F(NumberCompare, 3, 1) \
F(SmiLexicographicCompare, 2, 1) \
F(MaxSmi, 0, 1) \
F(IsSmi, 1, 1) \
F(ToName, 1, 1) \
F(Equals, 2, 1) \
F(StrictEquals, 2, 1) \
+ F(Compare, 3, 1) \
+ F(Compare_Strong, 3, 1) \
F(InstanceOf, 2, 1) \
F(HasInPrototypeChain, 2, 1) \
F(CreateIterResultObject, 2, 1) \
__ TailCallRuntime(strict() ? Runtime::kStrictEquals : Runtime::kEquals, 2,
1);
} else {
- 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)
- // tagged as a small integer.
- __ InvokeBuiltin(context_index, JUMP_FUNCTION);
+ __ TailCallRuntime(
+ is_strong(strength()) ? Runtime::kCompare_Strong : Runtime::kCompare, 3,
+ 1);
}
__ bind(&miss);