Commit 16f1d16c authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Brokerize DependOnStablePrototypeChains.

As well as a few other things in JSNativeContextSpecialization.

Bug: v8:7790
Change-Id: Ic13abec45797bb4c6cc66a140180122529c7288d
Reviewed-on: https://chromium-review.googlesource.com/c/1280327Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56670}
parent 34ec9ec7
...@@ -388,37 +388,34 @@ bool CompilationDependencies::Commit(Handle<Code> code) { ...@@ -388,37 +388,34 @@ bool CompilationDependencies::Commit(Handle<Code> code) {
} }
namespace { namespace {
// This function expects to never see a JSProxy.
void DependOnStablePrototypeChain(JSHeapBroker* broker, void DependOnStablePrototypeChain(JSHeapBroker* broker,
CompilationDependencies* deps, CompilationDependencies* deps, MapRef map,
Handle<Map> map, const JSObjectRef& last_prototype) {
MaybeHandle<JSReceiver> last_prototype) { while (true) {
for (PrototypeIterator i(broker->isolate(), map); !i.IsAtEnd(); i.Advance()) { map.SerializePrototype();
Handle<JSReceiver> const current = JSObjectRef proto = map.prototype().AsJSObject();
PrototypeIterator::GetCurrent<JSReceiver>(i); map = proto.map();
deps->DependOnStableMap( deps->DependOnStableMap(map);
MapRef(broker, handle(current->map(), broker->isolate()))); if (proto.equals(last_prototype)) break;
Handle<JSReceiver> last;
if (last_prototype.ToHandle(&last) && last.is_identical_to(current)) {
break;
}
} }
} }
} // namespace } // namespace
void CompilationDependencies::DependOnStablePrototypeChains( void CompilationDependencies::DependOnStablePrototypeChains(
JSHeapBroker* broker, Handle<Context> native_context, JSHeapBroker* broker, std::vector<Handle<Map>> const& receiver_maps,
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) { const JSObjectRef& holder) {
Isolate* isolate = holder->GetIsolate();
// Determine actual holder and perform prototype chain checks. // Determine actual holder and perform prototype chain checks.
for (auto map : receiver_maps) { for (auto map : receiver_maps) {
// Perform the implicit ToObject for primitives here. MapRef receiver_map(broker, map);
// Implemented according to ES6 section 7.3.2 GetV (V, P). if (receiver_map.IsPrimitiveMap()) {
Handle<JSFunction> constructor; // Perform the implicit ToObject for primitives here.
if (Map::GetConstructorFunction(map, native_context) // Implemented according to ES6 section 7.3.2 GetV (V, P).
.ToHandle(&constructor)) { base::Optional<JSFunctionRef> constructor =
map = handle(constructor->initial_map(), isolate); broker->native_context().GetConstructorFunction(receiver_map);
if (constructor.has_value()) receiver_map = constructor->initial_map();
} }
DependOnStablePrototypeChain(broker, this, map, holder); DependOnStablePrototypeChain(broker, this, receiver_map, holder);
} }
} }
......
...@@ -67,10 +67,9 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject { ...@@ -67,10 +67,9 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
// Depend on the stability of (the maps of) all prototypes of every class in // Depend on the stability of (the maps of) all prototypes of every class in
// {receiver_type} up to (and including) the {holder}. // {receiver_type} up to (and including) the {holder}.
// TODO(neis): Fully brokerize!
void DependOnStablePrototypeChains( void DependOnStablePrototypeChains(
JSHeapBroker* broker, Handle<Context> native_context, JSHeapBroker* broker, std::vector<Handle<Map>> const& receiver_maps,
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder); const JSObjectRef& holder);
// Like DependOnElementsKind but also applies to all nested allocation sites. // Like DependOnElementsKind but also applies to all nested allocation sites.
void DependOnElementsKinds(const AllocationSiteRef& site); void DependOnElementsKinds(const AllocationSiteRef& site);
......
...@@ -7072,7 +7072,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) { ...@@ -7072,7 +7072,7 @@ Reduction JSCallReducer::ReduceRegExpPrototypeTest(Node* node) {
Handle<JSObject> holder; Handle<JSObject> holder;
if (ai_exec.holder().ToHandle(&holder)) { if (ai_exec.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context(), ai_exec.receiver_maps(), holder); broker(), ai_exec.receiver_maps(), JSObjectRef(broker(), holder));
} }
if (need_map_check) { if (need_map_check) {
......
...@@ -610,6 +610,7 @@ class MapData : public HeapObjectData { ...@@ -610,6 +610,7 @@ class MapData : public HeapObjectData {
CHECK(InstanceTypeChecker::IsJSObject(instance_type())); CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
return in_object_properties_; return in_object_properties_;
} }
int constructor_function_index() const { return constructor_function_index_; }
// Extra information. // Extra information.
...@@ -649,6 +650,7 @@ class MapData : public HeapObjectData { ...@@ -649,6 +650,7 @@ class MapData : public HeapObjectData {
bool const can_transition_; bool const can_transition_;
int const in_object_properties_start_in_words_; int const in_object_properties_start_in_words_;
int const in_object_properties_; int const in_object_properties_;
int const constructor_function_index_;
bool serialized_elements_kind_generalizations_ = false; bool serialized_elements_kind_generalizations_ = false;
ZoneVector<MapData*> elements_kind_generalizations_; ZoneVector<MapData*> elements_kind_generalizations_;
...@@ -726,6 +728,9 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object) ...@@ -726,6 +728,9 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
: 0), : 0),
in_object_properties_( in_object_properties_(
object->IsJSObjectMap() ? object->GetInObjectProperties() : 0), object->IsJSObjectMap() ? object->GetInObjectProperties() : 0),
constructor_function_index_(object->IsPrimitiveMap()
? object->GetConstructorFunctionIndex()
: Map::kNoConstructorFunctionIndex),
elements_kind_generalizations_(broker->zone()) {} elements_kind_generalizations_(broker->zone()) {}
JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage, JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
...@@ -1893,6 +1898,10 @@ bool MapRef::IsFixedCowArrayMap() const { ...@@ -1893,6 +1898,10 @@ bool MapRef::IsFixedCowArrayMap() const {
return equals(MapRef(broker(), fixed_cow_array_map)); return equals(MapRef(broker(), fixed_cow_array_map));
} }
bool MapRef::IsPrimitiveMap() const {
return instance_type() <= LAST_PRIMITIVE_TYPE;
}
MapRef MapRef::FindFieldOwner(int descriptor_index) const { MapRef MapRef::FindFieldOwner(int descriptor_index) const {
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation; AllowHandleAllocation handle_allocation;
...@@ -2086,6 +2095,12 @@ bool MapRef::IsInobjectSlackTrackingInProgress() const { ...@@ -2086,6 +2095,12 @@ bool MapRef::IsInobjectSlackTrackingInProgress() const {
Map::kNoSlackTracking; Map::kNoSlackTracking;
} }
int MapRef::constructor_function_index() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, GetConstructorFunctionIndex);
CHECK(IsPrimitiveMap());
return data()->AsMap()->constructor_function_index();
}
bool MapRef::is_stable() const { bool MapRef::is_stable() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable); IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, is_stable);
return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3()); return !Map::IsUnstableBit::decode(data()->AsMap()->bit_field3());
...@@ -2156,6 +2171,27 @@ MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const { ...@@ -2156,6 +2171,27 @@ MapRef NativeContextRef::GetInitialJSArrayMap(ElementsKind kind) const {
} }
} }
base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
const MapRef& map) const {
CHECK(map.IsPrimitiveMap());
switch (map.constructor_function_index()) {
case Map::kNoConstructorFunctionIndex:
return base::nullopt;
case Context::BIGINT_FUNCTION_INDEX:
return bigint_function();
case Context::BOOLEAN_FUNCTION_INDEX:
return boolean_function();
case Context::NUMBER_FUNCTION_INDEX:
return number_function();
case Context::STRING_FUNCTION_INDEX:
return string_function();
case Context::SYMBOL_FUNCTION_INDEX:
return symbol_function();
default:
UNREACHABLE();
}
}
bool ObjectRef::BooleanValue() const { bool ObjectRef::BooleanValue() const {
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
......
...@@ -240,8 +240,13 @@ class ContextRef : public HeapObjectRef { ...@@ -240,8 +240,13 @@ class ContextRef : public HeapObjectRef {
#define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \ #define BROKER_COMPULSORY_NATIVE_CONTEXT_FIELDS(V) \
V(JSFunction, array_function) \ V(JSFunction, array_function) \
V(JSFunction, boolean_function) \
V(JSFunction, bigint_function) \
V(JSFunction, number_function) \
V(JSFunction, object_function) \ V(JSFunction, object_function) \
V(JSFunction, promise_function) \ V(JSFunction, promise_function) \
V(JSFunction, string_function) \
V(JSFunction, symbol_function) \
V(Map, fast_aliased_arguments_map) \ V(Map, fast_aliased_arguments_map) \
V(Map, initial_array_iterator_map) \ V(Map, initial_array_iterator_map) \
V(Map, initial_string_iterator_map) \ V(Map, initial_string_iterator_map) \
...@@ -282,6 +287,7 @@ class NativeContextRef : public ContextRef { ...@@ -282,6 +287,7 @@ class NativeContextRef : public ContextRef {
MapRef GetFunctionMapFromIndex(int index) const; MapRef GetFunctionMapFromIndex(int index) const;
MapRef GetInitialJSArrayMap(ElementsKind kind) const; MapRef GetInitialJSArrayMap(ElementsKind kind) const;
base::Optional<JSFunctionRef> GetConstructorFunction(const MapRef& map) const;
}; };
class NameRef : public HeapObjectRef { class NameRef : public HeapObjectRef {
...@@ -347,6 +353,7 @@ class MapRef : public HeapObjectRef { ...@@ -347,6 +353,7 @@ class MapRef : public HeapObjectRef {
int GetInObjectPropertiesStartInWords() const; int GetInObjectPropertiesStartInWords() const;
int NumberOfOwnDescriptors() const; int NumberOfOwnDescriptors() const;
int GetInObjectPropertyOffset(int index) const; int GetInObjectPropertyOffset(int index) const;
int constructor_function_index() const;
ElementsKind elements_kind() const; ElementsKind elements_kind() const;
bool is_stable() const; bool is_stable() const;
bool is_constructor() const; bool is_constructor() const;
...@@ -357,6 +364,7 @@ class MapRef : public HeapObjectRef { ...@@ -357,6 +364,7 @@ class MapRef : public HeapObjectRef {
bool IsInobjectSlackTrackingInProgress() const; bool IsInobjectSlackTrackingInProgress() const;
bool is_dictionary_map() const; bool is_dictionary_map() const;
bool IsFixedCowArrayMap() const; bool IsFixedCowArrayMap() const;
bool IsPrimitiveMap() const;
bool is_undetectable() const; bool is_undetectable() const;
bool is_callable() const; bool is_callable() const;
......
...@@ -422,8 +422,8 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { ...@@ -422,8 +422,8 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
Handle<JSObject> holder; Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context().object<Context>(), broker(), access_info.receiver_maps(),
access_info.receiver_maps(), holder); JSObjectRef(broker(), holder));
} }
// Check that {constructor} is actually {receiver}. // Check that {constructor} is actually {receiver}.
...@@ -448,8 +448,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) { ...@@ -448,8 +448,7 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
Handle<JSObject> holder; Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context().object<Context>(), broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
access_info.receiver_maps(), holder);
} else { } else {
holder = receiver; holder = receiver;
} }
...@@ -714,8 +713,7 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) { ...@@ -714,8 +713,7 @@ Reduction JSNativeContextSpecialization::ReduceJSResolvePromise(Node* node) {
Handle<JSObject> holder; Handle<JSObject> holder;
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context().object<Context>(), broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
access_info.receiver_maps(), holder);
} }
// Simply fulfill the {promise} with the {resolution}. // Simply fulfill the {promise} with the {resolution}.
...@@ -2031,8 +2029,7 @@ JSNativeContextSpecialization::BuildPropertyLoad( ...@@ -2031,8 +2029,7 @@ JSNativeContextSpecialization::BuildPropertyLoad(
PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies()); PropertyAccessBuilder access_builder(jsgraph(), broker(), dependencies());
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context().object<Context>(), broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
access_info.receiver_maps(), holder);
} }
// Generate the actual property access. // Generate the actual property access.
...@@ -2091,8 +2088,7 @@ JSNativeContextSpecialization::BuildPropertyStore( ...@@ -2091,8 +2088,7 @@ JSNativeContextSpecialization::BuildPropertyStore(
if (access_info.holder().ToHandle(&holder)) { if (access_info.holder().ToHandle(&holder)) {
DCHECK_NE(AccessMode::kStoreInLiteral, access_mode); DCHECK_NE(AccessMode::kStoreInLiteral, access_mode);
dependencies()->DependOnStablePrototypeChains( dependencies()->DependOnStablePrototypeChains(
broker(), native_context().object<Context>(), broker(), access_info.receiver_maps(), JSObjectRef(broker(), holder));
access_info.receiver_maps(), holder);
} }
DCHECK(!access_info.IsNotFound()); DCHECK(!access_info.IsNotFound());
...@@ -3140,7 +3136,8 @@ bool JSNativeContextSpecialization::InferReceiverMaps( ...@@ -3140,7 +3136,8 @@ bool JSNativeContextSpecialization::InferReceiverMaps(
// For untrusted receiver maps, we can still use the information // For untrusted receiver maps, we can still use the information
// if the maps are stable. // if the maps are stable.
for (size_t i = 0; i < maps.size(); ++i) { for (size_t i = 0; i < maps.size(); ++i) {
if (!maps[i]->is_stable()) return false; MapRef map(broker(), maps[i]);
if (!map.is_stable()) return false;
} }
for (size_t i = 0; i < maps.size(); ++i) { for (size_t i = 0; i < maps.size(); ++i) {
receiver_maps->push_back(maps[i]); receiver_maps->push_back(maps[i]);
......
...@@ -410,15 +410,15 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( ...@@ -410,15 +410,15 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
HeapObjectMatcher mtarget(GetValueInput(effect, 0)); HeapObjectMatcher mtarget(GetValueInput(effect, 0));
HeapObjectMatcher mnewtarget(GetValueInput(effect, 1)); HeapObjectMatcher mnewtarget(GetValueInput(effect, 1));
if (mtarget.HasValue() && mnewtarget.HasValue() && if (mtarget.HasValue() && mnewtarget.HasValue() &&
mnewtarget.Value()->IsJSFunction()) { mnewtarget.Ref(broker).IsJSFunction()) {
Handle<JSFunction> original_constructor = JSFunctionRef original_constructor =
Handle<JSFunction>::cast(mnewtarget.Value()); mnewtarget.Ref(broker).AsJSFunction();
if (original_constructor->has_initial_map()) { if (original_constructor.has_initial_map()) {
Handle<Map> initial_map(original_constructor->initial_map(), original_constructor.Serialize();
broker->isolate()); MapRef initial_map = original_constructor.initial_map();
if (initial_map->constructor_or_backpointer() == if (initial_map.constructor_or_backpointer().equals(
*mtarget.Value()) { mtarget.Ref(broker))) {
*maps_return = ZoneHandleSet<Map>(initial_map); *maps_return = ZoneHandleSet<Map>(initial_map.object<Map>());
return result; return result;
} }
} }
...@@ -438,7 +438,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps( ...@@ -438,7 +438,7 @@ NodeProperties::InferReceiverMapsResult NodeProperties::InferReceiverMaps(
Node* const value = GetValueInput(effect, 1); Node* const value = GetValueInput(effect, 1);
HeapObjectMatcher m(value); HeapObjectMatcher m(value);
if (m.HasValue()) { if (m.HasValue()) {
*maps_return = ZoneHandleSet<Map>(Handle<Map>::cast(m.Value())); *maps_return = ZoneHandleSet<Map>(m.Ref(broker).object<Map>());
return result; return result;
} }
} }
...@@ -566,8 +566,9 @@ bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver, ...@@ -566,8 +566,9 @@ bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
case IrOpcode::kJSToObject: case IrOpcode::kJSToObject:
return false; return false;
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
Handle<HeapObject> value = HeapObjectMatcher(receiver).Value(); HeapObjectRef value =
return value->IsPrimitive(); HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
return value.map().IsPrimitiveMap();
} }
default: { default: {
// We don't really care about the exact maps here, // We don't really care about the exact maps here,
...@@ -576,9 +577,10 @@ bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver, ...@@ -576,9 +577,10 @@ bool NodeProperties::CanBePrimitive(JSHeapBroker* broker, Node* receiver,
ZoneHandleSet<Map> maps; ZoneHandleSet<Map> maps;
if (InferReceiverMaps(broker, receiver, effect, &maps) != if (InferReceiverMaps(broker, receiver, effect, &maps) !=
kNoReceiverMaps) { kNoReceiverMaps) {
// Check if all {maps} are actually JSReceiver maps. // Check if one of the {maps} is not a JSReceiver map.
for (size_t i = 0; i < maps.size(); ++i) { for (size_t i = 0; i < maps.size(); ++i) {
if (!maps[i]->IsJSReceiverMap()) return true; MapRef map(broker, maps[i]);
if (!map.IsJSReceiverMap()) return true;
} }
return false; return false;
} }
...@@ -606,8 +608,10 @@ bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver, ...@@ -606,8 +608,10 @@ bool NodeProperties::CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
case IrOpcode::kToBoolean: case IrOpcode::kToBoolean:
return false; return false;
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
Handle<HeapObject> value = HeapObjectMatcher(receiver).Value(); HeapObjectRef value =
return value->IsNullOrUndefined(broker->isolate()); HeapObjectMatcher(receiver).Ref(broker).AsHeapObject();
OddballType type = value.map().oddball_type();
return type == OddballType::kNull || type == OddballType::kUndefined;
} }
default: default:
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment