| // 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_; } |
| 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_ |