Commit 3ea1ad23 authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[typedarray] Implement TypedArray.p.sort using Torque.

This CL implements TypedArray.p.sort in Torque. The Torque
version works basically the same as the existing JS builtin:

When no comparison function is provided, the C++ fast path builtin
is used. Otherwise a quicksort written in Torque is used, with
a InsertionSort fallback for smaller arrays.

The JS quicksort implementation also containes a more elaborate
third pivot calculation for larger arrays. This is currently not done.

Reported benchmark results are only for those, where a custom
comparison function is provided. The numbers for the C++ path stayed
the same.

Benchmark   Current (JS)       Torque    Speedup

IntTypes            83.9        263.7        3.1
BigIntTypes         32.1         54.6        1.7
FloatTypes          99.3        138.7        1.4

R=danno@chromium.org, jgruber@chromium.org

Bug: v8:7382
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I7abe7ceff525bab24f302d2f06b5961cca770d24
Reviewed-on: https://chromium-review.googlesource.com/1021691
Commit-Queue: Simon Zünd <szuend@google.com>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarPeter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52776}
parent 2393710a
......@@ -865,6 +865,7 @@ action("run_torque") {
inputs = [
"src/builtins/base.tq",
"src/builtins/array.tq",
"src/builtins/typed-array.tq",
]
outputs = [
......@@ -873,6 +874,8 @@ action("run_torque") {
"$target_gen_dir/builtins-array-from-dsl-gen.h",
"$target_gen_dir/builtins-base-from-dsl-gen.cc",
"$target_gen_dir/builtins-base-from-dsl-gen.h",
"$target_gen_dir/builtins-typed-array-from-dsl-gen.cc",
"$target_gen_dir/builtins-typed-array-from-dsl-gen.h",
]
args = [
......@@ -883,6 +886,7 @@ action("run_torque") {
rebase_path("$target_gen_dir", root_build_dir),
rebase_path("src/builtins/base.tq", root_build_dir),
rebase_path("src/builtins/array.tq", root_build_dir),
rebase_path("src/builtins/typed-array.tq", root_build_dir),
]
}
......@@ -1196,6 +1200,7 @@ v8_source_set("v8_initializers") {
sources = [
"$target_gen_dir/builtins-array-from-dsl-gen.cc",
"$target_gen_dir/builtins-base-from-dsl-gen.cc",
"$target_gen_dir/builtins-typed-array-from-dsl-gen.cc",
### gcmole(all) ###
"src/builtins/builtins-arguments-gen.cc",
......
......@@ -2919,6 +2919,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kTypedArrayPrototypeSlice, 2, false);
SimpleInstallFunction(prototype, "some", Builtins::kTypedArrayPrototypeSome,
1, false);
SimpleInstallFunction(prototype, "sort", Builtins::kTypedArrayPrototypeSort,
1, false);
SimpleInstallFunction(prototype, "subarray",
Builtins::kTypedArrayPrototypeSubArray, 2, false);
}
......
......@@ -13,6 +13,7 @@ type float64 generates 'TNode<Float64T>';
type bit generates 'TNode<BoolT>';
type int31 extends int32 generates 'TNode<Int32T>';
type RawPtr generates 'TNode<RawPtrT>';
type Number extends Object generates 'TNode<Number>';
type Smi extends Number generates 'TNode<Smi>';
type HeapObject extends Object generates 'TNode<HeapObject>';
......@@ -29,12 +30,16 @@ type FixedArray extends FixedArrayBase generates 'TNode<FixedArray>';
type FixedDoubleArray extends FixedArrayBase generates
'TNode<FixedDoubleArray>';
type JSArrayBuffer extends Object generates 'TNode<JSArrayBuffer>';
type JSArrayBufferView extends Object generates 'TNode<JSArrayBufferView>';
type JSTypedArray extends JSArrayBufferView generates 'TNode<JSTypedArray>';
type const_int32 generates 'int32_t';
type const_int31 extends const_int32 generates 'int32_t';
type const_float64 generates 'double';
type InstanceType extends int32 generates 'TNode<Int32T>';
type ElementsKind generates 'ElementsKind';
type ElementsKind extends const_int32 generates 'ElementsKind';
type LanguageMode extends Smi;
type ExtractFixedArrayFlags;
......@@ -49,6 +54,18 @@ const HOLEY_ELEMENTS: ElementsKind = 'HOLEY_ELEMENTS';
const PACKED_DOUBLE_ELEMENTS: ElementsKind = 'PACKED_DOUBLE_ELEMENTS';
const HOLEY_DOUBLE_ELEMENTS: ElementsKind = 'HOLEY_DOUBLE_ELEMENTS';
const UINT8_ELEMENTS: ElementsKind = 'UINT8_ELEMENTS';
const INT8_ELEMENTS: ElementsKind = 'INT8_ELEMENTS';
const UINT16_ELEMENTS: ElementsKind = 'UINT16_ELEMENTS';
const INT16_ELEMENTS: ElementsKind = 'INT16_ELEMENTS';
const UINT32_ELEMENTS: ElementsKind = 'UINT32_ELEMENTS';
const INT32_ELEMENTS: ElementsKind = 'INT32_ELEMENTS';
const FLOAT32_ELEMENTS: ElementsKind = 'FLOAT32_ELEMENTS';
const FLOAT64_ELEMENTS: ElementsKind = 'FLOAT64_ELEMENTS';
const UINT8_CLAMPED_ELEMENTS: ElementsKind = 'UINT8_CLAMPED_ELEMENTS';
const BIGUINT64_ELEMENTS: ElementsKind = 'BIGUINT64_ELEMENTS';
const BIGINT64_ELEMENTS: ElementsKind = 'BIGINT64_ELEMENTS';
const kOperationLessThan: CompareOperator = 'Operation::kLessThan';
const kOperationLessThanEqual: CompareOperator = 'Operation::kLessThanEqual';
const kOperationGreaterThan: CompareOperator = 'Operation::kGreaterThan';
......@@ -69,6 +86,12 @@ const kHasProperty: HasPropertyFlag = 'kHasProperty';
const kMaxSafeInteger: const_float64 = 'kMaxSafeInteger';
const kNotTypedArray: MessageTemplate = 'MessageTemplate::kNotTypedArray';
const kDetachedOperation: MessageTemplate =
'MessageTemplate::kDetachedOperation';
const kBadSortComparisonFunction: MessageTemplate =
'MessageTemplate::kBadSortComparisonFunction';
const hole: Object = 'TheHoleConstant()';
const null: Oddball = 'NullConstant()';
const undefined: Oddball = 'UndefinedConstant()';
......@@ -89,10 +112,13 @@ extern macro Print(String, Object);
extern macro DebugBreak();
extern macro ToInteger_Inline(Context, Object): Number;
extern macro ToLength_Inline(Context, Object): Number;
extern macro ToNumber_Inline(Context, Object): Number;
extern macro ToString_Inline(Context, Object): String;
extern macro GetProperty(Context, Object, Object): Object;
extern macro HasProperty(HeapObject, Object, Context, HasPropertyFlag): Oddball;
extern macro ThrowRangeError(Context, MessageTemplate): never;
extern macro ThrowTypeError(Context, MessageTemplate): never;
extern macro ThrowTypeError(Context, MessageTemplate, Object): never;
extern macro ArraySpeciesCreate(Context, Object, Number): Object;
extern macro EnsureArrayPushable(Map): int32 labels Bailout;
......@@ -127,6 +153,8 @@ extern operator '>' macro IntPtrGreaterThan(intptr, intptr): bit;
extern operator '<=' macro IntPtrLessThanOrEqual(intptr, intptr): bit;
extern operator '>=' macro IntPtrGreaterThanOrEqual(intptr, intptr): bit;
extern operator '==' macro Float64Equal(float64, float64): bit;
extern operator
'<' macro BranchIfNumberLessThan(Number, Number): never labels True, False;
extern operator
......@@ -143,9 +171,11 @@ extern operator '!=' macro WordNotEqual(Object, Object): bit;
extern operator '+' macro SmiAdd(Smi, Smi): Smi;
extern operator '-' macro SmiSub(Smi, Smi): Smi;
extern operator '>>>' macro SmiShr(Smi, const_int31): Smi;
extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
extern operator '-' macro IntPtrSub(intptr, intptr): intptr;
extern operator '>>>' macro WordShr(intptr, intptr): intptr;
extern operator '+' macro NumberAdd(Number, Number): Number;
extern operator '-' macro NumberSub(Number, Number): Number;
......@@ -194,6 +224,7 @@ extern operator 'convert<>' macro TruncateWordToWord32(intptr): int32;
extern operator 'convert<>' macro SmiTag(intptr): Smi;
extern operator 'convert<>' macro SmiUntag(Smi): intptr;
extern macro BranchIfFastJSArray(Object, Context): never labels True, False;
extern macro BranchIfNotFastJSArray(Object, Context): never labels True, False;
......@@ -203,11 +234,18 @@ extern macro IsArraySpeciesProtectorCellInvalid(): bit;
extern macro IsTypedArraySpeciesProtectorCellInvalid(): bit;
extern macro IsPromiseSpeciesProtectorCellInvalid(): bit;
extern operator
'.buffer' macro LoadTypedArrayBuffer(JSTypedArray): JSArrayBuffer;
extern operator '.data_ptr' macro LoadDataPtr(JSTypedArray): RawPtr;
extern operator '.elements_kind' macro LoadMapElementsKind(Map): int32;
extern operator '.elements_kind' macro LoadElementsKind(JSTypedArray): int32;
extern operator '.elements' macro LoadElements(Object): FixedArrayBase;
extern operator '.elements=' macro StoreElements(Object, FixedArrayBase);
extern operator '.length' macro LoadTypedArrayLength(JSTypedArray): Smi;
extern operator '.length' macro LoadJSArrayLength(JSArray): Number;
extern operator '.length=' macro StoreJSArrayLength(JSArray, Smi);
......@@ -251,3 +289,13 @@ macro HasPropertyObject(
return false;
}
}
extern macro IsCallable(Object): bit;
extern macro IsDetachedBuffer(JSArrayBuffer): bit;
type ParameterMode;
const kSmiParameters: ParameterMode = 'ParameterMode::SMI_PARAMETERS';
extern macro LoadFixedTypedArrayElementAsTagged(
RawPtr, Smi, ElementsKind, ParameterMode): Object;
extern macro StoreFixedTypedArrayElementFromTagged(
Context, RawPtr, Smi, Object, ElementsKind, ParameterMode);
......@@ -1196,6 +1196,27 @@ void TypedArrayBuiltinsAssembler::DispatchTypedArrayByElementsKind(
BIND(&next);
}
TNode<BoolT> TypedArrayBuiltinsAssembler::NumberIsNaN(TNode<Number> value) {
Label is_heapnumber(this), done(this);
TVARIABLE(BoolT, result);
GotoIf(TaggedIsNotSmi(value), &is_heapnumber);
result = Int32FalseConstant();
Goto(&done);
BIND(&is_heapnumber);
{
CSA_ASSERT(this, IsHeapNumber(value));
TNode<Float64T> value_f = LoadHeapNumberValue(CAST(value));
result = Float64NotEqual(value_f, value_f);
Goto(&done);
}
BIND(&done);
return result.value();
}
// ES #sec-get-%typedarray%.prototype.set
TF_BUILTIN(TypedArrayPrototypeSet, TypedArrayBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext));
......
......@@ -71,6 +71,15 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
// Returns the byte size of an element for a TypedArray elements kind.
TNode<IntPtrT> GetTypedArrayElementSize(TNode<Word32T> elements_kind);
TNode<Smi> LoadTypedArrayLength(TNode<JSTypedArray> typed_array) {
return LoadObjectField<Smi>(typed_array, JSTypedArray::kLengthOffset);
}
TNode<JSArrayBuffer> LoadTypedArrayBuffer(TNode<JSTypedArray> typed_array) {
return LoadObjectField<JSArrayBuffer>(typed_array,
JSTypedArray::kBufferOffset);
}
TNode<Object> GetDefaultConstructor(TNode<Context> context,
TNode<JSTypedArray> exemplar);
......@@ -126,6 +135,14 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
void DispatchTypedArrayByElementsKind(
TNode<Word32T> elements_kind, const TypedArraySwitchCase& case_function);
// Returns true iff number is NaN.
// TOOD(szuend): Remove when UncheckedCasts are supported in Torque.
TNode<BoolT> NumberIsNaN(TNode<Number> number);
// Always CSA_ASSERTs false.
// TODO(szuend): Remove when Unreachable is supported in Torque.
void AssertUnreachable() { CSA_ASSERT(this, Int32FalseConstant()); }
};
} // namespace internal
......
This diff is collapsed.
......@@ -394,6 +394,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
template <class... TArgs>
TNode<Object> Call(TNode<Context> context, TNode<Object> callable,
TNode<Object> receiver, TArgs... args) {
if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) {
return UncheckedCast<Object>(CallJS(
CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
context, callable, receiver, args...));
}
return UncheckedCast<Object>(CallJS(CodeFactory::Call(isolate()), context,
callable, receiver, args...));
}
......
......@@ -422,6 +422,16 @@ bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
return m.HasValue();
}
bool CodeAssembler::IsUndefinedConstant(TNode<Object> node) {
compiler::HeapObjectMatcher m(node);
return m.Is(isolate()->factory()->undefined_value());
}
bool CodeAssembler::IsNullConstant(TNode<Object> node) {
compiler::HeapObjectMatcher m(node);
return m.Is(isolate()->factory()->null_value());
}
Node* CodeAssembler::Parameter(int value) {
return raw_assembler()->Parameter(value);
}
......
......@@ -406,6 +406,7 @@ class SloppyTNode : public TNode<T> {
V(Float32GreaterThan, BoolT, Float32T, Float32T) \
V(Float32GreaterThanOrEqual, BoolT, Float32T, Float32T) \
V(Float64Equal, BoolT, Float64T, Float64T) \
V(Float64NotEqual, BoolT, Float64T, Float64T) \
V(Float64LessThan, BoolT, Float64T, Float64T) \
V(Float64LessThanOrEqual, BoolT, Float64T, Float64T) \
V(Float64GreaterThan, BoolT, Float64T, Float64T) \
......@@ -699,6 +700,9 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool ToSmiConstant(Node* node, Smi*& out_value);
bool ToIntPtrConstant(Node* node, intptr_t& out_value);
bool IsUndefinedConstant(TNode<Object> node);
bool IsNullConstant(TNode<Object> node);
TNode<Int32T> Signed(TNode<Word32T> x) { return UncheckedCast<Int32T>(x); }
TNode<IntPtrT> Signed(TNode<WordT> x) { return UncheckedCast<IntPtrT>(x); }
TNode<Uint32T> Unsigned(TNode<Word32T> x) {
......
......@@ -14,7 +14,6 @@
// array.js has to come before typedarray.js for this to work
var ArrayToString = utils.ImportNow("ArrayToString");
var InnerArrayJoin;
var InnerArraySort;
var InnerArrayToLocaleString;
macro TYPED_ARRAYS(FUNCTION)
......@@ -45,7 +44,6 @@ var GlobalTypedArray = %object_get_prototype_of(GlobalUint8Array);
utils.Import(function(from) {
InnerArrayJoin = from.InnerArrayJoin;
InnerArraySort = from.InnerArraySort;
InnerArrayToLocaleString = from.InnerArrayToLocaleString;
});
......@@ -59,26 +57,6 @@ function ValidateTypedArray(array, methodName) {
throw %make_type_error(kDetachedOperation, methodName);
}
// ES6 draft 05-18-15, section 22.2.3.25
DEFINE_METHOD(
GlobalTypedArray.prototype,
sort(comparefn) {
ValidateTypedArray(this, "%TypedArray%.prototype.sort");
if (!IS_UNDEFINED(comparefn) && !IS_CALLABLE(comparefn)) {
throw %make_type_error(kBadSortComparisonFunction, comparefn);
}
var length = %_TypedArrayGetLength(this);
if (IS_UNDEFINED(comparefn)) {
return %TypedArraySortFast(this);
}
return InnerArraySort(this, length, comparefn);
}
);
// ES6 section 22.2.3.27
DEFINE_METHOD(
......
......@@ -136,8 +136,6 @@
'built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer': [FAIL],
'built-ins/TypedArray/prototype/some/callbackfn-detachbuffer': [FAIL],
'built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer': [FAIL],
'built-ins/TypedArray/prototype/sort/detached-buffer-comparefn': [FAIL],
'built-ins/TypedArray/prototype/sort/BigInt/detached-buffer-comparefn': [FAIL],
# DataView functions should also throw on detached buffers
'built-ins/ArrayBuffer/prototype/byteLength/detached-buffer': [FAIL],
'built-ins/DataView/detached-buffer': [FAIL],
......
......@@ -28,6 +28,8 @@ group("v8_run_gcmole") {
"$target_gen_dir/../../builtins-array-from-dsl-gen.h",
"$target_gen_dir/../../builtins-base-from-dsl-gen.cc",
"$target_gen_dir/../../builtins-base-from-dsl-gen.h",
"$target_gen_dir/../../builtins-typed-array-from-dsl-gen.cc",
"$target_gen_dir/../../builtins-typed-array-from-dsl-gen.h",
]
deps = [
......
......@@ -172,33 +172,33 @@ KNOWN_MAPS = {
("RO_SPACE", 0x02921): (173, "Tuple2Map"),
("RO_SPACE", 0x02999): (171, "ScriptMap"),
("RO_SPACE", 0x02a01): (163, "InterceptorInfoMap"),
("RO_SPACE", 0x06891): (154, "AccessorInfoMap"),
("RO_SPACE", 0x06aa1): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x06b09): (155, "AccessorPairMap"),
("RO_SPACE", 0x06b71): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x06bd9): (157, "AllocationMementoMap"),
("RO_SPACE", 0x06c41): (158, "AllocationSiteMap"),
("RO_SPACE", 0x06ca9): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x06d11): (160, "ContextExtensionMap"),
("RO_SPACE", 0x06d79): (161, "DebugInfoMap"),
("RO_SPACE", 0x06de1): (162, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x06e49): (164, "InterpreterDataMap"),
("RO_SPACE", 0x06eb1): (165, "ModuleInfoEntryMap"),
("RO_SPACE", 0x06f19): (166, "ModuleMap"),
("RO_SPACE", 0x06f81): (167, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x06fe9): (168, "PromiseCapabilityMap"),
("RO_SPACE", 0x07051): (169, "PromiseReactionMap"),
("RO_SPACE", 0x070b9): (170, "PrototypeInfoMap"),
("RO_SPACE", 0x07121): (172, "StackFrameInfoMap"),
("RO_SPACE", 0x07189): (174, "Tuple3Map"),
("RO_SPACE", 0x071f1): (175, "WasmCompiledModuleMap"),
("RO_SPACE", 0x07259): (176, "WasmDebugInfoMap"),
("RO_SPACE", 0x072c1): (177, "WasmSharedModuleDataMap"),
("RO_SPACE", 0x07329): (178, "CallableTaskMap"),
("RO_SPACE", 0x07391): (179, "CallbackTaskMap"),
("RO_SPACE", 0x073f9): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x07461): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x074c9): (182, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x068c9): (154, "AccessorInfoMap"),
("RO_SPACE", 0x06ad9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x06b41): (155, "AccessorPairMap"),
("RO_SPACE", 0x06ba9): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x06c11): (157, "AllocationMementoMap"),
("RO_SPACE", 0x06c79): (158, "AllocationSiteMap"),
("RO_SPACE", 0x06ce1): (159, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x06d49): (160, "ContextExtensionMap"),
("RO_SPACE", 0x06db1): (161, "DebugInfoMap"),
("RO_SPACE", 0x06e19): (162, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x06e81): (164, "InterpreterDataMap"),
("RO_SPACE", 0x06ee9): (165, "ModuleInfoEntryMap"),
("RO_SPACE", 0x06f51): (166, "ModuleMap"),
("RO_SPACE", 0x06fb9): (167, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x07021): (168, "PromiseCapabilityMap"),
("RO_SPACE", 0x07089): (169, "PromiseReactionMap"),
("RO_SPACE", 0x070f1): (170, "PrototypeInfoMap"),
("RO_SPACE", 0x07159): (172, "StackFrameInfoMap"),
("RO_SPACE", 0x071c1): (174, "Tuple3Map"),
("RO_SPACE", 0x07229): (175, "WasmCompiledModuleMap"),
("RO_SPACE", 0x07291): (176, "WasmDebugInfoMap"),
("RO_SPACE", 0x072f9): (177, "WasmSharedModuleDataMap"),
("RO_SPACE", 0x07361): (178, "CallableTaskMap"),
("RO_SPACE", 0x073c9): (179, "CallbackTaskMap"),
("RO_SPACE", 0x07431): (180, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x07499): (181, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x07501): (182, "PromiseResolveThenableJobTaskMap"),
("MAP_SPACE", 0x02201): (138, "FreeSpaceMap"),
("MAP_SPACE", 0x02259): (152, "OnePointerFillerMap"),
("MAP_SPACE", 0x022b1): (152, "TwoPointerFillerMap"),
......
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