mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1105069 - Part 2: Implement GCCellPtr; r=jonco
--HG-- extra : rebase_source : 429ccde74ab4732c864582b776c223b1f81b198c
This commit is contained in:
parent
98a5f959aa
commit
21bfd50b31
@ -9,8 +9,6 @@
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/TracingAPI.h"
|
||||
#include "js/Utility.h"
|
||||
|
||||
@ -205,6 +203,81 @@ struct Zone
|
||||
};
|
||||
|
||||
} /* namespace shadow */
|
||||
|
||||
// A GC pointer, tagged with the trace kind.
|
||||
//
|
||||
// In general, a GC pointer should be stored with an exact type. This class
|
||||
// is for use when that is not possible because a single pointer must point
|
||||
// to several kinds of GC thing.
|
||||
class JS_FRIEND_API(GCCellPtr)
|
||||
{
|
||||
public:
|
||||
// Construction from a void* and trace kind.
|
||||
GCCellPtr(void *gcthing, JSGCTraceKind traceKind) : ptr(checkedCast(gcthing, traceKind)) {}
|
||||
|
||||
// Construction from an explicit type.
|
||||
explicit GCCellPtr(JSObject *obj) : ptr(checkedCast(obj, JSTRACE_OBJECT)) { }
|
||||
explicit GCCellPtr(JSFunction *fun) : ptr(checkedCast(fun, JSTRACE_OBJECT)) { }
|
||||
explicit GCCellPtr(JSString *str) : ptr(checkedCast(str, JSTRACE_STRING)) { }
|
||||
explicit GCCellPtr(JSFlatString *str) : ptr(checkedCast(str, JSTRACE_STRING)) { }
|
||||
explicit GCCellPtr(JSScript *script) : ptr(checkedCast(script, JSTRACE_SCRIPT)) { }
|
||||
explicit GCCellPtr(const Value &v);
|
||||
|
||||
// Not all compilers have nullptr_t yet, so use this instead of GCCellPtr(nullptr).
|
||||
static GCCellPtr NullPtr() { return GCCellPtr(nullptr, JSTRACE_NULL); }
|
||||
|
||||
JSGCTraceKind kind() const {
|
||||
JSGCTraceKind traceKind = JSGCTraceKind(ptr & JSTRACE_OUTOFLINE);
|
||||
if (traceKind != JSTRACE_OUTOFLINE)
|
||||
return traceKind;
|
||||
return outOfLineKind();
|
||||
}
|
||||
|
||||
// Allow CellPtr to be used as a js::gc::Cell.
|
||||
operator js::gc::Cell *() const { return asCell(); }
|
||||
js::gc::Cell *operator->() const { return asCell(); }
|
||||
|
||||
// Conversions to more specific types must match the kind. Access to
|
||||
// further refined types is not allowed directly from a GCCellPtr.
|
||||
JSObject *toObject() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_OBJECT);
|
||||
return reinterpret_cast<JSObject *>(asCell());
|
||||
}
|
||||
JSString *toString() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_STRING);
|
||||
return reinterpret_cast<JSString *>(asCell());
|
||||
}
|
||||
JSScript *toScript() const {
|
||||
MOZ_ASSERT(kind() == JSTRACE_SCRIPT);
|
||||
return reinterpret_cast<JSScript *>(asCell());
|
||||
}
|
||||
|
||||
// The CC's trace logger needs an identity that is XPIDL serializable.
|
||||
void *unsafeGetUntypedPtr() const {
|
||||
return reinterpret_cast<void *>(asCell());
|
||||
}
|
||||
|
||||
private:
|
||||
uintptr_t checkedCast(void *p, JSGCTraceKind traceKind) {
|
||||
js::gc::Cell *cell = static_cast<js::gc::Cell *>(p);
|
||||
MOZ_ASSERT((uintptr_t(p) & JSTRACE_OUTOFLINE) == 0);
|
||||
AssertGCThingHasType(cell, traceKind);
|
||||
// Note: the JSTRACE_OUTOFLINE bits are set on all out-of-line kinds
|
||||
// so that we can mask instead of branching.
|
||||
MOZ_ASSERT_IF(traceKind >= JSTRACE_OUTOFLINE,
|
||||
(traceKind & JSTRACE_OUTOFLINE) == JSTRACE_OUTOFLINE);
|
||||
return uintptr_t(p) | (traceKind & JSTRACE_OUTOFLINE);
|
||||
}
|
||||
|
||||
js::gc::Cell *asCell() const {
|
||||
return reinterpret_cast<js::gc::Cell *>(ptr & ~JSTRACE_OUTOFLINE);
|
||||
}
|
||||
|
||||
JSGCTraceKind outOfLineKind() const;
|
||||
|
||||
uintptr_t ptr;
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
namespace js {
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/NullPtr.h"
|
||||
|
||||
#include "jsalloc.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
|
@ -33,6 +33,7 @@ UNIFIED_SOURCES += [
|
||||
'testFreshGlobalEvalRedefinition.cpp',
|
||||
'testFunctionProperties.cpp',
|
||||
'testGCAllocator.cpp',
|
||||
'testGCCellPtr.cpp',
|
||||
'testGCChunkPool.cpp',
|
||||
'testGCExactRooting.cpp',
|
||||
'testGCFinalizeCallback.cpp',
|
||||
|
61
js/src/jsapi-tests/testGCCellPtr.cpp
Normal file
61
js/src/jsapi-tests/testGCCellPtr.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "gc/Heap.h"
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
JS::GCCellPtr
|
||||
GivesAndTakesCells(JS::GCCellPtr cell)
|
||||
{
|
||||
return cell;
|
||||
}
|
||||
|
||||
BEGIN_TEST(testGCCellPtr)
|
||||
{
|
||||
JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
|
||||
CHECK(obj);
|
||||
|
||||
JS::RootedString str(cx, JS_NewStringCopyZ(cx, "probably foobar"));
|
||||
CHECK(str);
|
||||
|
||||
const char *code = "function foo() { return 'bar'; }";
|
||||
JS::CompileOptions opts(cx);
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS_CompileScript(cx, obj, code, strlen(code), opts, &script));
|
||||
CHECK(script);
|
||||
|
||||
CHECK(!JS::GCCellPtr::NullPtr());
|
||||
|
||||
CHECK(JS::GCCellPtr(obj.get()));
|
||||
CHECK(JS::GCCellPtr(obj.get()).kind() == JSTRACE_OBJECT);
|
||||
CHECK(JS::GCCellPtr(JS::ObjectValue(*obj)).kind() == JSTRACE_OBJECT);
|
||||
|
||||
CHECK(JS::GCCellPtr(str.get()));
|
||||
CHECK(JS::GCCellPtr(str.get()).kind() == JSTRACE_STRING);
|
||||
CHECK(JS::GCCellPtr(JS::StringValue(str)).kind() == JSTRACE_STRING);
|
||||
|
||||
CHECK(JS::GCCellPtr(script.get()));
|
||||
CHECK(!JS::GCCellPtr::NullPtr());
|
||||
CHECK(JS::GCCellPtr(script.get()).kind() == JSTRACE_SCRIPT);
|
||||
|
||||
JS::GCCellPtr objcell(obj.get());
|
||||
JS::GCCellPtr scriptcell = JS::GCCellPtr(script.get());
|
||||
CHECK(GivesAndTakesCells(objcell));
|
||||
CHECK(GivesAndTakesCells(scriptcell));
|
||||
|
||||
JS::GCCellPtr copy = objcell;
|
||||
CHECK(copy == objcell);
|
||||
|
||||
CHECK(js::gc::GetGCThingRuntime(scriptcell) == rt);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testGCCellPtr)
|
@ -6939,8 +6939,9 @@ JS::AssertGCThingMustBeTenured(JSObject *obj)
|
||||
JS_FRIEND_API(void)
|
||||
js::gc::AssertGCThingHasType(js::gc::Cell *cell, JSGCTraceKind kind)
|
||||
{
|
||||
MOZ_ASSERT(cell);
|
||||
if (IsInsideNursery(cell))
|
||||
if (!cell)
|
||||
MOZ_ASSERT(kind == JSTRACE_NULL);
|
||||
else if (IsInsideNursery(cell))
|
||||
MOZ_ASSERT(kind == JSTRACE_OBJECT);
|
||||
else
|
||||
MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind);
|
||||
@ -7046,6 +7047,27 @@ JS::GCTraceKindToAscii(JSGCTraceKind kind)
|
||||
}
|
||||
}
|
||||
|
||||
JS::GCCellPtr::GCCellPtr(const Value &v)
|
||||
: ptr(0)
|
||||
{
|
||||
if (v.isString())
|
||||
ptr = checkedCast(v.toString(), JSTRACE_STRING);
|
||||
else if (v.isObject())
|
||||
ptr = checkedCast(&v.toObject(), JSTRACE_OBJECT);
|
||||
else if (v.isSymbol())
|
||||
ptr = checkedCast(v.toSymbol(), JSTRACE_SYMBOL);
|
||||
else
|
||||
ptr = checkedCast(nullptr, JSTRACE_NULL);
|
||||
}
|
||||
|
||||
JSGCTraceKind
|
||||
JS::GCCellPtr::outOfLineKind() const
|
||||
{
|
||||
MOZ_ASSERT(JSGCTraceKind(ptr & JSTRACE_OUTOFLINE) == JSTRACE_OUTOFLINE);
|
||||
MOZ_ASSERT(asCell()->isTenured());
|
||||
return MapAllocToTraceKind(asCell()->asTenured().getAllocKind());
|
||||
}
|
||||
|
||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
||||
void
|
||||
js::gc::CheckHashTablesAfterMovingGC(JSRuntime *rt)
|
||||
|
Loading…
Reference in New Issue
Block a user