Commit e7bd43c3 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[runtime] Cleanup native methods creation in js/intl.js.

This CL replaces usages of utils.InstallFunctions and utils.InstallGetter()
with the DEFINE_METHOD* macros that ensure that the native function is
created in proper form from the beginning. Thus the function will not
require further reconfiguring like adding a computed name or removing of
'prototype' property.

This CL is one of a series of cleanup CL which are the preliminary steps for
improving function closures creation.

Bug: v8:6459
Cq-Include-Trybots: master.tryserver.v8:v8_linux_noi18n_rel_ng
Change-Id: I667d70fae12a2f50d0fe18d958b6520110b4b573
Reviewed-on: https://chromium-review.googlesource.com/548075
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46278}
parent f9e0322a
...@@ -29,15 +29,11 @@ var GlobalNumber = global.Number; ...@@ -29,15 +29,11 @@ var GlobalNumber = global.Number;
var GlobalRegExp = global.RegExp; var GlobalRegExp = global.RegExp;
var GlobalString = global.String; var GlobalString = global.String;
var IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol"); var IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol");
var InstallFunctions = utils.InstallFunctions;
var InstallGetter = utils.InstallGetter;
var InternalArray = utils.InternalArray; var InternalArray = utils.InternalArray;
var MaxSimple; var MaxSimple;
var ObjectHasOwnProperty = global.Object.prototype.hasOwnProperty; var ObjectHasOwnProperty = global.Object.prototype.hasOwnProperty;
var OverrideFunction = utils.OverrideFunction;
var patternSymbol = utils.ImportNow("intl_pattern_symbol"); var patternSymbol = utils.ImportNow("intl_pattern_symbol");
var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); var resolvedSymbol = utils.ImportNow("intl_resolved_symbol");
var SetFunctionName = utils.SetFunctionName;
var StringSubstr = GlobalString.prototype.substr; var StringSubstr = GlobalString.prototype.substr;
var StringSubstring = GlobalString.prototype.substring; var StringSubstring = GlobalString.prototype.substring;
...@@ -49,11 +45,6 @@ utils.Import(function(from) { ...@@ -49,11 +45,6 @@ utils.Import(function(from) {
// Utilities for definitions // Utilities for definitions
function InstallFunction(object, name, func) {
InstallFunctions(object, DONT_ENUM, [name, func]);
}
/** /**
* Adds bound method to the prototype of the given object. * Adds bound method to the prototype of the given object.
*/ */
...@@ -61,41 +52,36 @@ function AddBoundMethod(obj, methodName, implementation, length, typename, ...@@ -61,41 +52,36 @@ function AddBoundMethod(obj, methodName, implementation, length, typename,
compat) { compat) {
%CheckIsBootstrapping(); %CheckIsBootstrapping();
var internalName = %CreatePrivateSymbol(methodName); var internalName = %CreatePrivateSymbol(methodName);
// Making getter an anonymous function will cause
// %DefineGetterPropertyUnchecked to properly set the "name" DEFINE_METHOD(
// property on each JSFunction instance created here, rather obj.prototype,
// than (as utils.InstallGetter would) on the SharedFunctionInfo get [methodName]() {
// associated with all functions returned from AddBoundMethod. var receiver = Unwrap(this, typename, obj, methodName, compat);
var getter = ANONYMOUS_FUNCTION(function() { if (IS_UNDEFINED(receiver[internalName])) {
var receiver = Unwrap(this, typename, obj, methodName, compat); var boundMethod;
if (IS_UNDEFINED(receiver[internalName])) { if (IS_UNDEFINED(length) || length === 2) {
var boundMethod; boundMethod =
if (IS_UNDEFINED(length) || length === 2) { ANONYMOUS_FUNCTION((fst, snd) => implementation(receiver, fst, snd));
boundMethod = } else if (length === 1) {
ANONYMOUS_FUNCTION((fst, snd) => implementation(receiver, fst, snd)); boundMethod = ANONYMOUS_FUNCTION(fst => implementation(receiver, fst));
} else if (length === 1) { } else {
boundMethod = ANONYMOUS_FUNCTION(fst => implementation(receiver, fst)); boundMethod = ANONYMOUS_FUNCTION((...args) => {
} else { // DateTimeFormat.format needs to be 0 arg method, but can still
boundMethod = ANONYMOUS_FUNCTION((...args) => { // receive an optional dateValue param. If one was provided, pass it
// DateTimeFormat.format needs to be 0 arg method, but can still // along.
// receive an optional dateValue param. If one was provided, pass it if (args.length > 0) {
// along. return implementation(receiver, args[0]);
if (args.length > 0) { } else {
return implementation(receiver, args[0]); return implementation(receiver);
} else { }
return implementation(receiver); });
} }
}); %SetNativeFlag(boundMethod);
receiver[internalName] = boundMethod;
} }
%SetNativeFlag(boundMethod); return receiver[internalName];
receiver[internalName] = boundMethod;
} }
return receiver[internalName]; );
});
%FunctionRemovePrototype(getter);
%DefineGetterPropertyUnchecked(obj.prototype, methodName, getter, DONT_ENUM);
%SetNativeFlag(getter);
} }
function IntlConstruct(receiver, constructor, create, newTarget, args, function IntlConstruct(receiver, constructor, create, newTarget, args,
...@@ -914,7 +900,9 @@ function BuildLanguageTagREs() { ...@@ -914,7 +900,9 @@ function BuildLanguageTagREs() {
} }
// ECMA 402 section 8.2.1 // ECMA 402 section 8.2.1
InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) { DEFINE_METHOD(
GlobalIntl,
getCanonicalLocales(locales) {
return makeArray(canonicalizeLocaleList(locales)); return makeArray(canonicalizeLocaleList(locales));
} }
); );
...@@ -1035,7 +1023,9 @@ function CollatorConstructor() { ...@@ -1035,7 +1023,9 @@ function CollatorConstructor() {
/** /**
* Collator resolvedOptions method. * Collator resolvedOptions method.
*/ */
InstallFunction(GlobalIntlCollator.prototype, 'resolvedOptions', function() { DEFINE_METHOD(
GlobalIntlCollator.prototype,
resolvedOptions() {
var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions', var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions',
false); false);
return { return {
...@@ -1057,7 +1047,9 @@ InstallFunction(GlobalIntlCollator.prototype, 'resolvedOptions', function() { ...@@ -1057,7 +1047,9 @@ InstallFunction(GlobalIntlCollator.prototype, 'resolvedOptions', function() {
* order in the returned list as in the input list. * order in the returned list as in the input list.
* Options are optional parameter. * Options are optional parameter.
*/ */
InstallFunction(GlobalIntlCollator, 'supportedLocalesOf', function(locales) { DEFINE_METHOD(
GlobalIntlCollator,
supportedLocalesOf(locales) {
return supportedLocalesOf('collator', locales, arguments[1]); return supportedLocalesOf('collator', locales, arguments[1]);
} }
); );
...@@ -1254,8 +1246,9 @@ function NumberFormatConstructor() { ...@@ -1254,8 +1246,9 @@ function NumberFormatConstructor() {
/** /**
* NumberFormat resolvedOptions method. * NumberFormat resolvedOptions method.
*/ */
InstallFunction(GlobalIntlNumberFormat.prototype, 'resolvedOptions', DEFINE_METHOD(
function() { GlobalIntlNumberFormat.prototype,
resolvedOptions() {
var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat, var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat,
'resolvedOptions', true); 'resolvedOptions', true);
var result = { var result = {
...@@ -1295,8 +1288,9 @@ InstallFunction(GlobalIntlNumberFormat.prototype, 'resolvedOptions', ...@@ -1295,8 +1288,9 @@ InstallFunction(GlobalIntlNumberFormat.prototype, 'resolvedOptions',
* order in the returned list as in the input list. * order in the returned list as in the input list.
* Options are optional parameter. * Options are optional parameter.
*/ */
InstallFunction(GlobalIntlNumberFormat, 'supportedLocalesOf', DEFINE_METHOD(
function(locales) { GlobalIntlNumberFormat,
supportedLocalesOf(locales) {
return supportedLocalesOf('numberformat', locales, arguments[1]); return supportedLocalesOf('numberformat', locales, arguments[1]);
} }
); );
...@@ -1614,8 +1608,9 @@ function DateTimeFormatConstructor() { ...@@ -1614,8 +1608,9 @@ function DateTimeFormatConstructor() {
/** /**
* DateTimeFormat resolvedOptions method. * DateTimeFormat resolvedOptions method.
*/ */
InstallFunction(GlobalIntlDateTimeFormat.prototype, 'resolvedOptions', DEFINE_METHOD(
function() { GlobalIntlDateTimeFormat.prototype,
resolvedOptions() {
var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat, var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat,
'resolvedOptions', true); 'resolvedOptions', true);
...@@ -1666,8 +1661,9 @@ InstallFunction(GlobalIntlDateTimeFormat.prototype, 'resolvedOptions', ...@@ -1666,8 +1661,9 @@ InstallFunction(GlobalIntlDateTimeFormat.prototype, 'resolvedOptions',
* order in the returned list as in the input list. * order in the returned list as in the input list.
* Options are optional parameter. * Options are optional parameter.
*/ */
InstallFunction(GlobalIntlDateTimeFormat, 'supportedLocalesOf', DEFINE_METHOD(
function(locales) { GlobalIntlDateTimeFormat,
supportedLocalesOf(locales) {
return supportedLocalesOf('dateformat', locales, arguments[1]); return supportedLocalesOf('dateformat', locales, arguments[1]);
} }
); );
...@@ -1691,8 +1687,9 @@ function formatDate(formatter, dateValue) { ...@@ -1691,8 +1687,9 @@ function formatDate(formatter, dateValue) {
return %InternalDateFormat(formatter, new GlobalDate(dateMs)); return %InternalDateFormat(formatter, new GlobalDate(dateMs));
} }
InstallFunction(GlobalIntlDateTimeFormat.prototype, 'formatToParts', DEFINE_METHOD(
function(dateValue) { GlobalIntlDateTimeFormat.prototype,
formatToParts(dateValue) {
CHECK_OBJECT_COERCIBLE(this, "Intl.DateTimeFormat.prototype.formatToParts"); CHECK_OBJECT_COERCIBLE(this, "Intl.DateTimeFormat.prototype.formatToParts");
if (!IS_OBJECT(this)) { if (!IS_OBJECT(this)) {
throw %make_type_error(kCalledOnNonObject, this); throw %make_type_error(kCalledOnNonObject, this);
...@@ -1810,8 +1807,9 @@ function v8BreakIteratorConstructor() { ...@@ -1810,8 +1807,9 @@ function v8BreakIteratorConstructor() {
/** /**
* BreakIterator resolvedOptions method. * BreakIterator resolvedOptions method.
*/ */
InstallFunction(GlobalIntlv8BreakIterator.prototype, 'resolvedOptions', DEFINE_METHOD(
function() { GlobalIntlv8BreakIterator.prototype,
resolvedOptions() {
if (!IS_UNDEFINED(new.target)) { if (!IS_UNDEFINED(new.target)) {
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
} }
...@@ -1833,8 +1831,9 @@ InstallFunction(GlobalIntlv8BreakIterator.prototype, 'resolvedOptions', ...@@ -1833,8 +1831,9 @@ InstallFunction(GlobalIntlv8BreakIterator.prototype, 'resolvedOptions',
* order in the returned list as in the input list. * order in the returned list as in the input list.
* Options are optional parameter. * Options are optional parameter.
*/ */
InstallFunction(GlobalIntlv8BreakIterator, 'supportedLocalesOf', DEFINE_METHOD(
function(locales) { GlobalIntlv8BreakIterator,
supportedLocalesOf(locales) {
if (!IS_UNDEFINED(new.target)) { if (!IS_UNDEFINED(new.target)) {
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
} }
...@@ -1976,7 +1975,9 @@ function LocaleConvertCase(s, locales, isToUpper) { ...@@ -1976,7 +1975,9 @@ function LocaleConvertCase(s, locales, isToUpper) {
* Compares this and that, and returns less than 0, 0 or greater than 0 value. * Compares this and that, and returns less than 0, 0 or greater than 0 value.
* Overrides the built-in method. * Overrides the built-in method.
*/ */
OverrideFunction(GlobalString.prototype, 'localeCompare', function(that) { DEFINE_METHOD(
GlobalString.prototype,
localeCompare(that) {
if (IS_NULL_OR_UNDEFINED(this)) { if (IS_NULL_OR_UNDEFINED(this)) {
throw %make_type_error(kMethodInvokedOnNullOrUndefined); throw %make_type_error(kMethodInvokedOnNullOrUndefined);
} }
...@@ -1988,26 +1989,31 @@ OverrideFunction(GlobalString.prototype, 'localeCompare', function(that) { ...@@ -1988,26 +1989,31 @@ OverrideFunction(GlobalString.prototype, 'localeCompare', function(that) {
} }
); );
function ToLocaleLowerCaseIntl(locales) { var StringPrototypeMethods = {};
CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase"); DEFINE_METHODS_LEN(
return LocaleConvertCase(TO_STRING(this), locales, false); StringPrototypeMethods,
} {
toLocaleLowerCase(locales) {
%FunctionSetLength(ToLocaleLowerCaseIntl, 0); CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase");
return LocaleConvertCase(TO_STRING(this), locales, false);
function ToLocaleUpperCaseIntl(locales) { }
CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
return LocaleConvertCase(TO_STRING(this), locales, true);
}
%FunctionSetLength(ToLocaleUpperCaseIntl, 0); toLocaleUpperCase(locales) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
return LocaleConvertCase(TO_STRING(this), locales, true);
}
},
0 /* Set function length of both methods. */
);
/** /**
* Formats a Number object (this) using locale and options values. * Formats a Number object (this) using locale and options values.
* If locale or options are omitted, defaults are used. * If locale or options are omitted, defaults are used.
*/ */
OverrideFunction(GlobalNumber.prototype, 'toLocaleString', function() { DEFINE_METHOD(
GlobalNumber.prototype,
toLocaleString() {
if (!(this instanceof GlobalNumber) && typeof(this) !== 'number') { if (!(this instanceof GlobalNumber) && typeof(this) !== 'number') {
throw %make_type_error(kMethodInvokedOnWrongType, "Number"); throw %make_type_error(kMethodInvokedOnWrongType, "Number");
} }
...@@ -2045,7 +2051,9 @@ function toLocaleDateTime(date, locales, options, required, defaults, service) { ...@@ -2045,7 +2051,9 @@ function toLocaleDateTime(date, locales, options, required, defaults, service) {
* If locale or options are omitted, defaults are used - both date and time are * If locale or options are omitted, defaults are used - both date and time are
* present in the output. * present in the output.
*/ */
OverrideFunction(GlobalDate.prototype, 'toLocaleString', function() { DEFINE_METHOD(
GlobalDate.prototype,
toLocaleString() {
var locales = arguments[0]; var locales = arguments[0];
var options = arguments[1]; var options = arguments[1];
return toLocaleDateTime( return toLocaleDateTime(
...@@ -2059,7 +2067,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleString', function() { ...@@ -2059,7 +2067,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleString', function() {
* If locale or options are omitted, defaults are used - only date is present * If locale or options are omitted, defaults are used - only date is present
* in the output. * in the output.
*/ */
OverrideFunction(GlobalDate.prototype, 'toLocaleDateString', function() { DEFINE_METHOD(
GlobalDate.prototype,
toLocaleDateString() {
var locales = arguments[0]; var locales = arguments[0];
var options = arguments[1]; var options = arguments[1];
return toLocaleDateTime( return toLocaleDateTime(
...@@ -2073,7 +2083,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleDateString', function() { ...@@ -2073,7 +2083,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleDateString', function() {
* If locale or options are omitted, defaults are used - only time is present * If locale or options are omitted, defaults are used - only time is present
* in the output. * in the output.
*/ */
OverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() { DEFINE_METHOD(
GlobalDate.prototype,
toLocaleTimeString() {
var locales = arguments[0]; var locales = arguments[0];
var options = arguments[1]; var options = arguments[1];
return toLocaleDateTime( return toLocaleDateTime(
...@@ -2081,15 +2093,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() { ...@@ -2081,15 +2093,9 @@ OverrideFunction(GlobalDate.prototype, 'toLocaleTimeString', function() {
} }
); );
%FunctionRemovePrototype(ToLocaleLowerCaseIntl);
%FunctionRemovePrototype(ToLocaleUpperCaseIntl);
utils.SetFunctionName(ToLocaleLowerCaseIntl, "toLocaleLowerCase");
utils.SetFunctionName(ToLocaleUpperCaseIntl, "toLocaleUpperCase");
utils.Export(function(to) { utils.Export(function(to) {
to.ToLocaleLowerCaseIntl = ToLocaleLowerCaseIntl; to.ToLocaleLowerCaseIntl = StringPrototypeMethods.toLocaleLowerCase;
to.ToLocaleUpperCaseIntl = ToLocaleUpperCaseIntl; to.ToLocaleUpperCaseIntl = StringPrototypeMethods.toLocaleUpperCase;
}); });
}) })
...@@ -99,6 +99,11 @@ macro SET_PRIVATE(obj, sym, val) = (obj[sym] = val); ...@@ -99,6 +99,11 @@ macro SET_PRIVATE(obj, sym, val) = (obj[sym] = val);
# To avoid ES2015 Function name inference. # To avoid ES2015 Function name inference.
macro ANONYMOUS_FUNCTION(fn) = (0, (fn)); macro ANONYMOUS_FUNCTION(fn) = (0, (fn));
macro DEFINE_METHODS_LEN(obj, class_def, len) = %DefineMethodsInternal(obj, class class_def, len);
macro DEFINE_METHOD_LEN(obj, method_def, len) = %DefineMethodsInternal(obj, class { method_def }, len);
macro DEFINE_METHODS(obj, class_def) = DEFINE_METHODS_LEN(obj, class_def, -1);
macro DEFINE_METHOD(obj, method_def) = DEFINE_METHOD_LEN(obj, method_def, -1);
# Constants. The compiler constant folds them. # Constants. The compiler constant folds them.
define INFINITY = (1/0); define INFINITY = (1/0);
define UNDEFINED = (void 0); define UNDEFINED = (void 0);
......
...@@ -130,7 +130,6 @@ RUNTIME_FUNCTION(Runtime_FunctionSetLength) { ...@@ -130,7 +130,6 @@ RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
CONVERT_ARG_CHECKED(JSFunction, fun, 0); CONVERT_ARG_CHECKED(JSFunction, fun, 0);
CONVERT_SMI_ARG_CHECKED(length, 1); CONVERT_SMI_ARG_CHECKED(length, 1);
CHECK((length & 0xC0000000) == 0xC0000000 || (length & 0xC0000000) == 0x0);
fun->shared()->set_length(length); fun->shared()->set_length(length);
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
......
...@@ -917,6 +917,64 @@ RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) { ...@@ -917,6 +917,64 @@ RUNTIME_FUNCTION(Runtime_CopyDataPropertiesWithExcludedProperties) {
return *target; return *target;
} }
namespace {
inline void TrySetNative(Handle<Object> maybe_func) {
if (!maybe_func->IsJSFunction()) return;
JSFunction::cast(*maybe_func)->shared()->set_native(true);
}
inline void TrySetNativeAndLength(Handle<Object> maybe_func, int length) {
if (!maybe_func->IsJSFunction()) return;
SharedFunctionInfo* shared = JSFunction::cast(*maybe_func)->shared();
shared->set_native(true);
if (length >= 0) {
shared->set_length(length);
}
}
} // namespace
RUNTIME_FUNCTION(Runtime_DefineMethodsInternal) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CHECK(isolate->bootstrapper()->IsActive());
CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, source_class, 1);
CONVERT_SMI_ARG_CHECKED(length, 2);
DCHECK(source_class->prototype()->IsJSObject());
Handle<JSObject> source(JSObject::cast(source_class->prototype()), isolate);
Handle<FixedArray> keys;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, keys,
KeyAccumulator::GetKeys(source, KeyCollectionMode::kOwnOnly,
ALL_PROPERTIES,
GetKeysConversion::kConvertToString));
for (int i = 0; i < keys->length(); ++i) {
Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
if (*key == isolate->heap()->constructor_string()) continue;
PropertyDescriptor descriptor;
Maybe<bool> did_get_descriptor =
JSReceiver::GetOwnPropertyDescriptor(isolate, source, key, &descriptor);
CHECK(did_get_descriptor.FromJust());
if (descriptor.has_value()) {
TrySetNativeAndLength(descriptor.value(), length);
} else {
if (descriptor.has_get()) TrySetNative(descriptor.get());
if (descriptor.has_set()) TrySetNative(descriptor.set());
}
Maybe<bool> success = JSReceiver::DefineOwnProperty(
isolate, target, key, &descriptor, Object::DONT_THROW);
CHECK(success.FromJust());
}
return isolate->heap()->undefined_value();
}
RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) { RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(4, args.length());
......
...@@ -428,6 +428,7 @@ namespace internal { ...@@ -428,6 +428,7 @@ namespace internal {
F(CopyDataPropertiesWithExcludedProperties, -1 /* >= 1 */, 1) \ F(CopyDataPropertiesWithExcludedProperties, -1 /* >= 1 */, 1) \
F(DefineGetterPropertyUnchecked, 4, 1) \ F(DefineGetterPropertyUnchecked, 4, 1) \
F(DefineSetterPropertyUnchecked, 4, 1) \ F(DefineSetterPropertyUnchecked, 4, 1) \
F(DefineMethodsInternal, 3, 1) \
F(ToObject, 1, 1) \ F(ToObject, 1, 1) \
F(ToPrimitive, 1, 1) \ F(ToPrimitive, 1, 1) \
F(ToPrimitive_Number, 1, 1) \ F(ToPrimitive_Number, 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