// Copyright 2015 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_NATIVE_CONTEXT_SPECIALIZATION_H_
#define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
#include "src/base/flags.h"
#include "src/compiler/graph-reducer.h"
#include "src/deoptimize-reason.h"
#include "src/feedback-vector.h"
namespace v8 {
namespace internal {
// Forward declarations.
class CompilationDependencies;
class Factory;
namespace compiler {
// Forward declarations.
enum class AccessMode;
class CommonOperatorBuilder;
class ElementAccessInfo;
class JSGraph;
class JSOperatorBuilder;
class MachineOperatorBuilder;
class PropertyAccessInfo;
class SimplifiedOperatorBuilder;
class TypeCache;
// Specializes a given JSGraph to a given native context, potentially constant
// folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal}
// nodes. And also specializes {LoadNamed} and {StoreNamed} nodes according
// to type feedback (if available).
class JSNativeContextSpecialization final : public AdvancedReducer {
public:
// Flags that control the mode of operation.
enum Flag {
kNoFlags = 0u,
kAccessorInliningEnabled = 1u << 0,
kBailoutOnUninitialized = 1u << 1,
kDeoptimizationEnabled = 1u << 2,
};
typedef base::Flags<Flag> Flags;
JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
Handle<Context> native_context,
CompilationDependencies* dependencies,
Zone* zone);
Reduction Reduce(Node* node) final;
private:
Reduction ReduceJSAdd(Node* node);
Reduction ReduceJSGetSuperConstructor(Node* node);
Reduction ReduceJSInstanceOf(Node* node);
Reduction ReduceJSOrdinaryHasInstance(Node* node);
Reduction ReduceJSLoadContext(Node* node);
Reduction ReduceJSLoadGlobal(Node* node);
Reduction ReduceJSStoreGlobal(Node* node);
Reduction ReduceJSLoadNamed(Node* node);
Reduction ReduceJSStoreNamed(Node* node);
Reduction ReduceJSLoadProperty(Node* node);
Reduction ReduceJSStoreProperty(Node* node);
Reduction ReduceJSStoreNamedOwn(Node* node);
Reduction ReduceJSStoreDataPropertyInLiteral(Node* node);
Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
MapHandleList const& receiver_maps,
AccessMode access_mode,
LanguageMode language_mode,
KeyedAccessStoreMode store_mode);
template <typename KeyedICNexus>
Reduction ReduceKeyedAccess(Node* node, Node* index, Node* value,
KeyedICNexus const& nexus, AccessMode access_mode,
LanguageMode language_mode,
KeyedAccessStoreMode store_mode);
Reduction ReduceNamedAccessFromNexus(Node* node, Node* value,
FeedbackNexus const& nexus,
Handle<Name> name,
AccessMode access_mode,
LanguageMode language_mode);
Reduction ReduceNamedAccess(Node* node, Node* value,
MapHandleList const& receiver_maps,
Handle<Name> name, AccessMode access_mode,
LanguageMode language_mode,
Handle<FeedbackVector> vector, FeedbackSlot slot,
Node* index = nullptr);
Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
Handle<Name> name, AccessMode access_mode,
Node* index = nullptr);
Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason);
// A triple of nodes that represents a continuation.
class ValueEffectControl final {
public:
ValueEffectControl(Node* value, Node* effect, Node* control)
: value_(value), effect_(effect), control_(control) {}
Node* value() const { return value_; }
Node* effect() const { return effect_; }
Node* control() const { return control_; }
private:
Node* const value_;
Node* const effect_;
Node* const control_;
};
// Construct the appropriate subgraph for property access.
ValueEffectControl BuildPropertyAccess(
Node* receiver, Node* value, Node* context, Node* frame_state,
Node* effect, Node* control, Handle<Name> name,
PropertyAccessInfo const& access_info, AccessMode access_mode,
LanguageMode language_mode, Handle<FeedbackVector> vector,
FeedbackSlot slot);
// Construct the appropriate subgraph for element access.
ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
Node* value, Node* effect,
Node* control,
ElementAccessInfo const& access_info,
AccessMode access_mode,
KeyedAccessStoreMode store_mode);
// Construct an appropriate heap object check.
Node* BuildCheckHeapObject(Node* receiver, Node** effect, Node* control);
// Construct an appropriate map check.
Node* BuildCheckMaps(Node* receiver, Node* effect, Node* control,
std::vector<Handle<Map>> const& maps);
// Adds stability dependencies on all prototypes of every class in
// {receiver_type} up to (and including) the {holder}.
void AssumePrototypesStable(std::vector<Handle<Map>> const& receiver_maps,
Handle<JSObject> holder);
// Checks if we can turn the hole into undefined when loading an element
// from an object with one of the {receiver_maps}; sets up appropriate
// code dependencies and might use the array protector cell.
bool CanTreatHoleAsUndefined(std::vector<Handle<Map>> const& receiver_maps);
// Extract receiver maps from {nexus} and filter based on {receiver} if
// possible.
bool ExtractReceiverMaps(Node* receiver, Node* effect,
FeedbackNexus const& nexus,
MapHandleList* receiver_maps);
// Try to infer maps for the given {receiver} at the current {effect}.
// If maps are returned then you can be sure that the {receiver} definitely
// has one of the returned maps at this point in the program (identified
// by {effect}).
bool InferReceiverMaps(Node* receiver, Node* effect,
MapHandleList* receiver_maps);
// Try to infer a root map for the {receiver} independent of the current
// program location.
MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
ValueEffectControl InlineApiCall(
Node* receiver, Node* context, Node* target, Node* frame_state,
Node* parameter, Node* effect, Node* control,
Handle<SharedFunctionInfo> shared_info,
Handle<FunctionTemplateInfo> function_template_info);
// Script context lookup logic.
struct ScriptContextTableLookupResult;
bool LookupInScriptContextTable(Handle<Name> name,
ScriptContextTableLookupResult* result);
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const;
Factory* factory() const;
CommonOperatorBuilder* common() const;
JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() const;
MachineOperatorBuilder* machine() const;
Flags flags() const { return flags_; }
Handle<JSGlobalObject> global_object() const { return global_object_; }
Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
Handle<Context> native_context() const { return native_context_; }
CompilationDependencies* dependencies() const { return dependencies_; }
Zone* zone() const { return zone_; }
JSGraph* const jsgraph_;
Flags const flags_;
Handle<JSGlobalObject> global_object_;
Handle<JSGlobalProxy> global_proxy_;
Handle<Context> native_context_;
CompilationDependencies* const dependencies_;
Zone* const zone_;
TypeCache const& type_cache_;
DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization);
};
DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_