[gasm] Implement parts of js call reducer using the graph assembler

An initial investigation of using GraphAssembler in JSCallReducer.

This CL ports two simple reductions (ReduceMathUnary,
ReduceMathBinary) as well as a slightly more involved reduction with
branching control flow (ReduceStringPrototypeSubstring). The graph
assembler abstracts away the details of maintaining effect and control
edges. Resulting code ends up looking very similar to CSA.

Newly introduced:
- Typing through TNode.
- IfBuilder1 for nicer if-then-else sequences that return exactly 1
  value. Future CLs will add more convenience builders that follow this
  pattern.
- Many small readability improvements through helper functions.

Bug: v8:9972
Change-Id: Iaa186b76c006e07c8d69a74f340a4912577a32a5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1914204
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65095}
This commit is contained in:
Jakob Gruber 2019-11-21 12:30:25 +01:00 committed by Commit Bot
parent 438f72f406
commit 002d5be898
6 changed files with 326 additions and 172 deletions

View File

@ -399,6 +399,13 @@ Node* GraphAssembler::LoadFramePointer() {
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF)
#undef SINGLETON_CONST_DEF
#define SINGLETON_CONST_TEST_DEF(Name) \
Node* GraphAssembler::Is##Name(Node* value) { \
return ReferenceEqual(value, Name##Constant()); \
}
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DEF)
#undef SINGLETON_CONST_TEST_DEF
#define PURE_UNOP_DEF(Name) \
Node* GraphAssembler::Name(Node* input) { \
return AddNode(graph()->NewNode(machine()->Name(), input)); \
@ -496,6 +503,40 @@ Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object,
index, value, effect(), control()));
}
Node* GraphAssembler::StringLength(Node* string) {
return AddNode(graph()->NewNode(simplified()->StringLength(), string));
}
Node* GraphAssembler::ReferenceEqual(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->ReferenceEqual(), lhs, rhs));
}
Node* GraphAssembler::NumberMin(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberMin(), lhs, rhs));
}
Node* GraphAssembler::NumberMax(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberMax(), lhs, rhs));
}
Node* GraphAssembler::NumberAdd(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberAdd(), lhs, rhs));
}
Node* GraphAssembler::NumberLessThan(Node* lhs, Node* rhs) {
return AddNode(graph()->NewNode(simplified()->NumberLessThan(), lhs, rhs));
}
Node* GraphAssembler::StringSubstring(Node* string, Node* from, Node* to) {
return AddNode(graph()->NewNode(simplified()->StringSubstring(), string, from,
to, effect(), control()));
}
Node* GraphAssembler::TypeGuard(Type type, Node* value) {
return AddNode(
graph()->NewNode(common()->TypeGuard(type), value, effect(), control()));
}
Node* GraphAssembler::DebugBreak() {
return AddNode(
graph()->NewNode(machine()->DebugBreak(), effect(), control()));

View File

@ -163,12 +163,12 @@ class GraphAssemblerLabel {
MachineRepresentation representations_[VarCount + 1];
};
class GraphAssembler {
class V8_EXPORT_PRIVATE GraphAssembler {
public:
// Constructs a GraphAssembler. If {schedule} is not null, the graph assembler
// will maintain the schedule as it updates blocks.
GraphAssembler(JSGraph* jsgraph, Zone* zone, Schedule* schedule = nullptr);
~GraphAssembler();
virtual ~GraphAssembler();
void Reset(BasicBlock* block);
void InitializeEffectControl(Node* effect, Node* control);
@ -220,6 +220,10 @@ class GraphAssembler {
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
#undef SINGLETON_CONST_DECL
#define SINGLETON_CONST_TEST_DECL(Name) Node* Is##Name(Node* value);
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DECL)
#undef SINGLETON_CONST_TEST_DECL
#define PURE_UNOP_DECL(Name) Node* Name(Node* input);
PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
#undef PURE_UNOP_DECL
@ -253,6 +257,15 @@ class GraphAssembler {
Node* StoreField(FieldAccess const&, Node* object, Node* value);
Node* StoreElement(ElementAccess const&, Node* object, Node* index,
Node* value);
Node* StringLength(Node* string);
Node* ReferenceEqual(Node* lhs, Node* rhs);
Node* NumberMin(Node* lhs, Node* rhs);
Node* NumberMax(Node* lhs, Node* rhs);
Node* NumberLessThan(Node* lhs, Node* rhs);
Node* NumberAdd(Node* lhs, Node* rhs);
Node* StringSubstring(Node* string, Node* from, Node* to);
Node* TypeGuard(Type type, Node* value);
Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
Node* Load(MachineType type, Node* object, Node* offset);
@ -324,7 +337,7 @@ class GraphAssembler {
Node* control() { return control_; }
Node* effect() { return effect_; }
private:
protected:
class BasicBlockUpdater;
template <typename... Vars>

View File

@ -10,11 +10,13 @@
#include "src/builtins/builtins-promise.h"
#include "src/builtins/builtins-utils.h"
#include "src/codegen/code-factory.h"
#include "src/codegen/tnode.h"
#include "src/compiler/access-builder.h"
#include "src/compiler/access-info.h"
#include "src/compiler/allocation-builder.h"
#include "src/compiler/compilation-dependencies.h"
#include "src/compiler/feedback-source.h"
#include "src/compiler/graph-assembler.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/map-inference.h"
@ -36,6 +38,252 @@ namespace v8 {
namespace internal {
namespace compiler {
namespace {
// Shorter lambda declarations with less visual clutter.
#define _ [&]() // NOLINT(whitespace/braces)
// STNode<T> is a shorter alias of SloppyTNode<T> for improved readability.
// TODO(jgruber): Switch to TNode once fewer explicit casts are necessary, i.e.
// once more underlying operations return typed nodes.
template <class T>
using STNode = SloppyTNode<T>;
template <class T>
constexpr Node* ToNodePtr(STNode<T> tnode) {
return static_cast<Node*>(tnode);
}
template <class T>
constexpr TNode<T> ToTNode(Node* node) {
return TNode<T>::UncheckedCast(node);
}
class JSCallReducerAssembler : public GraphAssembler {
public:
JSCallReducerAssembler(JSGraph* jsgraph, Zone* zone, STNode<Object> node)
: GraphAssembler(jsgraph, zone), node_(node) {
InitializeEffectControl(NodeProperties::GetEffectInput(node),
NodeProperties::GetControlInput(node));
}
virtual ~JSCallReducerAssembler() {}
TNode<Object> ReduceMathUnary(const Operator* op);
TNode<Object> ReduceMathBinary(const Operator* op);
TNode<String> ReduceStringPrototypeSubstring();
TNode<String> ReduceStringPrototypeSlice();
using NodeGenerator = std::function<Node*()>;
class IfBuilder1 {
public:
IfBuilder1(GraphAssembler* gasm, STNode<Object> cond)
: gasm_(gasm), cond_(cond) {}
IfBuilder1& ExpectTrue() {
hint_ = BranchHint::kTrue;
return *this;
}
IfBuilder1& ExpectFalse() {
hint_ = BranchHint::kFalse;
return *this;
}
IfBuilder1& Then(const NodeGenerator& body) {
then_body_ = body;
return *this;
}
IfBuilder1& Else(const NodeGenerator& body) {
else_body_ = body;
return *this;
}
TNode<Object> Value() {
DCHECK(then_body_);
DCHECK(else_body_);
auto if_true = (hint_ == BranchHint::kFalse) ? gasm_->MakeDeferredLabel()
: gasm_->MakeLabel();
auto if_false = (hint_ == BranchHint::kTrue) ? gasm_->MakeDeferredLabel()
: gasm_->MakeLabel();
auto merge = gasm_->MakeLabel(kPhiRepresentation);
gasm_->Branch(cond_, &if_true, &if_false);
gasm_->Bind(&if_true);
Node* then_result = then_body_();
gasm_->Goto(&merge, then_result);
gasm_->Bind(&if_false);
Node* else_result = else_body_();
gasm_->Goto(&merge, else_result);
gasm_->Bind(&merge);
return ToTNode<Object>(merge.PhiAt(0));
}
private:
static constexpr MachineRepresentation kPhiRepresentation =
MachineRepresentation::kTagged;
GraphAssembler* const gasm_;
const STNode<Object> cond_;
BranchHint hint_ = BranchHint::kNone;
NodeGenerator then_body_;
NodeGenerator else_body_;
};
IfBuilder1 SelectIf(STNode<Object> cond) { return {this, cond}; }
TNode<Number> SpeculativeToNumber(
STNode<Object> value,
NumberOperationHint hint = NumberOperationHint::kNumberOrOddball);
TNode<Smi> CheckSmi(STNode<Object> value);
TNode<String> CheckString(STNode<Object> value);
TNode<Smi> TypeGuardUnsignedSmall(STNode<Object> value);
private:
const FeedbackSource& feedback() const {
CallParameters const& p = CallParametersOf(node_ptr()->op());
return p.feedback();
}
TNode<Object> ValueInput(int index) {
return ToTNode<Object>(NodeProperties::GetValueInput(node_, index));
}
TNode<Object> ValueInputOrNaN(int index) {
return ToTNode<Object>(node_ptr()->op()->ValueInputCount() > index
? NodeProperties::GetValueInput(node_, index)
: NaNConstant());
}
TNode<Object> ValueInputOrUndefined(int index) {
return ToTNode<Object>(node_ptr()->op()->ValueInputCount() > index
? NodeProperties::GetValueInput(node_, index)
: UndefinedConstant());
}
private:
Node* node_ptr() const { return ToNodePtr(node_); }
const STNode<Object> node_;
};
TNode<Number> JSCallReducerAssembler::SpeculativeToNumber(
STNode<Object> value, NumberOperationHint hint) {
return ToTNode<Number>(AddNode(
graph()->NewNode(simplified()->SpeculativeToNumber(hint, feedback()),
ToNodePtr(value), effect(), control())));
}
TNode<Smi> JSCallReducerAssembler::CheckSmi(STNode<Object> value) {
return ToTNode<Smi>(
AddNode(graph()->NewNode(simplified()->CheckSmi(feedback()),
ToNodePtr(value), effect(), control())));
}
TNode<String> JSCallReducerAssembler::CheckString(STNode<Object> value) {
return ToTNode<String>(
AddNode(graph()->NewNode(simplified()->CheckString(feedback()),
ToNodePtr(value), effect(), control())));
}
TNode<Smi> JSCallReducerAssembler::TypeGuardUnsignedSmall(
STNode<Object> value) {
return ToTNode<Smi>(TypeGuard(Type::UnsignedSmall(), value));
}
TNode<Object> JSCallReducerAssembler::ReduceMathUnary(const Operator* op) {
STNode<Object> input = ValueInput(2);
STNode<Number> input_as_number = SpeculativeToNumber(input);
return ToTNode<Object>(graph()->NewNode(op, ToNodePtr(input_as_number)));
}
TNode<Object> JSCallReducerAssembler::ReduceMathBinary(const Operator* op) {
STNode<Object> left = ValueInput(2);
STNode<Object> right = ValueInputOrNaN(3);
STNode<Number> left_number = SpeculativeToNumber(left);
STNode<Number> right_number = SpeculativeToNumber(right);
return ToTNode<Object>(
graph()->NewNode(op, ToNodePtr(left_number), ToNodePtr(right_number)));
}
TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSubstring() {
STNode<Object> receiver = ValueInput(1);
STNode<Object> start = ValueInput(2);
STNode<Object> end = ValueInputOrUndefined(3);
STNode<String> receiver_string = CheckString(receiver);
STNode<Smi> start_smi = CheckSmi(start);
STNode<Smi> length = StringLength(receiver_string);
STNode<Smi> end_smi =
STNode<Smi>::UncheckedCast(SelectIf(IsUndefined(end))
.Then(_ { return length; })
.Else(_ { return CheckSmi(end); })
.ExpectFalse()
.Value());
STNode<Number> zero = ZeroConstant();
STNode<Number> finalStart = NumberMin(NumberMax(start_smi, zero), length);
STNode<Number> finalEnd = NumberMin(NumberMax(end_smi, zero), length);
STNode<Number> from = NumberMin(finalStart, finalEnd);
STNode<Number> to = NumberMax(finalStart, finalEnd);
return ToTNode<String>(StringSubstring(receiver_string, from, to));
}
TNode<String> JSCallReducerAssembler::ReduceStringPrototypeSlice() {
STNode<Object> receiver = ValueInput(1);
STNode<Object> start = ValueInput(2);
STNode<Object> end = ValueInputOrUndefined(3);
STNode<String> receiver_string = CheckString(receiver);
STNode<Smi> start_smi = CheckSmi(start);
STNode<Smi> length = StringLength(receiver_string);
STNode<Smi> end_smi =
STNode<Smi>::UncheckedCast(SelectIf(IsUndefined(end))
.Then(_ { return length; })
.Else(_ { return CheckSmi(end); })
.ExpectFalse()
.Value());
STNode<Number> zero = ZeroConstant();
STNode<Object> from_untyped =
SelectIf(NumberLessThan(start_smi, zero))
.Then(_ { return NumberMax(NumberAdd(length, start_smi), zero); })
.Else(_ { return NumberMin(start_smi, length); })
.ExpectFalse()
.Value();
// {from} is always in non-negative Smi range, but our typer cannot figure
// that out yet.
STNode<Smi> from = TypeGuardUnsignedSmall(from_untyped);
STNode<Number> to_untyped = STNode<Number>::UncheckedCast(
SelectIf(NumberLessThan(end_smi, zero))
.Then(_ { return NumberMax(NumberAdd(length, end_smi), zero); })
.Else(_ { return NumberMin(end_smi, length); })
.ExpectFalse()
.Value());
// {to} is always in non-negative Smi range, but our typer cannot figure that
// out yet.
STNode<Smi> to = TypeGuardUnsignedSmall(to_untyped);
return ToTNode<String>(
(SelectIf(NumberLessThan(from, to))
.Then(_ { return StringSubstring(receiver_string, from, to); })
.Else(_ { return EmptyStringConstant(); })
.ExpectTrue()
.Value()));
}
#undef _
} // namespace
Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
CallParameters const& p = CallParametersOf(node->op());
if (p.speculation_mode() == SpeculationMode::kDisallowSpeculation) {
@ -47,16 +295,10 @@ Reduction JSCallReducer::ReduceMathUnary(Node* node, const Operator* op) {
return Replace(value);
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* input = NodeProperties::GetValueInput(node, 2);
JSCallReducerAssembler a(jsgraph(), temp_zone(), node);
Node* value = a.ReduceMathUnary(op);
input = effect =
graph()->NewNode(simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball, p.feedback()),
input, effect, control);
Node* value = graph()->NewNode(op, input);
ReplaceWithValue(node, value, effect);
ReplaceWithValue(node, value, a.effect());
return Replace(value);
}
@ -70,23 +312,11 @@ Reduction JSCallReducer::ReduceMathBinary(Node* node, const Operator* op) {
ReplaceWithValue(node, value);
return Replace(value);
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* left = NodeProperties::GetValueInput(node, 2);
Node* right = node->op()->ValueInputCount() > 3
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->NaNConstant();
left = effect =
graph()->NewNode(simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball, p.feedback()),
left, effect, control);
right = effect =
graph()->NewNode(simplified()->SpeculativeToNumber(
NumberOperationHint::kNumberOrOddball, p.feedback()),
right, effect, control);
Node* value = graph()->NewNode(op, left, right);
ReplaceWithValue(node, value, effect);
JSCallReducerAssembler a(jsgraph(), temp_zone(), node);
Node* value = a.ReduceMathBinary(op);
ReplaceWithValue(node, value, a.effect());
return Replace(value);
}
@ -4063,58 +4293,10 @@ Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
return NoChange();
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* start = NodeProperties::GetValueInput(node, 2);
Node* end = node->op()->ValueInputCount() > 3
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
JSCallReducerAssembler a(jsgraph(), temp_zone(), node);
Node* value = a.ReduceStringPrototypeSubstring();
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
receiver, effect, control);
start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
effect, control);
Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
jsgraph()->UndefinedConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* vtrue = length;
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* vfalse = efalse = graph()->NewNode(simplified()->CheckSmi(p.feedback()),
end, efalse, if_false);
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
vtrue, vfalse, control);
Node* finalStart =
graph()->NewNode(simplified()->NumberMin(),
graph()->NewNode(simplified()->NumberMax(), start,
jsgraph()->ZeroConstant()),
length);
Node* finalEnd =
graph()->NewNode(simplified()->NumberMin(),
graph()->NewNode(simplified()->NumberMax(), end,
jsgraph()->ZeroConstant()),
length);
Node* from =
graph()->NewNode(simplified()->NumberMin(), finalStart, finalEnd);
Node* to = graph()->NewNode(simplified()->NumberMax(), finalStart, finalEnd);
Node* value = effect = graph()->NewNode(simplified()->StringSubstring(),
receiver, from, to, effect, control);
ReplaceWithValue(node, value, effect, control);
ReplaceWithValue(node, value, a.effect(), a.control());
return Replace(value);
}
@ -4126,98 +4308,11 @@ Reduction JSCallReducer::ReduceStringPrototypeSlice(Node* node) {
return NoChange();
}
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* receiver = NodeProperties::GetValueInput(node, 1);
Node* start = NodeProperties::GetValueInput(node, 2);
Node* end = node->op()->ValueInputCount() > 3
? NodeProperties::GetValueInput(node, 3)
: jsgraph()->UndefinedConstant();
JSCallReducerAssembler a(jsgraph(), temp_zone(), node);
Node* value = a.ReduceStringPrototypeSlice();
receiver = effect = graph()->NewNode(simplified()->CheckString(p.feedback()),
receiver, effect, control);
start = effect = graph()->NewNode(simplified()->CheckSmi(p.feedback()), start,
effect, control);
Node* length = graph()->NewNode(simplified()->StringLength(), receiver);
// Replace {end} argument with {length} if it is undefined.
{
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), end,
jsgraph()->UndefinedConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* vtrue = length;
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* vfalse = efalse = graph()->NewNode(
simplified()->CheckSmi(p.feedback()), end, efalse, if_false);
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
end = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
vtrue, vfalse, control);
}
Node* from = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
graph()->NewNode(simplified()->NumberLessThan(), start,
jsgraph()->ZeroConstant()),
graph()->NewNode(
simplified()->NumberMax(),
graph()->NewNode(simplified()->NumberAdd(), length, start),
jsgraph()->ZeroConstant()),
graph()->NewNode(simplified()->NumberMin(), start, length));
// {from} is always in non-negative Smi range, but our typer cannot
// figure that out yet.
from = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()),
from, effect, control);
Node* to = graph()->NewNode(
common()->Select(MachineRepresentation::kTagged, BranchHint::kFalse),
graph()->NewNode(simplified()->NumberLessThan(), end,
jsgraph()->ZeroConstant()),
graph()->NewNode(simplified()->NumberMax(),
graph()->NewNode(simplified()->NumberAdd(), length, end),
jsgraph()->ZeroConstant()),
graph()->NewNode(simplified()->NumberMin(), end, length));
// {to} is always in non-negative Smi range, but our typer cannot
// figure that out yet.
to = effect = graph()->NewNode(common()->TypeGuard(Type::UnsignedSmall()), to,
effect, control);
Node* result_string = nullptr;
// Return empty string if {from} is smaller than {to}.
{
Node* check = graph()->NewNode(simplified()->NumberLessThan(), from, to);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue = effect;
Node* vtrue = etrue = graph()->NewNode(simplified()->StringSubstring(),
receiver, from, to, etrue, if_true);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* vfalse = jsgraph()->EmptyStringConstant();
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
result_string =
graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
vtrue, vfalse, control);
}
ReplaceWithValue(node, result_string, effect, control);
return Replace(result_string);
ReplaceWithValue(node, value, a.effect(), a.control());
return Replace(value);
}
// ES #sec-string.prototype.substr

View File

@ -43,10 +43,12 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
using Flags = base::Flags<Flag>;
JSCallReducer(Editor* editor, JSGraph* jsgraph, JSHeapBroker* broker,
Flags flags, CompilationDependencies* dependencies)
Zone* temp_zone, Flags flags,
CompilationDependencies* dependencies)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
broker_(broker),
temp_zone_(temp_zone),
flags_(flags),
dependencies_(dependencies) {}
@ -250,6 +252,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
JSHeapBroker* broker() const { return broker_; }
Zone* temp_zone() const { return temp_zone_; }
Isolate* isolate() const;
Factory* factory() const;
NativeContextRef native_context() const;
@ -261,6 +264,7 @@ class V8_EXPORT_PRIVATE JSCallReducer final : public AdvancedReducer {
JSGraph* const jsgraph_;
JSHeapBroker* const broker_;
Zone* const temp_zone_;
Flags const flags_;
CompilationDependencies* const dependencies_;
std::set<Node*> waitlist_;

View File

@ -1285,6 +1285,7 @@ struct InliningPhase {
data->broker(), data->common(),
data->machine(), temp_zone);
JSCallReducer call_reducer(&graph_reducer, data->jsgraph(), data->broker(),
temp_zone,
data->info()->is_bailout_on_uninitialized()
? JSCallReducer::kBailoutOnUninitialized
: JSCallReducer::kNoFlags,

View File

@ -37,7 +37,7 @@ class JSCallReducerTest : public TypedGraphTest {
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph(), tick_counter());
JSCallReducer reducer(&graph_reducer, &jsgraph, broker(),
JSCallReducer reducer(&graph_reducer, &jsgraph, broker(), zone(),
JSCallReducer::kNoFlags, &deps_);
return reducer.Reduce(node);
}