Commit 0dc90304 authored by Ujjwal Sharma's avatar Ujjwal Sharma Committed by Commit Bot

[intl] Port V8BreakIterator.prototype.adoptText to C++

This increases the size of a V8BreakIterator instance by a word to store
the adopt text function.

The instance to be bound is stored on the context of this builtin function.

Bug: v8:5751
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I466ead6c8fc9d531d2213cfdd488fa1484496f69
Reviewed-on: https://chromium-review.googlesource.com/1186925
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55418}
parent 00afc6ad
......@@ -2997,6 +2997,18 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate_, prototype, factory->to_string_tag_symbol(),
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
SimpleInstallGetter(isolate_, prototype,
factory->InternalizeUtf8String("adoptText"),
Builtins::kBreakIteratorPrototypeAdoptText, false);
{
Handle<SharedFunctionInfo> info = SimpleCreateBuiltinSharedFunctionInfo(
isolate_, Builtins::kBreakIteratorInternalAdoptText,
factory->empty_string(), 1);
native_context()->set_break_iterator_internal_adopt_text_shared_fun(
*info);
}
}
{
......
......@@ -1391,7 +1391,9 @@ namespace internal {
/* ecma402 #sec-intl.collator.prototype.compare */ \
CPP(CollatorPrototypeCompare) \
/* ecma 402 #sec-collator-compare-functions*/ \
CPP(CollatorInternalCompare)
CPP(CollatorInternalCompare) \
CPP(BreakIteratorInternalAdoptText) \
CPP(BreakIteratorPrototypeAdoptText)
#else
#define BUILTIN_LIST_INTL(CPP, TFJ, TFS) \
/* no-op fallback version */ \
......
......@@ -1263,5 +1263,71 @@ BUILTIN(CollatorInternalCompare) {
return *Intl::CompareStrings(isolate, collator_holder, string_x, string_y);
}
BUILTIN(BreakIteratorPrototypeAdoptText) {
const char* const method = "get Intl.v8BreakIterator.prototype.adoptText";
HandleScope scope(isolate);
CHECK_RECEIVER(JSObject, break_iterator_holder, method);
if (!Intl::IsObjectOfType(isolate, break_iterator_holder,
Intl::Type::kBreakIterator)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
isolate->factory()->NewStringFromAsciiChecked(method),
break_iterator_holder));
}
Handle<Object> bound_adopt_text =
Handle<Object>(break_iterator_holder->GetEmbedderField(
V8BreakIterator::kBoundAdoptTextIndex),
isolate);
if (!bound_adopt_text->IsUndefined(isolate)) {
DCHECK(bound_adopt_text->IsJSFunction());
return *bound_adopt_text;
}
Handle<NativeContext> native_context(isolate->context()->native_context(),
isolate);
Handle<Context> context = isolate->factory()->NewBuiltinContext(
native_context, static_cast<int>(V8BreakIterator::ContextSlot::kLength));
context->set(static_cast<int>(V8BreakIterator::ContextSlot::kV8BreakIterator),
*break_iterator_holder);
Handle<SharedFunctionInfo> info = Handle<SharedFunctionInfo>(
native_context->break_iterator_internal_adopt_text_shared_fun(), isolate);
Handle<Map> map = isolate->strict_function_without_prototype_map();
Handle<JSFunction> new_bound_adopt_text_function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(map, info, context);
break_iterator_holder->SetEmbedderField(V8BreakIterator::kBoundAdoptTextIndex,
*new_bound_adopt_text_function);
return *new_bound_adopt_text_function;
}
BUILTIN(BreakIteratorInternalAdoptText) {
HandleScope scope(isolate);
Handle<Context> context = Handle<Context>(isolate->context(), isolate);
Handle<JSObject> break_iterator_holder = Handle<JSObject>(
JSObject::cast(context->get(
static_cast<int>(V8BreakIterator::ContextSlot::kV8BreakIterator))),
isolate);
DCHECK(Intl::IsObjectOfType(isolate, break_iterator_holder,
Intl::Type::kBreakIterator));
Handle<Object> input_text = args.atOrUndefined(isolate, 1);
Handle<String> text;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, text,
Object::ToString(isolate, input_text));
V8BreakIterator::AdoptText(isolate, break_iterator_holder, text);
return ReadOnlyRoots(isolate).undefined_value();
}
} // namespace internal
} // namespace v8
......@@ -217,6 +217,8 @@ enum ContextLookupFlags {
V(INTL_PLURAL_RULES_FUNCTION_INDEX, JSFunction, intl_plural_rules_function) \
V(INTL_V8_BREAK_ITERATOR_FUNCTION_INDEX, JSFunction, \
intl_v8_break_iterator_function) \
V(INTL_V8_BREAK_ITERATOR_INTERNAL_ADOPT_TEXT_SHARED_FUN, SharedFunctionInfo, \
break_iterator_internal_adopt_text_shared_fun) \
V(JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX, Map, \
js_array_packed_smi_elements_map) \
V(JS_ARRAY_HOLEY_SMI_ELEMENTS_MAP_INDEX, Map, \
......
......@@ -1375,15 +1375,6 @@ DEFINE_METHOD(
);
/**
* Adopts text to segment using the iterator. Old text, if present,
* gets discarded.
*/
function adoptText(iterator, text) {
%BreakIteratorAdoptText(iterator, TO_STRING(text));
}
/**
* Returns index of the first break in the string and moves current pointer.
*/
......@@ -1416,8 +1407,6 @@ function breakType(iterator) {
}
AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1,
BREAK_ITERATOR_TYPE, false);
AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0,
BREAK_ITERATOR_TYPE, false);
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0,
......
......@@ -813,7 +813,8 @@ icu::BreakIterator* V8BreakIterator::InitializeBreakIterator(
}
icu::BreakIterator* V8BreakIterator::UnpackBreakIterator(Handle<JSObject> obj) {
return reinterpret_cast<icu::BreakIterator*>(obj->GetEmbedderField(0));
return reinterpret_cast<icu::BreakIterator*>(
obj->GetEmbedderField(V8BreakIterator::kBreakIteratorIndex));
}
void V8BreakIterator::DeleteBreakIterator(
......@@ -823,6 +824,31 @@ void V8BreakIterator::DeleteBreakIterator(
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
void V8BreakIterator::AdoptText(Isolate* isolate,
Handle<JSObject> break_iterator_holder,
Handle<String> text) {
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
break_iterator_holder->GetEmbedderField(
V8BreakIterator::kUnicodeStringIndex));
delete u_text;
int length = text->length();
text = String::Flatten(isolate, text);
DisallowHeapAllocation no_gc;
String::FlatContent flat = text->GetFlatContent();
std::unique_ptr<uc16[]> sap;
const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
u_text = new icu::UnicodeString(text_value, length);
break_iterator_holder->SetEmbedderField(V8BreakIterator::kUnicodeStringIndex,
reinterpret_cast<Smi*>(u_text));
break_iterator->setText(*u_text);
}
MaybeHandle<String> Intl::ToString(Isolate* isolate,
const icu::UnicodeString& string) {
return isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
......
......@@ -184,10 +184,36 @@ class V8BreakIterator {
// holds the pointer gets garbage collected.
static void DeleteBreakIterator(const v8::WeakCallbackInfo<void>& data);
static void AdoptText(Isolate* isolate,
Handle<JSObject> break_iterator_holder,
Handle<String> text);
// Layout description.
static const int kBreakIterator = JSObject::kHeaderSize;
static const int kUnicodeString = kBreakIterator + kPointerSize;
static const int kSize = kUnicodeString + kPointerSize;
#define BREAK_ITERATOR_FIELDS(V) \
/* Pointer fields. */ \
V(kBreakIterator, kPointerSize) \
V(kUnicodeString, kPointerSize) \
V(kBoundAdoptText, kPointerSize) \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, BREAK_ITERATOR_FIELDS)
#undef BREAK_ITERATOR_FIELDS
// ContextSlot defines the context structure for the bound
// v8BreakIterator.prototype.adoptText function
enum class ContextSlot {
kV8BreakIterator = Context::MIN_CONTEXT_SLOTS,
kLength
};
// TODO(ryzokuken): Remove this and use regular accessors once v8BreakIterator
// is a subclass of JSObject
//
// This needs to be consistent with the above Layour Description
static const int kBreakIteratorIndex = 0;
static const int kUnicodeStringIndex = 1;
static const int kBoundAdoptTextIndex = 2;
private:
V8BreakIterator();
......
......@@ -371,9 +371,11 @@ RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
if (!break_iterator) return isolate->ThrowIllegalOperation();
local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(break_iterator));
local_object->SetEmbedderField(V8BreakIterator::kBreakIteratorIndex,
reinterpret_cast<Smi*>(break_iterator));
// Make sure that the pointer to adopted text is nullptr.
local_object->SetEmbedderField(1, static_cast<Smi*>(nullptr));
local_object->SetEmbedderField(V8BreakIterator::kUnicodeStringIndex,
static_cast<Smi*>(nullptr));
// Make object handle weak so we can delete the break iterator once GC kicks
// in.
......@@ -384,36 +386,6 @@ RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
return *local_object;
}
RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
break_iterator_holder->GetEmbedderField(1));
delete u_text;
int length = text->length();
text = String::Flatten(isolate, text);
DisallowHeapAllocation no_gc;
String::FlatContent flat = text->GetFlatContent();
std::unique_ptr<uc16[]> sap;
const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
u_text = new icu::UnicodeString(text_value, length);
break_iterator_holder->SetEmbedderField(1, reinterpret_cast<Smi*>(u_text));
break_iterator->setText(*u_text);
return ReadOnlyRoots(isolate).undefined_value();
}
RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
HandleScope scope(isolate);
......
......@@ -200,7 +200,6 @@ namespace internal {
#ifdef V8_INTL_SUPPORT
#define FOR_EACH_INTRINSIC_INTL(F) \
F(AvailableLocalesOf, 1, 1) \
F(BreakIteratorAdoptText, 2, 1) \
F(BreakIteratorBreakType, 1, 1) \
F(BreakIteratorCurrent, 1, 1) \
F(BreakIteratorFirst, 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