Commit 0ca84d06 authored by Daniel Ehrenberg's avatar Daniel Ehrenberg Committed by Commit Bot

Revert "[intl] Switch to using declared accessors"

This reverts commit 4968b2c4.

Reason for revert: Speculative revert for severe perf regression
https://bugs.chromium.org/p/chromium/issues/detail?id=716468#c3

Original change's description:
> [intl] Switch to using declared accessors
> 
> This patch cleans up the Intl code by switching to using declared
> accessors, rather than embedder fields, for holding references to
> ICU objects. Additionally:
> - Rename classes to be more similar to how other classes are named
> - Make some unreachable paths into check-fails, rather than throwing
>   JS exceptions
> - Move some macros from objects-inl.h into object-macros.h, to allow
>   the implementation here to not touch objects.h
> - Some setup logic is moved from runtime-i18n.cc to i18n.cc.
> 
> This patch leaves type tags as they are; a future patch should move
> from a special Intl type tagging system to object types as other system
> objects use. Future patches should also move more logic to i18n.cc
> 
> BUG=v8:5402,v8:5751,v8:6057
> CQ_INCLUDE_TRYBOTS=master.tryserver.v8:v8_linux_noi18n_rel_ng
> 
> Change-Id: Ia9cbb25cf8f52662e3deb15e64179d792c10842c
> Reviewed-on: https://chromium-review.googlesource.com/479651
> Commit-Queue: Daniel Ehrenberg <littledan@chromium.org>
> Reviewed-by: Adam Klein <adamk@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#44804}

TBR=adamk@chromium.org,marja@chromium.org,mstarzinger@chromium.org,littledan@chromium.org,jwolfe@igalia.com
# Not skipping CQ checks because original CL landed > 1 day ago.
BUG=v8:5402,v8:5751,v8:6057
CQ_INCLUDE_TRYBOTS=master.tryserver.v8:v8_linux_noi18n_rel_ng

Change-Id: I7a45d7def1f1de0f21e3efb7de9b31f6bcfea46d
Reviewed-on: https://chromium-review.googlesource.com/490328Reviewed-by: 's avatarDaniel Ehrenberg <littledan@chromium.org>
Commit-Queue: Daniel Ehrenberg <littledan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44992}
parent 1f629aac
......@@ -1715,7 +1715,6 @@ v8_source_set("v8_base") {
"src/objects/frame-array-inl.h",
"src/objects/frame-array.h",
"src/objects/hash-table.h",
"src/objects/intl-objects-inl.h",
"src/objects/intl-objects.cc",
"src/objects/intl-objects.h",
"src/objects/literal-objects.cc",
......@@ -2383,7 +2382,6 @@ v8_source_set("v8_base") {
"src/builtins/builtins-intl.cc",
"src/intl.cc",
"src/intl.h",
"src/objects/intl-objects-inl.h",
"src/objects/intl-objects.cc",
"src/objects/intl-objects.h",
"src/runtime/runtime-intl.cc",
......
......@@ -2641,7 +2641,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> date_time_format_constructor = InstallFunction(
intl, "DateTimeFormat", JS_OBJECT_TYPE, JSIntlDateTimeFormat::kSize,
intl, "DateTimeFormat", JS_OBJECT_TYPE, DateFormat::kSize,
date_time_format_prototype, Builtins::kIllegal);
JSObject::AddProperty(date_time_format_prototype,
factory->constructor_string(),
......@@ -2658,7 +2658,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> number_format_constructor = InstallFunction(
intl, "NumberFormat", JS_OBJECT_TYPE, JSIntlNumberFormat::kSize,
intl, "NumberFormat", JS_OBJECT_TYPE, NumberFormat::kSize,
number_format_prototype, Builtins::kIllegal);
JSObject::AddProperty(number_format_prototype,
factory->constructor_string(),
......@@ -2675,7 +2675,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> collator_constructor =
InstallFunction(intl, "Collator", JS_OBJECT_TYPE, JSIntlCollator::kSize,
InstallFunction(intl, "Collator", JS_OBJECT_TYPE, Collator::kSize,
collator_prototype, Builtins::kIllegal);
JSObject::AddProperty(collator_prototype, factory->constructor_string(),
collator_constructor, DONT_ENUM);
......@@ -2690,7 +2690,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> v8_break_iterator_constructor = InstallFunction(
intl, "v8BreakIterator", JS_OBJECT_TYPE, JSIntlV8BreakIterator::kSize,
intl, "v8BreakIterator", JS_OBJECT_TYPE, V8BreakIterator::kSize,
v8_break_iterator_prototype, Builtins::kIllegal);
JSObject::AddProperty(v8_break_iterator_prototype,
factory->constructor_string(),
......
......@@ -1286,6 +1286,15 @@ bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
return true;
}
#define FIELD_ADDR(p, offset) \
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
#define FIELD_ADDR_CONST(p, offset) \
(reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
#define READ_FIELD(p, offset) \
(*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset)))
#define ACQUIRE_READ_FIELD(p, offset) \
reinterpret_cast<Object*>(base::Acquire_Load( \
reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
......@@ -1294,6 +1303,9 @@ bool JSObject::PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
reinterpret_cast<Object*>(base::NoBarrier_Load( \
reinterpret_cast<const base::AtomicWord*>(FIELD_ADDR_CONST(p, offset))))
#define WRITE_FIELD(p, offset, value) \
(*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
#define RELEASE_WRITE_FIELD(p, offset, value) \
base::Release_Store( \
reinterpret_cast<base::AtomicWord*>(FIELD_ADDR(p, offset)), \
......@@ -8191,7 +8203,11 @@ SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)
#undef NOBARRIER_SMI_ACCESSORS
#undef BOOL_GETTER
#undef BOOL_ACCESSORS
#undef FIELD_ADDR
#undef FIELD_ADDR_CONST
#undef READ_FIELD
#undef NOBARRIER_READ_FIELD
#undef WRITE_FIELD
#undef NOBARRIER_WRITE_FIELD
#undef WRITE_BARRIER
#undef CONDITIONAL_WRITE_BARRIER
......
// Copyright 2017 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.
#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif // V8_INTL_SUPPORT
#ifndef V8_OBJECTS_INTL_OBJECTS_INL_H_
#define V8_OBJECTS_INTL_OBJECTS_INL_H_
#include "src/objects/intl-objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
#define PTR_ACCESSORS(holder, name, type, offset) \
inline type* holder::name() const { \
Object* obj = READ_FIELD(this, offset); \
DCHECK(obj->IsSmi()); \
return reinterpret_cast<type*>(obj); \
} \
inline void holder::set_##name(type* value) { \
Object* obj = reinterpret_cast<Object*>(value); \
DCHECK(obj->IsSmi()); \
WRITE_FIELD(this, offset, obj); \
}
namespace v8 {
namespace internal {
PTR_ACCESSORS(JSIntlDateTimeFormat, simple_date_format, icu::SimpleDateFormat,
kSimpleDateFormat)
PTR_ACCESSORS(JSIntlNumberFormat, decimal_format, icu::DecimalFormat,
kDecimalFormat)
PTR_ACCESSORS(JSIntlCollator, collator, icu::Collator, kCollator)
PTR_ACCESSORS(JSIntlV8BreakIterator, break_iterator, icu::BreakIterator,
kBreakIterator)
PTR_ACCESSORS(JSIntlV8BreakIterator, unicode_string, icu::UnicodeString,
kUnicodeString)
} // namespace internal
} // namespace v8
#undef PTR_ACCESSORS
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_INTL_OBJECTS_INL_H_
......@@ -14,8 +14,6 @@
#include "src/factory.h"
#include "src/isolate.h"
#include "src/objects-inl.h"
#include "src/objects/intl-objects-inl.h"
#include "unicode/brkiter.h"
#include "unicode/bytestream.h"
#include "unicode/calendar.h"
......@@ -695,7 +693,7 @@ void SetResolvedBreakIteratorSettings(Isolate* isolate,
} // namespace
// static
MaybeHandle<JSIntlDateTimeFormat> JSIntlDateTimeFormat::New(
icu::SimpleDateFormat* DateFormat::InitializeDateTimeFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
// Convert BCP47 into ICU locale format.
......@@ -708,7 +706,7 @@ MaybeHandle<JSIntlDateTimeFormat> JSIntlDateTimeFormat::New(
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
if (U_FAILURE(status) || icu_length == 0) {
FATAL("Locale lookup bug Intl.DateTimeFormat");
return NULL;
}
icu_locale = icu::Locale(icu_result);
}
......@@ -731,37 +729,20 @@ MaybeHandle<JSIntlDateTimeFormat> JSIntlDateTimeFormat::New(
SetResolvedDateSettings(isolate, icu_locale, date_format, resolved);
}
DCHECK_NOT_NULL(date_format);
Handle<JSFunction> constructor(
isolate->native_context()->intl_date_time_format_function());
Handle<Object> dtf_object;
ASSIGN_RETURN_ON_EXCEPTION(isolate, dtf_object,
JSObject::New(constructor, constructor),
JSIntlDateTimeFormat);
Handle<JSIntlDateTimeFormat> dtf(
reinterpret_cast<JSIntlDateTimeFormat*>(*dtf_object));
dtf->set_simple_date_format(date_format);
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*dtf);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
JSIntlDateTimeFormat::Delete,
WeakCallbackType::kFinalizer);
return date_format;
}
return dtf;
icu::SimpleDateFormat* DateFormat::UnpackDateFormat(Isolate* isolate,
Handle<JSObject> obj) {
return reinterpret_cast<icu::SimpleDateFormat*>(obj->GetEmbedderField(0));
}
void JSIntlDateTimeFormat::Delete(const v8::WeakCallbackInfo<void>& data) {
Object** wrapper = reinterpret_cast<Object**>(data.GetParameter());
JSIntlDateTimeFormat* dtf = reinterpret_cast<JSIntlDateTimeFormat*>(*wrapper);
delete dtf->simple_date_format();
GlobalHandles::Destroy(wrapper);
void DateFormat::DeleteDateFormat(const v8::WeakCallbackInfo<void>& data) {
delete reinterpret_cast<icu::SimpleDateFormat*>(data.GetInternalField(0));
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
MaybeHandle<JSIntlNumberFormat> JSIntlNumberFormat::New(
icu::DecimalFormat* NumberFormat::InitializeNumberFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
// Convert BCP47 into ICU locale format.
......@@ -774,7 +755,7 @@ MaybeHandle<JSIntlNumberFormat> JSIntlNumberFormat::New(
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
if (U_FAILURE(status) || icu_length == 0) {
FATAL("Locale lookup bug Intl.NumberFormat");
return NULL;
}
icu_locale = icu::Locale(icu_result);
}
......@@ -798,40 +779,23 @@ MaybeHandle<JSIntlNumberFormat> JSIntlNumberFormat::New(
SetResolvedNumberSettings(isolate, icu_locale, number_format, resolved);
}
DCHECK_NOT_NULL(number_format);
Handle<JSFunction> constructor(
isolate->native_context()->intl_number_format_function());
Handle<Object> nf_object;
ASSIGN_RETURN_ON_EXCEPTION(isolate, nf_object,
JSObject::New(constructor, constructor),
JSIntlNumberFormat);
Handle<JSIntlNumberFormat> nf(
reinterpret_cast<JSIntlNumberFormat*>(*nf_object));
nf->set_decimal_format(number_format);
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*nf);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
JSIntlNumberFormat::Delete,
WeakCallbackType::kFinalizer);
return number_format;
}
return nf;
icu::DecimalFormat* NumberFormat::UnpackNumberFormat(Isolate* isolate,
Handle<JSObject> obj) {
return reinterpret_cast<icu::DecimalFormat*>(obj->GetEmbedderField(0));
}
void JSIntlNumberFormat::Delete(const v8::WeakCallbackInfo<void>& data) {
Object** wrapper = reinterpret_cast<Object**>(data.GetParameter());
JSIntlNumberFormat* nf = reinterpret_cast<JSIntlNumberFormat*>(*wrapper);
delete nf->decimal_format();
GlobalHandles::Destroy(wrapper);
void NumberFormat::DeleteNumberFormat(const v8::WeakCallbackInfo<void>& data) {
delete reinterpret_cast<icu::DecimalFormat*>(data.GetInternalField(0));
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
MaybeHandle<JSIntlCollator> JSIntlCollator::New(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved) {
icu::Collator* Collator::InitializeCollator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved) {
// Convert BCP47 into ICU locale format.
UErrorCode status = U_ZERO_ERROR;
icu::Locale icu_locale;
......@@ -842,7 +806,7 @@ MaybeHandle<JSIntlCollator> JSIntlCollator::New(Isolate* isolate,
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
if (U_FAILURE(status) || icu_length == 0) {
FATAL("Locale lookup bug Intl.Collator");
return NULL;
}
icu_locale = icu::Locale(icu_result);
}
......@@ -864,35 +828,20 @@ MaybeHandle<JSIntlCollator> JSIntlCollator::New(Isolate* isolate,
SetResolvedCollatorSettings(isolate, icu_locale, collator, resolved);
}
DCHECK_NOT_NULL(collator);
Handle<JSFunction> constructor(
isolate->native_context()->intl_collator_function());
Handle<Object> coll_object;
ASSIGN_RETURN_ON_EXCEPTION(isolate, coll_object,
JSObject::New(constructor, constructor),
JSIntlCollator);
Handle<JSIntlCollator> coll(reinterpret_cast<JSIntlCollator*>(*coll_object));
coll->set_collator(collator);
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*coll);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
JSIntlCollator::Delete, WeakCallbackType::kFinalizer);
return collator;
}
return coll;
icu::Collator* Collator::UnpackCollator(Isolate* isolate,
Handle<JSObject> obj) {
return reinterpret_cast<icu::Collator*>(obj->GetEmbedderField(0));
}
void JSIntlCollator::Delete(const v8::WeakCallbackInfo<void>& data) {
Object** wrapper = reinterpret_cast<Object**>(data.GetParameter());
JSIntlCollator* coll = reinterpret_cast<JSIntlCollator*>(*wrapper);
delete coll->collator();
GlobalHandles::Destroy(wrapper);
void Collator::DeleteCollator(const v8::WeakCallbackInfo<void>& data) {
delete reinterpret_cast<icu::Collator*>(data.GetInternalField(0));
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
MaybeHandle<JSIntlV8BreakIterator> JSIntlV8BreakIterator::New(
icu::BreakIterator* V8BreakIterator::InitializeBreakIterator(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved) {
// Convert BCP47 into ICU locale format.
......@@ -905,7 +854,7 @@ MaybeHandle<JSIntlV8BreakIterator> JSIntlV8BreakIterator::New(
uloc_forLanguageTag(*bcp47_locale, icu_result, ULOC_FULLNAME_CAPACITY,
&icu_length, &status);
if (U_FAILURE(status) || icu_length == 0) {
FATAL("Locale lookup bug Intl.v8BreakIterator");
return NULL;
}
icu_locale = icu::Locale(icu_result);
}
......@@ -930,37 +879,19 @@ MaybeHandle<JSIntlV8BreakIterator> JSIntlV8BreakIterator::New(
resolved);
}
DCHECK_NOT_NULL(break_iterator);
Handle<JSFunction> constructor(
isolate->native_context()->intl_v8_break_iterator_function());
Handle<Object> br_object;
ASSIGN_RETURN_ON_EXCEPTION(isolate, br_object,
JSObject::New(constructor, constructor),
JSIntlV8BreakIterator);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*br_object));
br->set_break_iterator(break_iterator);
br->set_unicode_string(nullptr);
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*br);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
JSIntlV8BreakIterator::Delete,
WeakCallbackType::kFinalizer);
return break_iterator;
}
return br;
icu::BreakIterator* V8BreakIterator::UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj) {
return reinterpret_cast<icu::BreakIterator*>(obj->GetEmbedderField(0));
}
void JSIntlV8BreakIterator::Delete(const v8::WeakCallbackInfo<void>& data) {
Object** wrapper = reinterpret_cast<Object**>(data.GetParameter());
JSIntlV8BreakIterator* br =
reinterpret_cast<JSIntlV8BreakIterator*>(*wrapper);
delete br->break_iterator();
delete br->unicode_string();
GlobalHandles::Destroy(wrapper);
void V8BreakIterator::DeleteBreakIterator(
const v8::WeakCallbackInfo<void>& data) {
delete reinterpret_cast<icu::BreakIterator*>(data.GetInternalField(0));
delete reinterpret_cast<icu::UnicodeString*>(data.GetInternalField(1));
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
}
} // namespace internal
......
......@@ -17,98 +17,103 @@ class BreakIterator;
class Collator;
class DecimalFormat;
class SimpleDateFormat;
class UnicodeString;
}
namespace v8 {
namespace internal {
#define DECL_PTR_ACCESSORS(name, type) \
inline type* name() const; \
inline void set_##name(type* value);
template <typename T>
class Handle;
// Intl.DateTimeFormat
// ECMA-402#datetimeformat-objects
class JSIntlDateTimeFormat : public JSObject {
class DateFormat {
public:
DECL_PTR_ACCESSORS(simple_date_format, icu::SimpleDateFormat)
// Constructor for Intl.DateTimeFormat(), based on the resolved locale
// and user options. Writes resolved options into resolved.
MUST_USE_RESULT static MaybeHandle<JSIntlDateTimeFormat> New(
// Create a formatter for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::SimpleDateFormat* InitializeDateTimeFormat(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks date format object from corresponding JavaScript object.
static icu::SimpleDateFormat* UnpackDateFormat(Isolate* isolate,
Handle<JSObject> obj);
// Release memory we allocated for the DateFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteDateFormat(const v8::WeakCallbackInfo<void>& data);
// Layout description.
static const int kSimpleDateFormat = JSObject::kHeaderSize;
static const int kSize = kSimpleDateFormat + kPointerSize;
private:
// Finalizer responsible for freeing the icu::SimpleDateFormat
static void Delete(const v8::WeakCallbackInfo<void>& data);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSIntlDateTimeFormat);
DateFormat();
};
// Intl.NumberFormat
// ECMA-402#numberformat-objects
class JSIntlNumberFormat : public JSObject {
class NumberFormat {
public:
DECL_PTR_ACCESSORS(decimal_format, icu::DecimalFormat)
// Create a formatter for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::DecimalFormat* InitializeNumberFormat(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Constructor for Intl.NumberFormat(), based on the resolved locale
// and user options. Writes resolved options into resolved.
MUST_USE_RESULT static MaybeHandle<JSIntlNumberFormat> New(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks number format object from corresponding JavaScript object.
static icu::DecimalFormat* UnpackNumberFormat(Isolate* isolate,
Handle<JSObject> obj);
// Release memory we allocated for the NumberFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteNumberFormat(const v8::WeakCallbackInfo<void>& data);
// Layout description.
static const int kDecimalFormat = JSObject::kHeaderSize;
static const int kSize = kDecimalFormat + kPointerSize;
private:
// Finalizer responsible for freeing the icu::DecimalFormat
static void Delete(const v8::WeakCallbackInfo<void>& data);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSIntlNumberFormat);
NumberFormat();
};
// Intl.Collator
// ECMA-402#collator-objects
class JSIntlCollator : public JSObject {
class Collator {
public:
DECL_PTR_ACCESSORS(collator, icu::Collator)
// Create a collator for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::Collator* InitializeCollator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Constructor for Intl.Collator(), based on the resolved locale
// and user options. Writes resolved options into resolved.
MUST_USE_RESULT static MaybeHandle<JSIntlCollator> New(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks collator object from corresponding JavaScript object.
static icu::Collator* UnpackCollator(Isolate* isolate, Handle<JSObject> obj);
// Release memory we allocated for the Collator once the JS object that holds
// the pointer gets garbage collected.
static void DeleteCollator(const v8::WeakCallbackInfo<void>& data);
// Layout description.
static const int kCollator = JSObject::kHeaderSize;
static const int kSize = kCollator + kPointerSize;
private:
// Finalizer responsible for freeing the icu::Collator
static void Delete(const v8::WeakCallbackInfo<void>& data);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSIntlCollator);
Collator();
};
// Intl.v8BreakIterator, Custom non-standard V8 word break binding
// TODO(littledan,jwolfe): Specify, implement and ship Intl.Segmenter,
// allowing this interface to be deprecasted and removed.
class JSIntlV8BreakIterator : public JSObject {
class V8BreakIterator {
public:
DECL_PTR_ACCESSORS(break_iterator, icu::BreakIterator)
DECL_PTR_ACCESSORS(unicode_string, icu::UnicodeString)
// Create a BreakIterator for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::BreakIterator* InitializeBreakIterator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Constructor for Intl.v8BreakIterator(), based on the resolved locale
// and user options. Writes resolved options into resolved.
MUST_USE_RESULT static MaybeHandle<JSIntlV8BreakIterator> New(
Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks break iterator object from corresponding JavaScript object.
static icu::BreakIterator* UnpackBreakIterator(Isolate* isolate,
Handle<JSObject> obj);
// Release memory we allocated for the BreakIterator once the JS object that
// holds the pointer gets garbage collected.
static void DeleteBreakIterator(const v8::WeakCallbackInfo<void>& data);
// Layout description.
static const int kBreakIterator = JSObject::kHeaderSize;
......@@ -116,15 +121,9 @@ class JSIntlV8BreakIterator : public JSObject {
static const int kSize = kUnicodeString + kPointerSize;
private:
// Finalizer responsible for freeing the icu::BreakIterator
// and icu::UnicodeString
static void Delete(const v8::WeakCallbackInfo<void>& data);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSIntlV8BreakIterator);
V8BreakIterator();
};
#undef DECL_PTR_ACCESSORS
} // namespace internal
} // namespace v8
......
......@@ -8,7 +8,3 @@
#undef DECL_ACCESSORS
#undef DECLARE_CAST
#undef DECLARE_VERIFIER
#undef FIELD_ADDR
#undef FIELD_ADDR_CONST
#undef READ_FIELD
#undef WRITE_FIELD
......@@ -40,15 +40,3 @@
#else
#define DECLARE_VERIFIER(Name)
#endif
#define FIELD_ADDR(p, offset) \
(reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
#define FIELD_ADDR_CONST(p, offset) \
(reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
#define READ_FIELD(p, offset) \
(*reinterpret_cast<Object* const*>(FIELD_ADDR_CONST(p, offset)))
#define WRITE_FIELD(p, offset, value) \
(*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value)
......@@ -17,7 +17,6 @@
#include "src/intl.h"
#include "src/isolate-inl.h"
#include "src/messages.h"
#include "src/objects/intl-objects-inl.h"
#include "src/objects/intl-objects.h"
#include "src/utils.h"
......@@ -291,8 +290,27 @@ RUNTIME_FUNCTION(Runtime_CreateDateTimeFormat) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
RETURN_RESULT_OR_FAILURE(
isolate, JSIntlDateTimeFormat::New(isolate, locale, options, resolved));
Handle<JSFunction> constructor(
isolate->native_context()->intl_date_time_format_function());
Handle<JSObject> local_object;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
// Set date time formatter as embedder field of the resulting JS object.
icu::SimpleDateFormat* date_format =
DateFormat::InitializeDateTimeFormat(isolate, locale, options, resolved);
if (!date_format) return isolate->ThrowIllegalOperation();
local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(date_format));
// Make object handle weak so we can delete the data format once GC kicks in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
DateFormat::DeleteDateFormat,
WeakCallbackType::kInternalFields);
return *local_object;
}
RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
......@@ -306,10 +324,8 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormat) {
Handle<Object> value;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
Handle<JSIntlDateTimeFormat> dtf(
reinterpret_cast<JSIntlDateTimeFormat*>(*date_format_holder));
icu::SimpleDateFormat* date_format = dtf->simple_date_format();
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
CHECK_NOT_NULL(date_format);
icu::UnicodeString result;
......@@ -411,8 +427,7 @@ RUNTIME_FUNCTION(Runtime_InternalDateFormatToParts) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(date));
icu::SimpleDateFormat* date_format =
reinterpret_cast<JSIntlDateTimeFormat*>(*date_format_holder)
->simple_date_format();
DateFormat::UnpackDateFormat(isolate, date_format_holder);
CHECK_NOT_NULL(date_format);
icu::UnicodeString formatted;
......@@ -465,8 +480,26 @@ RUNTIME_FUNCTION(Runtime_CreateNumberFormat) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
RETURN_RESULT_OR_FAILURE(
isolate, JSIntlNumberFormat::New(isolate, locale, options, resolved));
Handle<JSFunction> constructor(
isolate->native_context()->intl_number_format_function());
Handle<JSObject> local_object;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
// Set number formatter as embedder field of the resulting JS object.
icu::DecimalFormat* number_format =
NumberFormat::InitializeNumberFormat(isolate, locale, options, resolved);
if (!number_format) return isolate->ThrowIllegalOperation();
local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(number_format));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
NumberFormat::DeleteNumberFormat,
WeakCallbackType::kInternalFields);
return *local_object;
}
RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
......@@ -481,8 +514,7 @@ RUNTIME_FUNCTION(Runtime_InternalNumberFormat) {
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(number));
icu::DecimalFormat* number_format =
reinterpret_cast<JSIntlNumberFormat*>(*number_format_holder)
->decimal_format();
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
CHECK_NOT_NULL(number_format);
icu::UnicodeString result;
......@@ -527,8 +559,26 @@ RUNTIME_FUNCTION(Runtime_CreateCollator) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
RETURN_RESULT_OR_FAILURE(
isolate, JSIntlCollator::New(isolate, locale, options, resolved));
Handle<JSFunction> constructor(
isolate->native_context()->intl_collator_function());
Handle<JSObject> local_object;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
// Set collator as embedder field of the resulting JS object.
icu::Collator* collator =
Collator::InitializeCollator(isolate, locale, options, resolved);
if (!collator) return isolate->ThrowIllegalOperation();
local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(collator));
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
Collator::DeleteCollator,
WeakCallbackType::kInternalFields);
return *local_object;
}
RUNTIME_FUNCTION(Runtime_InternalCompare) {
......@@ -540,8 +590,7 @@ RUNTIME_FUNCTION(Runtime_InternalCompare) {
CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
icu::Collator* collator =
reinterpret_cast<JSIntlCollator*>(*collator_holder)->collator();
icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
CHECK_NOT_NULL(collator);
string1 = String::Flatten(string1);
......@@ -577,8 +626,30 @@ RUNTIME_FUNCTION(Runtime_CreateBreakIterator) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
RETURN_RESULT_OR_FAILURE(
isolate, JSIntlV8BreakIterator::New(isolate, locale, options, resolved));
Handle<JSFunction> constructor(
isolate->native_context()->intl_v8_break_iterator_function());
Handle<JSObject> local_object;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, local_object,
JSObject::New(constructor, constructor));
// Set break iterator as embedder field of the resulting JS object.
icu::BreakIterator* break_iterator = V8BreakIterator::InitializeBreakIterator(
isolate, locale, options, resolved);
if (!break_iterator) return isolate->ThrowIllegalOperation();
local_object->SetEmbedderField(0, reinterpret_cast<Smi*>(break_iterator));
// Make sure that the pointer to adopted text is NULL.
local_object->SetEmbedderField(1, static_cast<Smi*>(nullptr));
// Make object handle weak so we can delete the break iterator once GC kicks
// in.
Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
GlobalHandles::MakeWeak(wrapper.location(), wrapper.location(),
V8BreakIterator::DeleteBreakIterator,
WeakCallbackType::kInternalFields);
return *local_object;
}
RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
......@@ -589,12 +660,12 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
icu::BreakIterator* break_iterator = br->break_iterator();
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
icu::UnicodeString* u_text = br->unicode_string();
icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
break_iterator_holder->GetEmbedderField(1));
delete u_text;
int length = text->length();
......@@ -604,7 +675,7 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorAdoptText) {
std::unique_ptr<uc16[]> sap;
const UChar* text_value = GetUCharBufferFromFlat(flat, &sap, length);
u_text = new icu::UnicodeString(text_value, length);
br->set_unicode_string(u_text);
break_iterator_holder->SetEmbedderField(1, reinterpret_cast<Smi*>(u_text));
break_iterator->setText(*u_text);
......@@ -618,9 +689,8 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorFirst) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
icu::BreakIterator* break_iterator = br->break_iterator();
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
return *isolate->factory()->NewNumberFromInt(break_iterator->first());
......@@ -633,9 +703,8 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorNext) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
icu::BreakIterator* break_iterator = br->break_iterator();
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
return *isolate->factory()->NewNumberFromInt(break_iterator->next());
......@@ -648,9 +717,8 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorCurrent) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
icu::BreakIterator* break_iterator = br->break_iterator();
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
return *isolate->factory()->NewNumberFromInt(break_iterator->current());
......@@ -663,9 +731,8 @@ RUNTIME_FUNCTION(Runtime_BreakIteratorBreakType) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
Handle<JSIntlV8BreakIterator> br(
reinterpret_cast<JSIntlV8BreakIterator*>(*break_iterator_holder));
icu::BreakIterator* break_iterator = br->break_iterator();
icu::BreakIterator* break_iterator =
V8BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
CHECK_NOT_NULL(break_iterator);
// TODO(cira): Remove cast once ICU fixes base BreakIterator class.
......
......@@ -1125,7 +1125,6 @@
'objects/frame-array-inl.h',
'objects/hash-table.h',
'objects/intl-objects.cc',
'objects/intl-objects-inl.h',
'objects/intl-objects.h',
'objects/literal-objects.cc',
'objects/literal-objects.h',
......@@ -1841,7 +1840,6 @@
'intl.cc',
'intl.h',
'objects/intl-objects.cc',
'objects/intl-objects-inl.h',
'objects/intl-objects.h',
'runtime/runtime-intl.cc',
],
......
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