Index: src/compiler/access-info.cc |
diff --git a/src/compiler/property-access-info.cc b/src/compiler/access-info.cc |
similarity index 80% |
rename from src/compiler/property-access-info.cc |
rename to src/compiler/access-info.cc |
index 930098ac8c305733841a02008c6afceb1f80e5e0..1603804d8e8f1d65d001f1839524dcfcd3ef90ea 100644 |
--- a/src/compiler/property-access-info.cc |
+++ b/src/compiler/access-info.cc |
@@ -6,7 +6,7 @@ |
#include "src/accessors.h" |
#include "src/compilation-dependencies.h" |
-#include "src/compiler/property-access-info.h" |
+#include "src/compiler/access-info.h" |
#include "src/field-index-inl.h" |
#include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
#include "src/type-cache.h" |
@@ -16,11 +16,35 @@ namespace v8 { |
namespace internal { |
namespace compiler { |
-std::ostream& operator<<(std::ostream& os, PropertyAccessMode access_mode) { |
+namespace { |
+ |
+bool CanInlineElementAccess(Handle<Map> map) { |
+ // TODO(bmeurer): IsJSObjectMap |
+ // TODO(bmeurer): !map->has_dictionary_elements() |
+ // TODO(bmeurer): !map->has_sloppy_arguments_elements() |
+ return map->IsJSArrayMap() && map->has_fast_elements() && |
+ !map->has_indexed_interceptor() && !map->is_access_check_needed(); |
+} |
+ |
+ |
+bool CanInlinePropertyAccess(Handle<Map> map) { |
+ // TODO(bmeurer): Add support for Number primitives. |
+ // if (map->instance_type() == HEAP_NUMBER_TYPE) return false; |
+ if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
+ return map->IsJSObjectMap() && !map->is_dictionary_map() && |
+ !map->has_named_interceptor() && |
+ // TODO(verwaest): Whitelist contexts to which we have access. |
+ !map->is_access_check_needed(); |
+} |
+ |
+} // namespace |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, AccessMode access_mode) { |
switch (access_mode) { |
- case PropertyAccessMode::kLoad: |
+ case AccessMode::kLoad: |
return os << "Load"; |
- case PropertyAccessMode::kStore: |
+ case AccessMode::kStore: |
return os << "Store"; |
} |
UNREACHABLE(); |
@@ -52,6 +76,9 @@ PropertyAccessInfo PropertyAccessInfo::DataField( |
} |
+ElementAccessInfo::ElementAccessInfo() : receiver_type_(Type::None()) {} |
+ |
+ |
PropertyAccessInfo::PropertyAccessInfo() |
: kind_(kInvalid), receiver_type_(Type::None()), field_type_(Type::Any()) {} |
@@ -86,9 +113,8 @@ PropertyAccessInfo::PropertyAccessInfo(MaybeHandle<JSObject> holder, |
field_type_(field_type) {} |
-PropertyAccessInfoFactory::PropertyAccessInfoFactory( |
- CompilationDependencies* dependencies, Handle<Context> native_context, |
- Zone* zone) |
+AccessInfoFactory::AccessInfoFactory(CompilationDependencies* dependencies, |
+ Handle<Context> native_context, Zone* zone) |
: dependencies_(dependencies), |
native_context_(native_context), |
isolate_(native_context->GetIsolate()), |
@@ -96,23 +122,52 @@ PropertyAccessInfoFactory::PropertyAccessInfoFactory( |
zone_(zone) {} |
-namespace { |
+bool AccessInfoFactory::ComputeElementAccessInfo( |
+ Handle<Map> map, AccessMode access_mode, ElementAccessInfo* access_info) { |
+ // Check if it is safe to inline element access for the {map}. |
+ if (!CanInlineElementAccess(map)) return false; |
-bool CanInlinePropertyAccess(Handle<Map> map) { |
- // TODO(bmeurer): Do something about the number stuff. |
- if (map->instance_type() == HEAP_NUMBER_TYPE) return false; |
- if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
- return map->IsJSObjectMap() && !map->is_dictionary_map() && |
- !map->has_named_interceptor() && |
- // TODO(verwaest): Whitelist contexts to which we have access. |
- !map->is_access_check_needed(); |
+ // TODO(bmeurer): Add support for holey elements. |
+ ElementsKind elements_kind = map->elements_kind(); |
+ if (IsHoleyElementsKind(elements_kind)) return false; |
+ |
+ // Certain (monomorphic) stores need a prototype chain check because shape |
+ // changes could allow callbacks on elements in the chain that are not |
+ // compatible with monomorphic keyed stores. |
+ MaybeHandle<JSObject> holder; |
+ if (access_mode == AccessMode::kStore && map->prototype()->IsJSObject()) { |
+ for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) { |
+ Handle<JSReceiver> prototype = |
+ PrototypeIterator::GetCurrent<JSReceiver>(i); |
+ if (!prototype->IsJSObject()) return false; |
+ holder = Handle<JSObject>::cast(prototype); |
+ } |
+ } |
+ |
+ *access_info = |
+ ElementAccessInfo(Type::Class(map, zone()), elements_kind, holder); |
+ return true; |
} |
-} // namespace |
+ |
+bool AccessInfoFactory::ComputeElementAccessInfos( |
+ MapHandleList const& maps, AccessMode access_mode, |
+ ZoneVector<ElementAccessInfo>* access_infos) { |
+ for (Handle<Map> map : maps) { |
+ if (Map::TryUpdate(map).ToHandle(&map)) { |
+ ElementAccessInfo access_info; |
+ if (!ComputeElementAccessInfo(map, access_mode, &access_info)) { |
+ return false; |
+ } |
+ access_infos->push_back(access_info); |
+ } |
+ } |
+ return true; |
+} |
-bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
- Handle<Map> map, Handle<Name> name, PropertyAccessMode access_mode, |
+bool AccessInfoFactory::ComputePropertyAccessInfo( |
+ Handle<Map> map, Handle<Name> name, AccessMode access_mode, |
PropertyAccessInfo* access_info) { |
// Check if it is safe to inline property access for the {map}. |
if (!CanInlinePropertyAccess(map)) return false; |
@@ -121,7 +176,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
Handle<Map> receiver_map = map; |
// We support fast inline cases for certain JSObject getters. |
- if (access_mode == PropertyAccessMode::kLoad && |
+ if (access_mode == AccessMode::kLoad && |
LookupSpecialFieldAccessor(map, name, access_info)) { |
return true; |
} |
@@ -133,7 +188,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
int const number = descriptors->SearchWithCache(*name, *map); |
if (number != DescriptorArray::kNotFound) { |
PropertyDetails const details = descriptors->GetDetails(number); |
- if (access_mode == PropertyAccessMode::kStore) { |
+ if (access_mode == AccessMode::kStore) { |
// Don't bother optimizing stores to read-only properties. |
if (details.IsReadOnly()) { |
return false; |
@@ -170,7 +225,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
Type::TaggedPointer(), zone()); |
if (field_type->Is(Type::None())) { |
// Store is not safe if the field type was cleared. |
- if (access_mode == PropertyAccessMode::kStore) return false; |
+ if (access_mode == AccessMode::kStore) return false; |
// The field type was cleared by the GC, so we don't know anything |
// about the contents now. |
@@ -216,7 +271,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
// Store to property not found on the receiver or any prototype, we need |
// to transition to a new data property. |
// Implemented according to ES6 section 9.1.9 [[Set]] (P, V, Receiver) |
- if (access_mode == PropertyAccessMode::kStore) { |
+ if (access_mode == AccessMode::kStore) { |
return LookupTransition(receiver_map, name, holder, access_info); |
} |
// The property was not found, return undefined or throw depending |
@@ -242,9 +297,8 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfo( |
} |
-bool PropertyAccessInfoFactory::ComputePropertyAccessInfos( |
- MapHandleList const& maps, Handle<Name> name, |
- PropertyAccessMode access_mode, |
+bool AccessInfoFactory::ComputePropertyAccessInfos( |
+ MapHandleList const& maps, Handle<Name> name, AccessMode access_mode, |
ZoneVector<PropertyAccessInfo>* access_infos) { |
for (Handle<Map> map : maps) { |
if (Map::TryUpdate(map).ToHandle(&map)) { |
@@ -259,7 +313,7 @@ bool PropertyAccessInfoFactory::ComputePropertyAccessInfos( |
} |
-bool PropertyAccessInfoFactory::LookupSpecialFieldAccessor( |
+bool AccessInfoFactory::LookupSpecialFieldAccessor( |
Handle<Map> map, Handle<Name> name, PropertyAccessInfo* access_info) { |
// Check for special JSObject field accessors. |
int offset; |
@@ -294,9 +348,9 @@ bool PropertyAccessInfoFactory::LookupSpecialFieldAccessor( |
} |
-bool PropertyAccessInfoFactory::LookupTransition( |
- Handle<Map> map, Handle<Name> name, MaybeHandle<JSObject> holder, |
- PropertyAccessInfo* access_info) { |
+bool AccessInfoFactory::LookupTransition(Handle<Map> map, Handle<Name> name, |
+ MaybeHandle<JSObject> holder, |
+ PropertyAccessInfo* access_info) { |
// Check if the {map} has a data transition with the given {name}. |
if (map->unused_property_fields() == 0) return false; |
Handle<Map> transition_map; |
@@ -349,9 +403,7 @@ bool PropertyAccessInfoFactory::LookupTransition( |
} |
-Factory* PropertyAccessInfoFactory::factory() const { |
- return isolate()->factory(); |
-} |
+Factory* AccessInfoFactory::factory() const { return isolate()->factory(); } |
} // namespace compiler |
} // namespace internal |