summaryrefslogtreecommitdiffstats
path: root/js/src/vm
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm')
-rw-r--r--js/src/vm/EnvironmentObject.cpp3
-rw-r--r--js/src/vm/NativeObject-inl.h8
-rw-r--r--js/src/vm/NativeObject.cpp14
-rw-r--r--js/src/vm/Runtime.cpp1
-rw-r--r--js/src/vm/Shape.h2
-rw-r--r--js/src/vm/Time.cpp12
-rw-r--r--js/src/vm/TypeInference.cpp92
-rw-r--r--js/src/vm/TypeInference.h59
8 files changed, 155 insertions, 36 deletions
diff --git a/js/src/vm/EnvironmentObject.cpp b/js/src/vm/EnvironmentObject.cpp
index a5aac2ab4..3680c5b7b 100644
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -408,7 +408,6 @@ const ObjectOps ModuleEnvironmentObject::objectOps_ = {
ModuleEnvironmentObject::setProperty,
ModuleEnvironmentObject::getOwnPropertyDescriptor,
ModuleEnvironmentObject::deleteProperty,
- nullptr, nullptr, /* watch/unwatch */
nullptr, /* getElements */
ModuleEnvironmentObject::enumerate,
nullptr
@@ -790,7 +789,6 @@ static const ObjectOps WithEnvironmentObjectOps = {
with_SetProperty,
with_GetOwnPropertyDescriptor,
with_DeleteProperty,
- nullptr, nullptr, /* watch/unwatch */
nullptr, /* getElements */
nullptr, /* enumerate (native enumeration of target doesn't work) */
nullptr,
@@ -1159,7 +1157,6 @@ static const ObjectOps RuntimeLexicalErrorObjectObjectOps = {
lexicalError_SetProperty,
lexicalError_GetOwnPropertyDescriptor,
lexicalError_DeleteProperty,
- nullptr, nullptr, /* watch/unwatch */
nullptr, /* getElements */
nullptr, /* enumerate (native enumeration of target doesn't work) */
nullptr, /* this */
diff --git a/js/src/vm/NativeObject-inl.h b/js/src/vm/NativeObject-inl.h
index e55e3db04..030d92c12 100644
--- a/js/src/vm/NativeObject-inl.h
+++ b/js/src/vm/NativeObject-inl.h
@@ -158,11 +158,11 @@ NativeObject::extendDenseElements(ExclusiveContext* cx,
MOZ_ASSERT(!denseElementsAreFrozen());
/*
- * Don't grow elements for non-extensible objects or watched objects. Dense
- * elements can be added/written with no extensible or watchpoint checks as
- * long as there is capacity for them.
+ * Don't grow elements for non-extensible objects. Dense elements can be
+ * added/written with no extensible checks as long as there is capacity
+ * for them.
*/
- if (!nonProxyIsExtensible() || watched()) {
+ if (!nonProxyIsExtensible()) {
MOZ_ASSERT(getDenseCapacity() == 0);
return DenseElementResult::Incomplete;
}
diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
index da0f59fe2..d801fad06 100644
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -9,8 +9,6 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Casting.h"
-#include "jswatchpoint.h"
-
#include "gc/Marking.h"
#include "js/Value.h"
#include "vm/Debugger.h"
@@ -602,7 +600,7 @@ NativeObject::maybeDensifySparseElements(js::ExclusiveContext* cx, HandleNativeO
return DenseElementResult::Incomplete;
/* Watch for conditions under which an object's elements cannot be dense. */
- if (!obj->nonProxyIsExtensible() || obj->watched())
+ if (!obj->nonProxyIsExtensible())
return DenseElementResult::Incomplete;
/*
@@ -2410,17 +2408,9 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
}
bool
-js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
+js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v,
HandleValue receiver, QualifiedBool qualified, ObjectOpResult& result)
{
- // Fire watchpoints, if any.
- RootedValue v(cx, value);
- if (MOZ_UNLIKELY(obj->watched())) {
- WatchpointMap* wpmap = cx->compartment()->watchpointMap;
- if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, &v))
- return false;
- }
-
// Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal
// method for ordinary objects. We substitute our own names for these names
// used in the spec: O -> pobj, P -> id, ownDesc -> shape.
diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp
index 5fc8e0e17..284a4f3d7 100644
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -34,7 +34,6 @@
#include "jsnativestack.h"
#include "jsobj.h"
#include "jsscript.h"
-#include "jswatchpoint.h"
#include "jswin.h"
#include "jswrapper.h"
diff --git a/js/src/vm/Shape.h b/js/src/vm/Shape.h
index fd6d843e0..85bc044a5 100644
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -387,7 +387,7 @@ class BaseShape : public gc::TenuredCell
INDEXED = 0x20,
/* (0x40 is unused) */
HAD_ELEMENTS_ACCESS = 0x80,
- WATCHED = 0x100,
+ /* (0x100 is unused) */
ITERATED_SINGLETON = 0x200,
NEW_GROUP_UNKNOWN = 0x400,
UNCACHEABLE_PROTO = 0x800,
diff --git a/js/src/vm/Time.cpp b/js/src/vm/Time.cpp
index 87531c148..a9a5b7f0f 100644
--- a/js/src/vm/Time.cpp
+++ b/js/src/vm/Time.cpp
@@ -11,6 +11,10 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/MathAlgorithms.h"
+#ifdef XP_SOLARIS
+#define _REENTRANT 1
+#endif
+
#include <string.h>
#include <time.h>
@@ -30,6 +34,10 @@
#ifdef XP_UNIX
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+extern int gettimeofday(struct timeval* tv);
+#endif
+
#include <sys/time.h>
#endif /* XP_UNIX */
@@ -42,7 +50,11 @@ PRMJ_Now()
{
struct timeval tv;
+#ifdef _SVID_GETTOD /* Defined only on Solaris, see Solaris <sys/types.h> */
+ gettimeofday(&tv);
+#else
gettimeofday(&tv, 0);
+#endif /* _SVID_GETTOD */
return int64_t(tv.tv_sec) * PRMJ_USEC_PER_SEC + int64_t(tv.tv_usec);
}
diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp
index 7c2c0194e..2b1fa0e3b 100644
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -2670,14 +2670,6 @@ ObjectGroup::updateNewPropertyTypes(ExclusiveContext* cx, JSObject* objArg, jsid
if (shape)
UpdatePropertyType(cx, types, obj, shape, false);
}
-
- if (obj->watched()) {
- /*
- * Mark the property as non-data, to inhibit optimizations on it
- * and avoid bypassing the watchpoint handler.
- */
- types->setNonDataProperty(cx);
- }
}
void
@@ -3084,29 +3076,39 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
};
bool
-js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx, ObjectGroup* group, HandleId id)
+js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx,
+ DPAConstraintInfo& constraintInfo,
+ ObjectGroup* group,
+ HandleId id,
+ bool* added)
{
/*
* Ensure that if the properties named here could have a getter, setter or
* a permanent property in any transitive prototype, the definite
* properties get cleared from the group.
*/
+
+ *added = false;
+
RootedObject proto(cx, group->proto().toObjectOrNull());
while (proto) {
ObjectGroup* protoGroup = JSObject::getGroup(cx, proto);
if (!protoGroup) {
- cx->recoverFromOutOfMemory();
return false;
}
if (protoGroup->unknownProperties())
- return false;
+ return true;
HeapTypeSet* protoTypes = protoGroup->getProperty(cx, proto, id);
- if (!protoTypes || protoTypes->nonDataProperty() || protoTypes->nonWritableProperty())
+ if (!protoTypes)
return false;
- if (!protoTypes->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(group)))
+ if (protoTypes->nonDataProperty() || protoTypes->nonWritableProperty())
+ return true;
+ if (!constraintInfo.addProtoConstraint(proto, id))
return false;
proto = proto->staticPrototype();
}
+
+ *added = true;
return true;
}
@@ -3612,6 +3614,43 @@ struct DestroyTypeNewScript
} // namespace
+bool DPAConstraintInfo::finishConstraints(JSContext* cx, ObjectGroup* group) {
+ for (const ProtoConstraint& constraint : protoConstraints_) {
+ ObjectGroup* protoGroup = constraint.proto->group();
+
+ // Note: we rely on the group's type information being unchanged since
+ // AddClearDefiniteGetterSetterForPrototypeChain.
+
+ bool unknownProperties = protoGroup->unknownProperties();
+ MOZ_RELEASE_ASSERT(!unknownProperties);
+
+ HeapTypeSet* protoTypes =
+ protoGroup->getProperty(cx, constraint.proto, constraint.id);
+ MOZ_RELEASE_ASSERT(protoTypes);
+
+ MOZ_ASSERT(!protoTypes->nonDataProperty());
+ MOZ_ASSERT(!protoTypes->nonWritableProperty());
+
+ if (!protoTypes->addConstraint(
+ cx,
+ cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(
+ group))) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+ }
+
+ for (const InliningConstraint& constraint : inliningConstraints_) {
+ if (!AddClearDefiniteFunctionUsesInScript(cx, group, constraint.caller,
+ constraint.callee)) {
+ ReportOutOfMemory(cx);
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool
TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate, bool force)
{
@@ -3715,10 +3754,17 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
return false;
Vector<Initializer> initializerVector(cx);
+
+ DPAConstraintInfo constraintInfo(cx);
RootedPlainObject templateRoot(cx, templateObject());
RootedFunction fun(cx, function());
- if (!jit::AnalyzeNewScriptDefiniteProperties(cx, fun, group, templateRoot, &initializerVector))
+ if (!jit::AnalyzeNewScriptDefiniteProperties(cx,
+ constraintInfo,
+ fun,
+ group,
+ templateRoot,
+ &initializerVector))
return false;
if (!group->newScript())
@@ -3772,6 +3818,14 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
// The definite properties analysis found exactly the properties that
// are held in common by the preliminary objects. No further analysis
// is needed.
+
+ if (!constraintInfo.finishConstraints(cx, group)) {
+ return false;
+ }
+ if (!group->newScript()) {
+ return true;
+ }
+
group->addDefiniteProperties(cx, templateObject()->lastProperty());
destroyNewScript.group = nullptr;
@@ -3793,6 +3847,16 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
if (!initialGroup)
return false;
+ // Add the constraints. Use the initialGroup as group referenced by the
+ // constraints because that's the group that will have the TypeNewScript
+ // associated with it. See the detachNewScript and setNewScript calls below.
+ if (!constraintInfo.finishConstraints(cx, initialGroup)) {
+ return false;
+ }
+ if (!group->newScript()) {
+ return true;
+ }
+
initialGroup->addDefiniteProperties(cx, templateObject()->lastProperty());
group->addDefiniteProperties(cx, prefixShape);
diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h
index 94ce7e871..fd021fc96 100644
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -789,8 +789,65 @@ class TemporaryTypeSet : public TypeSet
TypedArraySharedness* sharedness);
};
+// Stack class to record information about constraints that need to be added
+// after finishing the Definite Properties Analysis. When the analysis succeeds,
+// the |finishConstraints| method must be called to add the constraints to the
+// TypeSets.
+//
+// There are two constraint types managed here:
+//
+// 1. Proto constraints for HeapTypeSets, to guard against things like getters
+// and setters on the proto chain.
+//
+// 2. Inlining constraints for StackTypeSets, to invalidate when additional
+// functions could be called at call sites where we inlined a function.
+//
+// This class uses bare GC-thing pointers because GC is suppressed when the
+// analysis runs.
+class MOZ_RAII DPAConstraintInfo {
+ struct ProtoConstraint {
+ JSObject* proto;
+ jsid id;
+ ProtoConstraint(JSObject* proto, jsid id) : proto(proto), id(id) {}
+ };
+ struct InliningConstraint {
+ JSScript* caller;
+ JSScript* callee;
+ InliningConstraint(JSScript* caller, JSScript* callee)
+ : caller(caller), callee(callee) {}
+ };
+
+ JS::AutoCheckCannotGC nogc_;
+ Vector<ProtoConstraint, 8> protoConstraints_;
+ Vector<InliningConstraint, 4> inliningConstraints_;
+
+public:
+ explicit DPAConstraintInfo(JSContext* cx)
+ : nogc_(cx)
+ , protoConstraints_(cx)
+ , inliningConstraints_(cx)
+ {
+ }
+
+ DPAConstraintInfo(const DPAConstraintInfo&) = delete;
+ void operator=(const DPAConstraintInfo&) = delete;
+
+ MOZ_MUST_USE bool addProtoConstraint(JSObject* proto, jsid id) {
+ return protoConstraints_.emplaceBack(proto, id);
+ }
+ MOZ_MUST_USE bool addInliningConstraint(JSScript* caller, JSScript* callee) {
+ return inliningConstraints_.emplaceBack(caller, callee);
+ }
+
+ MOZ_MUST_USE bool finishConstraints(JSContext* cx, ObjectGroup* group);
+};
+
bool
-AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx, ObjectGroup* group, HandleId id);
+AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx,
+ DPAConstraintInfo& constraintInfo,
+ ObjectGroup* group,
+ HandleId id,
+ bool* added);
bool
AddClearDefiniteFunctionUsesInScript(JSContext* cx, ObjectGroup* group,