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

[runtime] Cleanup native methods creation in js/array.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
Change-Id: Iff4b0754677e8b71f893ea29a06da64b58b41b27
Reviewed-on: https://chromium-review.googlesource.com/548056
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46280}
parent e14c4c95
......@@ -385,13 +385,37 @@ Handle<JSFunction> SimpleCreateFunction(Isolate* isolate, Handle<String> name,
}
Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
Handle<String> name,
Handle<Name> property_name,
Handle<String> function_name,
Builtins::Name call, int len,
bool adapt,
PropertyAttributes attrs = DONT_ENUM) {
Handle<JSFunction> fun =
SimpleCreateFunction(base->GetIsolate(), name, call, len, adapt);
InstallFunction(base, fun, name, attrs);
SimpleCreateFunction(base->GetIsolate(), function_name, call, len, adapt);
InstallFunction(base, fun, property_name, attrs);
return fun;
}
Handle<JSFunction> SimpleInstallFunction(Handle<JSObject> base,
Handle<String> name,
Builtins::Name call, int len,
bool adapt,
PropertyAttributes attrs = DONT_ENUM) {
return SimpleInstallFunction(base, name, name, call, len, adapt, attrs);
}
Handle<JSFunction> SimpleInstallFunction(
Handle<JSObject> base, Handle<Name> property_name,
const char* function_name, Builtins::Name call, int len, bool adapt,
PropertyAttributes attrs = DONT_ENUM,
BuiltinFunctionId id = kInvalidBuiltinFunctionId) {
Factory* const factory = base->GetIsolate()->factory();
Handle<JSFunction> fun = SimpleInstallFunction(
base, property_name, factory->InternalizeUtf8String(function_name), call,
len, adapt, attrs);
if (id != kInvalidBuiltinFunctionId) {
fun->shared()->set_builtin_function_id(id);
}
return fun;
}
......@@ -1454,15 +1478,44 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
array_function->shared()->SetConstructStub(*code);
// Set up %ArrayPrototype%.
Handle<JSArray> array_prototype =
Handle<JSArray> proto =
Handle<JSArray>::cast(factory->NewJSObject(array_function, TENURED));
JSArray::Initialize(array_prototype, 0);
JSFunction::SetPrototype(array_function, array_prototype);
native_context()->set_initial_array_prototype(*array_prototype);
JSArray::Initialize(proto, 0);
JSFunction::SetPrototype(array_function, proto);
native_context()->set_initial_array_prototype(*proto);
Handle<JSFunction> is_arraylike = SimpleInstallFunction(
array_function, "isArray", Builtins::kArrayIsArray, 1, true);
native_context()->set_is_arraylike(*is_arraylike);
JSObject::AddProperty(proto, factory->constructor_string(), array_function,
DONT_ENUM);
SimpleInstallFunction(proto, "concat", Builtins::kArrayConcat, 1, false);
SimpleInstallFunction(proto, "pop", Builtins::kFastArrayPop, 0, false);
SimpleInstallFunction(proto, "push", Builtins::kFastArrayPush, 1, false);
SimpleInstallFunction(proto, "shift", Builtins::kFastArrayShift, 0, false);
SimpleInstallFunction(proto, "unshift", Builtins::kArrayUnshift, 1, false);
SimpleInstallFunction(proto, "slice", Builtins::kArraySlice, 2, false);
SimpleInstallFunction(proto, "splice", Builtins::kArraySplice, 2, false);
SimpleInstallFunction(proto, "includes", Builtins::kArrayIncludes, 1,
false);
SimpleInstallFunction(proto, "indexOf", Builtins::kArrayIndexOf, 1, false);
SimpleInstallFunction(proto, "keys", Builtins::kArrayPrototypeKeys, 0, true,
kArrayKeys);
SimpleInstallFunction(proto, "entries", Builtins::kArrayPrototypeEntries, 0,
true, kArrayEntries);
SimpleInstallFunction(proto, factory->iterator_symbol(), "values",
Builtins::kArrayPrototypeValues, 0, false, DONT_ENUM,
kArrayValues);
SimpleInstallFunction(proto, "forEach", Builtins::kArrayForEach, 1, false);
SimpleInstallFunction(proto, "filter", Builtins::kArrayFilter, 1, false);
SimpleInstallFunction(proto, "map", Builtins::kArrayMap, 1, false);
SimpleInstallFunction(proto, "every", Builtins::kArrayEvery, 1, false);
SimpleInstallFunction(proto, "some", Builtins::kArraySome, 1, false);
SimpleInstallFunction(proto, "reduce", Builtins::kArrayReduce, 1, false);
SimpleInstallFunction(proto, "reduceRight", Builtins::kArrayReduceRight, 1,
false);
}
{ // --- A r r a y I t e r a t o r ---
......@@ -4375,18 +4428,6 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
// This is necessary to enable fast checks for absence of elements
// on Array.prototype and below.
proto->set_elements(heap()->empty_fixed_array());
SimpleInstallFunction(proto, "concat", Builtins::kArrayConcat, 1, false);
Handle<JSFunction> for_each = SimpleInstallFunction(
proto, "forEach", Builtins::kArrayForEach, 1, false);
native_context()->set_array_for_each_iterator(*for_each);
SimpleInstallFunction(proto, "filter", Builtins::kArrayFilter, 1, false);
SimpleInstallFunction(proto, "map", Builtins::kArrayMap, 1, false);
SimpleInstallFunction(proto, "every", Builtins::kArrayEvery, 1, false);
SimpleInstallFunction(proto, "some", Builtins::kArraySome, 1, false);
SimpleInstallFunction(proto, "reduce", Builtins::kArrayReduce, 1, false);
SimpleInstallFunction(proto, "reduceRight", Builtins::kArrayReduceRight, 1,
false);
}
// Install InternalArray.prototype.concat
......
......@@ -327,37 +327,42 @@ function SimpleMove(array, start_i, del_count, len, num_additional_args) {
// -------------------------------------------------------------------
function ArrayToString() {
var array;
var func;
if (IS_ARRAY(this)) {
func = this.join;
if (func === ArrayJoin) {
return Join(this, this.length, ',', false);
var ArrayJoin;
DEFINE_METHOD(
GlobalArray.prototype,
toString() {
var array;
var func;
if (IS_ARRAY(this)) {
func = this.join;
if (func === ArrayJoin) {
return Join(this, this.length, ',', false);
}
array = this;
} else {
array = TO_OBJECT(this);
func = array.join;
}
array = this;
} else {
array = TO_OBJECT(this);
func = array.join;
}
if (!IS_CALLABLE(func)) {
return %_Call(ObjectToString, array);
if (!IS_CALLABLE(func)) {
return %_Call(ObjectToString, array);
}
return %_Call(func, array);
}
return %_Call(func, array);
}
);
function InnerArrayToLocaleString(array, length) {
return Join(array, TO_LENGTH(length), ',', true);
}
function ArrayToLocaleString() {
var array = TO_OBJECT(this);
var arrayLen = array.length;
return InnerArrayToLocaleString(array, arrayLen);
}
DEFINE_METHOD(
GlobalArray.prototype,
toLocaleString() {
var array = TO_OBJECT(this);
var arrayLen = array.length;
return InnerArrayToLocaleString(array, arrayLen);
}
);
function InnerArrayJoin(separator, array, length) {
......@@ -378,19 +383,22 @@ function InnerArrayJoin(separator, array, length) {
}
function ArrayJoin(separator) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
DEFINE_METHOD(
GlobalArray.prototype,
join(separator) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.join");
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
return InnerArrayJoin(separator, array, length);
}
return InnerArrayJoin(separator, array, length);
}
);
// Removes the last element from the array and returns it. See
// ECMA-262, section 15.4.4.6.
function ArrayPop() {
function ArrayPopFallback() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.pop");
var array = TO_OBJECT(this);
......@@ -410,7 +418,7 @@ function ArrayPop() {
// Appends the arguments to the end of the array and returns the new
// length of the array. See ECMA-262, section 15.4.4.7.
function ArrayPush() {
function ArrayPushFallback() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.push");
var array = TO_OBJECT(this);
......@@ -512,26 +520,29 @@ function GenericArrayReverse(array, len) {
}
function ArrayReverse() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
DEFINE_METHOD(
GlobalArray.prototype,
reverse() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
var array = TO_OBJECT(this);
var len = TO_LENGTH(array.length);
var isArray = IS_ARRAY(array);
var array = TO_OBJECT(this);
var len = TO_LENGTH(array.length);
var isArray = IS_ARRAY(array);
if (UseSparseVariant(array, len, isArray, len)) {
%NormalizeElements(array);
SparseReverse(array, len);
return array;
} else if (isArray && %_HasFastPackedElements(array)) {
return PackedArrayReverse(array, len);
} else {
return GenericArrayReverse(array, len);
if (UseSparseVariant(array, len, isArray, len)) {
%NormalizeElements(array);
SparseReverse(array, len);
return array;
} else if (isArray && %_HasFastPackedElements(array)) {
return PackedArrayReverse(array, len);
} else {
return GenericArrayReverse(array, len);
}
}
}
);
function ArrayShift() {
function ArrayShiftFallback() {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.shift");
var array = TO_OBJECT(this);
......@@ -558,7 +569,7 @@ function ArrayShift() {
}
function ArrayUnshift(arg1) { // length == 1
function ArrayUnshiftFallback(arg1) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.unshift");
var array = TO_OBJECT(this);
......@@ -582,7 +593,7 @@ function ArrayUnshift(arg1) { // length == 1
}
function ArraySlice(start, end) {
function ArraySliceFallback(start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.slice");
var array = TO_OBJECT(this);
......@@ -655,7 +666,7 @@ function ComputeSpliceDeleteCount(delete_count, num_arguments, len, start_i) {
}
function ArraySplice(start, delete_count) {
function ArraySpliceFallback(start, delete_count) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.splice");
var num_arguments = arguments.length;
......@@ -992,121 +1003,133 @@ function InnerArraySort(array, length, comparefn) {
}
function ArraySort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
DEFINE_METHOD(
GlobalArray.prototype,
sort(comparefn) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
return InnerArraySort(array, length, comparefn);
}
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
return InnerArraySort(array, length, comparefn);
}
);
function ArrayLastIndexOf(element, index) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf");
DEFINE_METHOD_LEN(
GlobalArray.prototype,
lastIndexOf(element, index) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.lastIndexOf");
var array = this;
var length = TO_LENGTH(this.length);
var array = this;
var length = TO_LENGTH(this.length);
if (length == 0) return -1;
if (arguments.length < 2) {
index = length - 1;
} else {
index = INVERT_NEG_ZERO(TO_INTEGER(index));
// If index is negative, index from end of the array.
if (index < 0) index += length;
// If index is still negative, do not search the array.
if (index < 0) return -1;
else if (index >= length) index = length - 1;
}
var min = 0;
var max = index;
if (UseSparseVariant(array, length, IS_ARRAY(array), index)) {
%NormalizeElements(array);
var indices = %GetArrayKeys(array, index + 1);
if (IS_NUMBER(indices)) {
// It's an interval.
max = indices; // Capped by index already.
// Fall through to loop below.
if (length == 0) return -1;
if (arguments.length < 2) {
index = length - 1;
} else {
if (indices.length == 0) return -1;
// Get all the keys in sorted order.
var sortedKeys = GetSortedArrayKeys(array, indices);
var i = sortedKeys.length - 1;
while (i >= 0) {
var key = sortedKeys[i];
if (array[key] === element) return key;
i--;
index = INVERT_NEG_ZERO(TO_INTEGER(index));
// If index is negative, index from end of the array.
if (index < 0) index += length;
// If index is still negative, do not search the array.
if (index < 0) return -1;
else if (index >= length) index = length - 1;
}
var min = 0;
var max = index;
if (UseSparseVariant(array, length, IS_ARRAY(array), index)) {
%NormalizeElements(array);
var indices = %GetArrayKeys(array, index + 1);
if (IS_NUMBER(indices)) {
// It's an interval.
max = indices; // Capped by index already.
// Fall through to loop below.
} else {
if (indices.length == 0) return -1;
// Get all the keys in sorted order.
var sortedKeys = GetSortedArrayKeys(array, indices);
var i = sortedKeys.length - 1;
while (i >= 0) {
var key = sortedKeys[i];
if (array[key] === element) return key;
i--;
}
return -1;
}
}
// Lookup through the array.
if (!IS_UNDEFINED(element)) {
for (var i = max; i >= min; i--) {
if (array[i] === element) return i;
}
return -1;
}
}
// Lookup through the array.
if (!IS_UNDEFINED(element)) {
for (var i = max; i >= min; i--) {
if (array[i] === element) return i;
if (IS_UNDEFINED(array[i]) && i in array) {
return i;
}
}
return -1;
}
for (var i = max; i >= min; i--) {
if (IS_UNDEFINED(array[i]) && i in array) {
return i;
}
}
return -1;
}
},
1 /* Set function length */
);
// ES#sec-array.prototype.copywithin
// (Array.prototype.copyWithin ( target, start [ , end ] )
function ArrayCopyWithin(target, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
target = TO_INTEGER(target);
var to;
if (target < 0) {
to = MaxSimple(length + target, 0);
} else {
to = MinSimple(target, length);
}
DEFINE_METHOD_LEN(
GlobalArray.prototype,
copyWithin(target, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.copyWithin");
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
target = TO_INTEGER(target);
var to;
if (target < 0) {
to = MaxSimple(length + target, 0);
} else {
to = MinSimple(target, length);
}
start = TO_INTEGER(start);
var from;
if (start < 0) {
from = MaxSimple(length + start, 0);
} else {
from = MinSimple(start, length);
}
start = TO_INTEGER(start);
var from;
if (start < 0) {
from = MaxSimple(length + start, 0);
} else {
from = MinSimple(start, length);
}
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
var final;
if (end < 0) {
final = MaxSimple(length + end, 0);
} else {
final = MinSimple(end, length);
}
end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
var final;
if (end < 0) {
final = MaxSimple(length + end, 0);
} else {
final = MinSimple(end, length);
}
var count = MinSimple(final - from, length - to);
var direction = 1;
if (from < to && to < (from + count)) {
direction = -1;
from = from + count - 1;
to = to + count - 1;
}
var count = MinSimple(final - from, length - to);
var direction = 1;
if (from < to && to < (from + count)) {
direction = -1;
from = from + count - 1;
to = to + count - 1;
}
while (count > 0) {
if (from in array) {
array[to] = array[from];
} else {
delete array[to];
while (count > 0) {
if (from in array) {
array[to] = array[from];
} else {
delete array[to];
}
from = from + direction;
to = to + direction;
count--;
}
from = from + direction;
to = to + direction;
count--;
}
return array;
}
return array;
},
2 /* Set function length */
);
function InnerArrayFind(predicate, thisArg, array, length) {
......@@ -1126,14 +1149,18 @@ function InnerArrayFind(predicate, thisArg, array, length) {
// ES6 draft 07-15-13, section 15.4.3.23
function ArrayFind(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
DEFINE_METHOD_LEN(
GlobalArray.prototype,
find(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.find");
var array = TO_OBJECT(this);
var length = TO_INTEGER(array.length);
var array = TO_OBJECT(this);
var length = TO_INTEGER(array.length);
return InnerArrayFind(predicate, thisArg, array, length);
}
return InnerArrayFind(predicate, thisArg, array, length);
},
1 /* Set function length */
);
function InnerArrayFindIndex(predicate, thisArg, array, length) {
......@@ -1153,123 +1180,132 @@ function InnerArrayFindIndex(predicate, thisArg, array, length) {
// ES6 draft 07-15-13, section 15.4.3.24
function ArrayFindIndex(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
DEFINE_METHOD_LEN(
GlobalArray.prototype,
findIndex(predicate, thisArg) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.findIndex");
var array = TO_OBJECT(this);
var length = TO_INTEGER(array.length);
var array = TO_OBJECT(this);
var length = TO_INTEGER(array.length);
return InnerArrayFindIndex(predicate, thisArg, array, length);
}
return InnerArrayFindIndex(predicate, thisArg, array, length);
},
1 /* Set function length */
);
// ES6, draft 04-05-14, section 22.1.3.6
function ArrayFill(value, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
DEFINE_METHOD_LEN(
GlobalArray.prototype,
fill(value, start, end) {
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.fill");
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
var array = TO_OBJECT(this);
var length = TO_LENGTH(array.length);
var i = IS_UNDEFINED(start) ? 0 : TO_INTEGER(start);
var end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
var i = IS_UNDEFINED(start) ? 0 : TO_INTEGER(start);
var end = IS_UNDEFINED(end) ? length : TO_INTEGER(end);
if (i < 0) {
i += length;
if (i < 0) i = 0;
} else {
if (i > length) i = length;
}
if (i < 0) {
i += length;
if (i < 0) i = 0;
} else {
if (i > length) i = length;
}
if (end < 0) {
end += length;
if (end < 0) end = 0;
} else {
if (end > length) end = length;
}
if (end < 0) {
end += length;
if (end < 0) end = 0;
} else {
if (end > length) end = length;
}
if ((end - i) > 0 && %object_is_frozen(array)) {
throw %make_type_error(kArrayFunctionsOnFrozen);
}
if ((end - i) > 0 && %object_is_frozen(array)) {
throw %make_type_error(kArrayFunctionsOnFrozen);
}
for (; i < end; i++)
array[i] = value;
return array;
}
for (; i < end; i++)
array[i] = value;
return array;
},
1 /* Set function length */
);
// ES6, draft 10-14-14, section 22.1.2.1
function ArrayFrom(arrayLike, mapfn, receiver) {
var items = TO_OBJECT(arrayLike);
var mapping = !IS_UNDEFINED(mapfn);
if (mapping) {
if (!IS_CALLABLE(mapfn)) {
throw %make_type_error(kCalledNonCallable, mapfn);
DEFINE_METHOD_LEN(
GlobalArray,
'from'(arrayLike, mapfn, receiver) {
var items = TO_OBJECT(arrayLike);
var mapping = !IS_UNDEFINED(mapfn);
if (mapping) {
if (!IS_CALLABLE(mapfn)) {
throw %make_type_error(kCalledNonCallable, mapfn);
}
}
}
var iterable = GetMethod(items, iteratorSymbol);
var k;
var result;
var mappedValue;
var nextValue;
var iterable = GetMethod(items, iteratorSymbol);
var k;
var result;
var mappedValue;
var nextValue;
if (!IS_UNDEFINED(iterable)) {
result = %IsConstructor(this) ? new this() : [];
k = 0;
if (!IS_UNDEFINED(iterable)) {
result = %IsConstructor(this) ? new this() : [];
k = 0;
for (nextValue of
{ [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
for (nextValue of
{ [iteratorSymbol]() { return GetIterator(items, iterable) } }) {
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
}
%CreateDataProperty(result, k, mappedValue);
k++;
}
%CreateDataProperty(result, k, mappedValue);
k++;
}
result.length = k;
return result;
} else {
var len = TO_LENGTH(items.length);
result = %IsConstructor(this) ? new this(len) : new GlobalArray(len);
result.length = k;
return result;
} else {
var len = TO_LENGTH(items.length);
result = %IsConstructor(this) ? new this(len) : new GlobalArray(len);
for (k = 0; k < len; ++k) {
nextValue = items[k];
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
for (k = 0; k < len; ++k) {
nextValue = items[k];
if (mapping) {
mappedValue = %_Call(mapfn, receiver, nextValue, k);
} else {
mappedValue = nextValue;
}
%CreateDataProperty(result, k, mappedValue);
}
%CreateDataProperty(result, k, mappedValue);
}
result.length = k;
return result;
}
}
result.length = k;
return result;
}
},
1 /* Set function length. */
);
// ES6, draft 05-22-14, section 22.1.2.3
function ArrayOf(...args) {
var length = args.length;
var constructor = this;
// TODO: Implement IsConstructor (ES6 section 7.2.5)
var array = %IsConstructor(constructor) ? new constructor(length) : [];
for (var i = 0; i < length; i++) {
%CreateDataProperty(array, i, args[i]);
DEFINE_METHOD(
GlobalArray,
of(...args) {
var length = args.length;
var constructor = this;
// TODO: Implement IsConstructor (ES6 section 7.2.5)
var array = %IsConstructor(constructor) ? new constructor(length) : [];
for (var i = 0; i < length; i++) {
%CreateDataProperty(array, i, args[i]);
}
array.length = length;
return array;
}
array.length = length;
return array;
}
);
// -------------------------------------------------------------------
// Set up non-enumerable constructor property on the Array.prototype
// object.
%AddNamedProperty(GlobalArray.prototype, "constructor", GlobalArray,
DONT_ENUM);
// Set up unscopable properties on the Array.prototype object.
var unscopables = {
__proto__: null,
......@@ -1285,107 +1321,64 @@ var unscopables = {
%AddNamedProperty(GlobalArray.prototype, unscopablesSymbol, unscopables,
DONT_ENUM | READ_ONLY);
%FunctionSetLength(ArrayFrom, 1);
// Set up non-enumerable functions on the Array object.
utils.InstallFunctions(GlobalArray, DONT_ENUM, [
"from", ArrayFrom,
"of", ArrayOf
]);
var specialFunctions = %SpecialArrayFunctions();
function getFunction(name, jsBuiltin, len) {
var f = jsBuiltin;
if (specialFunctions.hasOwnProperty(name)) {
f = specialFunctions[name];
}
if (!IS_UNDEFINED(len)) {
%FunctionSetLength(f, len);
}
return f;
};
var ArrayIndexOf = GlobalArray.prototype.indexOf;
var ArrayJoin = GlobalArray.prototype.join;
var ArrayPop = GlobalArray.prototype.pop;
var ArrayPush = GlobalArray.prototype.push;
var ArraySlice = GlobalArray.prototype.slice;
var ArrayShift = GlobalArray.prototype.shift;
var ArraySort = GlobalArray.prototype.sort;
var ArraySplice = GlobalArray.prototype.splice;
var ArrayToString = GlobalArray.prototype.toString;
var ArrayUnshift = GlobalArray.prototype.unshift;
// Array prototype functions that return iterators. They are exposed to the
// public API via Template::SetIntrinsicDataProperty().
var IteratorFunctions = {
"entries": getFunction("entries", null, 0),
"keys": getFunction("keys", null, 0),
"values": getFunction("values", null, 0)
}
// Set up non-enumerable functions of the Array.prototype object and
// set their names.
// Manipulate the length of some of the functions to meet
// expectations set by ECMA-262 or Mozilla.
utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"toString", getFunction("toString", ArrayToString),
"toLocaleString", getFunction("toLocaleString", ArrayToLocaleString),
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
"push", getFunction("push", ArrayPush, 1),
"reverse", getFunction("reverse", ArrayReverse),
"shift", getFunction("shift", ArrayShift),
"unshift", getFunction("unshift", ArrayUnshift, 1),
"slice", getFunction("slice", ArraySlice, 2),
"splice", getFunction("splice", ArraySplice, 2),
"sort", getFunction("sort", ArraySort),
"indexOf", getFunction("indexOf", null, 1),
"lastIndexOf", getFunction("lastIndexOf", ArrayLastIndexOf, 1),
"copyWithin", getFunction("copyWithin", ArrayCopyWithin, 2),
"find", getFunction("find", ArrayFind, 1),
"findIndex", getFunction("findIndex", ArrayFindIndex, 1),
"fill", getFunction("fill", ArrayFill, 1),
"includes", getFunction("includes", null, 1),
"entries", IteratorFunctions.entries,
"keys", IteratorFunctions.keys,
iteratorSymbol, IteratorFunctions.values
]);
var ArrayEntries = GlobalArray.prototype.entries;
var ArrayForEach = GlobalArray.prototype.forEach;
var ArrayKeys = GlobalArray.prototype.keys;
var ArrayValues = GlobalArray.prototype[iteratorSymbol];
%FunctionSetSharedName(IteratorFunctions.entries, "entries");
%FunctionSetSharedName(IteratorFunctions.keys, "keys");
%FunctionSetSharedName(IteratorFunctions.values, "values");
// The internal Array prototype doesn't need to be fancy, since it's never
// exposed to user code.
// Adding only the functions that are actually used.
utils.SetUpLockedPrototype(InternalArray, GlobalArray(), [
"indexOf", getFunction("indexOf", null),
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
"push", getFunction("push", ArrayPush),
"shift", getFunction("shift", ArrayShift),
"sort", getFunction("sort", ArraySort),
"splice", getFunction("splice", ArraySplice)
"indexOf", ArrayIndexOf,
"join", ArrayJoin,
"pop", ArrayPop,
"push", ArrayPush,
"shift", ArrayShift,
"sort", ArraySort,
"splice", ArraySplice
]);
utils.SetUpLockedPrototype(InternalPackedArray, GlobalArray(), [
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
"push", getFunction("push", ArrayPush),
"shift", getFunction("shift", ArrayShift)
"join", ArrayJoin,
"pop", ArrayPop,
"push", ArrayPush,
"shift", ArrayShift
]);
// V8 extras get a separate copy of InternalPackedArray. We give them the basic
// manipulation methods.
utils.SetUpLockedPrototype(extrasUtils.InternalPackedArray, GlobalArray(), [
"push", getFunction("push", ArrayPush),
"pop", getFunction("pop", ArrayPop),
"shift", getFunction("shift", ArrayShift),
"unshift", getFunction("unshift", ArrayUnshift),
"splice", getFunction("splice", ArraySplice),
"slice", getFunction("slice", ArraySlice)
"push", ArrayPush,
"pop", ArrayPop,
"shift", ArrayShift,
"unshift", ArrayUnshift,
"splice", ArraySplice,
"slice", ArraySlice
]);
// -------------------------------------------------------------------
// Exports
utils.Export(function(to) {
to.ArrayFrom = ArrayFrom;
to.ArrayJoin = ArrayJoin;
to.ArrayPush = ArrayPush;
to.ArrayToString = ArrayToString;
to.ArrayValues = IteratorFunctions.values,
to.ArrayValues = ArrayValues;
to.InnerArrayFind = InnerArrayFind;
to.InnerArrayFindIndex = InnerArrayFindIndex;
to.InnerArrayJoin = InnerArrayJoin;
......@@ -1394,15 +1387,17 @@ utils.Export(function(to) {
});
%InstallToContext([
"array_entries_iterator", IteratorFunctions.entries,
"array_keys_iterator", IteratorFunctions.keys,
"array_pop", ArrayPop,
"array_push", ArrayPush,
"array_shift", ArrayShift,
"array_splice", ArraySplice,
"array_slice", ArraySlice,
"array_unshift", ArrayUnshift,
"array_values_iterator", IteratorFunctions.values,
"array_entries_iterator", ArrayEntries,
"array_for_each_iterator", ArrayForEach,
"array_keys_iterator", ArrayKeys,
"array_values_iterator", ArrayValues,
// Fallback implementations of Array builtins.
"array_pop", ArrayPopFallback,
"array_push", ArrayPushFallback,
"array_shift", ArrayShiftFallback,
"array_splice", ArraySpliceFallback,
"array_slice", ArraySliceFallback,
"array_unshift", ArrayUnshiftFallback,
]);
});
......@@ -4655,6 +4655,7 @@ class ContextExtension : public Struct {
V(Atomics, xor, AtomicsXor)
enum BuiltinFunctionId {
kInvalidBuiltinFunctionId = -1,
kArrayCode,
#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
k##name,
......
......@@ -17,58 +17,6 @@
namespace v8 {
namespace internal {
static void InstallCode(
Isolate* isolate, Handle<JSObject> holder, const char* name,
Handle<Code> code, int argc = -1,
BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) {
Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
Handle<JSFunction> optimized =
isolate->factory()->NewFunctionWithoutPrototype(key, code, true);
if (argc < 0) {
optimized->shared()->DontAdaptArguments();
} else {
optimized->shared()->set_internal_formal_parameter_count(argc);
}
if (id >= 0) {
optimized->shared()->set_builtin_function_id(id);
}
optimized->shared()->set_language_mode(STRICT);
optimized->shared()->set_native(true);
JSObject::AddProperty(holder, key, optimized, NONE);
}
static void InstallBuiltin(
Isolate* isolate, Handle<JSObject> holder, const char* name,
Builtins::Name builtin_name, int argc = -1,
BuiltinFunctionId id = static_cast<BuiltinFunctionId>(-1)) {
InstallCode(isolate, holder, name,
handle(isolate->builtins()->builtin(builtin_name), isolate), argc,
id);
}
RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
HandleScope scope(isolate);
DCHECK_EQ(0, args.length());
Handle<JSObject> holder =
isolate->factory()->NewJSObject(isolate->object_function());
InstallBuiltin(isolate, holder, "pop", Builtins::kFastArrayPop);
InstallBuiltin(isolate, holder, "push", Builtins::kFastArrayPush);
InstallBuiltin(isolate, holder, "shift", Builtins::kFastArrayShift);
InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes);
InstallBuiltin(isolate, holder, "indexOf", Builtins::kArrayIndexOf);
InstallBuiltin(isolate, holder, "keys", Builtins::kArrayPrototypeKeys, 0,
kArrayKeys);
InstallBuiltin(isolate, holder, "values", Builtins::kArrayPrototypeValues, 0,
kArrayValues);
InstallBuiltin(isolate, holder, "entries", Builtins::kArrayPrototypeEntries,
0, kArrayEntries);
return *holder;
}
RUNTIME_FUNCTION(Runtime_FixedArrayGet) {
SealHandleScope shs(isolate);
DCHECK_EQ(2, args.length());
......
......@@ -37,7 +37,6 @@ namespace internal {
// are specified by inline comments
#define FOR_EACH_INTRINSIC_ARRAY(F) \
F(SpecialArrayFunctions, 0, 1) \
F(TransitionElementsKind, 2, 1) \
F(RemoveArrayHoles, 2, 1) \
F(MoveArrayContents, 2, 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