PageRenderTime 41ms CodeModel.GetById 10ms app.highlight 26ms RepoModel.GetById 2ms app.codeStats 0ms

/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
 40#ifndef jsscopeinlines_h___
 41#define jsscopeinlines_h___
 42
 43#include <new>
 44
 45#include "jsarray.h"
 46#include "jsbool.h"
 47#include "jscntxt.h"
 48#include "jsdbgapi.h"
 49#include "jsfun.h"
 50#include "jsobj.h"
 51#include "jsscope.h"
 52#include "jsgc.h"
 53#include "jsgcmark.h"
 54
 55#include "vm/ArgumentsObject.h"
 56#include "vm/ScopeObject.h"
 57#include "vm/StringObject.h"
 58
 59#include "jscntxtinlines.h"
 60#include "jsgcinlines.h"
 61#include "jsobjinlines.h"
 62
 63#include "vm/ScopeObject-inl.h"
 64
 65namespace js {
 66
 67inline
 68BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags)
 69{
 70    JS_ASSERT(!(objectFlags & ~OBJECT_FLAG_MASK));
 71    PodZero(this);
 72    this->clasp = clasp;
 73    this->parent = parent;
 74    this->flags = objectFlags;
 75}
 76
 77inline
 78BaseShape::BaseShape(Class *clasp, JSObject *parent, uint32_t objectFlags,
 79                     uint8_t attrs, js::PropertyOp rawGetter, js::StrictPropertyOp rawSetter)
 80{
 81    JS_ASSERT(!(objectFlags & ~OBJECT_FLAG_MASK));
 82    PodZero(this);
 83    this->clasp = clasp;
 84    this->parent = parent;
 85    this->flags = objectFlags;
 86    this->rawGetter = rawGetter;
 87    this->rawSetter = rawSetter;
 88    if ((attrs & JSPROP_GETTER) && rawGetter) {
 89        this->flags |= HAS_GETTER_OBJECT;
 90        JSObject::writeBarrierPost(this->getterObj, &this->getterObj);
 91    }
 92    if ((attrs & JSPROP_SETTER) && rawSetter) {
 93        this->flags |= HAS_SETTER_OBJECT;
 94        JSObject::writeBarrierPost(this->setterObj, &this->setterObj);
 95    }
 96}
 97
 98inline
 99BaseShape::BaseShape(const StackBaseShape &base)
100{
101    PodZero(this);
102    this->clasp = base.clasp;
103    this->parent = base.parent;
104    this->flags = base.flags;
105    this->rawGetter = base.rawGetter;
106    this->rawSetter = base.rawSetter;
107    if ((base.flags & HAS_GETTER_OBJECT) && base.rawGetter) {
108        JSObject::writeBarrierPost(this->getterObj, &this->getterObj);
109    }
110    if ((base.flags & HAS_SETTER_OBJECT) && base.rawSetter) {
111        JSObject::writeBarrierPost(this->setterObj, &this->setterObj);
112    }
113}
114
115inline BaseShape &
116BaseShape::operator=(const BaseShape &other)
117{
118    clasp = other.clasp;
119    parent = other.parent;
120    flags = other.flags;
121    slotSpan_ = other.slotSpan_;
122    if (flags & HAS_GETTER_OBJECT) {
123        getterObj = other.getterObj;
124        JSObject::writeBarrierPost(getterObj, &getterObj);
125    } else {
126        rawGetter = other.rawGetter;
127    }
128    if (flags & HAS_SETTER_OBJECT) {
129        setterObj = other.setterObj;
130        JSObject::writeBarrierPost(setterObj, &setterObj);
131    } else {
132        rawSetter = other.rawSetter;
133    }
134    return *this;
135}
136
137inline bool
138BaseShape::matchesGetterSetter(PropertyOp rawGetter, StrictPropertyOp rawSetter) const
139{
140    return rawGetter == this->rawGetter && rawSetter == this->rawSetter;
141}
142
143inline
144StackBaseShape::StackBaseShape(Shape *shape)
145  : flags(shape->getObjectFlags()),
146    clasp(shape->getObjectClass()),
147    parent(shape->getObjectParent())
148{
149    updateGetterSetter(shape->attrs, shape->getter(), shape->setter());
150}
151
152inline void
153StackBaseShape::updateGetterSetter(uint8_t attrs,
154                                   PropertyOp rawGetter,
155                                   StrictPropertyOp rawSetter)
156{
157    flags &= ~(BaseShape::HAS_GETTER_OBJECT | BaseShape::HAS_SETTER_OBJECT);
158    if ((attrs & JSPROP_GETTER) && rawGetter)
159        flags |= BaseShape::HAS_GETTER_OBJECT;
160    if ((attrs & JSPROP_SETTER) && rawSetter)
161        flags |= BaseShape::HAS_SETTER_OBJECT;
162
163    this->rawGetter = rawGetter;
164    this->rawSetter = rawSetter;
165}
166
167inline void
168BaseShape::adoptUnowned(UnownedBaseShape *other)
169{
170    /*
171     * This is a base shape owned by a dictionary object, update it to reflect the
172     * unowned base shape of a new last property.
173     */
174    JS_ASSERT(isOwned());
175    DebugOnly<uint32_t> flags = getObjectFlags();
176    JS_ASSERT((flags & other->getObjectFlags()) == flags);
177
178    uint32_t span = slotSpan();
179    PropertyTable *table = &this->table();
180
181    *this = *other;
182    setOwned(other);
183    setTable(table);
184    setSlotSpan(span);
185
186    assertConsistency();
187}
188
189inline void
190BaseShape::setOwned(UnownedBaseShape *unowned)
191{
192    flags |= OWNED_SHAPE;
193    this->unowned_ = unowned;
194}
195
196inline void
197BaseShape::assertConsistency()
198{
199#ifdef DEBUG
200    if (isOwned()) {
201        UnownedBaseShape *unowned = baseUnowned();
202        JS_ASSERT(hasGetterObject() == unowned->hasGetterObject());
203        JS_ASSERT(hasSetterObject() == unowned->hasSetterObject());
204        JS_ASSERT_IF(hasGetterObject(), getterObject() == unowned->getterObject());
205        JS_ASSERT_IF(hasSetterObject(), setterObject() == unowned->setterObject());
206        JS_ASSERT(getObjectParent() == unowned->getObjectParent());
207        JS_ASSERT(getObjectFlags() == unowned->getObjectFlags());
208    }
209#endif
210}
211
212inline
213Shape::Shape(const StackShape &other, uint32_t nfixed)
214  : base_(other.base),
215    propid_(other.propid),
216    slotInfo(other.maybeSlot() | (nfixed << FIXED_SLOTS_SHIFT)),
217    attrs(other.attrs),
218    flags(other.flags),
219    shortid_(other.shortid),
220    parent(NULL)
221{
222    kids.setNull();
223}
224
225inline
226Shape::Shape(UnownedBaseShape *base, uint32_t nfixed)
227  : base_(base),
228    propid_(JSID_EMPTY),
229    slotInfo(SHAPE_INVALID_SLOT | (nfixed << FIXED_SLOTS_SHIFT)),
230    attrs(JSPROP_SHARED),
231    flags(0),
232    shortid_(0),
233    parent(NULL)
234{
235    JS_ASSERT(base);
236    kids.setNull();
237}
238
239inline JSDHashNumber
240StackShape::hash() const
241{
242    JSDHashNumber hash = uintptr_t(base);
243
244    /* Accumulate from least to most random so the low bits are most random. */
245    hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & Shape::PUBLIC_FLAGS);
246    hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
247    hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
248    hash = JS_ROTATE_LEFT32(hash, 4) ^ slot_;
249    hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(propid);
250    return hash;
251}
252
253inline bool
254Shape::matches(const js::Shape *other) const
255{
256    return propid_.get() == other->propid_.get() &&
257           matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs,
258                                other->flags, other->shortid_);
259}
260
261inline bool
262Shape::matches(const StackShape &other) const
263{
264    return propid_.get() == other.propid &&
265           matchesParamsAfterId(other.base, other.slot_, other.attrs, other.flags, other.shortid);
266}
267
268inline bool
269Shape::matchesParamsAfterId(BaseShape *base, uint32_t aslot,
270                            uintN aattrs, uintN aflags, intN ashortid) const
271{
272    return base->unowned() == this->base()->unowned() &&
273           maybeSlot() == aslot &&
274           attrs == aattrs &&
275           ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
276           shortid_ == ashortid;
277}
278
279inline bool
280Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js::Value* vp) const
281{
282    JS_ASSERT(!hasDefaultGetter());
283
284    if (hasGetterValue()) {
285        JS_ASSERT(!isMethod());
286        js::Value fval = getterValue();
287        return js::InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
288    }
289
290    if (isMethod()) {
291        vp->setObject(*pobj->nativeGetMethod(this));
292        return pobj->methodReadBarrier(cx, *this, vp);
293    }
294
295    /*
296     * |with (it) color;| ends up here, as do XML filter-expressions.
297     * Avoid exposing the With object to native getters.
298     */
299    if (obj->isWith())
300        obj = &obj->asWith().object();
301    return js::CallJSPropertyOp(cx, getterOp(), receiver, getUserId(), vp);
302}
303
304inline bool
305Shape::set(JSContext* cx, JSObject* obj, bool strict, js::Value* vp) const
306{
307    JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
308
309    if (attrs & JSPROP_SETTER) {
310        js::Value fval = setterValue();
311        return js::InvokeGetterOrSetter(cx, obj, fval, 1, vp, vp);
312    }
313
314    if (attrs & JSPROP_GETTER)
315        return js_ReportGetterOnlyAssignment(cx);
316
317    /* See the comment in js::Shape::get as to why we check for With. */
318    if (obj->isWith())
319        obj = &obj->asWith().object();
320    return js::CallJSPropertyOpSetter(cx, setterOp(), obj, getUserId(), strict, vp);
321}
322
323inline void
324Shape::setParent(js::Shape *p)
325{
326    JS_ASSERT_IF(p && !p->hasMissingSlot() && !inDictionary(),
327                 p->maybeSlot() <= maybeSlot());
328    JS_ASSERT_IF(p && !inDictionary(),
329                 hasSlot() == (p->maybeSlot() != maybeSlot()));
330    parent = p;
331}
332
333inline void
334Shape::removeFromDictionary(JSObject *obj)
335{
336    JS_ASSERT(inDictionary());
337    JS_ASSERT(obj->inDictionaryMode());
338    JS_ASSERT(listp);
339
340    JS_ASSERT(obj->shape_->inDictionary());
341    JS_ASSERT(obj->shape_->listp == &obj->shape_);
342
343    if (parent)
344        parent->listp = listp;
345    *listp = parent;
346    listp = NULL;
347}
348
349inline void
350Shape::insertIntoDictionary(HeapPtrShape *dictp)
351{
352    /*
353     * Don't assert inDictionaryMode() here because we may be called from
354     * JSObject::toDictionaryMode via JSObject::newDictionaryShape.
355     */
356    JS_ASSERT(inDictionary());
357    JS_ASSERT(!listp);
358
359    JS_ASSERT_IF(*dictp, (*dictp)->inDictionary());
360    JS_ASSERT_IF(*dictp, (*dictp)->listp == dictp);
361    JS_ASSERT_IF(*dictp, compartment() == (*dictp)->compartment());
362
363    setParent(*dictp);
364    if (parent)
365        parent->listp = &parent;
366    listp = (HeapPtrShape *) dictp;
367    *dictp = this;
368}
369
370void
371Shape::initDictionaryShape(const StackShape &child, uint32_t nfixed, HeapPtrShape *dictp)
372{
373    new (this) Shape(child, nfixed);
374    this->flags |= IN_DICTIONARY;
375
376    this->listp = NULL;
377    insertIntoDictionary(dictp);
378}
379
380inline
381EmptyShape::EmptyShape(UnownedBaseShape *base, uint32_t nfixed)
382  : js::Shape(base, nfixed)
383{
384    /* Only empty shapes can be NON_NATIVE. */
385    if (!getObjectClass()->isNative())
386        flags |= NON_NATIVE;
387}
388
389inline void
390Shape::writeBarrierPre(const js::Shape *shape)
391{
392#ifdef JSGC_INCREMENTAL
393    if (!shape)
394        return;
395
396    JSCompartment *comp = shape->compartment();
397    if (comp->needsBarrier())
398        MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "write barrier");
399#endif
400}
401
402inline void
403Shape::writeBarrierPost(const js::Shape *shape, void *addr)
404{
405}
406
407inline void
408Shape::readBarrier(const Shape *shape)
409{
410#ifdef JSGC_INCREMENTAL
411    JSCompartment *comp = shape->compartment();
412    if (comp->needsBarrier())
413        MarkShapeUnbarriered(comp->barrierTracer(), const_cast<Shape *>(shape), "read barrier");
414#endif
415}
416
417inline void
418BaseShape::writeBarrierPre(BaseShape *base)
419{
420#ifdef JSGC_INCREMENTAL
421    if (!base)
422        return;
423
424    JSCompartment *comp = base->compartment();
425    if (comp->needsBarrier())
426        MarkBaseShapeUnbarriered(comp->barrierTracer(), base, "write barrier");
427#endif
428}
429
430inline void
431BaseShape::writeBarrierPost(BaseShape *shape, void *addr)
432{
433}
434
435inline void
436BaseShape::readBarrier(BaseShape *base)
437{
438#ifdef JSGC_INCREMENTAL
439    JSCompartment *comp = base->compartment();
440    if (comp->needsBarrier())
441        MarkBaseShapeUnbarriered(comp->barrierTracer(), base, "read barrier");
442#endif
443}
444
445} /* namespace js */
446
447#endif /* jsscopeinlines_h___ */