Commit 86002099 authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Brokerize typed-array element access.

Bug: v8:7790
Change-Id: Ice64279a94b4f25151c1b35da1f3c9c1117d3c80
Reviewed-on: https://chromium-review.googlesource.com/c/1270584
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56600}
parent e7a33bd7
......@@ -11,6 +11,7 @@
#include "src/compiler/graph-reducer.h"
#include "src/compiler/per-isolate-compiler-cache.h"
#include "src/objects-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-regexp-inl.h"
#include "src/objects/module-inl.h"
......@@ -227,6 +228,49 @@ void JSObjectData::SerializeObjectCreateMap(JSHeapBroker* broker) {
}
}
class JSTypedArrayData : public JSObjectData {
public:
JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSTypedArray> object);
bool is_on_heap() const { return is_on_heap_; }
size_t length_value() const { return length_value_; }
void* elements_external_pointer() const { return elements_external_pointer_; }
void Serialize(JSHeapBroker* broker);
HeapObjectData* buffer() const { return buffer_; }
private:
bool const is_on_heap_;
size_t const length_value_;
void* const elements_external_pointer_;
bool serialized_ = false;
HeapObjectData* buffer_ = nullptr;
};
JSTypedArrayData::JSTypedArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSTypedArray> object)
: JSObjectData(broker, storage, object),
is_on_heap_(object->is_on_heap()),
length_value_(object->length_value()),
elements_external_pointer_(
FixedTypedArrayBase::cast(object->elements())->external_pointer()) {}
void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
if (serialized_) return;
serialized_ = true;
TraceScope tracer(broker, this, "JSTypedArrayData::Serialize");
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(object());
if (!is_on_heap()) {
DCHECK_NULL(buffer_);
buffer_ = broker->GetOrCreateData(typed_array->buffer())->AsHeapObject();
}
}
class JSFunctionData : public JSObjectData {
public:
JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
......@@ -1652,6 +1696,13 @@ base::Optional<MapRef> JSObjectRef::GetObjectCreateMap() const {
: base::Optional<MapRef>();
}
#define DEF_TESTER(Type, ...) \
bool MapRef::Is##Type##Map() const { \
return InstanceTypeChecker::Is##Type(instance_type()); \
}
INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER
base::Optional<MapRef> MapRef::AsElementsKind(ElementsKind kind) const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleAllocation handle_allocation;
......@@ -1985,6 +2036,10 @@ BIMODAL_ACCESSOR(JSFunction, Map, initial_map)
BIMODAL_ACCESSOR(JSFunction, Object, prototype)
BIMODAL_ACCESSOR(JSFunction, SharedFunctionInfo, shared)
BIMODAL_ACCESSOR_C(JSTypedArray, bool, is_on_heap)
BIMODAL_ACCESSOR_C(JSTypedArray, size_t, length_value)
BIMODAL_ACCESSOR(JSTypedArray, HeapObject, buffer)
BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::ElementsKindBits)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::IsDeprecatedBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_dictionary_map, Map::IsDictionaryMapBit)
......@@ -2016,6 +2071,15 @@ BROKER_SFI_FIELDS(DEF_SFI_ACCESSOR)
BIMODAL_ACCESSOR_C(String, int, length)
void* JSTypedArrayRef::elements_external_pointer() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
return FixedTypedArrayBase::cast(object<JSTypedArray>()->elements())
->external_pointer();
}
return data()->AsJSTypedArray()->elements_external_pointer();
}
bool MapRef::IsInobjectSlackTrackingInProgress() const {
IF_BROKER_DISABLED_ACCESS_HANDLE_C(Map, IsInobjectSlackTrackingInProgress);
return Map::ConstructionCounterBits::decode(data()->AsMap()->bit_field3()) !=
......@@ -2391,6 +2455,12 @@ void NativeContextRef::Serialize() {
data()->AsNativeContext()->Serialize(broker());
}
void JSTypedArrayRef::Serialize() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSTypedArray()->Serialize(broker());
}
#undef BIMODAL_ACCESSOR
#undef BIMODAL_ACCESSOR_B
#undef BIMODAL_ACCESSOR_C
......
......@@ -35,6 +35,7 @@ enum class OddballType : uint8_t {
V(JSFunction) \
V(JSGlobalProxy) \
V(JSRegExp) \
V(JSTypedArray) \
/* Subtypes of Context */ \
V(NativeContext) \
/* Subtypes of FixedArray */ \
......@@ -358,6 +359,10 @@ class MapRef : public HeapObjectRef {
bool is_undetectable() const;
bool is_callable() const;
#define DEF_TESTER(Type, ...) bool Is##Type##Map() const;
INSTANCE_TYPE_CHECKERS(DEF_TESTER)
#undef DEF_TESTER
ObjectRef constructor_or_backpointer() const;
void SerializePrototype();
......@@ -456,6 +461,19 @@ class StringRef : public NameRef {
bool IsExternalString() const;
};
class JSTypedArrayRef : public JSObjectRef {
public:
using JSObjectRef::JSObjectRef;
bool is_on_heap() const;
size_t length_value() const;
void* elements_external_pointer() const;
void Serialize();
HeapObjectRef buffer() const;
};
class ModuleRef : public HeapObjectRef {
public:
using HeapObjectRef::HeapObjectRef;
......
......@@ -39,16 +39,18 @@ namespace compiler {
namespace {
bool HasNumberMaps(MapHandles const& maps) {
bool HasNumberMaps(JSHeapBroker* broker, MapHandles const& maps) {
for (auto map : maps) {
if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
MapRef map_ref(broker, map);
if (map_ref.IsHeapNumberMap()) return true;
}
return false;
}
bool HasOnlyJSArrayMaps(MapHandles const& maps) {
bool HasOnlyJSArrayMaps(JSHeapBroker* broker, MapHandles const& maps) {
for (auto map : maps) {
if (!map->IsJSArrayMap()) return false;
MapRef map_ref(broker, map);
if (!map_ref.IsJSArrayMap()) return false;
}
return true;
}
......@@ -1079,7 +1081,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
&receiver, &effect, control) &&
!access_builder.TryBuildNumberCheck(access_info.receiver_maps(),
&receiver, &effect, control)) {
if (HasNumberMaps(access_info.receiver_maps())) {
if (HasNumberMaps(js_heap_broker(), access_info.receiver_maps())) {
// We need to also let Smi {receiver}s through in this case, so
// we construct a diamond, guarded by the Sminess of the {receiver}
// and if {receiver} is not a Smi just emit a sequence of map checks.
......@@ -1124,7 +1126,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
// Check if {receiver} may be a number.
bool receiverissmi_possible = false;
for (PropertyAccessInfo const& access_info : access_infos) {
if (HasNumberMaps(access_info.receiver_maps())) {
if (HasNumberMaps(js_heap_broker(), access_info.receiver_maps())) {
receiverissmi_possible = true;
break;
}
......@@ -1188,7 +1190,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
}
// The Number case requires special treatment to also deal with Smis.
if (HasNumberMaps(receiver_maps)) {
if (HasNumberMaps(js_heap_broker(), receiver_maps)) {
// Join this check with the "receiver is smi" check above.
DCHECK_NOT_NULL(receiverissmi_effect);
DCHECK_NOT_NULL(receiverissmi_control);
......@@ -2441,12 +2443,14 @@ ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
UNREACHABLE();
}
MaybeHandle<JSTypedArray> GetTypedArrayConstant(Node* receiver) {
base::Optional<JSTypedArrayRef> GetTypedArrayConstant(JSHeapBroker* broker,
Node* receiver) {
HeapObjectMatcher m(receiver);
if (!m.HasValue()) return MaybeHandle<JSTypedArray>();
if (!m.Value()->IsJSTypedArray()) return MaybeHandle<JSTypedArray>();
Handle<JSTypedArray> typed_array = Handle<JSTypedArray>::cast(m.Value());
if (typed_array->is_on_heap()) return MaybeHandle<JSTypedArray>();
if (!m.HasValue()) return base::nullopt;
ObjectRef object = m.Ref(broker);
if (!object.IsJSTypedArray()) return base::nullopt;
JSTypedArrayRef typed_array = object.AsJSTypedArray();
if (typed_array.is_on_heap()) return base::nullopt;
return typed_array;
}
......@@ -2471,9 +2475,11 @@ JSNativeContextSpecialization::BuildElementAccess(
// Check if we can constant-fold information about the {receiver} (i.e.
// for asm.js-like code patterns).
Handle<JSTypedArray> typed_array;
if (GetTypedArrayConstant(receiver).ToHandle(&typed_array)) {
buffer = jsgraph()->HeapConstant(typed_array->GetBuffer());
base::Optional<JSTypedArrayRef> typed_array =
GetTypedArrayConstant(js_heap_broker(), receiver);
if (typed_array.has_value()) {
typed_array->Serialize();
buffer = jsgraph()->Constant(typed_array->buffer());
length =
jsgraph()->Constant(static_cast<double>(typed_array->length_value()));
......@@ -2481,9 +2487,8 @@ JSNativeContextSpecialization::BuildElementAccess(
// {external_pointer} might be invalid if the {buffer} was neutered, so
// we need to make sure that any access is properly guarded.
base_pointer = jsgraph()->ZeroConstant();
external_pointer = jsgraph()->PointerConstant(
FixedTypedArrayBase::cast(typed_array->elements())
->external_pointer());
external_pointer =
jsgraph()->PointerConstant(typed_array->elements_external_pointer());
} else {
// Load the {receiver}s length.
length = effect = graph()->NewNode(
......@@ -2681,7 +2686,8 @@ JSNativeContextSpecialization::BuildElementAccess(
}
// Check if the {receiver} is a JSArray.
bool receiver_is_jsarray = HasOnlyJSArrayMaps(receiver_maps);
bool receiver_is_jsarray =
HasOnlyJSArrayMaps(js_heap_broker(), receiver_maps);
// Load the length of the {receiver}.
Node* length = effect =
......
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