1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jscompartmentinlines.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,109 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jscompartmentinlines_h 1.11 +#define jscompartmentinlines_h 1.12 + 1.13 +#include "jscompartment.h" 1.14 + 1.15 +#include "gc/Barrier-inl.h" 1.16 + 1.17 +inline void 1.18 +JSCompartment::initGlobal(js::GlobalObject &global) 1.19 +{ 1.20 + JS_ASSERT(global.compartment() == this); 1.21 + JS_ASSERT(!global_); 1.22 + global_ = &global; 1.23 +} 1.24 + 1.25 +js::GlobalObject * 1.26 +JSCompartment::maybeGlobal() const 1.27 +{ 1.28 + JS_ASSERT_IF(global_, global_->compartment() == this); 1.29 + return global_; 1.30 +} 1.31 + 1.32 +js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSObject *target) 1.33 + : cx_(cx), 1.34 + origin_(cx->compartment_) 1.35 +{ 1.36 + cx_->enterCompartment(target->compartment()); 1.37 +} 1.38 + 1.39 +js::AutoCompartment::AutoCompartment(ExclusiveContext *cx, JSCompartment *target) 1.40 + : cx_(cx), 1.41 + origin_(cx_->compartment_) 1.42 +{ 1.43 + cx_->enterCompartment(target); 1.44 +} 1.45 + 1.46 +js::AutoCompartment::~AutoCompartment() 1.47 +{ 1.48 + cx_->leaveCompartment(origin_); 1.49 +} 1.50 + 1.51 +inline bool 1.52 +JSCompartment::wrap(JSContext *cx, JS::MutableHandleValue vp, JS::HandleObject existing) 1.53 +{ 1.54 + JS_ASSERT_IF(existing, vp.isObject()); 1.55 + 1.56 + /* Only GC things have to be wrapped or copied. */ 1.57 + if (!vp.isMarkable()) 1.58 + return true; 1.59 + 1.60 + /* Handle strings. */ 1.61 + if (vp.isString()) { 1.62 + JS::RootedString str(cx, vp.toString()); 1.63 + if (!wrap(cx, str.address())) 1.64 + return false; 1.65 + vp.setString(str); 1.66 + return true; 1.67 + } 1.68 + 1.69 + JS_ASSERT(vp.isObject()); 1.70 + 1.71 + /* 1.72 + * All that's left are objects. 1.73 + * 1.74 + * Object wrapping isn't the fastest thing in the world, in part because 1.75 + * we have to unwrap and invoke the prewrap hook to find the identity 1.76 + * object before we even start checking the cache. Neither of these 1.77 + * operations are needed in the common case, where we're just wrapping 1.78 + * a plain JS object from the wrappee's side of the membrane to the 1.79 + * wrapper's side. 1.80 + * 1.81 + * To optimize this, we note that the cache should only ever contain 1.82 + * identity objects - that is to say, objects that serve as the 1.83 + * canonical representation for a unique object identity observable by 1.84 + * script. Unwrap and prewrap are both steps that we take to get to the 1.85 + * identity of an incoming objects, and as such, they shuld never map 1.86 + * one identity object to another object. This means that we can safely 1.87 + * check the cache immediately, and only risk false negatives. Do this 1.88 + * in opt builds, and do both in debug builds so that we can assert 1.89 + * that we get the same answer. 1.90 + */ 1.91 +#ifdef DEBUG 1.92 + JS::RootedObject cacheResult(cx); 1.93 +#endif 1.94 + JS::RootedValue v(cx, vp); 1.95 + if (js::WrapperMap::Ptr p = crossCompartmentWrappers.lookup(v)) { 1.96 +#ifdef DEBUG 1.97 + cacheResult = &p->value().get().toObject(); 1.98 +#else 1.99 + vp.set(p->value()); 1.100 + return true; 1.101 +#endif 1.102 + } 1.103 + 1.104 + JS::RootedObject obj(cx, &vp.toObject()); 1.105 + if (!wrap(cx, &obj, existing)) 1.106 + return false; 1.107 + vp.setObject(*obj); 1.108 + JS_ASSERT_IF(cacheResult, obj == cacheResult); 1.109 + return true; 1.110 +} 1.111 + 1.112 +#endif /* jscompartmentinlines_h */