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