Commit e89d8b6a authored by franzih's avatar franzih Committed by Commit bot

[builtins] Migrate StringFromCodePoint to C++.

Instead of a JS implementation that calls C++ runtime functions, migrate String.fromCodePoint() to C++.

BUG=v8:5049

Review-Url: https://codereview.chromium.org/2038563003
Cr-Commit-Position: refs/heads/master@{#37293}
parent e09ea0a2
......@@ -1360,6 +1360,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(string_fun, "fromCharCode",
Builtins::kStringFromCharCode, 1, true);
// Install the String.fromCodePoint function.
SimpleInstallFunction(string_fun, "fromCodePoint",
Builtins::kStringFromCodePoint, 1, false);
// Create the %StringPrototype%
Handle<JSValue> prototype =
Handle<JSValue>::cast(factory->NewJSObject(string_fun, TENURED));
......
......@@ -4633,7 +4633,7 @@ void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
Node* code = assembler->Parameter(1);
Node* context = assembler->Parameter(4);
// Check if we have exactly one arguments (plus the implicit receiver), i.e.
// Check if we have exactly one argument (plus the implicit receiver), i.e.
// if the parent frame is not an arguments adaptor frame.
Label if_oneargument(assembler), if_notoneargument(assembler);
Node* parent_frame_pointer = assembler->LoadParentFramePointer();
......@@ -4811,6 +4811,99 @@ void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
}
}
namespace { // for String.fromCodePoint
bool IsValidCodePoint(Isolate* isolate, Handle<Object> value) {
if (!value->IsNumber() && !Object::ToNumber(value).ToHandle(&value)) {
return false;
}
if (Object::ToInteger(isolate, value).ToHandleChecked()->Number() !=
value->Number()) {
return false;
}
if (value->Number() < 0 || value->Number() > 0x10FFFF) {
return false;
}
return true;
}
uc32 NextCodePoint(Isolate* isolate, BuiltinArguments args, int index) {
Handle<Object> value = args.at<Object>(1 + index);
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::ToNumber(value), -1);
if (!IsValidCodePoint(isolate, value)) {
isolate->Throw(*isolate->factory()->NewRangeError(
MessageTemplate::kInvalidCodePoint, value));
return -1;
}
return DoubleToUint32(value->Number());
}
} // namespace
// ES6 section 21.1.2.2 String.fromCodePoint ( ...codePoints )
BUILTIN(StringFromCodePoint) {
HandleScope scope(isolate);
int const length = args.length() - 1;
if (length == 0) return isolate->heap()->empty_string();
DCHECK_LT(0, length);
// Optimistically assume that the resulting String contains only one byte
// characters.
List<uint8_t> one_byte_buffer(length);
uc32 code = 0;
int index;
for (index = 0; index < length; index++) {
code = NextCodePoint(isolate, args, index);
if (code < 0) {
return isolate->heap()->exception();
}
if (code > String::kMaxOneByteCharCode) {
break;
}
one_byte_buffer.Add(code);
}
if (index == length) {
RETURN_RESULT_OR_FAILURE(isolate, isolate->factory()->NewStringFromOneByte(
one_byte_buffer.ToConstVector()));
}
List<uc16> two_byte_buffer(length - index);
while (true) {
if (code <= unibrow::Utf16::kMaxNonSurrogateCharCode) {
two_byte_buffer.Add(code);
} else {
two_byte_buffer.Add(unibrow::Utf16::LeadSurrogate(code));
two_byte_buffer.Add(unibrow::Utf16::TrailSurrogate(code));
}
if (++index == length) {
break;
}
code = NextCodePoint(isolate, args, index);
if (code < 0) {
return isolate->heap()->exception();
}
}
Handle<SeqTwoByteString> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewRawTwoByteString(one_byte_buffer.length() +
two_byte_buffer.length()));
CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(),
one_byte_buffer.length());
CopyChars(result->GetChars() + one_byte_buffer.length(),
two_byte_buffer.ToConstVector().start(), two_byte_buffer.length());
return *result;
}
// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -161,6 +162,8 @@ class CodeStubAssembler;
V(ReflectSet) \
V(ReflectSetPrototypeOf) \
\
V(StringFromCodePoint) \
\
V(StringPrototypeTrim) \
V(StringPrototypeTrimLeft) \
V(StringPrototypeTrimRight) \
......
......@@ -747,33 +747,6 @@ function StringCodePointAt(pos) {
}
// ES6 Draft 05-22-2014, section 21.1.2.2
function StringFromCodePoint(_) { // length = 1
"use strict";
var code;
var length = arguments.length;
var index;
var result = "";
for (index = 0; index < length; index++) {
code = arguments[index];
if (!%_IsSmi(code)) {
code = TO_NUMBER(code);
}
if (code < 0 || code > 0x10FFFF || code !== TO_INTEGER(code)) {
throw MakeRangeError(kInvalidCodePoint, code);
}
if (code <= 0xFFFF) {
result += %_StringCharFromCode(code);
} else {
code -= 0x10000;
result += %_StringCharFromCode((code >>> 10) & 0x3FF | 0xD800);
result += %_StringCharFromCode(code & 0x3FF | 0xDC00);
}
}
return result;
}
// -------------------------------------------------------------------
// String methods related to templates
......@@ -802,7 +775,6 @@ function StringRaw(callSite) {
// Set up the non-enumerable functions on the String object.
utils.InstallFunctions(GlobalString, DONT_ENUM, [
"fromCodePoint", StringFromCodePoint,
"raw", StringRaw
]);
......
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