Commit 971e81ad authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[gasm] Implement ReduceArrayPrototypeForEach using the graph assembler

After landing a few relatively simple ports in preceding work, this CL
ports the more involved Array.prototype.forEach reduction, containing
checkpoints, JS and runtime calls, loops, and exceptions. With the
mechanisms introduced in this change, I'd expect a large chunk of
js-call reductions to be trivially portable.

Newly introduced:
- IfBuilder0 for if-then-else statements (with optional else).
- ForBuilder for for-loop statements.
- MayThrow() for exceptional control flow. Exceptional edges are
  automatically merged and wired into the outer graph if necessary.

Bug: v8:9972
Change-Id: I835bf90c5871fbd94a1d12721d44b500fbef75e2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1921798Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65193}
parent bb1c475d
......@@ -532,11 +532,34 @@ Node* GraphAssembler::StringSubstring(Node* string, Node* from, Node* to) {
to, effect(), control()));
}
Node* GraphAssembler::ObjectIsCallable(Node* value) {
return AddNode(graph()->NewNode(simplified()->ObjectIsCallable(), value));
}
Node* GraphAssembler::NumberIsFloat64Hole(Node* value) {
return AddNode(graph()->NewNode(simplified()->NumberIsFloat64Hole(), value));
}
Node* GraphAssembler::TypeGuard(Type type, Node* value) {
return AddNode(
graph()->NewNode(common()->TypeGuard(type), value, effect(), control()));
}
Node* GraphAssembler::Checkpoint(Node* frame_state) {
return AddNode(graph()->NewNode(common()->Checkpoint(), frame_state, effect(),
control()));
}
Node* GraphAssembler::LoopExit(Node* loop_header) {
return AddNode(
graph()->NewNode(common()->LoopExit(), control(), loop_header));
}
Node* GraphAssembler::LoopExitEffect() {
return AddNode(
graph()->NewNode(common()->LoopExitEffect(), effect(), control()));
}
Node* GraphAssembler::DebugBreak() {
return AddNode(
graph()->NewNode(machine()->DebugBreak(), effect(), control()));
......@@ -638,13 +661,19 @@ Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason,
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check) {
DCHECK_NOT_NULL(control());
BranchHint hint = BranchHint::kNone;
if (if_true->IsDeferred() != if_false->IsDeferred()) {
hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
}
Branch(condition, if_true, if_false, hint, is_safety_check);
}
void GraphAssembler::Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false, BranchHint hint,
IsSafetyCheck is_safety_check) {
DCHECK_NOT_NULL(control());
Node* branch = graph()->NewNode(common()->Branch(hint, is_safety_check),
condition, control());
......
......@@ -110,6 +110,7 @@ class BasicBlock;
V(NaN) \
V(NoContext) \
V(Null) \
V(One) \
V(TheHole) \
V(ToNumberBuiltin) \
V(True) \
......@@ -265,8 +266,13 @@ class V8_EXPORT_PRIVATE GraphAssembler {
Node* NumberLessThan(Node* lhs, Node* rhs);
Node* NumberAdd(Node* lhs, Node* rhs);
Node* StringSubstring(Node* string, Node* from, Node* to);
Node* ObjectIsCallable(Node* value);
Node* NumberIsFloat64Hole(Node* value);
Node* TypeGuard(Type type, Node* value);
Node* Checkpoint(Node* frame_state);
Node* LoopExit(Node* loop_header);
Node* LoopExitEffect();
Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
Node* Load(MachineType type, Node* object, Node* offset);
......@@ -300,6 +306,11 @@ class V8_EXPORT_PRIVATE GraphAssembler {
template <typename... Vars>
void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false, BranchHint hint,
IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
// Branch hints in this version are inferred from if_true/if_false deferred
// states.
void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
GraphAssemblerLabel<0u>* if_false,
IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
......
This diff is collapsed.
......@@ -27,6 +27,7 @@ class CommonOperatorBuilder;
class CompilationDependencies;
struct FeedbackSource;
struct FieldAccess;
class JSCallReducerAssembler;
class JSGraph;
class JSHeapBroker;
class JSOperatorBuilder;
......@@ -197,6 +198,9 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Reduction ReduceNumberConstructor(Node* node);
Reduction ReduceBigIntAsUintN(Node* node);
// The pendant to ReplaceWithValue when using GraphAssembler-based reductions.
Reduction ReplaceWithSubgraph(JSCallReducerAssembler* gasm, Node* subgraph);
// Helper to verify promise receiver maps are as expected.
// On bailout from a reduction, be sure to return inference.NoChange().
bool DoPromiseChecks(MapInference* inference);
......
......@@ -30,7 +30,6 @@ var eagerDeoptInCalled = function(deopt) {
};
a.forEach(sum);
};
;
%PrepareFunctionForOptimization(eagerDeoptInCalled);
eagerDeoptInCalled();
eagerDeoptInCalled();
......@@ -51,7 +50,6 @@ var eagerDeoptInCalled = function(deopt) {
};
a.forEach(sum);
};
;
%PrepareFunctionForOptimization(eagerDeoptInCalled);
eagerDeoptInCalled();
eagerDeoptInCalled();
......@@ -75,7 +73,6 @@ var eagerDeoptInCalled = function(deopt) {
};
a_noescape.forEach(sum);
};
;
%PrepareFunctionForOptimization(eagerDeoptInCalled);
eagerDeoptInCalled();
eagerDeoptInCalled();
......@@ -104,7 +101,6 @@ var lazyDeopt = function(deopt) {
%NeverOptimizeFunction(sum);
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -126,7 +122,6 @@ var lazyDeopt = function(deopt) {
};
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -150,7 +145,6 @@ var lazyDeopt = function(deopt) {
%NeverOptimizeFunction(sum);
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -175,7 +169,6 @@ var lazyDeopt = function(deopt) {
};
c.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -204,7 +197,6 @@ var lazyDeopt = function(deopt) {
caught = true;
}
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -234,7 +226,6 @@ var lazyDeopt = function(deopt) {
caught = true;
}
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -287,14 +278,12 @@ var lazyDeopt = function foobar(deopt) {
result += v;
if (i == 1) {
var e = new Error();
print(e.stack);
assertTrue(re.exec(e.stack) !== null);
}
};
var o = [1, 2, 3];
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -318,7 +307,6 @@ var lazyDeopt = function(deopt) {
var o = [1, 2, 3];
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -343,7 +331,6 @@ var lazyDeopt = function(deopt) {
var o = [1, 2, 3];
b.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
lazyDeopt();
lazyDeopt();
......@@ -365,7 +352,6 @@ var lazyDeopt = function() {
};
a.forEach(sum);
};
;
%PrepareFunctionForOptimization(lazyDeopt);
assertThrows(() => lazyDeopt());
assertThrows(() => lazyDeopt());
......
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