[runtime] Replace COMPARE/COMPARE_STRONG with proper Object::Compare.
authorbmeurer <bmeurer@chromium.org>
Fri, 18 Sep 2015 06:35:36 +0000 (23:35 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 18 Sep 2015 06:35:50 +0000 (06:35 +0000)
This removes the weird COMPARE and COMPARE_STRONG JavaScript builtins
and replaces them with a proper C++ implementation in Object::Compare
and appropriate wrappers Object::LessThan, Object::GreaterThan, and
friends that are intended to be used by a true/false returning CompareIC
in the future, as well as the interpreter.  As a short-term solution we
provide %Compare and %Compare_Strong entry points for the current
CompareIC that return the appropriate integer values expected by
fullcodegen currently.

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

BUG=v8:4307
LOG=n

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

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

19 files changed:
src/arm/code-stubs-arm.cc
src/arm64/code-stubs-arm64.cc
src/contexts.h
src/full-codegen/full-codegen.cc
src/full-codegen/full-codegen.h
src/hydrogen.cc
src/hydrogen.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-strings.cc
src/runtime/runtime.h
src/x64/code-stubs-x64.cc

index 8255942..7996779 100644 (file)
@@ -685,9 +685,6 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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;
@@ -700,7 +697,9 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
     // 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);
index 61bca1a..7173bdb 100644 (file)
@@ -656,9 +656,6 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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;
@@ -671,7 +668,9 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
     // 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);
index 69f6696..e5407f1 100644 (file)
@@ -92,8 +92,6 @@ enum BindingFlags {
 
 #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,                  \
index e889185..ea53844 100644 (file)
@@ -498,19 +498,6 @@ void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
 }
 
 
-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);
index dc11d15..3cdb6d5 100644 (file)
@@ -522,7 +522,6 @@ class FullCodeGenerator: public AstVisitor {
   F(StringCharCodeAt)                     \
   F(StringAdd)                            \
   F(SubString)                            \
-  F(StringCompare)                        \
   F(RegExpExec)                           \
   F(RegExpConstructResult)                \
   F(NumberToString)                       \
index 52184b3..135fafb 100644 (file)
@@ -12478,16 +12478,6 @@ void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
 }
 
 
-// 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)));
index f60f2cb..272bc5a 100644 (file)
@@ -2235,7 +2235,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   F(StringCharCodeAt)                  \
   F(StringAdd)                         \
   F(SubString)                         \
-  F(StringCompare)                     \
   F(RegExpExec)                        \
   F(RegExpConstructResult)             \
   F(NumberToString)                    \
index b61e1ef..e698c65 100644 (file)
@@ -1872,9 +1872,6 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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.
@@ -1882,7 +1879,9 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
     // 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);
index 3fd4842..ae03807 100644 (file)
@@ -731,9 +731,6 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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;
@@ -746,7 +743,9 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
     // 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);
index cb7e220..98ca852 100644 (file)
@@ -726,9 +726,6 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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;
@@ -741,7 +738,9 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
 
     // 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);
index 22736dc..1e0b683 100644 (file)
@@ -7076,6 +7076,78 @@ String* String::GetForwardedInternalizedString() {
 }
 
 
+// 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) {
index 4fa1b68..7db54aa 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "src/objects.h"
 
+#include <cmath>
 #include <iomanip>
 #include <sstream>
 
@@ -163,6 +164,19 @@ namespace {
 
 // 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;
@@ -184,6 +198,44 @@ bool NumberEquals(Handle<Object> x, Handle<Object> y) {
 
 
 // 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()) {
@@ -9603,6 +9655,69 @@ bool String::SlowEquals(Handle<String> one, Handle<String> two) {
 }
 
 
+// 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.
index 74ed139..e28081c 100644 (file)
@@ -800,6 +800,7 @@ enum FixedArraySubInstanceType {
 };
 
 
+// TODO(bmeurer): Remove this in favor of the ComparisonResult below.
 enum CompareResult {
   LESS      = -1,
   EQUAL     =  0,
@@ -809,6 +810,16 @@ enum CompareResult {
 };
 
 
+// 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);  \
@@ -1083,6 +1094,10 @@ class Object {
 
   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);
 
@@ -1148,6 +1163,16 @@ class Object {
       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,
@@ -8489,6 +8514,20 @@ class String: public Name {
   // 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);
index a49a3bd..9ace6ff 100644 (file)
@@ -38,57 +38,6 @@ var isConcatSpreadableSymbol =
 
 // ----------------------------------------------------------------------------
 
-/* -----------------------------------
-- - -   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   - - -
    -----------------------------
@@ -433,8 +382,6 @@ $toString = ToString;
 
 %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,
index bcdd89f..e4eae3a 100644 (file)
@@ -9,12 +9,6 @@
 #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 {
 
@@ -232,20 +226,6 @@ RUNTIME_FUNCTION(Runtime_NumberImul) {
 }
 
 
-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) {
index a1d9dfa..d2f1ee8 100644 (file)
@@ -1491,6 +1491,58 @@ RUNTIME_FUNCTION(Runtime_StrictEquals) {
 }
 
 
+// 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);
index 0e6bf83..b8ccbc8 100644 (file)
@@ -419,70 +419,22 @@ RUNTIME_FUNCTION(Runtime_CharFromCode) {
 
 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);
 }
 
 
index 546c33e..c1f72bb 100644 (file)
@@ -407,7 +407,6 @@ namespace internal {
   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)                       \
@@ -480,6 +479,8 @@ namespace internal {
   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)                    \
index 11f891c..dde834f 100644 (file)
@@ -1739,15 +1739,11 @@ void CompareICStub::GenerateGeneric(MacroAssembler* masm) {
     __ 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);