Commit 7bcd9265 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

Implement Array.prototype.reduceRight inlining in TF

Bug: v8:1956
Change-Id: I785986ed20e60e21966abe82a1567d239b22b416
Reviewed-on: https://chromium-review.googlesource.com/840026Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50283}
parent 699144a2
......@@ -2212,6 +2212,36 @@ TF_BUILTIN(ArrayReduceRightLoopContinuation, ArrayBuiltinCodeStubAssembler) {
MissingPropertyMode::kSkip, ForEachDirection::kReverse);
}
TF_BUILTIN(ArrayReduceRightLoopEagerDeoptContinuation,
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::kArrayReduceRightLoopContinuation));
Return(CallStub(stub, context, receiver, callbackfn, UndefinedConstant(),
accumulator, receiver, initial_k, len, UndefinedConstant()));
}
TF_BUILTIN(ArrayReduceRightLoopLazyDeoptContinuation,
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::kArrayReduceRightLoopContinuation));
Return(CallStub(stub, context, receiver, callbackfn, UndefinedConstant(),
result, receiver, initial_k, len, UndefinedConstant()));
}
TF_BUILTIN(ArrayReduceRight, ArrayBuiltinCodeStubAssembler) {
Node* argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
......
......@@ -311,6 +311,10 @@ namespace internal {
/* ES6 #sec-array.prototype.reduceRight */ \
TFS(ArrayReduceRightLoopContinuation, kReceiver, kCallbackFn, kThisArg, \
kAccumulator, kObject, kInitialK, kLength, kTo) \
TFJ(ArrayReduceRightLoopEagerDeoptContinuation, 4, kCallbackFn, kInitialK, \
kLength, kAccumulator) \
TFJ(ArrayReduceRightLoopLazyDeoptContinuation, 4, kCallbackFn, kInitialK, \
kLength, kResult) \
TFJ(ArrayReduceRight, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-array.prototype.entries */ \
TFJ(ArrayPrototypeEntries, 0) \
......
......@@ -185,6 +185,8 @@ Callable Builtins::CallableFor(Isolate* isolate, Name name) {
case kArrayMapLoopLazyDeoptContinuation:
case kArrayReduceLoopEagerDeoptContinuation:
case kArrayReduceLoopLazyDeoptContinuation:
case kArrayReduceRightLoopEagerDeoptContinuation:
case kArrayReduceRightLoopLazyDeoptContinuation:
case kConsoleAssert:
return Callable(code, BuiltinDescriptor(isolate));
default:
......@@ -239,6 +241,8 @@ bool Builtins::IsLazy(int index) {
case kArrayFilterLoopLazyDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayReduceLoopEagerDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayReduceLoopLazyDeoptContinuation: // https://crbug.com/v8/6786.
case kArrayReduceRightLoopEagerDeoptContinuation:
case kArrayReduceRightLoopLazyDeoptContinuation:
case kCheckOptimizationMarker:
case kCompileLazy:
case kDeserializeLazy:
......
This diff is collapsed.
......@@ -73,6 +73,7 @@ class JSCallReducer final : public AdvancedReducer {
Reduction ReduceReflectHas(Node* node);
Reduction ReduceArrayForEach(Handle<JSFunction> function, Node* node);
Reduction ReduceArrayReduce(Handle<JSFunction> function, Node* node);
Reduction ReduceArrayReduceRight(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 };
......
......@@ -867,3 +867,315 @@ assertEquals(undefined, arr.reduceRight(function(val) { return val }));
done = true;
assertEquals(null, g());
})();
(function OptimizedReduceRight() {
let count = 0;
let f = (a,current,i) => a + current * ++count;
let g = function(a) {
count = 0;
return a.reduceRight(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 count = 0;
let f = (a,current,i) => a + current * ++count;
let g = function(a) {
count = 0;
return a.reduceRight(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.reduceRight(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.reduceRight(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[9] = 1.5; }
return a + current;
};
let g = function() {
return array.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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.reduceRight(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