/js/src/jsscopeinlines.h

http://github.com/zpao/v8monkey · C Header · 447 lines · 338 code · 56 blank · 53 comment · 57 complexity · 34554ea5efe6f65d34161c507d617d0f MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. *
  3. * ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is Mozilla Communicator client code, released
  17. * March 31, 1998.
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Netscape Communications Corporation.
  21. * Portions created by the Initial Developer are Copyright (C) 1998
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. *
  26. * Alternatively, the contents of this file may be used under the terms of
  27. * either of the GNU General Public License Version 2 or later (the "GPL"),
  28. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29. * in which case the provisions of the GPL or the LGPL are applicable instead
  30. * of those above. If you wish to allow use of your version of this file only
  31. * under the terms of either the GPL or the LGPL, and not to allow others to
  32. * use your version of this file under the terms of the MPL, indicate your
  33. * decision by deleting the provisions above and replace them with the notice
  34. * and other provisions required by the GPL or the LGPL. If you do not delete
  35. * the provisions above, a recipient may use your version of this file under
  36. * the terms of any one of the MPL, the GPL or the LGPL.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. #ifndef jsscopeinlines_h___
  40. #define jsscopeinlines_h___
  41. #include <new>
  42. #include "jsarray.h"
  43. #include "jsbool.h"
  44. #include "jscntxt.h"
  45. #include "jsdbgapi.h"
  46. #include "jsfun.h"
  47. #include "jsobj.h"
  48. #include "jsscope.h"
  49. #include "jsgc.h"
  50. #include "jsgcmark.h"
  51. #include "vm/ArgumentsObject.h"
  52. #include "vm/ScopeObject.h"
  53. #include "vm/StringObject.h"
  54. #include "jscntxtinlines.h"
  55. #include "jsgcinlines.h"
  56. #include "jsobjinlines.h"
  57. #include "vm/ScopeObject-inl.h"
  58. namespace js {
  59. inline
  60. BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags)
  61. {
  62. JS_ASSERT(!(objectFlags & ~OBJECT_FLAG_MASK));
  63. PodZero(this);
  64. this->clasp = clasp;
  65. this->parent = parent;
  66. this->flags = objectFlags;
  67. }
  68. inline
  69. BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags,
  70. uint8_t attrs, js::PropertyOp rawGetter, js::StrictPropertyOp rawSetter)
  71. {
  72. JS_ASSERT(!(objectFlags & ~OBJECT_FLAG_MASK));
  73. PodZero(this);
  74. this->clasp = clasp;
  75. this->parent = parent;
  76. this->flags = objectFlags;
  77. this->rawGetter = rawGetter;
  78. this->rawSetter = rawSetter;
  79. if ((attrs & JSPROP_GETTER) && rawGetter) {
  80. this->flags |= HAS_GETTER_OBJECT;
  81. JSObject::writeBarrierPost(this->getterObj, &this->getterObj);
  82. }
  83. if ((attrs & JSPROP_SETTER) && rawSetter) {
  84. this->flags |= HAS_SETTER_OBJECT;
  85. JSObject::writeBarrierPost(this->setterObj, &this->setterObj);
  86. }
  87. }
  88. inline
  89. BaseShape::BaseShape(const StackBaseShape &base)
  90. {
  91. PodZero(this);
  92. this->clasp = base.clasp;
  93. this->parent = base.parent;
  94. this->flags = base.flags;
  95. this->rawGetter = base.rawGetter;
  96. this->rawSetter = base.rawSetter;
  97. if ((base.flags & HAS_GETTER_OBJECT) && base.rawGetter) {
  98. JSObject::writeBarrierPost(this->getterObj, &this->getterObj);
  99. }
  100. if ((base.flags & HAS_SETTER_OBJECT) && base.rawSetter) {
  101. JSObject::writeBarrierPost(this->setterObj, &this->setterObj);
  102. }
  103. }
  104. inline BaseShape &
  105. BaseShape::operator=(const BaseShape &other)
  106. {
  107. clasp = other.clasp;
  108. parent = other.parent;
  109. flags = other.flags;
  110. slotSpan_ = other.slotSpan_;
  111. if (flags & HAS_GETTER_OBJECT) {
  112. getterObj = other.getterObj;
  113. JSObject::writeBarrierPost(getterObj, &getterObj);
  114. } else {
  115. rawGetter = other.rawGetter;
  116. }
  117. if (flags & HAS_SETTER_OBJECT) {
  118. setterObj = other.setterObj;
  119. JSObject::writeBarrierPost(setterObj, &setterObj);
  120. } else {
  121. rawSetter = other.rawSetter;
  122. }
  123. return *this;
  124. }
  125. inline bool
  126. BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter) const
  127. {
  128. return rawGetter == this->rawGetter && rawSetter == this->rawSetter;
  129. }
  130. inline
  131. StackBaseShape::StackBaseShape(Shape *shape)
  132. : flags(shape->getObjectFlags()),
  133. clasp(shape->getObjectClass()),
  134. parent(shape->getObjectParent())
  135. {
  136. updateGetterSetter(shape->attrs, shape->getter(), shape->setter());
  137. }
  138. inline void
  139. StackBaseShape::updateGetterSetter(uint8_t attrs,
  140. PropertyOp rawGetter,
  141. StrictPropertyOp rawSetter)
  142. {
  143. flags &= ~(BaseShape::HAS_GETTER_OBJECT | BaseShape::HAS_SETTER_OBJECT);
  144. if ((attrs & JSPROP_GETTER) && rawGetter)
  145. flags |= BaseShape::HAS_GETTER_OBJECT;
  146. if ((attrs & JSPROP_SETTER) && rawSetter)
  147. flags |= BaseShape::HAS_SETTER_OBJECT;
  148. this->rawGetter = rawGetter;
  149. this->rawSetter = rawSetter;
  150. }
  151. inline void
  152. BaseShape::adoptUnowned(UnownedBaseShape *other)
  153. {
  154. /*
  155. * This is a base shape owned by a dictionary object, update it to reflect the
  156. * unowned base shape of a new last property.
  157. */
  158. JS_ASSERT(isOwned());
  159. DebugOnly<uint32_t> flags = getObjectFlags();
  160. JS_ASSERT((flags & other->getObjectFlags()) == flags);
  161. uint32_t span = slotSpan();
  162. PropertyTable *table = &this->table();
  163. *this = *other;
  164. setOwned(other);
  165. setTable(table);
  166. setSlotSpan(span);
  167. assertConsistency();
  168. }
  169. inline void
  170. BaseShape::setOwned(UnownedBaseShape *unowned)
  171. {
  172. flags |= OWNED_SHAPE;
  173. this->unowned_ = unowned;
  174. }
  175. inline void
  176. BaseShape::assertConsistency()
  177. {
  178. #ifdef DEBUG
  179. if (isOwned()) {
  180. UnownedBaseShape *unowned = baseUnowned();
  181. JS_ASSERT(hasGetterObject() == unowned->hasGetterObject());
  182. JS_ASSERT(hasSetterObject() == unowned->hasSetterObject());
  183. JS_ASSERT_IF(hasGetterObject(), getterObject() == unowned->getterObject());
  184. JS_ASSERT_IF(hasSetterObject(), setterObject() == unowned->setterObject());
  185. JS_ASSERT(getObjectParent() == unowned->getObjectParent());
  186. JS_ASSERT(getObjectFlags() == unowned->getObjectFlags());
  187. }
  188. #endif
  189. }
  190. inline
  191. Shape::Shape(const StackShape &other, uint32_t nfixed)
  192. : base_(other.base),
  193. propid_(other.propid),
  194. slotInfo(other.maybeSlot() | (nfixed << FIXED_SLOTS_SHIFT)),
  195. attrs(other.attrs),
  196. flags(other.flags),
  197. shortid_(other.shortid),
  198. parent(NULL)
  199. {
  200. kids.setNull();
  201. }
  202. inline
  203. Shape::Shape(UnownedBaseShape *base, uint32_t nfixed)
  204. : base_(base),
  205. propid_(JSID_EMPTY),
  206. slotInfo(SHAPE_INVALID_SLOT | (nfixed << FIXED_SLOTS_SHIFT)),
  207. attrs(JSPROP_SHARED),
  208. flags(0),
  209. shortid_(0),
  210. parent(NULL)
  211. {
  212. JS_ASSERT(base);
  213. kids.setNull();
  214. }
  215. inline JSDHashNumber
  216. StackShape::hash() const
  217. {
  218. JSDHashNumber hash = uintptr_t(base);
  219. /* Accumulate from least to most random so the low bits are most random. */
  220. hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & Shape::PUBLIC_FLAGS);
  221. hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
  222. hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
  223. hash = JS_ROTATE_LEFT32(hash, 4) ^ slot_;
  224. hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid);
  225. return hash;
  226. }
  227. inline bool
  228. Shape::matches(const js::Shape *other) const
  229. {
  230. return propid_.get() == other->propid_.get() &&
  231. matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
  232. other->flags, other->shortid_);
  233. }
  234. inline bool
  235. Shape::matches(const StackShape &other) const
  236. {
  237. return propid_.get() == other.propid &&
  238. matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, other.shortid);
  239. }
  240. inline bool
  241. Shape::matchesParamsAfterId(BaseShape *base, uint32_t aslot,
  242. uintN aattrs, uintN aflags, intN ashortid) const
  243. {
  244. return base->unowned() == this->base()->unowned() &&
  245. maybeSlot() == aslot &&
  246. attrs == aattrs &&
  247. ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
  248. shortid_ == ashortid;
  249. }
  250. inline bool
  251. Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js::Value* vp) const
  252. {
  253. JS_ASSERT(!hasDefaultGetter());
  254. if (hasGetterValue()) {
  255. JS_ASSERT(!isMethod());
  256. js::Value fval = getterValue();
  257. return js::InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
  258. }
  259. if (isMethod()) {
  260. vp->setObject(*pobj->nativeGetMethod(this));
  261. return pobj->methodReadBarrier(cx, *this, vp);
  262. }
  263. /*
  264. * |with (it) color;| ends up here, as do XML filter-expressions.
  265. * Avoid exposing the With object to native getters.
  266. */
  267. if (obj->isWith())
  268. obj = &obj->asWith().object();
  269. return js::CallJSPropertyOp(cx, getterOp(), receiver, getUserId(), vp);
  270. }
  271. inline bool
  272. Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
  273. {
  274. JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
  275. if (attrs & JSPROP_SETTER) {
  276. js::Value fval = setterValue();
  277. return js::InvokeGetterOrSetter(cx, obj, fval, 1, vp, vp);
  278. }
  279. if (attrs & JSPROP_GETTER)
  280. return js_ReportGetterOnlyAssignment(cx);
  281. /* See the comment in js::Shape::get as to why we check for With. */
  282. if (obj->isWith())
  283. obj = &obj->asWith().object();
  284. return js::CallJSPropertyOpSetter(cx, setterOp(), obj, getUserId(), strict, vp);
  285. }
  286. inline void
  287. Shape::setParent(js::Shape *p)
  288. {
  289. JS_ASSERT_IF(p && !p->hasMissingSlot() && !inDictionary(),
  290. p->maybeSlot() <= maybeSlot());
  291. JS_ASSERT_IF(p && !inDictionary(),
  292. hasSlot() == (p->maybeSlot() != maybeSlot()));
  293. parent = p;
  294. }
  295. inline void
  296. Shape::removeFromDictionary(JSObject *obj)
  297. {
  298. JS_ASSERT(inDictionary());
  299. JS_ASSERT(obj->inDictionaryMode());
  300. JS_ASSERT(listp);
  301. JS_ASSERT(obj->shape_->inDictionary());
  302. JS_ASSERT(obj->shape_->listp == &obj->shape_);
  303. if (parent)
  304. parent->listp = listp;
  305. *listp = parent;
  306. listp = NULL;
  307. }
  308. inline void
  309. Shape::insertIntoDictionary(HeapPtrShape *dictp)
  310. {
  311. /*
  312. * Don't assert inDictionaryMode() here because we may be called from
  313. * JSObject::toDictionaryMode via JSObject::newDictionaryShape.
  314. */
  315. JS_ASSERT(inDictionary());
  316. JS_ASSERT(!listp);
  317. JS_ASSERT_IF(*dictp, (*dictp)->inDictionary());
  318. JS_ASSERT_IF(*dictp, (*dictp)->listp == dictp);
  319. JS_ASSERT_IF(*dictp, compartment() == (*dictp)->compartment());
  320. setParent(*dictp);
  321. if (parent)
  322. parent->listp = &parent;
  323. listp = (HeapPtrShape *) dictp;
  324. *dictp = this;
  325. }
  326. void
  327. Shape::initDictionaryShape(const StackShape &child, uint32_t nfixed, HeapPtrShape *dictp)
  328. {
  329. new (this) Shape(child, nfixed);
  330. this->flags |= IN_DICTIONARY;
  331. this->listp = NULL;
  332. insertIntoDictionary(dictp);
  333. }
  334. inline
  335. EmptyShape::EmptyShape(UnownedBaseShape *base, uint32_t nfixed)
  336. : js::Shape(base, nfixed)
  337. {
  338. /* Only empty shapes can be NON_NATIVE. */
  339. if (!getObjectClass()->isNative())
  340. flags |= NON_NATIVE;
  341. }
  342. inline void
  343. Shape::writeBarrierPre(const js::Shape *shape)
  344. {
  345. #ifdef JSGC_INCREMENTAL
  346. if (!shape)
  347. return;
  348. JSCompartment *comp = shape->compartment();
  349. if (comp->needsBarrier())
  350. MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "write barrier");
  351. #endif
  352. }
  353. inline void
  354. Shape::writeBarrierPost(const js::Shape *shape, void *addr)
  355. {
  356. }
  357. inline void
  358. Shape::readBarrier(const Shape *shape)
  359. {
  360. #ifdef JSGC_INCREMENTAL
  361. JSCompartment *comp = shape->compartment();
  362. if (comp->needsBarrier())
  363. MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "read barrier");
  364. #endif
  365. }
  366. inline void
  367. BaseShape::writeBarrierPre(BaseShape *base)
  368. {
  369. #ifdef JSGC_INCREMENTAL
  370. if (!base)
  371. return;
  372. JSCompartment *comp = base->compartment();
  373. if (comp->needsBarrier())
  374. MarkBaseShapeUnbarriered(comp->barrierTracer(), base, "write barrier");
  375. #endif
  376. }
  377. inline void
  378. BaseShape::writeBarrierPost(BaseShape *shape, void *addr)
  379. {
  380. }
  381. inline void
  382. BaseShape::readBarrier(BaseShape *base)
  383. {
  384. #ifdef JSGC_INCREMENTAL
  385. JSCompartment *comp = base->compartment();
  386. if (comp->needsBarrier())
  387. MarkBaseShapeUnbarriered(comp->barrierTracer(), base, "read barrier");
  388. #endif
  389. }
  390. } /* namespace js */
  391. #endif /* jsscopeinlines_h___ */