// Copyright 2017 the V8 project authors. All rights reserved.
|
// Use of this source code is governed by a BSD-style license that can be
|
// found in the LICENSE file.
|
|
#ifndef V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
|
#define V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
|
|
#include "src/base/flags.h"
|
#include "src/compiler/graph-reducer.h"
|
#include "src/deoptimize-reason.h"
|
#include "src/handles.h"
|
|
namespace v8 {
|
namespace internal {
|
|
// Forward declarations.
|
class FeedbackNexus;
|
class FeedbackSlot;
|
|
namespace compiler {
|
|
// Forward declarations.
|
class JSGraph;
|
class Node;
|
class Operator;
|
|
// The type-hint lowering consumes feedback about high-level operations in order
|
// to potentially emit nodes using speculative simplified operators in favor of
|
// the generic JavaScript operators.
|
//
|
// This lowering is implemented as an early reduction and can be applied before
|
// nodes are placed into the initial graph. It provides the ability to shortcut
|
// 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.
|
// The result of the lowering is encapsulated in
|
// {the JSTypeHintLowering::LoweringResult} class.
|
class JSTypeHintLowering {
|
public:
|
// Flags that control the mode of operation.
|
enum Flag { kNoFlags = 0u, kBailoutOnUninitialized = 1u << 1 };
|
typedef base::Flags<Flag> Flags;
|
|
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 unary operations (e.g. negation).
|
LoweringResult ReduceUnaryOperation(const Operator* op, Node* operand,
|
Node* effect, Node* control,
|
FeedbackSlot slot) const;
|
|
// Potential reduction of binary (arithmetic, logical, shift and relational
|
// comparison) operations.
|
LoweringResult ReduceBinaryOperation(const Operator* op, Node* left,
|
Node* right, Node* effect, Node* control,
|
FeedbackSlot slot) const;
|
|
// Potential reduction to for..in operations
|
LoweringResult ReduceForInNextOperation(Node* receiver, Node* cache_array,
|
Node* cache_type, Node* index,
|
Node* effect, Node* control,
|
FeedbackSlot slot) const;
|
LoweringResult ReduceForInPrepareOperation(Node* enumerator, Node* effect,
|
Node* control,
|
FeedbackSlot slot) const;
|
|
// Potential reduction to ToNumber operations
|
LoweringResult ReduceToNumberOperation(Node* value, Node* effect,
|
Node* control,
|
FeedbackSlot slot) const;
|
|
// Potential reduction of call operations.
|
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.
|
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;
|
Node* TryBuildSoftDeopt(FeedbackNexus& nexus, Node* effect, Node* control,
|
DeoptimizeReason reson) const;
|
|
JSGraph* jsgraph() const { return jsgraph_; }
|
Isolate* isolate() const;
|
Flags flags() const { return flags_; }
|
const Handle<FeedbackVector>& feedback_vector() const {
|
return feedback_vector_;
|
}
|
|
JSGraph* jsgraph_;
|
Flags const flags_;
|
Handle<FeedbackVector> feedback_vector_;
|
|
DISALLOW_COPY_AND_ASSIGN(JSTypeHintLowering);
|
};
|
|
} // namespace compiler
|
} // namespace internal
|
} // namespace v8
|
|
#endif // V8_COMPILER_JS_TYPE_HINT_LOWERING_H_
|