Commit d667bf4a authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Introduce LoweringResult in type hint lowering.

Bug: v8:5267
Change-Id: Iea44ba7ee6ba09580176936e6157d63c53d06446
Reviewed-on: https://chromium-review.googlesource.com/646021
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47762}
parent ed17bab8
This diff is collapsed.
......@@ -178,31 +178,34 @@ class BytecodeGraphBuilder {
void BuildHoleCheckAndThrow(Node* condition, Runtime::FunctionId runtime_id,
Node* name = nullptr);
// Optional early lowering to the simplified operator level. Returns the node
// representing the lowered operation or {nullptr} if no lowering available.
// Note that the result has already been wired into the environment just like
// Optional early lowering to the simplified operator level. Note that
// the result has already been wired into the environment just like
// any other invocation of {NewNode} would do.
Node* TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, Node* right,
FeedbackSlot slot);
Node* TryBuildSimplifiedForInNext(Node* receiver, Node* cache_array,
Node* cache_type, Node* index,
FeedbackSlot slot);
Node* TryBuildSimplifiedToNumber(Node* input, FeedbackSlot slot);
Node* TryBuildSimplifiedCall(const Operator* op, Node* const* args,
int arg_count, FeedbackSlot slot);
Node* TryBuildSimplifiedConstruct(const Operator* op, Node* const* args,
int arg_count, FeedbackSlot slot);
Node* TryBuildSimplifiedLoadNamed(const Operator* op, Node* receiver,
FeedbackSlot slot);
Node* TryBuildSimplifiedLoadKeyed(const Operator* op, Node* receiver,
Node* key, FeedbackSlot slot);
Node* TryBuildSimplifiedStoreNamed(const Operator* op, Node* receiver,
Node* value, FeedbackSlot slot);
Node* TryBuildSimplifiedStoreKeyed(const Operator* op, Node* receiver,
Node* key, Node* value, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedBinaryOp(
const Operator* op, Node* left, Node* right, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInNext(
Node* receiver, Node* cache_array, Node* cache_type, Node* index,
FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedToNumber(
Node* input, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedCall(const Operator* op,
Node* const* args,
int arg_count,
FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedConstruct(
const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadNamed(
const Operator* op, Node* receiver, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadKeyed(
const Operator* op, Node* receiver, Node* key, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreNamed(
const Operator* op, Node* receiver, Node* value, FeedbackSlot slot);
JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreKeyed(
const Operator* op, Node* receiver, Node* key, Node* value,
FeedbackSlot slot);
// Applies the given early reduction onto the current environment.
void ApplyEarlyReduction(Reduction reduction);
void ApplyEarlyReduction(JSTypeHintLowering::LoweringResult reduction);
// Check the context chain for extensions, for lookup fast paths.
Environment* CheckContextExtensions(uint32_t depth);
......
......@@ -212,10 +212,9 @@ JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph,
Flags flags)
: jsgraph_(jsgraph), flags_(flags), feedback_vector_(feedback_vector) {}
Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
Node* left, Node* right,
Node* effect, Node* control,
FeedbackSlot slot) const {
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
const Operator* op, Node* left, Node* right, Node* effect, Node* control,
FeedbackSlot slot) const {
switch (op->opcode()) {
case IrOpcode::kJSStrictEqual:
break;
......@@ -226,7 +225,7 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
case IrOpcode::kJSGreaterThanOrEqual: {
JSSpeculativeBinopBuilder b(this, op, left, right, effect, control, slot);
if (Node* node = b.TryBuildNumberCompare()) {
return Reduction(node);
return LoweringResult::SideEffectFree(node, node, control);
}
break;
}
......@@ -243,7 +242,7 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
case IrOpcode::kJSModulus: {
JSSpeculativeBinopBuilder b(this, op, left, right, effect, control, slot);
if (Node* node = b.TryBuildNumberBinop()) {
return Reduction(node);
return LoweringResult::SideEffectFree(node, node, control);
}
break;
}
......@@ -251,10 +250,10 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
UNREACHABLE();
break;
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceForInNextOperation(
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceForInNextOperation(
Node* receiver, Node* cache_array, Node* cache_type, Node* index,
Node* effect, Node* control, FeedbackSlot slot) const {
DCHECK(!slot.IsInvalid());
......@@ -262,7 +261,7 @@ Reduction JSTypeHintLowering::ReduceForInNextOperation(
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForForIn)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
if (!nexus.IsGeneric()) {
effect =
......@@ -272,14 +271,13 @@ Reduction JSTypeHintLowering::ReduceForInNextOperation(
jsgraph()->simplified()->LoadElement(
AccessBuilder::ForEnumCacheKeysElement()),
cache_array, index, effect, control);
return Reduction(node);
return LoweringResult::SideEffectFree(node, node, control);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceToNumberOperation(Node* input, Node* effect,
Node* control,
FeedbackSlot slot) const {
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceToNumberOperation(
Node* input, Node* effect, Node* control, FeedbackSlot slot) const {
DCHECK(!slot.IsInvalid());
BinaryOpICNexus nexus(feedback_vector(), slot);
NumberOperationHint hint;
......@@ -288,16 +286,14 @@ Reduction JSTypeHintLowering::ReduceToNumberOperation(Node* input, Node* effect,
Node* node = jsgraph()->graph()->NewNode(
jsgraph()->simplified()->SpeculativeToNumber(hint), input, effect,
control);
return Reduction(node);
return LoweringResult::SideEffectFree(node, node, control);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceCallOperation(const Operator* op,
Node* const* args,
int arg_count, Node* effect,
Node* control,
FeedbackSlot slot) const {
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceCallOperation(
const Operator* op, Node* const* args, int arg_count, Node* effect,
Node* control, FeedbackSlot slot) const {
DCHECK(op->opcode() == IrOpcode::kJSCall ||
op->opcode() == IrOpcode::kJSCallWithSpread);
DCHECK(!slot.IsInvalid());
......@@ -305,12 +301,12 @@ Reduction JSTypeHintLowering::ReduceCallOperation(const Operator* op,
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForCall)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceConstructOperation(
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceConstructOperation(
const Operator* op, Node* const* args, int arg_count, Node* effect,
Node* control, FeedbackSlot slot) const {
DCHECK(op->opcode() == IrOpcode::kJSConstruct ||
......@@ -320,13 +316,13 @@ Reduction JSTypeHintLowering::ReduceConstructOperation(
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForConstruct)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
const Operator* op, Node* obj, Node* effect, Node* control,
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadNamedOperation(
const Operator* op, Node* receiver, Node* effect, Node* control,
FeedbackSlot slot) const {
DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode());
DCHECK(!slot.IsInvalid());
......@@ -334,12 +330,12 @@ Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceLoadKeyedOperation(
JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadKeyedOperation(
const Operator* op, Node* obj, Node* key, Node* effect, Node* control,
FeedbackSlot slot) const {
DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode());
......@@ -348,14 +344,16 @@ Reduction JSTypeHintLowering::ReduceLoadKeyedOperation(
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceStoreNamedOperation(
const Operator* op, Node* obj, Node* val, Node* effect, Node* control,
FeedbackSlot slot) const {
JSTypeHintLowering::LoweringResult
JSTypeHintLowering::ReduceStoreNamedOperation(const Operator* op, Node* obj,
Node* val, Node* effect,
Node* control,
FeedbackSlot slot) const {
DCHECK(op->opcode() == IrOpcode::kJSStoreNamed ||
op->opcode() == IrOpcode::kJSStoreNamedOwn);
DCHECK(!slot.IsInvalid());
......@@ -363,23 +361,25 @@ Reduction JSTypeHintLowering::ReduceStoreNamedOperation(
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Reduction JSTypeHintLowering::ReduceStoreKeyedOperation(
const Operator* op, Node* obj, Node* key, Node* val, Node* effect,
Node* control, FeedbackSlot slot) const {
JSTypeHintLowering::LoweringResult
JSTypeHintLowering::ReduceStoreKeyedOperation(const Operator* op, Node* obj,
Node* key, Node* val,
Node* effect, Node* control,
FeedbackSlot slot) const {
DCHECK_EQ(IrOpcode::kJSStoreProperty, op->opcode());
DCHECK(!slot.IsInvalid());
KeyedStoreICNexus nexus(feedback_vector(), slot);
if (Node* node = TryBuildSoftDeopt(
nexus, effect, control,
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess)) {
return Reduction(node);
return LoweringResult::Exit(node);
}
return Reduction();
return LoweringResult::NoChange();
}
Node* JSTypeHintLowering::TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect,
......
......@@ -33,13 +33,8 @@ class Operator;
// the JavaScript-level operators and directly emit simplified-level operators
// even during initial graph building. This is the reason this lowering doesn't
// follow the interface of the reducer framework used after graph construction.
//
// Also note that all reductions returned by this lowering will not produce any
// control-output, but might very well produce an effect-output. The one node
// returned as a replacement must fully describe the effect (i.e. produce the
// effect and carry {Operator::Property} for the entire lowering). Use-sites
// rely on this invariant, if it ever changes we need to switch the interface
// away from using the {Reduction} class.
// The result of the lowering is encapsulated in
// {the JSTypeHintLowering::LoweringResult} class.
class JSTypeHintLowering {
public:
// Flags that control the mode of operation.
......@@ -49,45 +44,104 @@ class JSTypeHintLowering {
JSTypeHintLowering(JSGraph* jsgraph, Handle<FeedbackVector> feedback_vector,
Flags flags);
// {LoweringResult} describes the result of lowering. The following outcomes
// are possible:
//
// - operation was lowered to a side-effect-free operation, the resulting
// value, effect and control can be obtained by the {value}, {effect} and
// {control} methods.
//
// - operation was lowered to a graph exit (deoptimization). The caller
// should connect {effect} and {control} nodes to the end.
//
// - no lowering happened. The caller needs to create the generic version
// of the operation.
class LoweringResult {
public:
Node* value() const { return value_; }
Node* effect() const { return effect_; }
Node* control() const { return control_; }
bool Changed() const { return kind_ != LoweringResultKind::kNoChange; }
bool IsExit() const { return kind_ == LoweringResultKind::kExit; }
bool IsSideEffectFree() const {
return kind_ == LoweringResultKind::kSideEffectFree;
}
static LoweringResult SideEffectFree(Node* value, Node* effect,
Node* control) {
DCHECK_NOT_NULL(effect);
DCHECK_NOT_NULL(control);
return LoweringResult(LoweringResultKind::kSideEffectFree, value, effect,
control);
}
static LoweringResult NoChange() {
return LoweringResult(LoweringResultKind::kNoChange, nullptr, nullptr,
nullptr);
}
static LoweringResult Exit(Node* control) {
return LoweringResult(LoweringResultKind::kExit, nullptr, nullptr,
control);
}
private:
enum class LoweringResultKind { kNoChange, kSideEffectFree, kExit };
LoweringResult(LoweringResultKind kind, Node* value, Node* effect,
Node* control)
: kind_(kind), value_(value), effect_(effect), control_(control) {}
LoweringResultKind kind_;
Node* value_;
Node* effect_;
Node* control_;
};
// Potential reduction of binary (arithmetic, logical, shift and relational
// comparison) operations.
Reduction ReduceBinaryOperation(const Operator* op, Node* left, Node* right,
Node* effect, Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceBinaryOperation(const Operator* op, Node* left,
Node* right, Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction to ForInNext operations
Reduction ReduceForInNextOperation(Node* receiver, Node* cache_array,
Node* cache_type, Node* index,
Node* effect, Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceForInNextOperation(Node* receiver, Node* cache_array,
Node* cache_type, Node* index,
Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction to ToNumber operations
Reduction ReduceToNumberOperation(Node* value, Node* effect, Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceToNumberOperation(Node* value, Node* effect,
Node* control,
FeedbackSlot slot) const;
// Potential reduction of call operations.
Reduction ReduceCallOperation(const Operator* op, Node* const* args,
int arg_count, Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction of construct operations.
Reduction ReduceConstructOperation(const Operator* op, Node* const* args,
LoweringResult ReduceCallOperation(const Operator* op, Node* const* args,
int arg_count, Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction of construct operations.
LoweringResult ReduceConstructOperation(const Operator* op, Node* const* args,
int arg_count, Node* effect,
Node* control,
FeedbackSlot slot) const;
// Potential reduction of property access operations.
Reduction ReduceLoadNamedOperation(const Operator* op, Node* obj,
Node* effect, Node* control,
FeedbackSlot slot) const;
Reduction ReduceLoadKeyedOperation(const Operator* op, Node* obj, Node* key,
Node* effect, Node* control,
FeedbackSlot slot) const;
Reduction ReduceStoreNamedOperation(const Operator* op, Node* obj, Node* val,
Node* effect, Node* control,
FeedbackSlot slot) const;
Reduction ReduceStoreKeyedOperation(const Operator* op, Node* obj, Node* key,
Node* val, Node* effect, Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceLoadNamedOperation(const Operator* op, Node* obj,
Node* effect, Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceLoadKeyedOperation(const Operator* op, Node* obj,
Node* key, Node* effect,
Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceStoreNamedOperation(const Operator* op, Node* obj,
Node* val, Node* effect,
Node* control,
FeedbackSlot slot) const;
LoweringResult ReduceStoreKeyedOperation(const Operator* op, Node* obj,
Node* key, Node* val, Node* effect,
Node* control,
FeedbackSlot slot) const;
private:
friend class JSSpeculativeBinopBuilder;
......
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