michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jscompartmentinlines_h michael@0: #define jscompartmentinlines_h michael@0: michael@0: #include "jscompartment.h" michael@0: michael@0: #include "gc/Barrier-inl.h" michael@0: michael@0: inline void michael@0: JSCompartment::initGlobal(js::GlobalObject &global) michael@0: { michael@0: JS_ASSERT(global.compartment() == this); michael@0: JS_ASSERT(!global_); michael@0: global_ = &global; michael@0: } michael@0: michael@0: js::GlobalObject * michael@0: JSCompartment::maybeGlobal() const michael@0: { michael@0: JS_ASSERT_IF(global_, global_->compartment() == this); michael@0: return global_; michael@0: } michael@0: michael@0: js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target) michael@0: : cx_(cx), michael@0: origin_(cx->compartment_) michael@0: { michael@0: cx_->enterCompartment(target->compartment()); michael@0: } michael@0: michael@0: js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSCompartment *target) michael@0: : cx_(cx), michael@0: origin_(cx_->compartment_) michael@0: { michael@0: cx_->enterCompartment(target); michael@0: } michael@0: michael@0: js::AutoCompartment::~AutoCompartment() michael@0: { michael@0: cx_->leaveCompartment(origin_); michael@0: } michael@0: michael@0: inline bool michael@0: JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing) michael@0: { michael@0: JS_ASSERT_IF(existing, vp.isObject()); michael@0: michael@0: /* Only GC things have to be wrapped or copied. */ michael@0: if (!vp.isMarkable()) michael@0: return true; michael@0: michael@0: /* Handle strings. */ michael@0: if (vp.isString()) { michael@0: JS::RootedString str(cx, vp.toString()); michael@0: if (!wrap(cx, str.address())) michael@0: return false; michael@0: vp.setString(str); michael@0: return true; michael@0: } michael@0: michael@0: JS_ASSERT(vp.isObject()); michael@0: michael@0: /* michael@0: * All that's left are objects. michael@0: * michael@0: * Object wrapping isn't the fastest thing in the world, in part because michael@0: * we have to unwrap and invoke the prewrap hook to find the identity michael@0: * object before we even start checking the cache. Neither of these michael@0: * operations are needed in the common case, where we're just wrapping michael@0: * a plain JS object from the wrappee's side of the membrane to the michael@0: * wrapper's side. michael@0: * michael@0: * To optimize this, we note that the cache should only ever contain michael@0: * identity objects - that is to say, objects that serve as the michael@0: * canonical representation for a unique object identity observable by michael@0: * script. Unwrap and prewrap are both steps that we take to get to the michael@0: * identity of an incoming objects, and as such, they shuld never map michael@0: * one identity object to another object. This means that we can safely michael@0: * check the cache immediately, and only risk false negatives. Do this michael@0: * in opt builds, and do both in debug builds so that we can assert michael@0: * that we get the same answer. michael@0: */ michael@0: #ifdef DEBUG michael@0: JS::RootedObject cacheResult(cx); michael@0: #endif michael@0: JS::RootedValue v(cx, vp); michael@0: if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) { michael@0: #ifdef DEBUG michael@0: cacheResult = &p->value().get().toObject(); michael@0: #else michael@0: vp.set(p->value()); michael@0: return true; michael@0: #endif michael@0: } michael@0: michael@0: JS::RootedObject obj(cx, &vp.toObject()); michael@0: if (!wrap(cx, &obj, existing)) michael@0: return false; michael@0: vp.setObject(*obj); michael@0: JS_ASSERT_IF(cacheResult, obj == cacheResult); michael@0: return true; michael@0: } michael@0: michael@0: #endif /* jscompartmentinlines_h */