Commit 8ffbd333 authored by petermarshall's avatar petermarshall Committed by Commit bot

[builtins] Move StringLocaleCompare to a builtin.

CQ_INCLUDE_TRYBOTS=master.tryserver.v8:v8_linux_noi18n_rel_ng

BUG=v8:5364

Review-Url: https://codereview.chromium.org/2313393005
Cr-Commit-Position: refs/heads/master@{#39347}
parent d15f45d4
......@@ -1395,6 +1395,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
1, true);
SimpleInstallFunction(prototype, "charCodeAt",
Builtins::kStringPrototypeCharCodeAt, 1, true);
SimpleInstallFunction(prototype, "localeCompare",
Builtins::kStringPrototypeLocaleCompare, 1, true);
SimpleInstallFunction(prototype, "normalize",
Builtins::kStringPrototypeNormalize, 0, false);
SimpleInstallFunction(prototype, "toString",
......
......@@ -477,6 +477,57 @@ void Builtins::Generate_StringPrototypeCharCodeAt(
assembler->Return(result);
}
// ES6 section 21.1.3.10 String.prototype.localeCompare ( that )
//
// This function is implementation specific. For now, we do not
// do anything locale specific.
// If internationalization is enabled, then i18n.js will override this function
// and provide the proper functionality, so this is just a fallback.
BUILTIN(StringPrototypeLocaleCompare) {
HandleScope handle_scope(isolate);
DCHECK_EQ(2, args.length());
TO_THIS_STRING(str1, "String.prototype.localeCompare");
Handle<String> str2;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, str2, Object::ToString(isolate, args.at<Object>(1)));
if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
int str1_length = str1->length();
int str2_length = str2->length();
// Decide trivial cases without flattening.
if (str1_length == 0) {
if (str2_length == 0) return Smi::FromInt(0); // Equal.
return Smi::FromInt(-str2_length);
} else {
if (str2_length == 0) return Smi::FromInt(str1_length);
}
int end = str1_length < str2_length ? str1_length : str2_length;
// No need to flatten if we are going to find the answer on the first
// character. At this point we know there is at least one character
// in each string, due to the trivial case handling above.
int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
str1 = String::Flatten(str1);
str2 = String::Flatten(str2);
DisallowHeapAllocation no_gc;
String::FlatContent flat1 = str1->GetFlatContent();
String::FlatContent flat2 = str2->GetFlatContent();
for (int i = 0; i < end; i++) {
if (flat1.Get(i) != flat2.Get(i)) {
return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
}
}
return Smi::FromInt(str1_length - str2_length);
}
// ES6 section 21.1.3.12 String.prototype.normalize ( [form] )
//
// Simply checks the argument is valid and returns the string itself.
......
......@@ -535,6 +535,8 @@ namespace internal {
TFJ(StringPrototypeCharAt, 2) \
/* ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) */ \
TFJ(StringPrototypeCharCodeAt, 2) \
/* ES6 section 21.1.3.10 String.prototype.localeCompare ( that ) */ \
CPP(StringPrototypeLocaleCompare) \
/* ES6 section 21.1.3.12 String.prototype.normalize ( [form] ) */ \
CPP(StringPrototypeNormalize) \
/* ES6 section 21.1.3.25 String.prototype.toString () */ \
......
......@@ -87,17 +87,6 @@ function StringLastIndexOf(pat, pos) { // length == 1
%FunctionSetLength(StringLastIndexOf, 1);
// ECMA-262 section 15.5.4.9
//
// This function is implementation specific. For now, we do not
// do anything locale specific.
function StringLocaleCompareJS(other) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.localeCompare");
return %StringLocaleCompare(TO_STRING(this), TO_STRING(other));
}
// ES6 21.1.3.11.
function StringMatchJS(pattern) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.match");
......@@ -714,7 +703,6 @@ utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [
"includes", StringIncludes,
"indexOf", StringIndexOf,
"lastIndexOf", StringLastIndexOf,
"localeCompare", StringLocaleCompareJS,
"match", StringMatchJS,
"repeat", StringRepeat,
"replace", StringReplace,
......
......@@ -193,50 +193,6 @@ RUNTIME_FUNCTION(Runtime_StringLastIndexOf) {
}
RUNTIME_FUNCTION(Runtime_StringLocaleCompare) {
HandleScope handle_scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
int str1_length = str1->length();
int str2_length = str2->length();
// Decide trivial cases without flattening.
if (str1_length == 0) {
if (str2_length == 0) return Smi::FromInt(0); // Equal.
return Smi::FromInt(-str2_length);
} else {
if (str2_length == 0) return Smi::FromInt(str1_length);
}
int end = str1_length < str2_length ? str1_length : str2_length;
// No need to flatten if we are going to find the answer on the first
// character. At this point we know there is at least one character
// in each string, due to the trivial case handling above.
int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
str1 = String::Flatten(str1);
str2 = String::Flatten(str2);
DisallowHeapAllocation no_gc;
String::FlatContent flat1 = str1->GetFlatContent();
String::FlatContent flat2 = str2->GetFlatContent();
for (int i = 0; i < end; i++) {
if (flat1.Get(i) != flat2.Get(i)) {
return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
}
}
return Smi::FromInt(str1_length - str2_length);
}
RUNTIME_FUNCTION(Runtime_SubString) {
HandleScope scope(isolate);
DCHECK(args.length() == 3);
......
......@@ -798,7 +798,6 @@ namespace internal {
F(StringReplaceOneCharWithString, 3, 1) \
F(StringIndexOf, 3, 1) \
F(StringLastIndexOf, 3, 1) \
F(StringLocaleCompare, 2, 1) \
F(SubString, 3, 1) \
F(StringAdd, 2, 1) \
F(InternalizeString, 1, 1) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment