Commit 2c84924f authored by mvstanton's avatar mvstanton Committed by Commit bot

[Builtins] New Array.prototype.filter implementation observability bug.

filter creates an output array with the Array species constructor for
storing values from the input array that pass the user-supplied
predicate function. Our new array builtins are implemented such that
if we fall out of the fast path, we'll pick up where we left off
in a continuation function. It's important to pass the index of
where we left off appending to the output array, because otherwise
we will read it at the start of the continuation function.

That would be observable, and a spec violation.

BUG=

Review-Url: https://codereview.chromium.org/2771483002
Cr-Commit-Position: refs/heads/master@{#44023}
parent e046b80a
......@@ -128,24 +128,6 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
return ArraySpeciesCreate(context(), o(), SmiConstant(0));
}
void FilterResultIndexReinitializer() {
Variable merged_length(this, MachineRepresentation::kTagged);
Label has_length(this, &merged_length), not_js_array(this);
GotoIf(DoesntHaveInstanceType(a(), JS_ARRAY_TYPE), &not_js_array);
merged_length.Bind(LoadJSArrayLength(a()));
Goto(&has_length);
Bind(&not_js_array);
Node* len_property =
GetProperty(context(), a(), isolate()->factory()->length_string());
merged_length.Bind(
CallStub(CodeFactory::ToLength(isolate()), context(), len_property));
Goto(&has_length);
Bind(&has_length);
Node* len = merged_length.value();
to_.Bind(len);
}
Node* FilterProcessor(Node* k_value, Node* k) {
Node* callback_result = CallJS(CodeFactory::Call(isolate()), context(),
callbackfn(), this_arg(), k_value, k, o());
......@@ -167,8 +149,6 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
void NullPostLoopAction() {}
void NullResultIndexReinitializer() {}
protected:
Node* context() { return context_; }
Node* receiver() { return receiver_; }
......@@ -273,14 +253,14 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
slow_case_continuation, context(), target, new_target(),
Int32Constant(IteratingArrayBuiltinLoopContinuationDescriptor::kArity),
receiver(), callbackfn(), this_arg(), a_.value(), o(), k_.value(),
len());
len(), to_.value());
}
void InitIteratingArrayBuiltinLoopContinuation(Node* context, Node* receiver,
Node* callbackfn,
Node* this_arg, Node* a,
Node* o, Node* initial_k,
Node* len) {
Node* len, Node* to) {
context_ = context;
this_arg_ = this_arg;
callbackfn_ = callbackfn;
......@@ -288,13 +268,11 @@ class ArrayBuiltinCodeStubAssembler : public CodeStubAssembler {
k_.Bind(initial_k);
o_ = o;
len_ = len;
to_.Bind(to);
}
void GenerateIteratingArrayBuiltinLoopContinuation(
const BuiltinResultIndexInitializer& index_initializer,
const CallResultProcessor& processor, const PostLoopAction& action) {
index_initializer(this);
// 8. Repeat, while k < len
Label loop(this, {&k_, &a_, &to_});
Label after_loop(this);
......@@ -618,12 +596,13 @@ TF_BUILTIN(ArrayForEachLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(
context, receiver, callbackfn, this_arg, array, object, initial_k, len);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer,
&ArrayBuiltinCodeStubAssembler::ForEachProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
......@@ -655,12 +634,13 @@ TF_BUILTIN(ArraySomeLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(
context, receiver, callbackfn, this_arg, array, object, initial_k, len);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer,
&ArrayBuiltinCodeStubAssembler::SomeProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
......@@ -692,12 +672,13 @@ TF_BUILTIN(ArrayEveryLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(
context, receiver, callbackfn, this_arg, array, object, initial_k, len);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer,
&ArrayBuiltinCodeStubAssembler::EveryProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
......@@ -729,13 +710,13 @@ TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, accumulator, object,
initial_k, len);
initial_k, len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::NullResultIndexReinitializer,
&ArrayBuiltinCodeStubAssembler::ReduceProcessor,
&ArrayBuiltinCodeStubAssembler::ReducePostLoopAction);
}
......@@ -767,12 +748,13 @@ TF_BUILTIN(ArrayFilterLoopContinuation, ArrayBuiltinCodeStubAssembler) {
Node* object = Parameter(Descriptor::kObject);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* to = Parameter(Descriptor::kTo);
InitIteratingArrayBuiltinLoopContinuation(
context, receiver, callbackfn, this_arg, array, object, initial_k, len);
InitIteratingArrayBuiltinLoopContinuation(context, receiver, callbackfn,
this_arg, array, object, initial_k,
len, to);
GenerateIteratingArrayBuiltinLoopContinuation(
&ArrayBuiltinCodeStubAssembler::FilterResultIndexReinitializer,
&ArrayBuiltinCodeStubAssembler::FilterProcessor,
&ArrayBuiltinCodeStubAssembler::NullPostLoopAction);
}
......
......@@ -285,24 +285,24 @@ class Isolate;
/* ES6 #sec-array.prototype.unshift */ \
CPP(ArrayUnshift) \
/* ES6 #sec-array.prototype.foreach */ \
TFJ(ArrayForEachLoopContinuation, 6, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength) \
TFJ(ArrayForEachLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayForEach, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.every */ \
TFJ(ArrayEveryLoopContinuation, 6, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength) \
TFJ(ArrayEveryLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayEvery, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.some */ \
TFJ(ArraySomeLoopContinuation, 6, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength) \
TFJ(ArraySomeLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArraySome, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.filter */ \
TFJ(ArrayFilterLoopContinuation, 6, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength) \
TFJ(ArrayFilterLoopContinuation, 7, kCallbackFn, kThisArg, kArray, kObject, \
kInitialK, kLength, kTo) \
TFJ(ArrayFilter, 2, kCallbackFn, kThisArg) \
/* ES6 #sec-array.prototype.reduce */ \
TFJ(ArrayReduceLoopContinuation, 6, kCallbackFn, kThisArg, kAccumulator, \
kObject, kInitialK, kLength) \
TFJ(ArrayReduceLoopContinuation, 7, kCallbackFn, kThisArg, kAccumulator, \
kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduce, 2, kCallbackFn, kInitialValue) \
/* ES6 #sec-array.prototype.entries */ \
TFJ(ArrayPrototypeEntries, 0) \
......
......@@ -34,6 +34,8 @@
#define REPEAT_1_TO_10(V, T) REPEAT_1_TO_9(V, T) V(T, T, T, T, T, T, T, T, T, T)
#define REPEAT_1_TO_11(V, T) \
REPEAT_1_TO_10(V, T) V(T, T, T, T, T, T, T, T, T, T, T)
#define REPEAT_1_TO_12(V, T) \
REPEAT_1_TO_11(V, T) V(T, T, T, T, T, T, T, T, T, T, T, T)
namespace v8 {
namespace internal {
......@@ -630,7 +632,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallStub( \
const CallInterfaceDescriptor& descriptor, Node*, __VA_ARGS__);
REPEAT_1_TO_11(INSTANTIATE, Node*)
REPEAT_1_TO_12(INSTANTIATE, Node*)
#undef INSTANTIATE
template <class... TArgs>
......
......@@ -728,7 +728,7 @@ class IteratingArrayBuiltinLoopContinuationDescriptor
: public BuiltinDescriptor {
public:
DEFINE_BUILTIN_PARAMETERS(kCallback, kThisArg, kArray, kObject, kInitialK,
kLength)
kLength, kTo)
DECLARE_BUILTIN_DESCRIPTOR(IteratingArrayBuiltinLoopContinuationDescriptor)
};
......
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