diff options
Diffstat (limited to 'js/src/jscompartmentinlines.h')
-rw-r--r-- | js/src/jscompartmentinlines.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/js/src/jscompartmentinlines.h b/js/src/jscompartmentinlines.h new file mode 100644 index 000000000..08d315db0 --- /dev/null +++ b/js/src/jscompartmentinlines.h @@ -0,0 +1,126 @@ +/* -*- 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/. */ + +#ifndef jscompartmentinlines_h +#define jscompartmentinlines_h + +#include "jscompartment.h" + +#include "gc/Barrier.h" + +#include "jscntxtinlines.h" + +inline void +JSCompartment::initGlobal(js::GlobalObject& global) +{ + MOZ_ASSERT(global.compartment() == this); + MOZ_ASSERT(!global_); + global_.set(&global); +} + +js::GlobalObject* +JSCompartment::maybeGlobal() const +{ + MOZ_ASSERT_IF(global_, global_->compartment() == this); + return global_; +} + +js::GlobalObject* +JSCompartment::unsafeUnbarrieredMaybeGlobal() const +{ + return *global_.unsafeGet(); +} + +js::AutoCompartment::AutoCompartment(ExclusiveContext* cx, JSObject* target, + js::AutoLockForExclusiveAccess* maybeLock /* = nullptr */) + : cx_(cx), + origin_(cx->compartment_), + maybeLock_(maybeLock) +{ + cx_->enterCompartment(target->compartment(), maybeLock); +} + +js::AutoCompartment::AutoCompartment(ExclusiveContext* cx, JSCompartment* target, + js::AutoLockForExclusiveAccess* maybeLock /* = nullptr */) + : cx_(cx), + origin_(cx_->compartment_), + maybeLock_(maybeLock) +{ + cx_->enterCompartment(target, maybeLock); +} + +js::AutoCompartment::~AutoCompartment() +{ + cx_->leaveCompartment(origin_, maybeLock_); +} + +inline bool +JSCompartment::wrap(JSContext* cx, JS::MutableHandleValue vp) +{ + /* Only GC things have to be wrapped or copied. */ + if (!vp.isMarkable()) + return true; + + /* + * Symbols are GC things, but never need to be wrapped or copied because + * they are always allocated in the atoms compartment. + */ + if (vp.isSymbol()) + return true; + + /* Handle strings. */ + if (vp.isString()) { + JS::RootedString str(cx, vp.toString()); + if (!wrap(cx, &str)) + return false; + vp.setString(str); + return true; + } + + MOZ_ASSERT(vp.isObject()); + + /* + * All that's left are objects. + * + * Object wrapping isn't the fastest thing in the world, in part because + * we have to unwrap and invoke the prewrap hook to find the identity + * object before we even start checking the cache. Neither of these + * operations are needed in the common case, where we're just wrapping + * a plain JS object from the wrappee's side of the membrane to the + * wrapper's side. + * + * To optimize this, we note that the cache should only ever contain + * identity objects - that is to say, objects that serve as the + * canonical representation for a unique object identity observable by + * script. Unwrap and prewrap are both steps that we take to get to the + * identity of an incoming objects, and as such, they shuld never map + * one identity object to another object. This means that we can safely + * check the cache immediately, and only risk false negatives. Do this + * in opt builds, and do both in debug builds so that we can assert + * that we get the same answer. + */ +#ifdef DEBUG + JS::RootedObject cacheResult(cx); +#endif + JS::RootedValue v(cx, vp); + if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(js::CrossCompartmentKey(v))) { +#ifdef DEBUG + cacheResult = &p->value().get().toObject(); +#else + vp.set(p->value().get()); + return true; +#endif + } + + JS::RootedObject obj(cx, &vp.toObject()); + if (!wrap(cx, &obj)) + return false; + vp.setObject(*obj); + MOZ_ASSERT_IF(cacheResult, obj == cacheResult); + return true; +} + +#endif /* jscompartmentinlines_h */ |