Commit dffaff77 authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Move cachedOrNewService to C++ w/o caching

Stage 1 of https://goo.gl/ooFdqJ

Bug: v8:7958,v8:7960,v8:7961
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Iabc69e547760122699a526a1255cb42bf9ddacb4
Reviewed-on: https://chromium-review.googlesource.com/c/1212466
Commit-Queue: Frank Tang <ftang@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarAleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57203}
parent 474a6d63
......@@ -703,10 +703,6 @@ action("js2c") {
"$target_gen_dir/libraries.cc",
]
if (v8_enable_i18n_support) {
sources += [ "src/js/intl.js" ]
}
args = [
rebase_path("$target_gen_dir/libraries.cc", root_build_dir),
"CORE",
......
......@@ -3004,6 +3004,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
isolate_, intl, "Collator", JS_INTL_COLLATOR_TYPE, JSCollator::kSize,
0, factory->the_hole_value(), Builtins::kCollatorConstructor);
collator_constructor->shared()->DontAdaptArguments();
InstallWithIntrinsicDefaultProto(isolate_, collator_constructor,
Context::INTL_COLLATOR_FUNCTION_INDEX);
SimpleInstallFunction(isolate(), collator_constructor,
"supportedLocalesOf",
......
......@@ -856,7 +856,7 @@ BUILTIN(DatePrototypeToLocaleDateString) {
args.atOrUndefined(isolate, 2), // options
JSDateTimeFormat::RequiredOption::kDate, // required
JSDateTimeFormat::DefaultsOption::kDate, // defaults
"dateformatdate")); // service
Intl::CacheType::kDateTimeFormatForDateToLocaleDateString));
}
// ecma402 #sup-date.prototype.tolocalestring
......@@ -875,7 +875,7 @@ BUILTIN(DatePrototypeToLocaleString) {
args.atOrUndefined(isolate, 2), // options
JSDateTimeFormat::RequiredOption::kAny, // required
JSDateTimeFormat::DefaultsOption::kAll, // defaults
"dateformatall")); // service
Intl::CacheType::kDateTimeFormatForDateToLocaleString));
}
// ecma402 #sup-date.prototype.tolocaletimestring
......@@ -894,7 +894,7 @@ BUILTIN(DatePrototypeToLocaleTimeString) {
args.atOrUndefined(isolate, 2), // options
JSDateTimeFormat::RequiredOption::kTime, // required
JSDateTimeFormat::DefaultsOption::kTime, // defaults
"dateformattime")); // service
Intl::CacheType::kDateTimeFormatForDateToLocaleTimeString));
}
#endif // V8_INTL_SUPPORT
......
......@@ -88,8 +88,6 @@ enum ContextLookupFlags {
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \
V(CACHED_OR_NEW_SERVICE_LOCALE_FUNCTION_INDEX, JSFunction, \
cached_or_new_service) \
V(SET_ADD_INDEX, JSFunction, set_add) \
V(SET_DELETE_INDEX, JSFunction, set_delete) \
V(SET_HAS_INDEX, JSFunction, set_has) \
......@@ -202,13 +200,14 @@ enum ContextLookupFlags {
V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \
V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
V(INTL_COLLATOR_FUNCTION_INDEX, JSFunction, intl_collator_function) \
V(INTL_DATE_TIME_FORMAT_FUNCTION_INDEX, JSFunction, \
intl_date_time_format_function) \
V(INTL_NUMBER_FORMAT_FUNCTION_INDEX, JSFunction, \
intl_number_format_function) \
V(INTL_LOCALE_FUNCTION_INDEX, JSFunction, intl_locale_function) \
V(INTL_SEGMENT_ITERATOR_MAP_INDEX, Map, intl_segment_iterator_map) \
V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
V(JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX, Map, \
js_array_packed_smi_elements_map) \
V(JS_ARRAY_HOLEY_SMI_ELEMENTS_MAP_INDEX, Map, \
......
// Copyright 2013 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.
// ECMAScript 402 API implementation.
/**
* Intl object is a single object that has some named properties,
* all of which are constructors.
*/
(function(global) {
"use strict";
%CheckIsBootstrapping();
// -------------------------------------------------------------------
// Imports
var GlobalIntl = global.Intl;
var GlobalIntlDateTimeFormat = GlobalIntl.DateTimeFormat;
var GlobalIntlNumberFormat = GlobalIntl.NumberFormat;
var GlobalIntlCollator = GlobalIntl.Collator;
// -------------------------------------------------------------------
// Save references to Intl objects and methods we use, for added security.
var savedObjects = {
__proto__: null,
'collator': GlobalIntlCollator,
'numberformat': GlobalIntlNumberFormat,
'dateformatall': GlobalIntlDateTimeFormat,
'dateformatdate': GlobalIntlDateTimeFormat,
'dateformattime': GlobalIntlDateTimeFormat
};
// Default (created with undefined locales and options parameters) collator,
// number and date format instances. They'll be created as needed.
var defaultObjects = {
__proto__: null,
'collator': UNDEFINED,
'numberformat': UNDEFINED,
'dateformatall': UNDEFINED,
'dateformatdate': UNDEFINED,
'dateformattime': UNDEFINED,
};
function clearDefaultObjects() {
defaultObjects['dateformatall'] = UNDEFINED;
defaultObjects['dateformatdate'] = UNDEFINED;
defaultObjects['dateformattime'] = UNDEFINED;
}
var date_cache_version = 0;
function checkDateCacheCurrent() {
var new_date_cache_version = %DateCacheVersion();
if (new_date_cache_version == date_cache_version) {
return;
}
date_cache_version = new_date_cache_version;
clearDefaultObjects();
}
/**
* Returns cached or newly created instance of a given service.
* We cache only default instances (where no locales or options are provided).
*/
function cachedOrNewService(service, locales, options, defaults) {
var useOptions = (IS_UNDEFINED(defaults)) ? options : defaults;
if (IS_UNDEFINED(locales) && IS_UNDEFINED(options)) {
checkDateCacheCurrent();
if (IS_UNDEFINED(defaultObjects[service])) {
defaultObjects[service] = new savedObjects[service](locales, useOptions);
}
return defaultObjects[service];
}
return new savedObjects[service](locales, useOptions);
}
// TODO(ftang) remove the %InstallToContext once
// cachedOrNewService is available in C++
%InstallToContext([
"cached_or_new_service", cachedOrNewService
]);
})
......@@ -389,21 +389,6 @@ std::string Intl::GetNumberingSystem(const icu::Locale& icu_locale) {
return value;
}
MaybeHandle<JSObject> Intl::CachedOrNewService(
Isolate* isolate, Handle<String> service, Handle<Object> locales,
Handle<Object> options, Handle<Object> internal_options) {
Handle<Object> result;
Handle<Object> undefined_value(ReadOnlyRoots(isolate).undefined_value(),
isolate);
Handle<Object> args[] = {service, locales, options, internal_options};
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
Execution::Call(isolate, isolate->cached_or_new_service(),
undefined_value, arraysize(args), args),
JSArray);
return Handle<JSObject>::cast(result);
}
icu::Locale Intl::CreateICULocale(const std::string& bcp47_locale) {
DisallowHeapAllocation no_gc;
......@@ -1155,12 +1140,11 @@ MaybeHandle<Object> Intl::StringLocaleCompare(Isolate* isolate,
Handle<String> string2,
Handle<Object> locales,
Handle<Object> options) {
Factory* factory = isolate->factory();
Handle<JSObject> collator;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, collator,
CachedOrNewService(isolate, factory->NewStringFromStaticChars("collator"),
locales, options, factory->undefined_value()),
CachedOrNew(isolate, Intl::CacheType::kCollatorForStringLocaleCompare,
locales, options),
Object);
CHECK(collator->IsJSCollator());
return Intl::CompareStrings(isolate, Handle<JSCollator>::cast(collator),
......@@ -1194,14 +1178,13 @@ MaybeHandle<String> Intl::NumberToLocaleString(Isolate* isolate,
Handle<Object> num,
Handle<Object> locales,
Handle<Object> options) {
Factory* factory = isolate->factory();
Handle<JSObject> number_format_holder;
// 2. Let numberFormat be ? Construct(%NumberFormat%, « locales, options »).
ASSIGN_RETURN_ON_EXCEPTION(
isolate, number_format_holder,
CachedOrNewService(isolate,
factory->NewStringFromStaticChars("numberformat"),
locales, options, factory->undefined_value()),
CachedOrNew(isolate,
Intl::CacheType::kNumberFormatForNumberToLocaleString,
locales, options),
String);
DCHECK(number_format_holder->IsJSNumberFormat());
Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>(
......@@ -1983,5 +1966,45 @@ Maybe<Intl::MatcherOption> Intl::GetLocaleMatcher(Isolate* isolate,
Intl::MatcherOption::kLookup);
}
template <typename T>
MaybeHandle<JSObject> New(Isolate* isolate, Object* constructor_obj,
Handle<Object> locales, Handle<Object> options) {
Handle<JSFunction> constructor =
Handle<JSFunction>(JSFunction::cast(constructor_obj), isolate);
Handle<JSObject> result;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, result,
JSObject::New(constructor, constructor, Handle<AllocationSite>::null()),
JSObject);
return T::Initialize(isolate, Handle<T>::cast(result), locales, options);
}
MaybeHandle<JSObject> Intl::CachedOrNew(Isolate* isolate,
Intl::CacheType cache_type,
Handle<Object> locales,
Handle<Object> options) {
// TODO(ftang): we may add cache mechanism here if both locales and locales
// are undefined.
Handle<Context> native_context =
Handle<Context>(isolate->context()->native_context(), isolate);
switch (cache_type) {
case Intl::CacheType::kCollatorForStringLocaleCompare:
return New<JSCollator>(isolate, native_context->intl_collator_function(),
locales, options);
case Intl::CacheType::kNumberFormatForNumberToLocaleString:
return New<JSNumberFormat>(isolate,
native_context->intl_number_format_function(),
locales, options);
case Intl::CacheType::kDateTimeFormatForDateToLocaleString:
case Intl::CacheType::kDateTimeFormatForDateToLocaleDateString:
case Intl::CacheType::kDateTimeFormatForDateToLocaleTimeString:
return New<JSDateTimeFormat>(
isolate, native_context->intl_date_time_format_function(), locales,
options);
}
}
} // namespace internal
} // namespace v8
......@@ -264,6 +264,20 @@ class Intl {
static const uint8_t* ToLatin1LowerTable();
static String* ConvertOneByteToLower(String* src, String* dst);
enum class CacheType {
kCollatorForStringLocaleCompare,
kDateTimeFormatForDateToLocaleString,
kDateTimeFormatForDateToLocaleDateString,
kDateTimeFormatForDateToLocaleTimeString,
kNumberFormatForNumberToLocaleString
};
// Factory method to create DateTimeFormat, NumberFormat and Collator
// for Date.prototype.toLocale(String|DateString|TimeString),
// Number.toLocaleString, and String.prototype.localeCompare.
V8_WARN_UNUSED_RESULT static MaybeHandle<JSObject> CachedOrNew(
Isolate* isolate, Intl::CacheType cache_type, Handle<Object> locales,
Handle<Object> options);
};
} // namespace internal
......
......@@ -473,7 +473,7 @@ MaybeHandle<String> JSDateTimeFormat::DateTimeFormat(
MaybeHandle<String> JSDateTimeFormat::ToLocaleDateTime(
Isolate* isolate, Handle<Object> date, Handle<Object> locales,
Handle<Object> options, RequiredOption required, DefaultsOption defaults,
const char* service) {
Intl::CacheType cache_type) {
Factory* factory = isolate->factory();
// 1. Let x be ? thisTimeValue(this value);
if (!date->IsJSDate()) {
......@@ -499,9 +499,7 @@ MaybeHandle<String> JSDateTimeFormat::ToLocaleDateTime(
Handle<JSObject> object;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, object,
Intl::CachedOrNewService(isolate,
factory->NewStringFromAsciiChecked(service),
locales, options, internal_options),
Intl::CachedOrNew(isolate, cache_type, locales, internal_options),
String);
CHECK(object->IsJSDateTimeFormat());
......
......@@ -13,6 +13,7 @@
#include <string>
#include "src/isolate.h"
#include "src/objects/intl-objects.h"
#include "src/objects/managed.h"
// Has to be the last include (doesn't have include guards):
......@@ -21,7 +22,7 @@
namespace U_ICU_NAMESPACE {
class Locale;
class SimpleDateFormat;
}
} // namespace U_ICU_NAMESPACE
namespace v8 {
namespace internal {
......@@ -68,7 +69,7 @@ class JSDateTimeFormat : public JSObject {
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToLocaleDateTime(
Isolate* isolate, Handle<Object> date, Handle<Object> locales,
Handle<Object> options, RequiredOption required, DefaultsOption defaults,
const char* service);
Intl::CacheType cache_type);
static std::set<std::string> GetAvailableLocales();
......
......@@ -113,23 +113,5 @@ RUNTIME_FUNCTION(Runtime_StringToUpperCaseIntl) {
RETURN_RESULT_OR_FAILURE(isolate, Intl::ConvertToUpper(isolate, s));
}
RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
if (isolate->serializer_enabled())
return ReadOnlyRoots(isolate).undefined_value();
if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
Handle<FixedArray> date_cache_version =
isolate->factory()->NewFixedArray(1, TENURED);
date_cache_version->set(0, Smi::kZero);
isolate->eternal_handles()->CreateSingleton(
isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
}
Handle<FixedArray> date_cache_version =
Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
EternalHandles::DATE_CACHE_VERSION));
return date_cache_version->get(0);
}
} // namespace internal
} // namespace v8
......@@ -200,7 +200,6 @@ namespace internal {
#ifdef V8_INTL_SUPPORT
#define FOR_EACH_INTRINSIC_INTL(F, I) \
F(CanonicalizeLanguageTag, 1, 1) \
F(DateCacheVersion, 0, 1) \
F(FormatList, 2, 1) \
F(FormatListToParts, 2, 1) \
F(GetDefaultICULocale, 0, 1) \
......
......@@ -193,28 +193,5 @@ TEST(DateParseLegacyUseCounter) {
CHECK_EQ(1, legacy_parse_count);
}
#ifdef V8_INTL_SUPPORT
TEST(DateCacheVersion) {
FLAG_allow_natives_syntax = true;
v8::Isolate* isolate = CcTest::isolate();
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope scope(isolate);
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
v8::Local<v8::Number> date_cache_version =
v8::Local<v8::Number>::Cast(CompileRun("%DateCacheVersion()"));
CHECK(date_cache_version->IsNumber());
CHECK_EQ(0.0, date_cache_version->NumberValue(context).FromMaybe(-1.0));
v8::Date::DateTimeConfigurationChangeNotification(isolate);
date_cache_version =
v8::Local<v8::Number>::Cast(CompileRun("%DateCacheVersion()"));
CHECK(date_cache_version->IsNumber());
CHECK_EQ(1.0, date_cache_version->NumberValue(context).FromMaybe(-1.0));
}
#endif // V8_INTL_SUPPORT
} // namespace internal
} // namespace v8
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