summaryrefslogtreecommitdiffstats
path: root/js/src/vm/Activation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/Activation.cpp')
-rw-r--r--js/src/vm/Activation.cpp84
1 files changed, 84 insertions, 0 deletions
diff --git a/js/src/vm/Activation.cpp b/js/src/vm/Activation.cpp
new file mode 100644
index 0000000000..19b383c9c5
--- /dev/null
+++ b/js/src/vm/Activation.cpp
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ * 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 "vm/Activation-inl.h"
+
+#include "mozilla/Assertions.h" // MOZ_ASSERT
+
+#include "gc/GC.h" // js::gc::AutoSuppressGC
+#include "jit/CalleeToken.h" // js::jit::CalleeToken{IsFunction,To{Function,Script}}
+#include "js/RootingAPI.h" // JS::Rooted
+#include "js/Value.h" // JS::Value
+#include "vm/JSContext.h" // JSContext, js::TlsContext
+#include "vm/Stack.h" // js::InterpreterFrame
+
+#include "vm/Compartment-inl.h" // JS::Compartment::wrap
+
+using namespace js;
+
+using JS::ObjectOrNullValue;
+using JS::Rooted;
+using JS::UndefinedValue;
+using JS::Value;
+
+Value ActivationEntryMonitor::asyncStack(JSContext* cx) {
+ Rooted<Value> stack(cx, ObjectOrNullValue(cx->asyncStackForNewActivations()));
+ if (!cx->compartment()->wrap(cx, &stack)) {
+ cx->clearPendingException();
+ return UndefinedValue();
+ }
+ return stack;
+}
+
+void ActivationEntryMonitor::init(JSContext* cx, InterpreterFrame* entryFrame) {
+ // The InterpreterFrame is not yet part of an Activation, so it won't
+ // be traced if we trigger GC here. Suppress GC to avoid this.
+ gc::AutoSuppressGC suppressGC(cx);
+ Rooted<Value> stack(cx, asyncStack(cx));
+ const char* asyncCause = cx->asyncCauseForNewActivations;
+ if (entryFrame->isFunctionFrame()) {
+ entryMonitor_->Entry(cx, &entryFrame->callee(), stack, asyncCause);
+ } else {
+ entryMonitor_->Entry(cx, entryFrame->script(), stack, asyncCause);
+ }
+}
+
+void ActivationEntryMonitor::init(JSContext* cx, jit::CalleeToken entryToken) {
+ // The CalleeToken is not traced at this point and we also don't want
+ // a GC to discard the code we're about to enter, so we suppress GC.
+ gc::AutoSuppressGC suppressGC(cx);
+ RootedValue stack(cx, asyncStack(cx));
+ const char* asyncCause = cx->asyncCauseForNewActivations;
+ if (jit::CalleeTokenIsFunction(entryToken)) {
+ entryMonitor_->Entry(cx_, jit::CalleeTokenToFunction(entryToken), stack,
+ asyncCause);
+ } else {
+ entryMonitor_->Entry(cx_, jit::CalleeTokenToScript(entryToken), stack,
+ asyncCause);
+ }
+}
+
+void Activation::registerProfiling() {
+ MOZ_ASSERT(isProfiling());
+ cx_->profilingActivation_ = this;
+}
+
+void Activation::unregisterProfiling() {
+ MOZ_ASSERT(isProfiling());
+ MOZ_ASSERT(cx_->profilingActivation_ == this);
+ cx_->profilingActivation_ = prevProfiling_;
+}
+
+ActivationIterator::ActivationIterator(JSContext* cx)
+ : activation_(cx->activation_) {
+ MOZ_ASSERT(cx == TlsContext.get());
+}
+
+ActivationIterator& ActivationIterator::operator++() {
+ MOZ_ASSERT(activation_);
+ activation_ = activation_->prev();
+ return *this;
+}