[turbofan] Basic brokerization for ReduceNamedAccess
Bug: v8:7790 Change-Id: I65e050929a45c3391c5c9c9b0d814ae536664cf4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1564067 Commit-Queue: Georg Neis <neis@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Cr-Commit-Position: refs/heads/master@{#60828}
This commit is contained in:
parent
20a93efef5
commit
d7fb4a64c1
@ -3787,7 +3787,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
|
||||
// Try to specialize JSConstruct {node}s with constant {target}s.
|
||||
HeapObjectMatcher m(target);
|
||||
if (m.HasValue()) {
|
||||
HeapObjectRef target_ref = m.Ref(broker()).AsHeapObject();
|
||||
HeapObjectRef target_ref = m.Ref(broker());
|
||||
|
||||
// Raise a TypeError if the {target} is not a constructor.
|
||||
if (!target_ref.map().is_constructor()) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
#include "src/api-inl.h"
|
||||
#include "src/ast/modules.h"
|
||||
#include "src/bootstrapper.h"
|
||||
#include "src/boxed-float.h"
|
||||
@ -16,6 +17,7 @@
|
||||
#include "src/compiler/per-isolate-compiler-cache.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects/allocation-site-inl.h"
|
||||
#include "src/objects/api-callbacks.h"
|
||||
#include "src/objects/cell-inl.h"
|
||||
#include "src/objects/heap-number-inl.h"
|
||||
#include "src/objects/instance-type-inl.h"
|
||||
@ -23,6 +25,7 @@
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-regexp-inl.h"
|
||||
#include "src/objects/module-inl.h"
|
||||
#include "src/objects/templates.h"
|
||||
#include "src/utils.h"
|
||||
#include "src/vector-slot-pair.h"
|
||||
|
||||
@ -108,7 +111,7 @@ class PropertyCellData : public HeapObjectData {
|
||||
PropertyDetails property_details() const { return property_details_; }
|
||||
|
||||
void Serialize(JSHeapBroker* broker);
|
||||
ObjectData* value() { return value_; }
|
||||
ObjectData* value() const { return value_; }
|
||||
|
||||
private:
|
||||
PropertyDetails const property_details_;
|
||||
@ -117,6 +120,47 @@ class PropertyCellData : public HeapObjectData {
|
||||
ObjectData* value_ = nullptr;
|
||||
};
|
||||
|
||||
class FunctionTemplateInfoData : public HeapObjectData {
|
||||
public:
|
||||
FunctionTemplateInfoData(JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<FunctionTemplateInfo> object);
|
||||
|
||||
void Serialize(JSHeapBroker* broker);
|
||||
ObjectData* call_code() const { return call_code_; }
|
||||
|
||||
private:
|
||||
bool serialized_ = false;
|
||||
ObjectData* call_code_ = nullptr;
|
||||
};
|
||||
|
||||
class CallHandlerInfoData : public HeapObjectData {
|
||||
public:
|
||||
CallHandlerInfoData(JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<CallHandlerInfo> object);
|
||||
|
||||
Address callback() const { return callback_; }
|
||||
|
||||
void Serialize(JSHeapBroker* broker);
|
||||
ObjectData* data() const { return data_; }
|
||||
|
||||
private:
|
||||
Address const callback_;
|
||||
|
||||
bool serialized_ = false;
|
||||
ObjectData* data_ = nullptr;
|
||||
};
|
||||
|
||||
FunctionTemplateInfoData::FunctionTemplateInfoData(
|
||||
JSHeapBroker* broker, ObjectData** storage,
|
||||
Handle<FunctionTemplateInfo> object)
|
||||
: HeapObjectData(broker, storage, object) {}
|
||||
|
||||
CallHandlerInfoData::CallHandlerInfoData(JSHeapBroker* broker,
|
||||
ObjectData** storage,
|
||||
Handle<CallHandlerInfo> object)
|
||||
: HeapObjectData(broker, storage, object),
|
||||
callback_(v8::ToCData<Address>(object->callback())) {}
|
||||
|
||||
void JSHeapBroker::IncrementTracingIndentation() { ++trace_indentation_; }
|
||||
|
||||
void JSHeapBroker::DecrementTracingIndentation() { --trace_indentation_; }
|
||||
@ -156,6 +200,30 @@ void PropertyCellData::Serialize(JSHeapBroker* broker) {
|
||||
value_ = broker->GetOrCreateData(cell->value());
|
||||
}
|
||||
|
||||
void FunctionTemplateInfoData::Serialize(JSHeapBroker* broker) {
|
||||
if (serialized_) return;
|
||||
serialized_ = true;
|
||||
|
||||
TraceScope tracer(broker, this, "FunctionTemplateInfoData::Serialize");
|
||||
auto function_template_info = Handle<FunctionTemplateInfo>::cast(object());
|
||||
DCHECK_NULL(call_code_);
|
||||
call_code_ = broker->GetOrCreateData(function_template_info->call_code());
|
||||
|
||||
if (call_code_->IsCallHandlerInfo()) {
|
||||
call_code_->AsCallHandlerInfo()->Serialize(broker);
|
||||
}
|
||||
}
|
||||
|
||||
void CallHandlerInfoData::Serialize(JSHeapBroker* broker) {
|
||||
if (serialized_) return;
|
||||
serialized_ = true;
|
||||
|
||||
TraceScope tracer(broker, this, "CallHandlerInfoData::Serialize");
|
||||
auto call_handler_info = Handle<CallHandlerInfo>::cast(object());
|
||||
DCHECK_NULL(data_);
|
||||
data_ = broker->GetOrCreateData(call_handler_info->data());
|
||||
}
|
||||
|
||||
class JSObjectField {
|
||||
public:
|
||||
bool IsDouble() const { return object_ == nullptr; }
|
||||
@ -799,6 +867,12 @@ class MapData : public HeapObjectData {
|
||||
return constructor_;
|
||||
}
|
||||
|
||||
void SerializeBackPointer(JSHeapBroker* broker);
|
||||
HeapObjectData* GetBackPointer() const {
|
||||
CHECK(serialized_backpointer_);
|
||||
return backpointer_;
|
||||
}
|
||||
|
||||
void SerializePrototype(JSHeapBroker* broker);
|
||||
bool serialized_prototype() const { return serialized_prototype_; }
|
||||
ObjectData* prototype() const {
|
||||
@ -836,6 +910,9 @@ class MapData : public HeapObjectData {
|
||||
bool serialized_constructor_ = false;
|
||||
ObjectData* constructor_ = nullptr;
|
||||
|
||||
bool serialized_backpointer_ = false;
|
||||
HeapObjectData* backpointer_ = nullptr;
|
||||
|
||||
bool serialized_prototype_ = false;
|
||||
ObjectData* prototype_ = nullptr;
|
||||
|
||||
@ -1554,6 +1631,16 @@ void MapData::SerializeConstructor(JSHeapBroker* broker) {
|
||||
constructor_ = broker->GetOrCreateData(map->GetConstructor());
|
||||
}
|
||||
|
||||
void MapData::SerializeBackPointer(JSHeapBroker* broker) {
|
||||
if (serialized_backpointer_) return;
|
||||
serialized_backpointer_ = true;
|
||||
|
||||
TraceScope tracer(broker, this, "MapData::SerializeBackPointer");
|
||||
Handle<Map> map = Handle<Map>::cast(object());
|
||||
DCHECK_NULL(backpointer_);
|
||||
backpointer_ = broker->GetOrCreateData(map->GetBackPointer())->AsHeapObject();
|
||||
}
|
||||
|
||||
void MapData::SerializePrototype(JSHeapBroker* broker) {
|
||||
if (serialized_prototype_) return;
|
||||
serialized_prototype_ = true;
|
||||
@ -2541,6 +2628,7 @@ BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
|
||||
BIMODAL_ACCESSOR(Map, HeapObject, prototype)
|
||||
BIMODAL_ACCESSOR_C(Map, InstanceType, instance_type)
|
||||
BIMODAL_ACCESSOR(Map, Object, GetConstructor)
|
||||
BIMODAL_ACCESSOR(Map, HeapObject, GetBackPointer)
|
||||
|
||||
#define DEF_NATIVE_CONTEXT_ACCESSOR(type, name) \
|
||||
BIMODAL_ACCESSOR(NativeContext, type, name)
|
||||
@ -2550,6 +2638,10 @@ BROKER_NATIVE_CONTEXT_FIELDS(DEF_NATIVE_CONTEXT_ACCESSOR)
|
||||
BIMODAL_ACCESSOR(PropertyCell, Object, value)
|
||||
BIMODAL_ACCESSOR_C(PropertyCell, PropertyDetails, property_details)
|
||||
|
||||
BIMODAL_ACCESSOR(FunctionTemplateInfo, Object, call_code)
|
||||
|
||||
BIMODAL_ACCESSOR(CallHandlerInfo, Object, data)
|
||||
|
||||
BIMODAL_ACCESSOR_C(SharedFunctionInfo, int, builtin_id)
|
||||
BIMODAL_ACCESSOR(SharedFunctionInfo, BytecodeArray, GetBytecodeArray)
|
||||
#define DEF_SFI_ACCESSOR(type, name) \
|
||||
@ -2615,6 +2707,13 @@ bool StringRef::IsExternalString() const {
|
||||
return data()->AsString()->is_external_string();
|
||||
}
|
||||
|
||||
Address CallHandlerInfoRef::callback() const {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) {
|
||||
return v8::ToCData<Address>(object()->callback());
|
||||
}
|
||||
return HeapObjectRef::data()->AsCallHandlerInfo()->callback();
|
||||
}
|
||||
|
||||
bool StringRef::IsSeqString() const {
|
||||
IF_BROKER_DISABLED_ACCESS_HANDLE_C(String, IsSeqString);
|
||||
return data()->AsString()->is_seq_string();
|
||||
@ -2888,6 +2987,11 @@ void FeedbackVectorRef::SerializeSlots() {
|
||||
data()->AsFeedbackVector()->SerializeSlots(broker());
|
||||
}
|
||||
|
||||
bool NameRef::IsUniqueName() const {
|
||||
// Must match Name::IsUniqueName.
|
||||
return IsInternalizedString() || IsSymbol();
|
||||
}
|
||||
|
||||
ObjectRef JSRegExpRef::data() const {
|
||||
IF_BROKER_DISABLED_ACCESS_HANDLE(JSRegExp, Object, data);
|
||||
return ObjectRef(broker(), ObjectRef::data()->AsJSRegExp()->data());
|
||||
@ -3027,6 +3131,12 @@ void MapRef::SerializeOwnDescriptors() {
|
||||
data()->AsMap()->SerializeOwnDescriptors(broker());
|
||||
}
|
||||
|
||||
void MapRef::SerializeBackPointer() {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) return;
|
||||
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
|
||||
data()->AsMap()->SerializeBackPointer(broker());
|
||||
}
|
||||
|
||||
void MapRef::SerializePrototype() {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) return;
|
||||
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
|
||||
@ -3085,6 +3195,12 @@ void PropertyCellRef::Serialize() {
|
||||
data()->AsPropertyCell()->Serialize(broker());
|
||||
}
|
||||
|
||||
void FunctionTemplateInfoRef::Serialize() {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) return;
|
||||
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
|
||||
data()->AsFunctionTemplateInfo()->Serialize(broker());
|
||||
}
|
||||
|
||||
base::Optional<PropertyCellRef> JSGlobalProxyRef::GetPropertyCell(
|
||||
NameRef const& name, bool serialize) const {
|
||||
if (broker()->mode() == JSHeapBroker::kDisabled) {
|
||||
|
@ -21,8 +21,9 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class BytecodeArray;
|
||||
class VectorSlotPair;
|
||||
class CallHandlerInfo;
|
||||
class FixedDoubleArray;
|
||||
class FunctionTemplateInfo;
|
||||
class HeapNumber;
|
||||
class InternalizedString;
|
||||
class JSBoundFunction;
|
||||
@ -32,6 +33,7 @@ class JSRegExp;
|
||||
class JSTypedArray;
|
||||
class NativeContext;
|
||||
class ScriptContextTable;
|
||||
class VectorSlotPair;
|
||||
|
||||
namespace compiler {
|
||||
|
||||
@ -72,11 +74,13 @@ enum class OddballType : uint8_t {
|
||||
V(Symbol) \
|
||||
/* Subtypes of HeapObject */ \
|
||||
V(AllocationSite) \
|
||||
V(CallHandlerInfo) \
|
||||
V(Cell) \
|
||||
V(Code) \
|
||||
V(DescriptorArray) \
|
||||
V(FeedbackVector) \
|
||||
V(FixedArrayBase) \
|
||||
V(FunctionTemplateInfo) \
|
||||
V(HeapNumber) \
|
||||
V(JSObject) \
|
||||
V(Map) \
|
||||
@ -377,6 +381,8 @@ class NameRef : public HeapObjectRef {
|
||||
public:
|
||||
using HeapObjectRef::HeapObjectRef;
|
||||
Handle<Name> object() const;
|
||||
|
||||
bool IsUniqueName() const;
|
||||
};
|
||||
|
||||
class ScriptContextTableRef : public HeapObjectRef {
|
||||
@ -409,6 +415,26 @@ class FeedbackVectorRef : public HeapObjectRef {
|
||||
void SerializeSlots();
|
||||
};
|
||||
|
||||
class FunctionTemplateInfoRef : public HeapObjectRef {
|
||||
public:
|
||||
using HeapObjectRef::HeapObjectRef;
|
||||
Handle<FunctionTemplateInfo> object() const;
|
||||
|
||||
void Serialize();
|
||||
ObjectRef call_code() const;
|
||||
};
|
||||
|
||||
class CallHandlerInfoRef : public HeapObjectRef {
|
||||
public:
|
||||
using HeapObjectRef::HeapObjectRef;
|
||||
Handle<CallHandlerInfo> object() const;
|
||||
|
||||
Address callback() const;
|
||||
|
||||
void Serialize();
|
||||
ObjectRef data() const;
|
||||
};
|
||||
|
||||
class AllocationSiteRef : public HeapObjectRef {
|
||||
public:
|
||||
using HeapObjectRef::HeapObjectRef;
|
||||
@ -467,13 +493,14 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
|
||||
bool supports_fast_array_resize() const;
|
||||
bool IsMapOfCurrentGlobalProxy() const;
|
||||
|
||||
OddballType oddball_type() const;
|
||||
|
||||
#define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
|
||||
INSTANCE_TYPE_CHECKERS(DEF_TESTER)
|
||||
#undef DEF_TESTER
|
||||
|
||||
ObjectRef GetConstructor() const;
|
||||
OddballType oddball_type() const;
|
||||
base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
|
||||
void SerializeBackPointer();
|
||||
HeapObjectRef GetBackPointer() const;
|
||||
|
||||
void SerializePrototype();
|
||||
bool serialized_prototype() const;
|
||||
@ -493,6 +520,11 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
|
||||
FieldIndex GetFieldIndexFor(int descriptor_index) const;
|
||||
ObjectRef GetFieldType(int descriptor_index) const;
|
||||
bool IsUnboxedDoubleField(int descriptor_index) const;
|
||||
|
||||
// Available after calling JSFunctionRef::Serialize on a function that has
|
||||
// this map as initial map.
|
||||
ObjectRef GetConstructor() const;
|
||||
base::Optional<MapRef> AsElementsKind(ElementsKind kind) const;
|
||||
};
|
||||
|
||||
class FixedArrayBaseRef : public HeapObjectRef {
|
||||
|
@ -774,7 +774,7 @@ namespace {
|
||||
|
||||
FieldAccess ForPropertyCellValue(MachineRepresentation representation,
|
||||
Type type, MaybeHandle<Map> map,
|
||||
Handle<Name> name) {
|
||||
NameRef const& name) {
|
||||
WriteBarrierKind kind = kFullWriteBarrier;
|
||||
if (representation == MachineRepresentation::kTaggedSigned) {
|
||||
kind = kNoWriteBarrier;
|
||||
@ -783,25 +783,25 @@ FieldAccess ForPropertyCellValue(MachineRepresentation representation,
|
||||
}
|
||||
MachineType r = MachineType::TypeForRepresentation(representation);
|
||||
FieldAccess access = {
|
||||
kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind};
|
||||
kTaggedBase, PropertyCell::kValueOffset, name.object(), map, type, r,
|
||||
kind};
|
||||
return access;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
Node* node, Node* receiver, Node* value, Handle<Name> name,
|
||||
Node* node, Node* receiver, Node* value, NameRef const& name,
|
||||
AccessMode access_mode, Node* key) {
|
||||
NameRef name_ref(broker(), name);
|
||||
base::Optional<PropertyCellRef> cell =
|
||||
native_context().global_proxy_object().GetPropertyCell(name_ref);
|
||||
native_context().global_proxy_object().GetPropertyCell(name);
|
||||
return cell.has_value() ? ReduceGlobalAccess(node, receiver, value, name,
|
||||
access_mode, key, *cell)
|
||||
: NoChange();
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
|
||||
Node* node, Node* receiver, Node* value, Handle<Name> name,
|
||||
Node* node, Node* receiver, Node* value, NameRef const& name,
|
||||
AccessMode access_mode, Node* key, PropertyCellRef const& property_cell) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
@ -1024,8 +1024,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) {
|
||||
}
|
||||
|
||||
CHECK(processed->IsPropertyCell());
|
||||
return ReduceGlobalAccess(node, nullptr, nullptr, p.name(), AccessMode::kLoad,
|
||||
nullptr, processed->property_cell());
|
||||
return ReduceGlobalAccess(node, nullptr, nullptr, NameRef(broker(), p.name()),
|
||||
AccessMode::kLoad, nullptr,
|
||||
processed->property_cell());
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
@ -1057,7 +1058,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
}
|
||||
|
||||
if (processed->IsPropertyCell()) {
|
||||
return ReduceGlobalAccess(node, nullptr, value, p.name(),
|
||||
return ReduceGlobalAccess(node, nullptr, value, NameRef(broker(), p.name()),
|
||||
AccessMode::kStore, nullptr,
|
||||
processed->property_cell());
|
||||
}
|
||||
@ -1066,8 +1067,8 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
Node* node, Node* value, MapHandles const& receiver_maps, Handle<Name> name,
|
||||
AccessMode access_mode, Node* key) {
|
||||
Node* node, Node* value, MapHandles const& receiver_maps,
|
||||
NameRef const& name, AccessMode access_mode, Node* key) {
|
||||
DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
|
||||
node->opcode() == IrOpcode::kJSStoreNamed ||
|
||||
node->opcode() == IrOpcode::kJSLoadProperty ||
|
||||
@ -1095,7 +1096,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
graph()->zone());
|
||||
ZoneVector<PropertyAccessInfo> access_infos(zone());
|
||||
if (!access_info_factory.ComputePropertyAccessInfos(
|
||||
receiver_maps, name, access_mode, &access_infos)) {
|
||||
receiver_maps, name.object(), access_mode, &access_infos)) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
@ -1330,7 +1331,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
|
||||
Node* node, Node* value, FeedbackNexus const& nexus, Handle<Name> name,
|
||||
Node* node, Node* value, FeedbackNexus const& nexus, NameRef const& name,
|
||||
AccessMode access_mode) {
|
||||
DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
|
||||
node->opcode() == IrOpcode::kJSStoreNamed ||
|
||||
@ -1364,12 +1365,12 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode());
|
||||
NamedAccess const& p = NamedAccessOf(node->op());
|
||||
Node* const receiver = NodeProperties::GetValueInput(node, 0);
|
||||
NameRef name(broker(), p.name());
|
||||
|
||||
// Check if we have a constant receiver.
|
||||
HeapObjectMatcher m(receiver);
|
||||
if (m.HasValue()) {
|
||||
ObjectRef object = m.Ref(broker());
|
||||
NameRef name(broker(), p.name());
|
||||
if (object.IsJSFunction() &&
|
||||
name.equals(ObjectRef(broker(), factory()->prototype_string()))) {
|
||||
// Optimize "prototype" property of functions.
|
||||
@ -1404,7 +1405,7 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
||||
FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
|
||||
|
||||
// Try to lower the named access based on the {receiver_maps}.
|
||||
return ReduceNamedAccessFromNexus(node, jsgraph()->Dead(), nexus, p.name(),
|
||||
return ReduceNamedAccessFromNexus(node, jsgraph()->Dead(), nexus, name,
|
||||
AccessMode::kLoad);
|
||||
}
|
||||
|
||||
@ -1418,8 +1419,8 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamed(Node* node) {
|
||||
FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
|
||||
|
||||
// Try to lower the named access based on the {receiver_maps}.
|
||||
return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
|
||||
AccessMode::kStore);
|
||||
return ReduceNamedAccessFromNexus(
|
||||
node, value, nexus, NameRef(broker(), p.name()), AccessMode::kStore);
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
|
||||
@ -1432,7 +1433,8 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreNamedOwn(Node* node) {
|
||||
FeedbackNexus nexus(p.feedback().vector(), p.feedback().slot());
|
||||
|
||||
// Try to lower the creation of a named property based on the {receiver_maps}.
|
||||
return ReduceNamedAccessFromNexus(node, value, nexus, p.name(),
|
||||
return ReduceNamedAccessFromNexus(node, value, nexus,
|
||||
NameRef(broker(), p.name()),
|
||||
AccessMode::kStoreInLiteral);
|
||||
}
|
||||
|
||||
@ -1714,7 +1716,7 @@ Reduction JSNativeContextSpecialization::ReduceKeyedLoadFromHeapConstant(
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
HeapObjectMatcher mreceiver(receiver);
|
||||
HeapObjectRef receiver_ref = mreceiver.Ref(broker()).AsHeapObject();
|
||||
HeapObjectRef receiver_ref = mreceiver.Ref(broker());
|
||||
if (receiver_ref.map().oddball_type() == OddballType::kHole ||
|
||||
receiver_ref.map().oddball_type() == OddballType::kNull ||
|
||||
receiver_ref.map().oddball_type() == OddballType::kUndefined ||
|
||||
@ -1821,8 +1823,9 @@ Reduction JSNativeContextSpecialization::ReduceKeyedAccess(
|
||||
// Check if we have feedback for a named access.
|
||||
base::Optional<NameRef> name = GetNameFeedback(broker(), nexus);
|
||||
if (name.has_value()) {
|
||||
return ReduceNamedAccess(node, value, receiver_maps, name->object(),
|
||||
access_mode, key);
|
||||
DCHECK_EQ(nexus.GetKeyType(), PROPERTY);
|
||||
return ReduceNamedAccess(node, value, receiver_maps, *name, access_mode,
|
||||
key);
|
||||
}
|
||||
|
||||
// Try to lower element access based on the {receiver_maps}.
|
||||
@ -2026,24 +2029,23 @@ Node* JSNativeContextSpecialization::InlinePropertyGetterCall(
|
||||
PropertyAccessInfo const& access_info) {
|
||||
Node* target = jsgraph()->Constant(access_info.constant());
|
||||
FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op());
|
||||
Handle<SharedFunctionInfo> shared_info =
|
||||
frame_info.shared_info().ToHandleChecked();
|
||||
// Introduce the call to the getter function.
|
||||
Node* value;
|
||||
if (access_info.constant()->IsJSFunction()) {
|
||||
ObjectRef constant(broker(), access_info.constant());
|
||||
if (constant.IsJSFunction()) {
|
||||
value = *effect = *control = graph()->NewNode(
|
||||
jsgraph()->javascript()->Call(2, CallFrequency(), VectorSlotPair(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined),
|
||||
target, receiver, context, frame_state, *effect, *control);
|
||||
} else {
|
||||
DCHECK(access_info.constant()->IsFunctionTemplateInfo());
|
||||
Handle<FunctionTemplateInfo> function_template_info(
|
||||
Handle<FunctionTemplateInfo>::cast(access_info.constant()));
|
||||
DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
|
||||
auto function_template_info = constant.AsFunctionTemplateInfo();
|
||||
function_template_info.Serialize();
|
||||
Node* holder =
|
||||
access_info.holder().is_null()
|
||||
? receiver
|
||||
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
|
||||
SharedFunctionInfoRef shared_info(
|
||||
broker(), frame_info.shared_info().ToHandleChecked());
|
||||
value = InlineApiCall(receiver, holder, frame_state, nullptr, effect,
|
||||
control, shared_info, function_template_info);
|
||||
}
|
||||
@ -2065,23 +2067,22 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
|
||||
PropertyAccessInfo const& access_info) {
|
||||
Node* target = jsgraph()->Constant(access_info.constant());
|
||||
FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op());
|
||||
Handle<SharedFunctionInfo> shared_info =
|
||||
frame_info.shared_info().ToHandleChecked();
|
||||
// Introduce the call to the setter function.
|
||||
if (access_info.constant()->IsJSFunction()) {
|
||||
ObjectRef constant(broker(), access_info.constant());
|
||||
if (constant.IsJSFunction()) {
|
||||
*effect = *control = graph()->NewNode(
|
||||
jsgraph()->javascript()->Call(3, CallFrequency(), VectorSlotPair(),
|
||||
ConvertReceiverMode::kNotNullOrUndefined),
|
||||
target, receiver, value, context, frame_state, *effect, *control);
|
||||
} else {
|
||||
DCHECK(access_info.constant()->IsFunctionTemplateInfo());
|
||||
Handle<FunctionTemplateInfo> function_template_info(
|
||||
Handle<FunctionTemplateInfo>::cast(access_info.constant()));
|
||||
DCHECK(!function_template_info->call_code()->IsUndefined(isolate()));
|
||||
auto function_template_info = constant.AsFunctionTemplateInfo();
|
||||
function_template_info.Serialize();
|
||||
Node* holder =
|
||||
access_info.holder().is_null()
|
||||
? receiver
|
||||
: jsgraph()->Constant(access_info.holder().ToHandleChecked());
|
||||
SharedFunctionInfoRef shared_info(
|
||||
broker(), frame_info.shared_info().ToHandleChecked());
|
||||
InlineApiCall(receiver, holder, frame_state, value, effect, control,
|
||||
shared_info, function_template_info);
|
||||
}
|
||||
@ -2098,11 +2099,10 @@ void JSNativeContextSpecialization::InlinePropertySetterCall(
|
||||
|
||||
Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
Node* receiver, Node* holder, Node* frame_state, Node* value, Node** effect,
|
||||
Node** control, Handle<SharedFunctionInfo> shared_info,
|
||||
Handle<FunctionTemplateInfo> function_template_info) {
|
||||
Handle<CallHandlerInfo> call_handler_info = handle(
|
||||
CallHandlerInfo::cast(function_template_info->call_code()), isolate());
|
||||
Handle<Object> call_data_object(call_handler_info->data(), isolate());
|
||||
Node** control, SharedFunctionInfoRef const& shared_info,
|
||||
FunctionTemplateInfoRef const& function_template_info) {
|
||||
auto call_handler_info =
|
||||
function_template_info.call_code().AsCallHandlerInfo();
|
||||
|
||||
// Only setters have a value.
|
||||
int const argc = value == nullptr ? 0 : 1;
|
||||
@ -2116,8 +2116,8 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
1 /* implicit receiver */,
|
||||
CallDescriptor::kNeedsFrameState);
|
||||
|
||||
Node* data = jsgraph()->Constant(call_data_object);
|
||||
ApiFunction function(v8::ToCData<Address>(call_handler_info->callback()));
|
||||
Node* data = jsgraph()->Constant(call_handler_info.data());
|
||||
ApiFunction function(call_handler_info.callback());
|
||||
Node* function_reference =
|
||||
graph()->NewNode(common()->ExternalConstant(ExternalReference::Create(
|
||||
&function, ExternalReference::DIRECT_API_CALL)));
|
||||
@ -2146,11 +2146,10 @@ Node* JSNativeContextSpecialization::InlineApiCall(
|
||||
JSNativeContextSpecialization::ValueEffectControl
|
||||
JSNativeContextSpecialization::BuildPropertyLoad(
|
||||
Node* receiver, Node* context, Node* frame_state, Node* effect,
|
||||
Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
|
||||
Node* control, NameRef const& name, ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info) {
|
||||
// Determine actual holder and perform prototype chain checks.
|
||||
Handle<JSObject> holder;
|
||||
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
|
||||
if (access_info.holder().ToHandle(&holder)) {
|
||||
dependencies()->DependOnStablePrototypeChains(
|
||||
access_info.receiver_maps(), kStartAtPrototype,
|
||||
@ -2176,6 +2175,7 @@ JSNativeContextSpecialization::BuildPropertyLoad(
|
||||
value = graph()->NewNode(simplified()->StringLength(), receiver);
|
||||
} else {
|
||||
DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
|
||||
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
|
||||
value = access_builder.BuildLoadDataField(name, access_info, receiver,
|
||||
&effect, &control);
|
||||
}
|
||||
@ -2196,14 +2196,13 @@ JSNativeContextSpecialization::BuildPropertyTest(
|
||||
|
||||
Node* value = access_info.IsNotFound() ? jsgraph()->FalseConstant()
|
||||
: jsgraph()->TrueConstant();
|
||||
|
||||
return ValueEffectControl(value, effect, control);
|
||||
}
|
||||
|
||||
JSNativeContextSpecialization::ValueEffectControl
|
||||
JSNativeContextSpecialization::BuildPropertyAccess(
|
||||
Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
|
||||
Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
|
||||
Node* control, NameRef const& name, ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info, AccessMode access_mode) {
|
||||
switch (access_mode) {
|
||||
case AccessMode::kLoad:
|
||||
@ -2223,7 +2222,7 @@ JSNativeContextSpecialization::BuildPropertyAccess(
|
||||
JSNativeContextSpecialization::ValueEffectControl
|
||||
JSNativeContextSpecialization::BuildPropertyStore(
|
||||
Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
|
||||
Node* control, Handle<Name> name, ZoneVector<Node*>* if_exceptions,
|
||||
Node* control, NameRef const& name, ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info, AccessMode access_mode) {
|
||||
// Determine actual holder and perform prototype chain checks.
|
||||
Handle<JSObject> holder;
|
||||
@ -2265,7 +2264,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
|
||||
FieldAccess field_access = {
|
||||
kTaggedBase,
|
||||
field_index.offset(),
|
||||
name,
|
||||
name.object(),
|
||||
MaybeHandle<Map>(),
|
||||
field_type,
|
||||
MachineType::TypeForRepresentation(field_representation),
|
||||
@ -2298,13 +2297,11 @@ JSNativeContextSpecialization::BuildPropertyStore(
|
||||
field_access.write_barrier_kind = kPointerWriteBarrier;
|
||||
} else {
|
||||
// We just store directly to the MutableHeapNumber.
|
||||
FieldAccess const storage_access = {kTaggedBase,
|
||||
field_index.offset(),
|
||||
name,
|
||||
MaybeHandle<Map>(),
|
||||
Type::OtherInternal(),
|
||||
MachineType::TaggedPointer(),
|
||||
kPointerWriteBarrier};
|
||||
FieldAccess const storage_access = {
|
||||
kTaggedBase, field_index.offset(),
|
||||
name.object(), MaybeHandle<Map>(),
|
||||
Type::OtherInternal(), MachineType::TaggedPointer(),
|
||||
kPointerWriteBarrier};
|
||||
storage = effect =
|
||||
graph()->NewNode(simplified()->LoadField(storage_access),
|
||||
storage, effect, control);
|
||||
@ -2393,14 +2390,15 @@ JSNativeContextSpecialization::BuildPropertyStore(
|
||||
if (access_info.transition_map().ToHandle(&transition_map)) {
|
||||
// Check if we need to grow the properties backing store
|
||||
// with this transitioning store.
|
||||
Handle<Map> original_map(Map::cast(transition_map->GetBackPointer()),
|
||||
isolate());
|
||||
if (original_map->UnusedPropertyFields() == 0) {
|
||||
MapRef transition_map_ref(broker(), transition_map);
|
||||
transition_map_ref.SerializeBackPointer();
|
||||
MapRef original_map = transition_map_ref.GetBackPointer().AsMap();
|
||||
if (original_map.UnusedPropertyFields() == 0) {
|
||||
DCHECK(!field_index.is_inobject());
|
||||
|
||||
// Reallocate the properties {storage}.
|
||||
storage = effect = BuildExtendPropertiesBackingStore(
|
||||
MapRef(broker(), original_map), storage, effect, control);
|
||||
original_map, storage, effect, control);
|
||||
|
||||
// Perform the actual store.
|
||||
effect = graph()->NewNode(simplified()->StoreField(field_access),
|
||||
@ -2459,15 +2457,16 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
|
||||
if (!Map::TryUpdate(isolate(), receiver_map).ToHandle(&receiver_map))
|
||||
return NoChange();
|
||||
|
||||
Handle<Name> cached_name(
|
||||
Name::cast(nexus.GetFeedbackExtra()->GetHeapObjectAssumeStrong()),
|
||||
isolate());
|
||||
NameRef cached_name(
|
||||
broker(),
|
||||
handle(Name::cast(nexus.GetFeedbackExtra()->GetHeapObjectAssumeStrong()),
|
||||
isolate()));
|
||||
|
||||
PropertyAccessInfo access_info;
|
||||
AccessInfoFactory access_info_factory(broker(), dependencies(),
|
||||
graph()->zone());
|
||||
if (!access_info_factory.ComputePropertyAccessInfo(
|
||||
receiver_map, cached_name, AccessMode::kStoreInLiteral,
|
||||
receiver_map, cached_name.object(), AccessMode::kStoreInLiteral,
|
||||
&access_info)) {
|
||||
return NoChange();
|
||||
}
|
||||
@ -2485,7 +2484,7 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreDataPropertyInLiteral(
|
||||
// Ensure that {name} matches the cached name.
|
||||
Node* name = NodeProperties::GetValueInput(node, 1);
|
||||
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), name,
|
||||
jsgraph()->HeapConstant(cached_name));
|
||||
jsgraph()->Constant(cached_name));
|
||||
effect = graph()->NewNode(simplified()->CheckIf(DeoptimizeReason::kWrongName),
|
||||
check, effect, control);
|
||||
|
||||
@ -3249,15 +3248,15 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore(
|
||||
return a.Finish();
|
||||
}
|
||||
|
||||
Node* JSNativeContextSpecialization::BuildCheckEqualsName(Handle<Name> name,
|
||||
Node* JSNativeContextSpecialization::BuildCheckEqualsName(NameRef const& name,
|
||||
Node* value,
|
||||
Node* effect,
|
||||
Node* control) {
|
||||
DCHECK(name->IsUniqueName());
|
||||
DCHECK(name.IsUniqueName());
|
||||
Operator const* const op =
|
||||
name->IsSymbol() ? simplified()->CheckEqualsSymbol()
|
||||
: simplified()->CheckEqualsInternalizedString();
|
||||
return graph()->NewNode(op, jsgraph()->HeapConstant(name), value, effect,
|
||||
name.IsSymbol() ? simplified()->CheckEqualsSymbol()
|
||||
: simplified()->CheckEqualsInternalizedString();
|
||||
return graph()->NewNode(op, jsgraph()->Constant(name), value, effect,
|
||||
control);
|
||||
}
|
||||
|
||||
|
@ -105,17 +105,17 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
KeyedAccessStoreMode store_mode);
|
||||
Reduction ReduceNamedAccessFromNexus(Node* node, Node* value,
|
||||
FeedbackNexus const& nexus,
|
||||
Handle<Name> name,
|
||||
NameRef const& name,
|
||||
AccessMode access_mode);
|
||||
Reduction ReduceNamedAccess(Node* node, Node* value,
|
||||
MapHandles const& receiver_maps,
|
||||
Handle<Name> name, AccessMode access_mode,
|
||||
NameRef const& name, AccessMode access_mode,
|
||||
Node* key = nullptr);
|
||||
Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
|
||||
Handle<Name> name, AccessMode access_mode,
|
||||
NameRef const& name, AccessMode access_mode,
|
||||
Node* key = nullptr);
|
||||
Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value,
|
||||
Handle<Name> name, AccessMode access_mode,
|
||||
NameRef const& name, AccessMode access_mode,
|
||||
Node* key, PropertyCellRef const& property_cell);
|
||||
Reduction ReduceKeyedLoadFromHeapConstant(Node* node, Node* key,
|
||||
FeedbackNexus const& nexus,
|
||||
@ -154,20 +154,20 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
ValueEffectControl BuildPropertyAccess(Node* receiver, Node* value,
|
||||
Node* context, Node* frame_state,
|
||||
Node* effect, Node* control,
|
||||
Handle<Name> name,
|
||||
NameRef const& name,
|
||||
ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info,
|
||||
AccessMode access_mode);
|
||||
ValueEffectControl BuildPropertyLoad(Node* receiver, Node* context,
|
||||
Node* frame_state, Node* effect,
|
||||
Node* control, Handle<Name> name,
|
||||
Node* control, NameRef const& name,
|
||||
ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info);
|
||||
|
||||
ValueEffectControl BuildPropertyStore(Node* receiver, Node* value,
|
||||
Node* context, Node* frame_state,
|
||||
Node* effect, Node* control,
|
||||
Handle<Name> name,
|
||||
NameRef const& name,
|
||||
ZoneVector<Node*>* if_exceptions,
|
||||
PropertyAccessInfo const& access_info,
|
||||
AccessMode access_mode);
|
||||
@ -188,8 +188,8 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
PropertyAccessInfo const& access_info);
|
||||
Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state,
|
||||
Node* value, Node** effect, Node** control,
|
||||
Handle<SharedFunctionInfo> shared_info,
|
||||
Handle<FunctionTemplateInfo> function_template_info);
|
||||
SharedFunctionInfoRef const& shared_info,
|
||||
FunctionTemplateInfoRef const& function_template_info);
|
||||
|
||||
// Construct the appropriate subgraph for element access.
|
||||
ValueEffectControl BuildElementAccess(
|
||||
@ -208,7 +208,7 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
|
||||
|
||||
// Construct appropriate subgraph to check that the {value} matches
|
||||
// the previously recorded {name} feedback.
|
||||
Node* BuildCheckEqualsName(Handle<Name> name, Node* value, Node* effect,
|
||||
Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect,
|
||||
Node* control);
|
||||
|
||||
// Checks if we can turn the hole into undefined when loading an element
|
||||
|
@ -196,8 +196,8 @@ struct HeapObjectMatcher final
|
||||
return this->HasValue() && this->Value().address() == value.address();
|
||||
}
|
||||
|
||||
ObjectRef Ref(JSHeapBroker* broker) const {
|
||||
return ObjectRef(broker, this->Value());
|
||||
HeapObjectRef Ref(JSHeapBroker* broker) const {
|
||||
return HeapObjectRef(broker, this->Value());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -391,7 +391,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
|
||||
ZoneHandleSet<Map>* maps_return) {
|
||||
HeapObjectMatcher m(receiver);
|
||||
if (m.HasValue()) {
|
||||
HeapObjectRef receiver = m.Ref(broker).AsHeapObject();
|
||||
HeapObjectRef receiver = m.Ref(broker);
|
||||
// We don't use ICs for the Array.prototype and the Object.prototype
|
||||
// because the runtime has to be able to intercept them properly, so
|
||||
// we better make sure that TurboFan doesn't outsmart the system here
|
||||
@ -575,8 +575,7 @@ bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
|
||||
case IrOpcode::kJSToObject:
|
||||
return false;
|
||||
case IrOpcode::kHeapConstant: {
|
||||
HeapObjectRef value =
|
||||
HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
|
||||
HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
|
||||
return value.map().IsPrimitiveMap();
|
||||
}
|
||||
default: {
|
||||
@ -617,8 +616,7 @@ bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
|
||||
case IrOpcode::kToBoolean:
|
||||
return false;
|
||||
case IrOpcode::kHeapConstant: {
|
||||
HeapObjectRef value =
|
||||
HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
|
||||
HeapObjectRef value = HeapObjectMatcher(receiver).Ref(broker);
|
||||
OddballType type = value.map().oddball_type();
|
||||
return type == OddballType::kNull || type == OddballType::kUndefined;
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ void PropertyAccessBuilder::BuildCheckMaps(Node* receiver, Node** effect,
|
||||
MapHandles const& receiver_maps) {
|
||||
HeapObjectMatcher m(receiver);
|
||||
if (m.HasValue()) {
|
||||
MapRef receiver_map = m.Ref(broker()).AsHeapObject().map();
|
||||
MapRef receiver_map = m.Ref(broker()).map();
|
||||
if (receiver_map.is_stable()) {
|
||||
for (Handle<Map> map : receiver_maps) {
|
||||
if (MapRef(broker(), map).equals(receiver_map)) {
|
||||
@ -195,7 +195,8 @@ Node* PropertyAccessBuilder::ResolveHolder(
|
||||
}
|
||||
|
||||
Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
|
||||
Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver) {
|
||||
NameRef const& name, PropertyAccessInfo const& access_info,
|
||||
Node* receiver) {
|
||||
// Optimize immutable property loads.
|
||||
|
||||
// First, determine if we have a constant holder to load from.
|
||||
@ -204,14 +205,14 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
|
||||
if (!access_info.holder().ToHandle(&holder)) {
|
||||
// Otherwise, try to match the {receiver} as a constant.
|
||||
HeapObjectMatcher m(receiver);
|
||||
if (!m.HasValue() || !m.Value()->IsJSObject()) return nullptr;
|
||||
if (!m.HasValue() || !m.Ref(broker()).IsJSObject()) return nullptr;
|
||||
|
||||
// Let us make sure the actual map of the constant receiver is among
|
||||
// the maps in {access_info}.
|
||||
Handle<Map> receiver_map = handle(m.Value()->map(), isolate());
|
||||
MapRef receiver_map = m.Ref(broker()).map();
|
||||
if (std::find_if(access_info.receiver_maps().begin(),
|
||||
access_info.receiver_maps().end(), [&](Handle<Map> map) {
|
||||
return map.address() == receiver_map.address();
|
||||
return map.address() == receiver_map.object().address();
|
||||
}) == access_info.receiver_maps().end()) {
|
||||
// The map of the receiver is not in the feedback, let us bail out.
|
||||
return nullptr;
|
||||
@ -229,7 +230,7 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
|
||||
|
||||
// TODO(turbofan): Given that we already have the field_index here, we
|
||||
// might be smarter in the future and not rely on the LookupIterator.
|
||||
LookupIterator it(isolate(), holder, name,
|
||||
LookupIterator it(isolate(), holder, name.object(),
|
||||
LookupIterator::OWN_SKIP_INTERCEPTOR);
|
||||
if (it.state() == LookupIterator::DATA) {
|
||||
bool is_readonly_non_configurable = it.IsReadOnly() && !it.IsConfigurable();
|
||||
@ -257,7 +258,7 @@ Node* PropertyAccessBuilder::TryBuildLoadConstantDataField(
|
||||
}
|
||||
|
||||
Node* PropertyAccessBuilder::BuildLoadDataField(
|
||||
Handle<Name> name, PropertyAccessInfo const& access_info, Node* receiver,
|
||||
NameRef const& name, PropertyAccessInfo const& access_info, Node* receiver,
|
||||
Node** effect, Node** control) {
|
||||
DCHECK(access_info.IsDataField() || access_info.IsDataConstantField());
|
||||
if (Node* value =
|
||||
@ -278,7 +279,7 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
|
||||
FieldAccess field_access = {
|
||||
kTaggedBase,
|
||||
field_index.offset(),
|
||||
name,
|
||||
name.object(),
|
||||
MaybeHandle<Map>(),
|
||||
field_type,
|
||||
MachineType::TypeForRepresentation(field_representation),
|
||||
@ -287,14 +288,11 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
|
||||
if (field_representation == MachineRepresentation::kFloat64) {
|
||||
if (!field_index.is_inobject() || field_index.is_hidden_field() ||
|
||||
!FLAG_unbox_double_fields) {
|
||||
FieldAccess const storage_access = {kTaggedBase,
|
||||
field_index.offset(),
|
||||
name,
|
||||
MaybeHandle<Map>(),
|
||||
Type::OtherInternal(),
|
||||
MachineType::TaggedPointer(),
|
||||
kPointerWriteBarrier,
|
||||
LoadSensitivity::kCritical};
|
||||
FieldAccess const storage_access = {
|
||||
kTaggedBase, field_index.offset(),
|
||||
name.object(), MaybeHandle<Map>(),
|
||||
Type::OtherInternal(), MachineType::TaggedPointer(),
|
||||
kPointerWriteBarrier, LoadSensitivity::kCritical};
|
||||
storage = *effect = graph()->NewNode(
|
||||
simplified()->LoadField(storage_access), storage, *effect, *control);
|
||||
field_access.offset = HeapNumber::kValueOffset;
|
||||
@ -305,8 +303,9 @@ Node* PropertyAccessBuilder::BuildLoadDataField(
|
||||
// used by the LoadElimination to eliminate map checks on the result.
|
||||
Handle<Map> field_map;
|
||||
if (access_info.field_map().ToHandle(&field_map)) {
|
||||
if (field_map->is_stable()) {
|
||||
dependencies()->DependOnStableMap(MapRef(broker(), field_map));
|
||||
MapRef field_map_ref(broker(), field_map);
|
||||
if (field_map_ref.is_stable()) {
|
||||
dependencies()->DependOnStableMap(field_map_ref);
|
||||
field_access.map = field_map;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/js-heap-broker.h"
|
||||
#include "src/handles.h"
|
||||
#include "src/objects/map.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
@ -46,7 +47,7 @@ class PropertyAccessBuilder {
|
||||
|
||||
// Builds the actual load for data-field and data-constant-field
|
||||
// properties (without heap-object or map checks).
|
||||
Node* BuildLoadDataField(Handle<Name> name,
|
||||
Node* BuildLoadDataField(NameRef const& name,
|
||||
PropertyAccessInfo const& access_info,
|
||||
Node* receiver, Node** effect, Node** control);
|
||||
|
||||
@ -59,7 +60,7 @@ class PropertyAccessBuilder {
|
||||
CommonOperatorBuilder* common() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
|
||||
Node* TryBuildLoadConstantDataField(Handle<Name> name,
|
||||
Node* TryBuildLoadConstantDataField(NameRef const& name,
|
||||
PropertyAccessInfo const& access_info,
|
||||
Node* receiver);
|
||||
// Returns a node with the holder for the property access described by
|
||||
|
@ -684,10 +684,10 @@ void Map::AppendDescriptor(Isolate* isolate, Descriptor* desc) {
|
||||
#endif
|
||||
}
|
||||
|
||||
Object Map::GetBackPointer() const {
|
||||
HeapObject Map::GetBackPointer() const {
|
||||
Object object = constructor_or_backpointer();
|
||||
if (object->IsMap()) {
|
||||
return object;
|
||||
return Map::cast(object);
|
||||
}
|
||||
return GetReadOnlyRoots().undefined_value();
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ class Map : public HeapObject {
|
||||
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
||||
// [back pointer]: points back to the parent map from which a transition
|
||||
// leads to this map. The field overlaps with the constructor (see above).
|
||||
inline Object GetBackPointer() const;
|
||||
inline HeapObject GetBackPointer() const;
|
||||
inline void SetBackPointer(Object value,
|
||||
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user