#ifndef V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
#define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_
#include <optional>
#include "src/base/flags.h"
#include "src/compiler/graph-assembler.h"
#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-heap-broker.h"
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
class Factory;
class JSGlobalObject;
class JSGlobalProxy;
namespace compiler {
enum class AccessMode : uint8_t;
class CommonOperatorBuilder;
class CompilationDependencies;
class ElementAccessInfo;
class JSGraph;
class JSHeapBroker;
class JSOperatorBuilder;
class MachineOperatorBuilder;
class PropertyAccessInfo;
class SimplifiedOperatorBuilder;
class TypeCache;
class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
: public AdvancedReducer {
public:
enum Flag {
kNoFlags = 0u,
kBailoutOnUninitialized = 1u << 0,
};
using Flags = base::Flags<Flag>;
JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph,
JSHeapBroker* broker, Flags flags, Zone* zone,
Zone* shared_zone);
JSNativeContextSpecialization(const JSNativeContextSpecialization&) = delete;
JSNativeContextSpecialization& operator=(
const JSNativeContextSpecialization&) = delete;
const char* reducer_name() const override {
return "JSNativeContextSpecialization";
}
Reduction Reduce(Node* node) final;
static std::optional<size_t> GetMaxStringLength(JSHeapBroker* broker,
Node* node);
private:
Reduction ReduceJSAdd(Node* node);
Reduction ReduceJSAsyncFunctionEnter(Node* node);
Reduction ReduceJSAsyncFunctionReject(Node* node);
Reduction ReduceJSAsyncFunctionResolve(Node* node);
Reduction ReduceJSGetSuperConstructor(Node* node);
Reduction ReduceJSFindNonDefaultConstructorOrConstruct(Node* node);
Reduction ReduceJSInstanceOf(Node* node);
Reduction ReduceJSHasInPrototypeChain(Node* node);
Reduction ReduceJSOrdinaryHasInstance(Node* node);
Reduction ReduceJSPromiseResolve(Node* node);
Reduction ReduceJSResolvePromise(Node* node);
Reduction ReduceJSLoadGlobal(Node* node);
Reduction ReduceJSStoreGlobal(Node* node);
Reduction ReduceJSLoadNamed(Node* node);
Reduction ReduceJSLoadNamedFromSuper(Node* node);
Reduction ReduceJSGetIterator(Node* node);
Reduction ReduceJSSetNamedProperty(Node* node);
Reduction ReduceJSHasProperty(Node* node);
Reduction ReduceJSLoadProperty(Node* node);
Reduction ReduceJSSetKeyedProperty(Node* node);
Reduction ReduceJSDefineKeyedOwnProperty(Node* node);
Reduction ReduceJSDefineNamedOwnProperty(Node* node);
Reduction ReduceJSDefineKeyedOwnPropertyInLiteral(Node* node);
Reduction ReduceJSStoreInArrayLiteral(Node* node);
Reduction ReduceJSToObject(Node* node);
Reduction ReduceElementAccess(Node* node, Node* index, Node* value,
ElementAccessFeedback const& feedback);
Reduction ReducePropertyAccess(Node* node, Node* key,
OptionalNameRef static_name, Node* value,
FeedbackSource const& source,
AccessMode access_mode);
Reduction ReduceNamedAccess(Node* node, Node* value,
NamedAccessFeedback const& feedback,
AccessMode access_mode, Node* key = nullptr);
Reduction ReduceMegaDOMPropertyAccess(
Node* node, Node* value, MegaDOMPropertyAccessFeedback const& feedback,
FeedbackSource const& source);
Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object,
Node* receiver, Node* value, NameRef name,
AccessMode access_mode, Node* key,
PropertyCellRef property_cell,
Node* effect = nullptr);
Reduction ReduceElementLoadFromHeapConstant(Node* node, Node* key,
AccessMode access_mode,
KeyedAccessLoadMode load_mode);
Reduction ReduceElementAccessOnString(Node* node, Node* index, Node* value,
KeyedAccessMode const& keyed_mode);
Reduction ReduceEagerDeoptimize(Node* node, DeoptimizeReason reason);
Reduction ReduceJSToString(Node* node);
Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node);
Handle<String> CreateStringConstant(Node* node);
class ValueEffectControl final {
public:
ValueEffectControl()
: value_(nullptr), effect_(nullptr), control_(nullptr) {}
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* value_;
Node* effect_;
Node* control_;
};
std::optional<ValueEffectControl> BuildPropertyAccess(
Node* lookup_start_object, Node* receiver, Node* value, Node* context,
Node* frame_state, Node* effect, Node* control, NameRef name,
ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info,
AccessMode access_mode);
std::optional<ValueEffectControl> BuildPropertyLoad(
Node* lookup_start_object, Node* receiver, Node* context,
Node* frame_state, Node* effect, Node* control, NameRef name,
ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info);
ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
Node* context, Node* frame_state,
Node* effect, Node* control,
NameRef name,
ZoneVector<Node*>* if_exceptions,
PropertyAccessInfo const& access_info,
AccessMode access_mode);
ValueEffectControl BuildPropertyTest(Node* effect, Node* control,
PropertyAccessInfo const& access_info);
Node* InlinePropertyGetterCall(Node* receiver,
ConvertReceiverMode receiver_mode,
Node* lookup_start_object, Node* context,
Node* frame_state, Node** effect,
Node** control,
ZoneVector<Node*>* if_exceptions,
PropertyAccessInfo const& access_info);
void InlinePropertySetterCall(Node* receiver, Node* value, Node* context,
Node* frame_state, Node** effect,
Node** control,
ZoneVector<Node*>* if_exceptions,
PropertyAccessInfo const& access_info);
Node* InlineApiCall(Node* receiver, Node* frame_state, Node* value,
Node** effect, Node** control,
FunctionTemplateInfoRef function_template_info,
const FeedbackSource& feedback);
ValueEffectControl BuildElementAccess(
Node* receiver, Node* index, Node* value, Node* effect, Node* control,
Node* context, ElementAccessInfo const& access_info,
LanguageMode language_mode, KeyedAccessMode const& keyed_mode,
ZoneVector<Node*>* if_exceptions, Node* frame_state);
ValueEffectControl BuildElementAccessForTypedArrayOrRabGsabTypedArray(
Node* receiver, Node* index, Node* value, Node* effect, Node* control,
Node* context, ElementsKind elements_kind,
KeyedAccessMode const& keyed_mode);
#if V8_ENABLE_WEBASSEMBLY
ValueEffectControl BuildPrototypeProxyElementAccess(
Node* receiver, Node* index, Node* value, Node* effect, Node* control,
Node* context, ElementAccessInfo const& access_info,
LanguageMode language_mode, KeyedAccessMode const& keyed_mode,
ZoneVector<Node*>* if_exceptions, Node* frame_state);
#endif
Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length,
Node** effect, Node** control,
KeyedAccessLoadMode load_mode);
Node* BuildExtendPropertiesBackingStore(MapRef map, Node* properties,
Node* effect, Node* control);
Node* BuildCheckEqualsName(NameRef name, Node* value, Node* effect,
Node* control);
bool StringCanSafelyBeRead(Node* const node, Handle<String> str);
bool CanTreatHoleAsUndefined(ZoneVector<MapRef> const& receiver_maps);
void RemoveImpossibleMaps(Node* object, ZoneVector<MapRef>* maps) const;
ElementAccessFeedback const& TryRefineElementAccessFeedback(
ElementAccessFeedback const& feedback, Node* receiver,
Effect effect) const;
bool InferMaps(Node* object, Effect effect, ZoneVector<MapRef>* maps) const;
OptionalMapRef InferRootMap(Node* object) const;
enum InferHasInPrototypeChainResult {
kIsInPrototypeChain,
kIsNotInPrototypeChain,
kMayBeInPrototypeChain
};
InferHasInPrototypeChainResult InferHasInPrototypeChain(
Node* receiver, Effect effect, HeapObjectRef prototype);
Node* BuildLoadPrototypeFromObject(Node* object, Node* effect, Node* control);
std::pair<Node*, Node*> ReleaseEffectAndControlFromAssembler(
JSGraphAssembler* assembler);
TFGraph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
JSHeapBroker* broker() const { return broker_; }
Isolate* isolate() const;
Factory* factory() const;
CommonOperatorBuilder* common() const;
JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() const;
Flags flags() const { return flags_; }
DirectHandle<JSGlobalObject> global_object() const { return global_object_; }
DirectHandle<JSGlobalProxy> global_proxy() const { return global_proxy_; }
NativeContextRef native_context() const {
return broker()->target_native_context();
}
CompilationDependencies* dependencies() const {
return broker()->dependencies();
}
Zone* zone() const { return zone_; }
Zone* shared_zone() const { return shared_zone_; }
JSGraph* const jsgraph_;
JSHeapBroker* const broker_;
Flags const flags_;
Handle<JSGlobalObject> global_object_;
Handle<JSGlobalProxy> global_proxy_;
Zone* const zone_;
Zone* const shared_zone_;
TypeCache const* type_cache_;
ZoneUnorderedSet<IndirectHandle<String>, IndirectHandle<String>::hash,
IndirectHandle<String>::equal_to>
created_strings_;
};
DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags)
}
}
}
#endif