summaryrefslogtreecommitdiffstats
path: root/js/src/jit/TypedObjectPrediction.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jit/TypedObjectPrediction.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jit/TypedObjectPrediction.cpp')
-rw-r--r--js/src/jit/TypedObjectPrediction.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/js/src/jit/TypedObjectPrediction.cpp b/js/src/jit/TypedObjectPrediction.cpp
new file mode 100644
index 000000000..c01ad5eda
--- /dev/null
+++ b/js/src/jit/TypedObjectPrediction.cpp
@@ -0,0 +1,308 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/TypedObjectPrediction.h"
+
+using namespace js;
+using namespace jit;
+
+static const size_t ALL_FIELDS = SIZE_MAX;
+
+// Sets the prediction to be the common prefix of descrA and descrB,
+// considering at most the first max fields.
+//
+// In the case where the current prediction is a specific struct,
+// and we are now seeing a second struct, then descrA and descrB will be
+// the current and new struct and max will be ALL_FIELDS.
+//
+// In the case where the current prediction is already a prefix, and
+// we are now seeing an additional struct, then descrA will be the
+// current struct and max will be the current prefix length, and
+// descrB will be the new struct.
+//
+// (Note that in general it is not important which struct is passed as
+// descrA and which struct is passed as descrB, as the operation is
+// symmetric.)
+void
+TypedObjectPrediction::markAsCommonPrefix(const StructTypeDescr& descrA,
+ const StructTypeDescr& descrB,
+ size_t max)
+{
+ // count is the number of fields in common. It begins as the min
+ // of the number of fields from descrA, descrB, and max, and then
+ // is decremented as we find uncommon fields.
+ if (max > descrA.fieldCount())
+ max = descrA.fieldCount();
+ if (max > descrB.fieldCount())
+ max = descrB.fieldCount();
+
+ size_t i = 0;
+ for (; i < max; i++) {
+ if (&descrA.fieldName(i) != &descrB.fieldName(i))
+ break;
+ if (&descrA.fieldDescr(i) != &descrB.fieldDescr(i))
+ break;
+ MOZ_ASSERT(descrA.fieldOffset(i) == descrB.fieldOffset(i));
+ }
+
+ if (i == 0) {
+ // empty prefix is not particularly useful.
+ markInconsistent();
+ } else {
+ setPrefix(descrA, i);
+ }
+}
+
+void
+TypedObjectPrediction::addDescr(const TypeDescr& descr)
+{
+ switch (predictionKind()) {
+ case Empty:
+ return setDescr(descr);
+
+ case Inconsistent:
+ return; // keep same state
+
+ case Descr: {
+ if (&descr == data_.descr)
+ return; // keep same state
+
+ if (descr.kind() != data_.descr->kind())
+ return markInconsistent();
+
+ if (descr.kind() != type::Struct)
+ return markInconsistent();
+
+ const StructTypeDescr& structDescr = descr.as<StructTypeDescr>();
+ const StructTypeDescr& currentDescr = data_.descr->as<StructTypeDescr>();
+ markAsCommonPrefix(structDescr, currentDescr, ALL_FIELDS);
+ return;
+ }
+
+ case Prefix:
+ if (descr.kind() != type::Struct)
+ return markInconsistent();
+
+ markAsCommonPrefix(*data_.prefix.descr,
+ descr.as<StructTypeDescr>(),
+ data_.prefix.fields);
+ return;
+ }
+
+ MOZ_CRASH("Bad predictionKind");
+}
+
+type::Kind
+TypedObjectPrediction::kind() const
+{
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ break;
+
+ case TypedObjectPrediction::Descr:
+ return descr().kind();
+
+ case TypedObjectPrediction::Prefix:
+ return prefix().descr->kind();
+ }
+
+ MOZ_CRASH("Bad prediction kind");
+}
+
+bool
+TypedObjectPrediction::ofArrayKind() const
+{
+ switch (kind()) {
+ case type::Scalar:
+ case type::Reference:
+ case type::Simd:
+ case type::Struct:
+ return false;
+
+ case type::Array:
+ return true;
+ }
+
+ MOZ_CRASH("Bad kind");
+}
+
+bool
+TypedObjectPrediction::hasKnownSize(uint32_t* out) const
+{
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ return false;
+
+ case TypedObjectPrediction::Descr:
+ *out = descr().size();
+ return true;
+
+ case TypedObjectPrediction::Prefix:
+ // We only know a prefix of the struct fields, hence we do not
+ // know its complete size.
+ return false;
+
+ default:
+ MOZ_CRASH("Bad prediction kind");
+ }
+}
+
+const TypedProto*
+TypedObjectPrediction::getKnownPrototype() const
+{
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ return nullptr;
+
+ case TypedObjectPrediction::Descr:
+ if (descr().is<ComplexTypeDescr>())
+ return &descr().as<ComplexTypeDescr>().instancePrototype();
+ return nullptr;
+
+ case TypedObjectPrediction::Prefix:
+ // We only know a prefix of the struct fields, hence we cannot
+ // say for certain what its prototype will be.
+ return nullptr;
+
+ default:
+ MOZ_CRASH("Bad prediction kind");
+ }
+}
+
+template<typename T>
+typename T::Type
+TypedObjectPrediction::extractType() const
+{
+ MOZ_ASSERT(kind() == T::Kind);
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ break;
+
+ case TypedObjectPrediction::Descr:
+ return descr().as<T>().type();
+
+ case TypedObjectPrediction::Prefix:
+ break; // Prefixes are always structs, never scalars etc
+ }
+
+ MOZ_CRASH("Bad prediction kind");
+}
+
+ScalarTypeDescr::Type
+TypedObjectPrediction::scalarType() const
+{
+ return extractType<ScalarTypeDescr>();
+}
+
+ReferenceTypeDescr::Type
+TypedObjectPrediction::referenceType() const
+{
+ return extractType<ReferenceTypeDescr>();
+}
+
+SimdType
+TypedObjectPrediction::simdType() const
+{
+ return descr().as<SimdTypeDescr>().type();
+}
+
+bool
+TypedObjectPrediction::hasKnownArrayLength(int32_t* length) const
+{
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ return false;
+
+ case TypedObjectPrediction::Descr:
+ // In later patches, this condition will always be true
+ // so long as this represents an array
+ if (descr().is<ArrayTypeDescr>()) {
+ *length = descr().as<ArrayTypeDescr>().length();
+ return true;
+ }
+ return false;
+
+ case TypedObjectPrediction::Prefix:
+ // Prefixes are always structs, never arrays
+ return false;
+
+ default:
+ MOZ_CRASH("Bad prediction kind");
+ }
+}
+
+TypedObjectPrediction
+TypedObjectPrediction::arrayElementType() const
+{
+ MOZ_ASSERT(ofArrayKind());
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ break;
+
+ case TypedObjectPrediction::Descr:
+ return TypedObjectPrediction(descr().as<ArrayTypeDescr>().elementType());
+
+ case TypedObjectPrediction::Prefix:
+ break; // Prefixes are always structs, never arrays
+ }
+ MOZ_CRASH("Bad prediction kind");
+}
+
+bool
+TypedObjectPrediction::hasFieldNamedPrefix(const StructTypeDescr& descr,
+ size_t fieldCount,
+ jsid id,
+ size_t* fieldOffset,
+ TypedObjectPrediction* out,
+ size_t* index) const
+{
+ // Find the index of the field |id| if any.
+ if (!descr.fieldIndex(id, index))
+ return false;
+
+ // Check whether the index falls within our known safe prefix.
+ if (*index >= fieldCount)
+ return false;
+
+ // Load the offset and type.
+ *fieldOffset = descr.fieldOffset(*index);
+ *out = TypedObjectPrediction(descr.fieldDescr(*index));
+ return true;
+}
+
+bool
+TypedObjectPrediction::hasFieldNamed(jsid id,
+ size_t* fieldOffset,
+ TypedObjectPrediction* fieldType,
+ size_t* fieldIndex) const
+{
+ MOZ_ASSERT(kind() == type::Struct);
+
+ switch (predictionKind()) {
+ case TypedObjectPrediction::Empty:
+ case TypedObjectPrediction::Inconsistent:
+ return false;
+
+ case TypedObjectPrediction::Descr:
+ return hasFieldNamedPrefix(
+ descr().as<StructTypeDescr>(), ALL_FIELDS,
+ id, fieldOffset, fieldType, fieldIndex);
+
+ case TypedObjectPrediction::Prefix:
+ return hasFieldNamedPrefix(
+ *prefix().descr, prefix().fields,
+ id, fieldOffset, fieldType, fieldIndex);
+
+ default:
+ MOZ_CRASH("Bad prediction kind");
+ }
+}