Commit 14cd4b54 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

Implement Array.prototype.reduce inlining in TF

Bug: v8:1956,v8:4869
Change-Id: Id5822319c14142be2dd984c922b2b65717b96dee
Reviewed-on: https://chromium-review.googlesource.com/803974
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50261}
parent d5fbf7c5
......@@ -2119,6 +2119,36 @@ TF_BUILTIN(ArrayReduceLoopContinuation, ArrayBuiltinCodeStubAssembler) {
MissingPropertyMode::kSkip);
}
TF_BUILTIN(ArrayReduceLoopEagerDeoptContinuation,
ArrayBuiltinCodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* accumulator = Parameter(Descriptor::kAccumulator);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Callable stub(
Builtins::CallableFor(isolate(), Builtins::kArrayReduceLoopContinuation));
Return(CallStub(stub, context, receiver, callbackfn, UndefinedConstant(),
accumulator, receiver, initial_k, len, UndefinedConstant()));
}
TF_BUILTIN(ArrayReduceLoopLazyDeoptContinuation,
ArrayBuiltinCodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* receiver = Parameter(Descriptor::kReceiver);
Node* callbackfn = Parameter(Descriptor::kCallbackFn);
Node* initial_k = Parameter(Descriptor::kInitialK);
Node* len = Parameter(Descriptor::kLength);
Node* result = Parameter(Descriptor::kResult);
Callable stub(
Builtins::CallableFor(isolate(), Builtins::kArrayReduceLoopContinuation));
Return(CallStub(stub, context, receiver, callbackfn, UndefinedConstant(),
result, receiver, initial_k, len, UndefinedConstant()));
}
TF_BUILTIN(ArrayReduce, ArrayBuiltinCodeStubAssembler) {
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
......
......@@ -303,6 +303,10 @@ namespace internal {
/* ES6 #sec-array.prototype.reduce */ \
TFS(ArrayReduceLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduceLoopEagerDeoptContinuation, 4, kCallbackFn, kInitialK, \
kLength, kAccumulator) \
TFJ(ArrayReduceLoopLazyDeoptContinuation, 4, kCallbackFn, kInitialK, \
kLength, kResult) \
TFJ(ArrayReduce, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.reduceRight */ \
TFS(ArrayReduceRightLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
......
......@@ -183,6 +183,8 @@ Callable Builtins::CallableFor(Isolate* isolate, Name name) {
case kArrayForEachLoopLazyDeoptContinuation:
case kArrayMapLoopEagerDeoptContinuation:
case kArrayMapLoopLazyDeoptContinuation:
case kArrayReduceLoopEagerDeoptContinuation:
case kArrayReduceLoopLazyDeoptContinuation:
case kConsoleAssert:
return Callable(code, BuiltinDescriptor(isolate));
default:
......@@ -235,6 +237,8 @@ bool Builtins::IsLazy(int index) {
case kArrayMapLoopLazyDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayFilterLoopEagerDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayFilterLoopLazyDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayReduceLoopEagerDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayReduceLoopLazyDeoptContinuation: // https://crbug.com/v8/6786.
case kCheckOptimizationMarker:
case kCompileLazy:
case kDeserializeLazy:
......
This diff is collapsed.
......@@ -72,6 +72,7 @@ class JSCallReducer final : public AdvancedReducer {
Reduction ReduceReflectGetPrototypeOf(Node* node);
Reduction ReduceReflectHas(Node* node);
Reduction ReduceArrayForEach(Handle<JSFunction> function, Node* node);
Reduction ReduceArrayReduce(Handle<JSFunction> function, Node* node);
Reduction ReduceArrayMap(Handle<JSFunction> function, Node* node);
Reduction ReduceArrayFilter(Handle<JSFunction> function, Node* node);
enum class ArrayFindVariant : uint8_t { kFind, kFindIndex };
......
......@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
/**
* @fileoverview Test reduce and reduceRight
*/
......@@ -557,3 +559,311 @@ assertEquals(undefined, arr.reduceRight(function(val) { return val }));
}, 'initial')
}, 'do not continue');
})();
(function OptimizedReduce() {
let f = (a,current) => a + current;
let g = function(a) {
return a.reduce(f);
}
let a = [1,2,3,4,5,6,7,8,9,10];
g(a); g(a);
let total = g(a);
%OptimizeFunctionOnNextCall(g);
assertEquals(total, g(a));
})();
(function OptimizedReduceEmpty() {
let f = (a,current) => a + current;
let g = function(a) {
return a.reduce(f);
}
let a = [1,2,3,4,5,6,7,8,9,10];
g(a); g(a); g(a);
%OptimizeFunctionOnNextCall(g);
g(a);
assertThrows(() => g([]));
})();
(function OptimizedReduceLazyDeopt() {
let deopt = false;
let f = (a,current) => { if (deopt) %DeoptimizeNow(); return a + current; };
let g = function(a) {
return a.reduce(f);
}
let a = [1,2,3,4,5,6,7,8,9,10];
g(a); g(a);
let total = g(a);
%OptimizeFunctionOnNextCall(g);
g(a);
deopt = true;
assertEquals(total, g(a));
})();
(function OptimizedReduceLazyDeoptMiddleOfIteration() {
let deopt = false;
let f = (a,current) => {
if (current == 6 && deopt) %DeoptimizeNow();
return a + current;
};
let g = function(a) {
return a.reduce(f);
}
let a = [11,22,33,45,56,6,77,84,93,101];
g(a); g(a);
let total = g(a);
%OptimizeFunctionOnNextCall(g);
g(a);
deopt = true;
assertEquals(total, g(a));
})();
(function OptimizedReduceEagerDeoptMiddleOfIteration() {
let deopt = false;
let array = [11,22,33,45,56,6,77,84,93,101];
let f = (a,current) => {
if (current == 6 && deopt) {array[0] = 1.5; }
return a + current;
};
let g = function() {
return array.reduce(f);
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
deopt = true;
g();
deopt = false;
array = [11,22,33,45,56,6,77,84,93,101];
%OptimizeFunctionOnNextCall(g);
g();
deopt = true;
assertEquals(total, g());
})();
(function ReduceCatch() {
let f = (a,current) => {
return a + current;
};
let g = function() {
try {
return array.reduce(f);
} catch (e) {
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
g();
assertEquals(total, g());
})();
(function ReduceThrow() {
let done = false;
let f = (a, current) => {
if (done) throw "x";
return a + current;
};
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
(function ReduceThrow() {
let done = false;
let f = (a, current) => {
if (done) throw "x";
return a + current;
};
%NeverOptimizeFunction(f);
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
(function ReduceFinally() {
let done = false;
let f = (a, current) => {
if (done) throw "x";
return a + current;
};
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
} finally {
if (done) return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
(function ReduceFinallyNoInline() {
let done = false;
let f = (a, current) => {
if (done) throw "x";
return a + current;
};
%NeverOptimizeFunction(f);
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
} finally {
if (done) return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
(function ReduceNonCallableOpt() {
let done = false;
let f = (a, current) => {
return a + current;
};
let array = [1,2,3];
let g = function() {
return array.reduce(f);
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g(); g();
assertEquals(6, g());
f = null;
assertThrows(() => g());
})();
(function ReduceCatchInlineDeopt() {
let done = false;
let f = (a, current) => {
if (done) {
%DeoptimizeNow();
throw "x";
}
return a + current;
};
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
if (done) return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
(function ReduceFinallyInlineDeopt() {
let done = false;
let f = (a, current) => {
if (done) {
%DeoptimizeNow();
throw "x";
}
return a + current;
};
let array = [1,2,3];
let g = function() {
try {
return array.reduce(f);
} catch (e) {
} finally {
if (done) return null;
}
}
g(); g();
let total = g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
done = false;
g(); g();
%OptimizeFunctionOnNextCall(g);
g();
assertEquals(6, g());
done = true;
assertEquals(null, g());
})();
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