Commit 95b09e3e authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Support named access on global proxy in serializer

Process feedback and hints for Lda/StaNamed bytecodes w.r.t. access on
the global proxy. This stores the property cells (or their absence) on
the JSGlobalProxyData.

Bug: v8:7790
Change-Id: Iadedea5494611c1b2ed38b6ce75687e084cc27f9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1499499
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60411}
parent 4f2586b9
...@@ -702,6 +702,9 @@ class MapData : public HeapObjectData { ...@@ -702,6 +702,9 @@ class MapData : public HeapObjectData {
bool supports_fast_array_resize() const { bool supports_fast_array_resize() const {
return supports_fast_array_resize_; return supports_fast_array_resize_;
} }
bool IsMapOfCurrentGlobalProxy() const {
return is_map_of_current_global_proxy_;
}
// Extra information. // Extra information.
...@@ -750,6 +753,7 @@ class MapData : public HeapObjectData { ...@@ -750,6 +753,7 @@ class MapData : public HeapObjectData {
int const unused_property_fields_; int const unused_property_fields_;
bool const supports_fast_array_iteration_; bool const supports_fast_array_iteration_;
bool const supports_fast_array_resize_; bool const supports_fast_array_resize_;
bool const is_map_of_current_global_proxy_;
bool serialized_elements_kind_generalizations_ = false; bool serialized_elements_kind_generalizations_ = false;
ZoneVector<MapData*> elements_kind_generalizations_; ZoneVector<MapData*> elements_kind_generalizations_;
...@@ -865,6 +869,8 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object) ...@@ -865,6 +869,8 @@ MapData::MapData(JSHeapBroker* broker, ObjectData** storage, Handle<Map> object)
SupportsFastArrayIteration(broker->isolate(), object)), SupportsFastArrayIteration(broker->isolate(), object)),
supports_fast_array_resize_( supports_fast_array_resize_(
SupportsFastArrayResize(broker->isolate(), object)), SupportsFastArrayResize(broker->isolate(), object)),
is_map_of_current_global_proxy_(
object->IsMapOfGlobalProxy(broker->isolate()->native_context())),
elements_kind_generalizations_(broker->zone()) {} elements_kind_generalizations_(broker->zone()) {}
JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage, JSFunctionData::JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
...@@ -1328,10 +1334,65 @@ void CellData::Serialize(JSHeapBroker* broker) { ...@@ -1328,10 +1334,65 @@ void CellData::Serialize(JSHeapBroker* broker) {
class JSGlobalProxyData : public JSObjectData { class JSGlobalProxyData : public JSObjectData {
public: public:
JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage, JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalProxy> object) Handle<JSGlobalProxy> object);
: JSObjectData(broker, storage, object) {}
PropertyCellData* GetPropertyCell(JSHeapBroker* broker, NameData* name,
bool serialize);
private:
// Properties that either
// (1) are known to exist as property cells on the global object, or
// (2) are known not to (possibly they don't exist at all).
// In case (2), the second pair component is nullptr.
ZoneVector<std::pair<NameData*, PropertyCellData*>> properties_;
}; };
JSGlobalProxyData::JSGlobalProxyData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSGlobalProxy> object)
: JSObjectData(broker, storage, object), properties_(broker->zone()) {}
base::Optional<PropertyCellRef> GetPropertyCellFromHeap(JSHeapBroker* broker,
Handle<Name> name) {
LookupIterator it(broker->isolate(),
handle(broker->native_context().object()->global_object(),
broker->isolate()),
name, LookupIterator::OWN);
it.TryLookupCachedProperty();
if (it.state() == LookupIterator::DATA &&
it.GetHolder<JSObject>()->IsJSGlobalObject()) {
return PropertyCellRef(broker, it.GetPropertyCell());
}
return base::nullopt;
}
PropertyCellData* JSGlobalProxyData::GetPropertyCell(JSHeapBroker* broker,
NameData* name,
bool serialize) {
CHECK_NOT_NULL(name);
for (auto const& p : properties_) {
if (p.first == name) return p.second;
}
if (!serialize) {
AllowHandleAllocation handle_allocation_;
AllowHandleDereference handle_dereference_;
AllowHeapAllocation heap_allocation_;
TRACE(broker, "GetPropertyCell: missing knowledge about global property "
<< Brief(*name->object()) << "\n");
return nullptr;
}
PropertyCellData* result = nullptr;
base::Optional<PropertyCellRef> cell =
GetPropertyCellFromHeap(broker, Handle<Name>::cast(name->object()));
if (cell.has_value()) {
cell->Serialize();
result = cell->data()->AsPropertyCell();
}
properties_.push_back({name, result});
return result;
}
class CodeData : public HeapObjectData { class CodeData : public HeapObjectData {
public: public:
CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object) CodeData(JSHeapBroker* broker, ObjectData** storage, Handle<Code> object)
...@@ -2019,6 +2080,15 @@ bool MapRef::supports_fast_array_resize() const { ...@@ -2019,6 +2080,15 @@ bool MapRef::supports_fast_array_resize() const {
return data()->AsMap()->supports_fast_array_resize(); return data()->AsMap()->supports_fast_array_resize();
} }
bool MapRef::IsMapOfCurrentGlobalProxy() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
AllowHandleAllocation handle_allocation;
return object()->IsMapOfGlobalProxy(broker()->isolate()->native_context());
}
return data()->AsMap()->IsMapOfCurrentGlobalProxy();
}
int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const { int JSFunctionRef::InitialMapInstanceSizeWithMinSlack() const {
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
...@@ -2875,6 +2945,18 @@ void PropertyCellRef::Serialize() { ...@@ -2875,6 +2945,18 @@ void PropertyCellRef::Serialize() {
data()->AsPropertyCell()->Serialize(broker()); data()->AsPropertyCell()->Serialize(broker());
} }
base::Optional<PropertyCellRef> JSGlobalProxyRef::GetPropertyCell(
NameRef const& name, bool serialize) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
return GetPropertyCellFromHeap(broker(), name.object());
}
PropertyCellData* property_cell_data =
data()->AsJSGlobalProxy()->GetPropertyCell(
broker(), name.data()->AsName(), serialize);
if (property_cell_data == nullptr) return base::nullopt;
return PropertyCellRef(broker(), property_cell_data);
}
bool CanInlineElementAccess(MapRef const& map) { bool CanInlineElementAccess(MapRef const& map) {
if (!map.IsJSObjectMap()) return false; if (!map.IsJSObjectMap()) return false;
if (map.is_access_check_needed()) return false; if (map.is_access_check_needed()) return false;
...@@ -2911,7 +2993,6 @@ PropertyCellRef GlobalAccessFeedback::property_cell() const { ...@@ -2911,7 +2993,6 @@ PropertyCellRef GlobalAccessFeedback::property_cell() const {
DCHECK(IsPropertyCell()); DCHECK(IsPropertyCell());
return cell_or_context_.AsPropertyCell(); return cell_or_context_.AsPropertyCell();
} }
ContextRef GlobalAccessFeedback::script_context() const { ContextRef GlobalAccessFeedback::script_context() const {
DCHECK(IsScriptContextSlot()); DCHECK(IsScriptContextSlot());
return cell_or_context_.AsContext(); return cell_or_context_.AsContext();
...@@ -2925,11 +3006,11 @@ bool GlobalAccessFeedback::immutable() const { ...@@ -2925,11 +3006,11 @@ bool GlobalAccessFeedback::immutable() const {
return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_); return FeedbackNexus::ImmutabilityBit::decode(index_and_immutable_);
} }
base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantValue() const { base::Optional<ObjectRef> GlobalAccessFeedback::GetConstantHint() const {
if (IsScriptContextSlot() && immutable()) { if (IsScriptContextSlot()) {
// Return the value of this global variable if it's guaranteed to be if (immutable()) return script_context().get(slot_index());
// constant. } else {
return script_context().get(slot_index()); return property_cell().value();
} }
return {}; return {};
} }
......
...@@ -132,6 +132,8 @@ class ObjectRef { ...@@ -132,6 +132,8 @@ class ObjectRef {
ObjectData* data_; // Should be used only by object() getters. ObjectData* data_; // Should be used only by object() getters.
private: private:
friend class JSGlobalProxyRef;
friend class JSGlobalProxyData;
JSHeapBroker* broker_; JSHeapBroker* broker_;
}; };
...@@ -448,6 +450,7 @@ class MapRef : public HeapObjectRef { ...@@ -448,6 +450,7 @@ class MapRef : public HeapObjectRef {
bool is_migration_target() const; bool is_migration_target() const;
bool supports_fast_array_iteration() const; bool supports_fast_array_iteration() const;
bool supports_fast_array_resize() const; bool supports_fast_array_resize() const;
bool IsMapOfCurrentGlobalProxy() const;
#define DEF_TESTER(Type, ...) bool Is##Type##Map() const; #define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
INSTANCE_TYPE_CHECKERS(DEF_TESTER) INSTANCE_TYPE_CHECKERS(DEF_TESTER)
...@@ -610,6 +613,16 @@ class JSGlobalProxyRef : public JSObjectRef { ...@@ -610,6 +613,16 @@ class JSGlobalProxyRef : public JSObjectRef {
public: public:
using JSObjectRef::JSObjectRef; using JSObjectRef::JSObjectRef;
Handle<JSGlobalProxy> object() const; Handle<JSGlobalProxy> object() const;
// If {serialize} is false:
// If the property is known to exist as a property cell (on the global
// object), return that property cell. Otherwise (not known to exist as a
// property cell or known not to exist as a property cell) return nothing.
// If {serialize} is true:
// Like above but potentially access the heap and serialize the necessary
// information.
base::Optional<PropertyCellRef> GetPropertyCell(NameRef const& name,
bool serialize = false) const;
}; };
class CodeRef : public HeapObjectRef { class CodeRef : public HeapObjectRef {
...@@ -653,7 +666,7 @@ class GlobalAccessFeedback : public ProcessedFeedback { ...@@ -653,7 +666,7 @@ class GlobalAccessFeedback : public ProcessedFeedback {
int slot_index() const; int slot_index() const;
bool immutable() const; bool immutable() const;
base::Optional<ObjectRef> GetConstantValue() const; base::Optional<ObjectRef> GetConstantHint() const;
private: private:
ObjectRef const cell_or_context_; ObjectRef const cell_or_context_;
......
...@@ -785,16 +785,12 @@ FieldAccess ForPropertyCellValue(MachineRepresentation representation, ...@@ -785,16 +785,12 @@ FieldAccess ForPropertyCellValue(MachineRepresentation representation,
Reduction JSNativeContextSpecialization::ReduceGlobalAccess( Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
Node* node, Node* receiver, Node* value, Handle<Name> name, Node* node, Node* receiver, Node* value, Handle<Name> name,
AccessMode access_mode, Node* index) { AccessMode access_mode, Node* index) {
// Lookup on the global object. We only deal with own data properties NameRef name_ref(broker(), name);
// of the global object here (represented as PropertyCell). base::Optional<PropertyCellRef> cell =
LookupIterator it(isolate(), global_object(), name, LookupIterator::OWN); native_context().global_proxy_object().GetPropertyCell(name_ref);
it.TryLookupCachedProperty(); return cell.has_value() ? ReduceGlobalAccess(node, receiver, value, name,
if (it.state() != LookupIterator::DATA) return NoChange(); access_mode, index, *cell)
if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange(); : NoChange();
PropertyCellRef property_cell(broker(), it.GetPropertyCell());
property_cell.Serialize();
return ReduceGlobalAccess(node, receiver, value, name, access_mode, index,
property_cell);
} }
Reduction JSNativeContextSpecialization::ReduceGlobalAccess( Reduction JSNativeContextSpecialization::ReduceGlobalAccess(
...@@ -1095,18 +1091,12 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess( ...@@ -1095,18 +1091,12 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// native contexts' global proxy, and turn that into a direct access // native contexts' global proxy, and turn that into a direct access
// to the current native contexts' global object instead. // to the current native contexts' global object instead.
if (receiver_maps.size() == 1) { if (receiver_maps.size() == 1) {
Handle<Map> receiver_map = receiver_maps.front(); MapRef receiver_map(broker(), receiver_maps.front());
if (receiver_map->IsJSGlobalProxyMap()) { if (receiver_map.IsMapOfCurrentGlobalProxy()) {
Object maybe_constructor = receiver_map->GetConstructor();
// Detached global proxies have |null| as their constructor.
if (maybe_constructor->IsJSFunction() &&
JSFunction::cast(maybe_constructor)->native_context() ==
*native_context().object()) {
return ReduceGlobalAccess(node, receiver, value, name, access_mode, return ReduceGlobalAccess(node, receiver, value, name, access_mode,
index); index);
} }
} }
}
// Compute property access infos for the receiver maps. // Compute property access infos for the receiver maps.
AccessInfoFactory access_info_factory(broker(), dependencies(), AccessInfoFactory access_info_factory(broker(), dependencies(),
...@@ -1358,7 +1348,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus( ...@@ -1358,7 +1348,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccessFromNexus(
// Check if we are accessing the current native contexts' global proxy. // Check if we are accessing the current native contexts' global proxy.
HeapObjectMatcher m(receiver); HeapObjectMatcher m(receiver);
if (m.HasValue() && m.Value().is_identical_to(global_proxy())) { if (m.HasValue() &&
m.Ref(broker()).equals(native_context().global_proxy_object())) {
// Optimize accesses to the current native contexts' global proxy. // Optimize accesses to the current native contexts' global proxy.
return ReduceGlobalAccess(node, nullptr, value, name, access_mode); return ReduceGlobalAccess(node, nullptr, value, name, access_mode);
} }
......
...@@ -705,7 +705,7 @@ void SerializerForBackgroundCompilation::VisitLdaGlobal( ...@@ -705,7 +705,7 @@ void SerializerForBackgroundCompilation::VisitLdaGlobal(
GlobalAccessFeedback const* feedback = ProcessFeedbackForGlobalAccess(slot); GlobalAccessFeedback const* feedback = ProcessFeedbackForGlobalAccess(slot);
if (feedback != nullptr) { if (feedback != nullptr) {
// We may be able to contribute to accumulator constant hints. // We may be able to contribute to accumulator constant hints.
base::Optional<ObjectRef> value = feedback->GetConstantValue(); base::Optional<ObjectRef> value = feedback->GetConstantHint();
if (value.has_value()) { if (value.has_value()) {
environment()->accumulator_hints().AddConstant(value->object()); environment()->accumulator_hints().AddConstant(value->object());
} }
...@@ -733,7 +733,22 @@ void SerializerForBackgroundCompilation::VisitStaGlobal( ...@@ -733,7 +733,22 @@ void SerializerForBackgroundCompilation::VisitStaGlobal(
ProcessFeedbackForGlobalAccess(slot); ProcessFeedbackForGlobalAccess(slot);
} }
// Note: We never use the same feeedback slot for multiple access modes. namespace {
template <class MapContainer>
MapHandles GetRelevantReceiverMaps(Isolate* isolate, MapContainer const& maps) {
MapHandles result;
for (Handle<Map> map : maps) {
if (Map::TryUpdate(isolate, map).ToHandle(&map) &&
!map->is_abandoned_prototype_map()) {
DCHECK(!map->is_deprecated());
result.push_back(map);
}
}
return result;
}
} // namespace
// Note: We never use the same feedback slot for multiple access modes.
void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
FeedbackSlot slot, AccessMode mode) { FeedbackSlot slot, AccessMode mode) {
if (slot.IsInvalid()) return; if (slot.IsInvalid()) return;
...@@ -743,8 +758,6 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -743,8 +758,6 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
FeedbackSource source(nexus); FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return; if (broker()->HasFeedback(source)) return;
if (nexus.ic_state() == MEGAMORPHIC) return;
if (nexus.GetKeyType() == PROPERTY) { if (nexus.GetKeyType() == PROPERTY) {
CHECK_NE(mode, AccessMode::kStoreInLiteral); CHECK_NE(mode, AccessMode::kStoreInLiteral);
return; // TODO(neis): Support named access. return; // TODO(neis): Support named access.
...@@ -755,7 +768,8 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -755,7 +768,8 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
MapHandles maps; MapHandles maps;
nexus.ExtractMaps(&maps); nexus.ExtractMaps(&maps);
ElementAccessFeedback const* processed = ElementAccessFeedback const* processed =
broker()->ProcessFeedbackMapsForElementAccess(maps); broker()->ProcessFeedbackMapsForElementAccess(
GetRelevantReceiverMaps(broker()->isolate(), maps));
broker()->SetFeedback(source, processed); broker()->SetFeedback(source, processed);
if (processed == nullptr) return; if (processed == nullptr) return;
...@@ -776,6 +790,36 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess( ...@@ -776,6 +790,36 @@ void SerializerForBackgroundCompilation::ProcessFeedbackForKeyedPropertyAccess(
} }
} }
void SerializerForBackgroundCompilation::ProcessMapForNamedPropertyAccess(
MapRef const& map, NameRef const& name) {
// For JSNativeContextSpecialization::ReduceNamedAccess.
if (map.IsMapOfCurrentGlobalProxy()) {
broker()->native_context().global_proxy_object().GetPropertyCell(name,
true);
}
}
// Note: We never use the same feedback slot for multiple names.
void SerializerForBackgroundCompilation::ProcessFeedbackForNamedPropertyAccess(
FeedbackSlot slot, NameRef const& name) {
if (slot.IsInvalid()) return;
if (environment()->function().feedback_vector.is_null()) return;
FeedbackNexus nexus(environment()->function().feedback_vector, slot);
FeedbackSource source(nexus);
if (broker()->HasFeedback(source)) return;
MapHandles maps;
nexus.ExtractMaps(&maps);
for (Handle<Map> map : GetRelevantReceiverMaps(broker()->isolate(), maps)) {
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), name);
}
// NamedProperty support is still WIP. For now we don't have any actual data
// to store, so use nullptr to at least record that we processed the feedback.
broker()->SetFeedback(source, nullptr);
}
void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
BytecodeArrayIterator* iterator) { BytecodeArrayIterator* iterator) {
FeedbackSlot slot = iterator->GetSlotOperand(1); FeedbackSlot slot = iterator->GetSlotOperand(1);
...@@ -783,6 +827,42 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty( ...@@ -783,6 +827,42 @@ void SerializerForBackgroundCompilation::VisitLdaKeyedProperty(
environment()->accumulator_hints().Clear(); environment()->accumulator_hints().Clear();
} }
void SerializerForBackgroundCompilation::ProcessNamedPropertyAccess(
Hints const& receiver, NameRef const& name, FeedbackSlot slot) {
if (!slot.IsInvalid()) ProcessFeedbackForNamedPropertyAccess(slot, name);
for (Handle<Map> map :
GetRelevantReceiverMaps(broker()->isolate(), receiver.maps())) {
ProcessMapForNamedPropertyAccess(MapRef(broker(), map), name);
}
JSGlobalProxyRef global_proxy =
broker()->native_context().global_proxy_object();
for (Handle<Object> object : receiver.constants()) {
// For JSNativeContextSpecialization::ReduceNamedAccessFromNexus.
if (object.equals(global_proxy.object())) {
global_proxy.GetPropertyCell(name, true);
}
}
environment()->accumulator_hints().Clear();
}
void SerializerForBackgroundCompilation::VisitLdaNamedProperty(
BytecodeArrayIterator* iterator) {
Hints const& receiver =
environment()->register_hints(iterator->GetRegisterOperand(0));
Handle<Name> name(Name::cast(iterator->GetConstantForIndexOperand(1)),
broker()->isolate());
FeedbackSlot slot = iterator->GetSlotOperand(2);
ProcessNamedPropertyAccess(receiver, NameRef(broker(), name), slot);
}
void SerializerForBackgroundCompilation::VisitStaNamedProperty(
BytecodeArrayIterator* iterator) {
VisitLdaNamedProperty(iterator);
}
void SerializerForBackgroundCompilation::VisitTestIn( void SerializerForBackgroundCompilation::VisitTestIn(
BytecodeArrayIterator* iterator) { BytecodeArrayIterator* iterator) {
FeedbackSlot slot = iterator->GetSlotOperand(1); FeedbackSlot slot = iterator->GetSlotOperand(1);
...@@ -798,8 +878,8 @@ void SerializerForBackgroundCompilation::VisitStaKeyedProperty( ...@@ -798,8 +878,8 @@ void SerializerForBackgroundCompilation::VisitStaKeyedProperty(
ProcessFeedbackForKeyedPropertyAccess(slot, AccessMode::kStore); ProcessFeedbackForKeyedPropertyAccess(slot, AccessMode::kStore);
// Process hints about constants.
for (Handle<Object> object : receiver.constants()) { for (Handle<Object> object : receiver.constants()) {
// For JSNativeContextSpecialization::ReduceElementAccess.
if (object->IsJSTypedArray()) JSTypedArrayRef(broker(), object).Serialize(); if (object->IsJSTypedArray()) JSTypedArrayRef(broker(), object).Serialize();
} }
......
...@@ -56,9 +56,7 @@ namespace compiler { ...@@ -56,9 +56,7 @@ namespace compiler {
V(LdaContextSlot) \ V(LdaContextSlot) \
V(LdaCurrentContextSlot) \ V(LdaCurrentContextSlot) \
V(LdaImmutableContextSlot) \ V(LdaImmutableContextSlot) \
V(LdaImmutableCurrentContextSlot) \ V(LdaImmutableCurrentContextSlot)
V(LdaNamedProperty) \
V(LdaNamedPropertyNoFeedback)
#define UNCONDITIONAL_JUMPS_LIST(V) \ #define UNCONDITIONAL_JUMPS_LIST(V) \
V(Jump) \ V(Jump) \
...@@ -86,6 +84,8 @@ namespace compiler { ...@@ -86,6 +84,8 @@ namespace compiler {
V(JumpIfUndefinedConstant) V(JumpIfUndefinedConstant)
#define INGORED_BYTECODE_LIST(V) \ #define INGORED_BYTECODE_LIST(V) \
V(LdaNamedPropertyNoFeedback) \
V(StaNamedPropertyNoFeedback) \
V(TestEqual) \ V(TestEqual) \
V(TestEqualStrict) \ V(TestEqualStrict) \
V(TestLessThan) \ V(TestLessThan) \
...@@ -125,6 +125,7 @@ namespace compiler { ...@@ -125,6 +125,7 @@ namespace compiler {
V(LdaKeyedProperty) \ V(LdaKeyedProperty) \
V(LdaLookupGlobalSlot) \ V(LdaLookupGlobalSlot) \
V(LdaLookupGlobalSlotInsideTypeof) \ V(LdaLookupGlobalSlotInsideTypeof) \
V(LdaNamedProperty) \
V(LdaNull) \ V(LdaNull) \
V(Ldar) \ V(Ldar) \
V(LdaSmi) \ V(LdaSmi) \
...@@ -136,6 +137,7 @@ namespace compiler { ...@@ -136,6 +137,7 @@ namespace compiler {
V(StaGlobal) \ V(StaGlobal) \
V(StaInArrayLiteral) \ V(StaInArrayLiteral) \
V(StaKeyedProperty) \ V(StaKeyedProperty) \
V(StaNamedProperty) \
V(Star) \ V(Star) \
V(TestIn) \ V(TestIn) \
V(Wide) \ V(Wide) \
...@@ -243,6 +245,8 @@ class SerializerForBackgroundCompilation { ...@@ -243,6 +245,8 @@ class SerializerForBackgroundCompilation {
bool with_spread = false); bool with_spread = false);
void ProcessJump(interpreter::BytecodeArrayIterator* iterator); void ProcessJump(interpreter::BytecodeArrayIterator* iterator);
void MergeAfterJump(interpreter::BytecodeArrayIterator* iterator); void MergeAfterJump(interpreter::BytecodeArrayIterator* iterator);
void ProcessNamedPropertyAccess(Hints const& receiver, NameRef const& name,
FeedbackSlot slot);
Hints RunChildSerializer(CompilationSubject function, Hints RunChildSerializer(CompilationSubject function,
base::Optional<Hints> new_target, base::Optional<Hints> new_target,
...@@ -251,6 +255,9 @@ class SerializerForBackgroundCompilation { ...@@ -251,6 +255,9 @@ class SerializerForBackgroundCompilation {
GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot); GlobalAccessFeedback const* ProcessFeedbackForGlobalAccess(FeedbackSlot slot);
void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot, void ProcessFeedbackForKeyedPropertyAccess(FeedbackSlot slot,
AccessMode mode); AccessMode mode);
void ProcessFeedbackForNamedPropertyAccess(FeedbackSlot slot,
NameRef const& name);
void ProcessMapForNamedPropertyAccess(MapRef const& map, NameRef const& name);
JSHeapBroker* broker() const { return broker_; } JSHeapBroker* broker() const { return broker_; }
Zone* zone() const { return zone_; } Zone* zone() const { return zone_; }
......
...@@ -56,6 +56,18 @@ MaybeHandle<JSFunction> Map::GetConstructorFunction( ...@@ -56,6 +56,18 @@ MaybeHandle<JSFunction> Map::GetConstructorFunction(
return MaybeHandle<JSFunction>(); return MaybeHandle<JSFunction>();
} }
bool Map::IsMapOfGlobalProxy(Handle<NativeContext> native_context) const {
DisallowHeapAllocation no_gc;
if (IsJSGlobalProxyMap()) {
Object maybe_constructor = GetConstructor();
// Detached global proxies have |null| as their constructor.
return maybe_constructor.IsJSFunction() &&
JSFunction::cast(maybe_constructor).native_context() ==
*native_context;
}
return false;
}
void Map::PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index, void Map::PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index,
PropertyKind kind, PropertyKind kind,
PropertyAttributes attributes) { PropertyAttributes attributes) {
......
...@@ -895,6 +895,9 @@ class Map : public HeapObject { ...@@ -895,6 +895,9 @@ class Map : public HeapObject {
InstanceType instance_type); InstanceType instance_type);
inline bool CanHaveFastTransitionableElementsKind() const; inline bool CanHaveFastTransitionableElementsKind() const;
// Whether this is the map of the given native context's global proxy.
bool IsMapOfGlobalProxy(Handle<NativeContext> native_context) const;
private: private:
// This byte encodes either the instance size without the in-object slack or // This byte encodes either the instance size without the in-object slack or
// the slack size in properties backing store. // the slack size in properties backing store.
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// Flags: --allow-natives-syntax
function Foo(a, b) { function Foo(a, b) {
var bname = "b"; var bname = "b";
this["a"] = a; this["a"] = a;
...@@ -29,3 +31,29 @@ for (var i = 0; i < 6; i++) { ...@@ -29,3 +31,29 @@ for (var i = 0; i < 6; i++) {
var f = new Foo(i + "", (i + 2) + ""); var f = new Foo(i + "", (i + 2) + "");
assertEquals((i + "") + ((i + 2) + ""), f.x); assertEquals((i + "") + ((i + 2) + ""), f.x);
} }
{
function Global(i) { this.bla = i }
Global(0);
Global(1);
%OptimizeFunctionOnNextCall(Global);
Global(2);
assertEquals(bla, 2);
}
{
function access(obj) { obj.bla = 42 }
access({a: 0});
access({b: 0});
access({c: 0});
access({d: 0});
access({e: 0});
var global = this;
function foo() { access(global) };
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
foo();
}
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