/* -*- 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-inl.h" inline void JSCompartment::initGlobal(js::GlobalObject &global) { JS_ASSERT(global.compartment() == this); JS_ASSERT(!global_); global_ = &global; } js::GlobalObject * JSCompartment::maybeGlobal() const { JS_ASSERT_IF(global_, global_->compartment() == this); return global_; } js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target) : cx_(cx), origin_(cx->compartment_) { cx_->enterCompartment(target->compartment()); } js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSCompartment *target) : cx_(cx), origin_(cx_->compartment_) { cx_->enterCompartment(target); } js::AutoCompartment::~AutoCompartment() { cx_->leaveCompartment(origin_); } inline bool JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing) { JS_ASSERT_IF(existing, vp.isObject()); /* Only GC things have to be wrapped or copied. */ if (!vp.isMarkable()) return true; /* Handle strings. */ if (vp.isString()) { JS::RootedString str(cx, vp.toString()); if (!wrap(cx, str.address())) return false; vp.setString(str); return true; } JS_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(v)) { #ifdef DEBUG cacheResult = &p->value.get().toObject(); #else vp.set(p->value); return true; #endif } JS::RootedObject obj(cx, &vp.toObject()); if (!wrap(cx, &obj, existing)) return false; vp.setObject(*obj); JS_ASSERT_IF(cacheResult, obj == cacheResult); return true; } #endif /* jscompartmentinlines_h */