mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 966575 Part 13 -- Remove type repr completely, replacing with atomized strings r=sfink
This commit is contained in:
parent
ad08b39137
commit
464bac9d95
@ -137,7 +137,7 @@ class Float32x4Defn {
|
||||
} // namespace js
|
||||
|
||||
const JSFunctionSpec js::Float32x4Defn::TypeDescriptorMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
|
||||
JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
|
||||
JS_FS_END
|
||||
@ -158,7 +158,7 @@ const JSFunctionSpec js::Float32x4Defn::TypedObjectMethods[] = {
|
||||
};
|
||||
|
||||
const JSFunctionSpec js::Int32x4Defn::TypeDescriptorMethods[] = {
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
|
||||
JS_SELF_HOSTED_FN("toSource", "DescrToSource", 0, 0),
|
||||
JS_SELF_HOSTED_FN("array", "ArrayShorthand", 1, 0),
|
||||
JS_SELF_HOSTED_FN("equivalent", "TypeDescrEquivalent", 1, 0),
|
||||
JS_FS_END,
|
||||
@ -180,19 +180,16 @@ const JSFunctionSpec js::Int32x4Defn::TypedObjectMethods[] = {
|
||||
|
||||
template<typename T>
|
||||
static JSObject *
|
||||
CreateX4Class(JSContext *cx, Handle<GlobalObject*> global)
|
||||
CreateX4Class(JSContext *cx,
|
||||
Handle<GlobalObject*> global,
|
||||
HandlePropertyName stringRepr)
|
||||
{
|
||||
const X4TypeDescr::Type type = T::type;
|
||||
|
||||
RootedObject funcProto(cx, global->getOrCreateFunctionPrototype(cx));
|
||||
if (!funcProto)
|
||||
return nullptr;
|
||||
|
||||
// Create type representation.
|
||||
|
||||
RootedObject typeReprObj(cx);
|
||||
typeReprObj = X4TypeRepresentation::Create(cx, T::type);
|
||||
if (!typeReprObj)
|
||||
return nullptr;
|
||||
|
||||
// Create prototype property, which inherits from Object.prototype.
|
||||
|
||||
RootedObject objProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
@ -207,12 +204,20 @@ CreateX4Class(JSContext *cx, Handle<GlobalObject*> global)
|
||||
|
||||
Rooted<X4TypeDescr*> x4(cx);
|
||||
x4 = NewObjectWithProto<X4TypeDescr>(cx, funcProto, global, TenuredObject);
|
||||
if (!x4 || !InitializeCommonTypeDescriptorProperties(cx, x4, typeReprObj))
|
||||
if (!x4)
|
||||
return nullptr;
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_TYPE_REPR, ObjectValue(*typeReprObj));
|
||||
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_KIND, Int32Value(TypeDescr::X4));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_STRING_REPR, StringValue(stringRepr));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_ALIGNMENT, Int32Value(X4TypeDescr::size(type)));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_SIZE, Int32Value(X4TypeDescr::alignment(type)));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_OPAQUE, BooleanValue(false));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_TYPE, Int32Value(T::type));
|
||||
x4->initReservedSlot(JS_DESCR_SLOT_PROTO, ObjectValue(*proto));
|
||||
|
||||
if (!CreateUserSizeAndAlignmentProperties(cx, x4))
|
||||
return nullptr;
|
||||
|
||||
// Link constructor to prototype and install properties.
|
||||
|
||||
if (!JS_DefineFunctions(cx, x4, T::TypeDescriptorMethods))
|
||||
@ -310,7 +315,9 @@ SIMDObject::initClass(JSContext *cx, Handle<GlobalObject *> global)
|
||||
|
||||
// float32x4
|
||||
|
||||
RootedObject float32x4Object(cx, CreateX4Class<Float32x4Defn>(cx, global));
|
||||
RootedObject float32x4Object(cx);
|
||||
float32x4Object = CreateX4Class<Float32x4Defn>(cx, global,
|
||||
cx->names().float32x4);
|
||||
if (!float32x4Object)
|
||||
return nullptr;
|
||||
|
||||
@ -325,7 +332,9 @@ SIMDObject::initClass(JSContext *cx, Handle<GlobalObject *> global)
|
||||
|
||||
// int32x4
|
||||
|
||||
RootedObject int32x4Object(cx, CreateX4Class<Int32x4Defn>(cx, global));
|
||||
RootedObject int32x4Object(cx);
|
||||
int32x4Object = CreateX4Class<Int32x4Defn>(cx, global,
|
||||
cx->names().int32x4);
|
||||
if (!int32x4Object)
|
||||
return nullptr;
|
||||
|
||||
|
@ -1,858 +0,0 @@
|
||||
/* -*- 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 "builtin/TypeRepresentation.h"
|
||||
|
||||
#include "mozilla/HashFunctions.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsnum.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace mozilla;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Class def'n for the owner object
|
||||
|
||||
const Class TypeRepresentation::class_ = {
|
||||
"TypeRepresentation",
|
||||
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(JS_TYPEREPR_SLOTS),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_DeletePropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
JS_ConvertStub,
|
||||
obj_finalize,
|
||||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
obj_trace,
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Hashing
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::match(TypeRepresentation *key1,
|
||||
TypeRepresentation *key2)
|
||||
{
|
||||
if (key1->kind() != key2->kind())
|
||||
return false;
|
||||
|
||||
switch (key1->kind()) {
|
||||
case TypeDescr::Scalar:
|
||||
return matchScalars(key1->asScalar(), key2->asScalar());
|
||||
|
||||
case TypeDescr::Reference:
|
||||
return matchReferences(key1->asReference(), key2->asReference());
|
||||
|
||||
case TypeDescr::X4:
|
||||
return matchX4s(key1->asX4(), key2->asX4());
|
||||
|
||||
case TypeDescr::Struct:
|
||||
return matchStructs(key1->asStruct(), key2->asStruct());
|
||||
|
||||
case TypeDescr::SizedArray:
|
||||
return matchSizedArrays(key1->asSizedArray(),
|
||||
key2->asSizedArray());
|
||||
|
||||
case TypeDescr::UnsizedArray:
|
||||
return matchUnsizedArrays(key1->asUnsizedArray(),
|
||||
key2->asUnsizedArray());
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid kind");
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchScalars(ScalarTypeRepresentation *key1,
|
||||
ScalarTypeRepresentation *key2)
|
||||
{
|
||||
return key1->type() == key2->type();
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchReferences(ReferenceTypeRepresentation *key1,
|
||||
ReferenceTypeRepresentation *key2)
|
||||
{
|
||||
return key1->type() == key2->type();
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchX4s(X4TypeRepresentation *key1,
|
||||
X4TypeRepresentation *key2)
|
||||
{
|
||||
return key1->type() == key2->type();
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchStructs(StructTypeRepresentation *key1,
|
||||
StructTypeRepresentation *key2)
|
||||
{
|
||||
if (key1->fieldCount() != key2->fieldCount())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < key1->fieldCount(); i++) {
|
||||
if (key1->field(i).propertyName != key2->field(i).propertyName)
|
||||
return false;
|
||||
|
||||
if (key1->field(i).typeRepr != key2->field(i).typeRepr)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchSizedArrays(SizedArrayTypeRepresentation *key1,
|
||||
SizedArrayTypeRepresentation *key2)
|
||||
{
|
||||
// We assume that these pointers have been canonicalized:
|
||||
return key1->element() == key2->element() &&
|
||||
key1->length() == key2->length();
|
||||
}
|
||||
|
||||
bool
|
||||
TypeRepresentationHasher::matchUnsizedArrays(UnsizedArrayTypeRepresentation *key1,
|
||||
UnsizedArrayTypeRepresentation *key2)
|
||||
{
|
||||
// We assume that these pointers have been canonicalized:
|
||||
return key1->element() == key2->element();
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hash(TypeRepresentation *key) {
|
||||
switch (key->kind()) {
|
||||
case TypeDescr::Scalar:
|
||||
return hashScalar(key->asScalar());
|
||||
|
||||
case TypeDescr::Reference:
|
||||
return hashReference(key->asReference());
|
||||
|
||||
case TypeDescr::X4:
|
||||
return hashX4(key->asX4());
|
||||
|
||||
case TypeDescr::Struct:
|
||||
return hashStruct(key->asStruct());
|
||||
|
||||
case TypeDescr::UnsizedArray:
|
||||
return hashUnsizedArray(key->asUnsizedArray());
|
||||
|
||||
case TypeDescr::SizedArray:
|
||||
return hashSizedArray(key->asSizedArray());
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid kind");
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashScalar(ScalarTypeRepresentation *key)
|
||||
{
|
||||
return HashGeneric(key->kind(), key->type());
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashReference(ReferenceTypeRepresentation *key)
|
||||
{
|
||||
return HashGeneric(key->kind(), key->type());
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashX4(X4TypeRepresentation *key)
|
||||
{
|
||||
return HashGeneric(key->kind(), key->type());
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashStruct(StructTypeRepresentation *key)
|
||||
{
|
||||
HashNumber hash = HashGeneric(key->kind());
|
||||
for (HashNumber i = 0; i < key->fieldCount(); i++) {
|
||||
hash = AddToHash(hash, key->field(i).propertyName.get());
|
||||
hash = AddToHash(hash, key->field(i).typeRepr);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashSizedArray(SizedArrayTypeRepresentation *key)
|
||||
{
|
||||
return HashGeneric(key->kind(), key->element(), key->length());
|
||||
}
|
||||
|
||||
HashNumber
|
||||
TypeRepresentationHasher::hashUnsizedArray(UnsizedArrayTypeRepresentation *key)
|
||||
{
|
||||
return HashGeneric(key->kind(), key->element());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Constructors
|
||||
|
||||
TypeRepresentation::TypeRepresentation(TypeDescr::Kind kind,
|
||||
size_t align,
|
||||
bool opaque)
|
||||
: kind_(kind),
|
||||
opaque_(opaque),
|
||||
alignment_(align)
|
||||
{}
|
||||
|
||||
SizedTypeRepresentation::SizedTypeRepresentation(SizedTypeDescr::Kind kind,
|
||||
bool opaque,
|
||||
size_t size,
|
||||
size_t align)
|
||||
: TypeRepresentation(kind, align, opaque),
|
||||
size_(size)
|
||||
{}
|
||||
|
||||
ScalarTypeRepresentation::ScalarTypeRepresentation(ScalarTypeDescr::Type type)
|
||||
: SizedTypeRepresentation(TypeDescr::Scalar,
|
||||
false,
|
||||
ScalarTypeDescr::size(type),
|
||||
ScalarTypeDescr::alignment(type)),
|
||||
type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
static size_t X4Sizes[] = {
|
||||
#define X4_SIZE(_kind, _type, _name) \
|
||||
sizeof(_type) * 4,
|
||||
JS_FOR_EACH_X4_TYPE_REPR(X4_SIZE) 0
|
||||
#undef X4_SIZE
|
||||
};
|
||||
|
||||
X4TypeRepresentation::X4TypeRepresentation(X4TypeDescr::Type type)
|
||||
: SizedTypeRepresentation(X4TypeDescr::X4, false, X4Sizes[type], X4Sizes[type]),
|
||||
type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
ReferenceTypeRepresentation::ReferenceTypeRepresentation(ReferenceTypeDescr::Type type)
|
||||
: SizedTypeRepresentation(TypeDescr::Reference, true, 0, 1),
|
||||
type_(type)
|
||||
{
|
||||
switch (type) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
size_ = sizeof(js::HeapValue);
|
||||
alignment_ = MOZ_ALIGNOF(js::HeapValue);
|
||||
break;
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
size_ = sizeof(js::HeapPtrObject);
|
||||
alignment_ = MOZ_ALIGNOF(js::HeapPtrObject);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SizedArrayTypeRepresentation::SizedArrayTypeRepresentation(SizedTypeRepresentation *element,
|
||||
size_t length)
|
||||
: SizedTypeRepresentation(TypeDescr::SizedArray, element->opaque(),
|
||||
element->size() * length, element->alignment()),
|
||||
element_(element),
|
||||
length_(length)
|
||||
{
|
||||
}
|
||||
|
||||
UnsizedArrayTypeRepresentation::UnsizedArrayTypeRepresentation(SizedTypeRepresentation *element)
|
||||
: TypeRepresentation(TypeDescr::UnsizedArray, element->alignment(),
|
||||
element->opaque()),
|
||||
element_(element)
|
||||
{
|
||||
}
|
||||
|
||||
static inline size_t alignTo(size_t address, size_t align) {
|
||||
JS_ASSERT(IsPowerOfTwo(align));
|
||||
return (address + align - 1) & -align;
|
||||
}
|
||||
|
||||
StructField::StructField(size_t index,
|
||||
PropertyName *propertyName,
|
||||
SizedTypeRepresentation *typeRepr,
|
||||
size_t offset)
|
||||
: index(index),
|
||||
propertyName(propertyName),
|
||||
typeRepr(typeRepr),
|
||||
offset(offset)
|
||||
{}
|
||||
|
||||
StructTypeRepresentation::StructTypeRepresentation()
|
||||
: SizedTypeRepresentation(TypeDescr::Struct, false, 0, 1),
|
||||
fieldCount_(0) // see ::init() below!
|
||||
{
|
||||
// note: size_, alignment_, and opaque_ are computed in ::init() below
|
||||
}
|
||||
|
||||
bool
|
||||
StructTypeRepresentation::init(JSContext *cx,
|
||||
AutoPropertyNameVector &names,
|
||||
AutoObjectVector &typeReprOwners)
|
||||
{
|
||||
JS_ASSERT(names.length() == typeReprOwners.length());
|
||||
fieldCount_ = names.length();
|
||||
|
||||
// We compute alignment into the field `align_` directly in the
|
||||
// loop below, but not `size_` because we have to very careful
|
||||
// about overflow. For now, we always use a int32_t for
|
||||
// consistency across build environments.
|
||||
int32_t totalSize = 0;
|
||||
|
||||
// These will be adjusted in the loop below:
|
||||
alignment_ = 1;
|
||||
opaque_ = false;
|
||||
|
||||
for (size_t i = 0; i < names.length(); i++) {
|
||||
SizedTypeRepresentation *fieldTypeRepr =
|
||||
fromOwnerObject(*typeReprOwners[i])->asSized();
|
||||
|
||||
if (fieldTypeRepr->opaque())
|
||||
opaque_ = true;
|
||||
|
||||
int32_t alignedSize = alignTo(totalSize, fieldTypeRepr->alignment());
|
||||
if (alignedSize < totalSize) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
|
||||
new(fields() + i) StructField(i, names[i],
|
||||
fieldTypeRepr, alignedSize);
|
||||
alignment_ = js::Max(alignment_, fieldTypeRepr->alignment());
|
||||
|
||||
int32_t incrementedSize = alignedSize + fieldTypeRepr->size();
|
||||
if (incrementedSize < alignedSize) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
|
||||
totalSize = incrementedSize;
|
||||
}
|
||||
|
||||
int32_t alignedSize = alignTo(totalSize, alignment_);
|
||||
if (alignedSize < totalSize) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_ = alignedSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Interning
|
||||
|
||||
JSObject *
|
||||
TypeRepresentation::addToTableOrFree(JSContext *cx,
|
||||
TypeRepresentationHash::AddPtr &p)
|
||||
{
|
||||
JS_ASSERT(!ownerObject_);
|
||||
Rooted<GlobalObject*> global(cx, cx->global());
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
// First, attempt to add the type representation to the table.
|
||||
if (!comp->typeReprs.relookupOrAdd(p, this, this)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
js_free(this); // do not finalize, not present in the table
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject objectProto(cx, global->getOrCreateObjectPrototype(cx));
|
||||
if (!objectProto)
|
||||
return nullptr;
|
||||
|
||||
// Now that the object is in the table, try to make the owner
|
||||
// object. If this succeeds, then the owner will remove from the
|
||||
// table once it is finalized. Otherwise, if this fails, we must
|
||||
// remove ourselves from the table ourselves and report an error.
|
||||
RootedObject ownerObject(cx);
|
||||
ownerObject = NewObjectWithGivenProto(cx, &class_, objectProto,
|
||||
cx->global(), TenuredObject);
|
||||
if (!ownerObject) {
|
||||
comp->typeReprs.remove(this);
|
||||
js_free(this);
|
||||
return nullptr;
|
||||
}
|
||||
ownerObject->setPrivate(this);
|
||||
ownerObject->initReservedSlot(JS_TYPEREPR_SLOT_KIND, Int32Value(kind()));
|
||||
ownerObject_.init(ownerObject);
|
||||
return &*ownerObject;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
class TypeRepresentationHelper {
|
||||
public:
|
||||
template<typename D, typename T>
|
||||
static JSObject *CreateSimple(JSContext *cx, typename D::Type type) {
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
TypeRepresentationHash::AddPtr p;
|
||||
{
|
||||
T sample(type);
|
||||
p = comp->typeReprs.lookupForAdd(&sample);
|
||||
}
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
// Note: cannot use cx->new_ because constructor is private.
|
||||
T *ptr = (T *) cx->malloc_(sizeof(T));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
new(ptr) T(type);
|
||||
|
||||
return ptr->addToTableOrFree(cx, p);
|
||||
}
|
||||
};
|
||||
} // namespace js
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
ScalarTypeRepresentation::Create(JSContext *cx,
|
||||
ScalarTypeDescr::Type type)
|
||||
{
|
||||
return TypeRepresentationHelper::CreateSimple<ScalarTypeDescr,
|
||||
ScalarTypeRepresentation>(cx, type);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
X4TypeRepresentation::Create(JSContext *cx,
|
||||
X4TypeDescr::Type type)
|
||||
{
|
||||
return TypeRepresentationHelper::CreateSimple<X4TypeDescr,
|
||||
X4TypeRepresentation>(cx, type);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
ReferenceTypeRepresentation::Create(JSContext *cx,
|
||||
ReferenceTypeDescr::Type type)
|
||||
{
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
TypeRepresentationHash::AddPtr p;
|
||||
{
|
||||
ReferenceTypeRepresentation sample(type);
|
||||
p = comp->typeReprs.lookupForAdd(&sample);
|
||||
}
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
// Note: cannot use cx->new_ because constructor is private.
|
||||
ReferenceTypeRepresentation *ptr =
|
||||
(ReferenceTypeRepresentation *) cx->malloc_(
|
||||
sizeof(ReferenceTypeRepresentation));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
new(ptr) ReferenceTypeRepresentation(type);
|
||||
|
||||
return ptr->addToTableOrFree(cx, p);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
SizedArrayTypeRepresentation::Create(JSContext *cx,
|
||||
SizedTypeRepresentation *element,
|
||||
size_t length)
|
||||
{
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
// Overly conservative, since we are using `size_t` to represent
|
||||
// size, but `SafeMul` operators on `int32_t` types. Still, it
|
||||
// should be good enough for now.
|
||||
int32_t temp;
|
||||
if (!SafeMul(element->size(), length, &temp)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_TYPEDOBJECT_TOO_BIG);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TypeRepresentationHash::AddPtr p;
|
||||
{
|
||||
SizedArrayTypeRepresentation sample(element, length);
|
||||
p = comp->typeReprs.lookupForAdd(&sample);
|
||||
}
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
// Note: cannot use cx->new_ because constructor is private.
|
||||
SizedArrayTypeRepresentation *ptr =
|
||||
(SizedArrayTypeRepresentation *) cx->malloc_(
|
||||
sizeof(SizedArrayTypeRepresentation));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
new(ptr) SizedArrayTypeRepresentation(element, length);
|
||||
|
||||
return ptr->addToTableOrFree(cx, p);
|
||||
}
|
||||
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
UnsizedArrayTypeRepresentation::Create(JSContext *cx,
|
||||
SizedTypeRepresentation *element)
|
||||
{
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
TypeRepresentationHash::AddPtr p;
|
||||
{
|
||||
UnsizedArrayTypeRepresentation sample(element);
|
||||
p = comp->typeReprs.lookupForAdd(&sample);
|
||||
}
|
||||
if (p)
|
||||
return (*p)->ownerObject();
|
||||
|
||||
// Note: cannot use cx->new_ because constructor is private.
|
||||
UnsizedArrayTypeRepresentation *ptr =
|
||||
(UnsizedArrayTypeRepresentation *) cx->malloc_(
|
||||
sizeof(UnsizedArrayTypeRepresentation));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
new(ptr) UnsizedArrayTypeRepresentation(element);
|
||||
|
||||
return ptr->addToTableOrFree(cx, p);
|
||||
}
|
||||
|
||||
/*static*/
|
||||
JSObject *
|
||||
StructTypeRepresentation::Create(JSContext *cx,
|
||||
AutoPropertyNameVector &names,
|
||||
AutoObjectVector &typeReprOwners)
|
||||
{
|
||||
size_t count = names.length();
|
||||
JSCompartment *comp = cx->compartment();
|
||||
|
||||
// Note: cannot use cx->new_ because constructor is private.
|
||||
size_t size = sizeof(StructTypeRepresentation) + count * sizeof(StructField);
|
||||
StructTypeRepresentation *ptr =
|
||||
(StructTypeRepresentation *) cx->malloc_(size);
|
||||
new(ptr) StructTypeRepresentation();
|
||||
if (!ptr->init(cx, names, typeReprOwners))
|
||||
return nullptr;
|
||||
|
||||
TypeRepresentationHash::AddPtr p = comp->typeReprs.lookupForAdd(ptr);
|
||||
if (p) {
|
||||
js_free(ptr); // do not finalize, not present in the table
|
||||
return (*p)->ownerObject();
|
||||
}
|
||||
|
||||
return ptr->addToTableOrFree(cx, p);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Tracing
|
||||
|
||||
void
|
||||
TypeRepresentation::mark(JSTracer *trace)
|
||||
{
|
||||
// Push our owner object onto the mark stack. When our owner
|
||||
// object's trace callback is called, we will trace its
|
||||
// contents. This is the typical scheme for marking objects. See
|
||||
// gc/Marking.cpp for more details.
|
||||
gc::MarkObject(trace, &ownerObject_, "typeRepresentation_ownerObject");
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
TypeRepresentation::obj_trace(JSTracer *trace, JSObject *object)
|
||||
{
|
||||
fromOwnerObject(*object)->traceFields(trace);
|
||||
}
|
||||
|
||||
void
|
||||
TypeRepresentation::traceFields(JSTracer *trace)
|
||||
{
|
||||
mark(trace); // don't forget to mark the self-reference here!
|
||||
|
||||
switch (kind()) {
|
||||
case TypeDescr::Scalar:
|
||||
case TypeDescr::Reference:
|
||||
case TypeDescr::X4:
|
||||
break;
|
||||
|
||||
case TypeDescr::Struct:
|
||||
asStruct()->traceStructFields(trace);
|
||||
break;
|
||||
|
||||
case TypeDescr::SizedArray:
|
||||
asSizedArray()->traceSizedArrayFields(trace);
|
||||
break;
|
||||
|
||||
case TypeDescr::UnsizedArray:
|
||||
asUnsizedArray()->traceUnsizedArrayFields(trace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StructTypeRepresentation::traceStructFields(JSTracer *trace)
|
||||
{
|
||||
for (size_t i = 0; i < fieldCount(); i++) {
|
||||
gc::MarkString(trace, &fields()[i].propertyName, "typerepr_field_propertyName");
|
||||
fields()[i].typeRepr->mark(trace);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SizedArrayTypeRepresentation::traceSizedArrayFields(JSTracer *trace)
|
||||
{
|
||||
this->mark(trace);
|
||||
element_->mark(trace);
|
||||
}
|
||||
|
||||
void
|
||||
UnsizedArrayTypeRepresentation::traceUnsizedArrayFields(JSTracer *trace)
|
||||
{
|
||||
this->mark(trace);
|
||||
element_->mark(trace);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Finalization
|
||||
|
||||
/*static*/ void
|
||||
TypeRepresentation::obj_finalize(js::FreeOp *fop, JSObject *object)
|
||||
{
|
||||
JSCompartment *comp = object->compartment();
|
||||
TypeRepresentation *typeRepr = fromOwnerObject(*object);
|
||||
comp->typeReprs.remove(typeRepr);
|
||||
js_free(typeRepr);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Walking memory
|
||||
|
||||
template<typename V>
|
||||
static void
|
||||
visitReferences(SizedTypeRepresentation *repr,
|
||||
uint8_t *mem,
|
||||
V& visitor)
|
||||
{
|
||||
if (repr->transparent())
|
||||
return;
|
||||
|
||||
switch (repr->kind()) {
|
||||
case TypeDescr::Scalar:
|
||||
case TypeDescr::X4:
|
||||
return;
|
||||
|
||||
case TypeDescr::Reference:
|
||||
visitor.visitReference(repr->asReference(), mem);
|
||||
return;
|
||||
|
||||
case TypeDescr::SizedArray:
|
||||
{
|
||||
SizedArrayTypeRepresentation *arrayRepr = repr->asSizedArray();
|
||||
SizedTypeRepresentation *elementRepr = arrayRepr->element();
|
||||
for (size_t i = 0; i < arrayRepr->length(); i++) {
|
||||
visitReferences(elementRepr, mem, visitor);
|
||||
mem += elementRepr->size();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case TypeDescr::UnsizedArray:
|
||||
{
|
||||
MOZ_ASSUME_UNREACHABLE("Only Sized Type representations");
|
||||
}
|
||||
|
||||
case TypeDescr::Struct:
|
||||
{
|
||||
StructTypeRepresentation *structRepr = repr->asStruct();
|
||||
for (size_t i = 0; i < structRepr->fieldCount(); i++) {
|
||||
const StructField &f = structRepr->field(i);
|
||||
visitReferences(f.typeRepr, mem + f.offset, visitor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid type repr kind");
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Initializing instances
|
||||
|
||||
namespace js {
|
||||
class MemoryInitVisitor {
|
||||
const JSRuntime *rt_;
|
||||
|
||||
public:
|
||||
MemoryInitVisitor(const JSRuntime *rt)
|
||||
: rt_(rt)
|
||||
{}
|
||||
|
||||
void visitReference(ReferenceTypeRepresentation *repr, uint8_t *mem);
|
||||
};
|
||||
} // namespace js
|
||||
|
||||
void
|
||||
js::MemoryInitVisitor::visitReference(ReferenceTypeRepresentation *repr, uint8_t *mem)
|
||||
{
|
||||
switch (repr->type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
{
|
||||
js::HeapValue *heapValue = reinterpret_cast<js::HeapValue *>(mem);
|
||||
heapValue->init(UndefinedValue());
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
{
|
||||
js::HeapPtrObject *objectPtr =
|
||||
reinterpret_cast<js::HeapPtrObject *>(mem);
|
||||
objectPtr->init(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
{
|
||||
js::HeapPtrString *stringPtr =
|
||||
reinterpret_cast<js::HeapPtrString *>(mem);
|
||||
stringPtr->init(rt_->emptyString);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid kind");
|
||||
}
|
||||
|
||||
void
|
||||
SizedTypeRepresentation::initInstance(const JSRuntime *rt,
|
||||
uint8_t *mem,
|
||||
size_t length)
|
||||
{
|
||||
JS_ASSERT(length >= 1);
|
||||
|
||||
MemoryInitVisitor visitor(rt);
|
||||
|
||||
// Initialize the 0th instance
|
||||
memset(mem, 0, size());
|
||||
if (opaque())
|
||||
visitReferences(this, mem, visitor);
|
||||
|
||||
// Stamp out N copies of later instances
|
||||
uint8_t *target = mem;
|
||||
for (size_t i = 1; i < length; i++) {
|
||||
target += size();
|
||||
memcpy(target, mem, size());
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Tracing instances
|
||||
|
||||
namespace js {
|
||||
class MemoryTracingVisitor {
|
||||
JSTracer *trace_;
|
||||
|
||||
public:
|
||||
|
||||
MemoryTracingVisitor(JSTracer *trace)
|
||||
: trace_(trace)
|
||||
{}
|
||||
|
||||
void visitReference(ReferenceTypeRepresentation *repr, uint8_t *mem);
|
||||
};
|
||||
} // namespace js
|
||||
|
||||
void
|
||||
js::MemoryTracingVisitor::visitReference(ReferenceTypeRepresentation *repr, uint8_t *mem)
|
||||
{
|
||||
switch (repr->type()) {
|
||||
case ReferenceTypeDescr::TYPE_ANY:
|
||||
{
|
||||
js::HeapValue *heapValue = reinterpret_cast<js::HeapValue *>(mem);
|
||||
gc::MarkValue(trace_, heapValue, "reference-val");
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_OBJECT:
|
||||
{
|
||||
js::HeapPtrObject *objectPtr =
|
||||
reinterpret_cast<js::HeapPtrObject *>(mem);
|
||||
if (*objectPtr)
|
||||
gc::MarkObject(trace_, objectPtr, "reference-obj");
|
||||
return;
|
||||
}
|
||||
|
||||
case ReferenceTypeDescr::TYPE_STRING:
|
||||
{
|
||||
js::HeapPtrString *stringPtr =
|
||||
reinterpret_cast<js::HeapPtrString *>(mem);
|
||||
if (*stringPtr)
|
||||
gc::MarkString(trace_, stringPtr, "reference-str");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSUME_UNREACHABLE("Invalid kind");
|
||||
}
|
||||
|
||||
void
|
||||
SizedTypeRepresentation::traceInstance(JSTracer *trace,
|
||||
uint8_t *mem,
|
||||
size_t length)
|
||||
{
|
||||
MemoryTracingVisitor visitor(trace);
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
visitReferences(this, mem, visitor);
|
||||
mem += size();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Misc
|
||||
|
||||
const StructField *
|
||||
StructTypeRepresentation::fieldNamed(jsid id) const
|
||||
{
|
||||
if (!JSID_IS_ATOM(id))
|
||||
return nullptr;
|
||||
|
||||
uint32_t unused;
|
||||
JSAtom *atom = JSID_TO_ATOM(id);
|
||||
|
||||
if (atom->isIndex(&unused))
|
||||
return nullptr;
|
||||
|
||||
PropertyName *name = atom->asPropertyName();
|
||||
|
||||
for (size_t i = 0; i < fieldCount(); i++) {
|
||||
if (field(i).propertyName.get() == name)
|
||||
return &field(i);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
TypeRepresentation::isOwnerObject(JSObject &obj)
|
||||
{
|
||||
return obj.getClass() == &class_;
|
||||
}
|
||||
|
||||
/*static*/ TypeRepresentation *
|
||||
TypeRepresentation::fromOwnerObject(JSObject &obj)
|
||||
{
|
||||
JS_ASSERT(obj.getClass() == &class_);
|
||||
return (TypeRepresentation*) obj.getPrivate();
|
||||
}
|
||||
|
||||
|
@ -1,433 +0,0 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
#ifndef builtin_TypeRepresentation_h
|
||||
#define builtin_TypeRepresentation_h
|
||||
|
||||
/*
|
||||
* Type Representations are canonical versions of user-defined type
|
||||
* descriptors. Using the typed objects API, users are free to define
|
||||
* new type descriptors representing C-like type definitions. Each such
|
||||
* type descriptor has a distinct prototype and identity, even if it
|
||||
* describes the same logical type as another type
|
||||
* descriptor. Generally speaking, though, the only thing the compiler
|
||||
* cares about is the binary data layout implied by a type descriptor.
|
||||
*
|
||||
* Therefore, we link each such type descriptor to one canonical *type
|
||||
* representation*. The type representation is itself an object, but
|
||||
* this object is never exposed to user code (it is used by self-hosted
|
||||
* code). Type representations are interned into a hashset in the
|
||||
* compartment (typeReprs), meaning that you can compare two type
|
||||
* representations for equality just using `==`. If they are equal,
|
||||
* it means that they represent the same binary layout.
|
||||
*
|
||||
* # Creation and canonicalization:
|
||||
*
|
||||
* Each kind of `TypeRepresentation` object includes a `New` method
|
||||
* that will create a canonical instance of it. So, for example, you
|
||||
* can do `ScalarTypeRepresentation::Create(Uint8)` to get the
|
||||
* canonical representation of uint8. The object that is returned is
|
||||
* designed to be immutable, and the API permits only read access.
|
||||
*
|
||||
* # Integration with TI:
|
||||
*
|
||||
* Each TypeRepresentation has an associated Type Object. This Type
|
||||
* Object is used as the type object for all type descriptors with this
|
||||
* representation. The type object has an associated addendum linking
|
||||
* to the type representation, thus allowing the jit to deduce
|
||||
* information about type descriptors that appear in expressions.
|
||||
*
|
||||
* # Memory management:
|
||||
*
|
||||
* Each TypeRepresentations has an associated JSObject, called its
|
||||
* owned object. When this object is finalized, the TypeRepresentation*
|
||||
* will be freed (and removed from the interning table, see
|
||||
* below). Therefore, if you reference a TypeRepresentation*, you must
|
||||
* ensure this owner object is traced. In type objects, this is done by
|
||||
* invoking TypeRepresentation::mark(); in binary data type
|
||||
* descriptors, the owner object for the type is stored in
|
||||
* `SLOT_TYPE_REPR`.
|
||||
*
|
||||
* The canonicalization table maintains *weak references* to the
|
||||
* TypeRepresentation* pointers. That is, the table is not traced.
|
||||
* Instead, whenever an object is created, it is paired with its owner
|
||||
* object, and the finalizer of the owner object removes the pointer
|
||||
* from the table and then frees the pointer.
|
||||
*
|
||||
* # Opacity
|
||||
*
|
||||
* A type representation is considered "opaque" if it contains
|
||||
* references (strings, objects, any). In those cases we have to be
|
||||
* more limited with respect to aliasing etc to preserve portability
|
||||
* across engines (for example, we don't want to expose sizeof(Any))
|
||||
* and memory safety.
|
||||
*/
|
||||
|
||||
#include "jsalloc.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/TypedObjectConstants.h"
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/HashTable.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class TypeRepresentation;
|
||||
class SizedTypeRepresentation;
|
||||
class ScalarTypeRepresentation;
|
||||
class ReferenceTypeRepresentation;
|
||||
class X4TypeRepresentation;
|
||||
class SizedArrayTypeRepresentation;
|
||||
class UnsizedArrayTypeRepresentation;
|
||||
class StructTypeRepresentation;
|
||||
|
||||
struct Class;
|
||||
class StringBuffer;
|
||||
|
||||
struct TypeRepresentationHasher
|
||||
{
|
||||
typedef TypeRepresentation *Lookup;
|
||||
static HashNumber hash(TypeRepresentation *key);
|
||||
static bool match(TypeRepresentation *key1, TypeRepresentation *key2);
|
||||
|
||||
private:
|
||||
static HashNumber hashScalar(ScalarTypeRepresentation *key);
|
||||
static HashNumber hashReference(ReferenceTypeRepresentation *key);
|
||||
static HashNumber hashX4(X4TypeRepresentation *key);
|
||||
static HashNumber hashStruct(StructTypeRepresentation *key);
|
||||
static HashNumber hashUnsizedArray(UnsizedArrayTypeRepresentation *key);
|
||||
static HashNumber hashSizedArray(SizedArrayTypeRepresentation *key);
|
||||
|
||||
static bool matchScalars(ScalarTypeRepresentation *key1,
|
||||
ScalarTypeRepresentation *key2);
|
||||
static bool matchReferences(ReferenceTypeRepresentation *key1,
|
||||
ReferenceTypeRepresentation *key2);
|
||||
static bool matchX4s(X4TypeRepresentation *key1,
|
||||
X4TypeRepresentation *key2);
|
||||
static bool matchStructs(StructTypeRepresentation *key1,
|
||||
StructTypeRepresentation *key2);
|
||||
static bool matchSizedArrays(SizedArrayTypeRepresentation *key1,
|
||||
SizedArrayTypeRepresentation *key2);
|
||||
static bool matchUnsizedArrays(UnsizedArrayTypeRepresentation *key1,
|
||||
UnsizedArrayTypeRepresentation *key2);
|
||||
};
|
||||
|
||||
typedef js::HashSet<TypeRepresentation *,
|
||||
TypeRepresentationHasher,
|
||||
RuntimeAllocPolicy> TypeRepresentationHash;
|
||||
|
||||
class TypeRepresentationHelper;
|
||||
|
||||
class TypeRepresentation {
|
||||
protected:
|
||||
TypeRepresentation(TypeDescr::Kind kind, size_t alignment, bool opaque);
|
||||
|
||||
// in order to call addToTableOrFree()
|
||||
friend class TypeRepresentationHelper;
|
||||
|
||||
TypeDescr::Kind kind_;
|
||||
bool opaque_;
|
||||
size_t alignment_;
|
||||
|
||||
JSObject *addToTableOrFree(JSContext *cx, TypeRepresentationHash::AddPtr &p);
|
||||
|
||||
private:
|
||||
static const Class class_;
|
||||
static void obj_trace(JSTracer *trace, JSObject *object);
|
||||
static void obj_finalize(js::FreeOp *fop, JSObject *object);
|
||||
|
||||
HeapPtrObject ownerObject_;
|
||||
void traceFields(JSTracer *tracer);
|
||||
|
||||
public:
|
||||
TypeDescr::Kind kind() const { return kind_; }
|
||||
bool opaque() const { return opaque_; }
|
||||
bool transparent() const { return !opaque_; }
|
||||
JSObject *ownerObject() const { return ownerObject_.get(); }
|
||||
size_t alignment() const { return alignment_; }
|
||||
|
||||
static bool isOwnerObject(JSObject &obj);
|
||||
static TypeRepresentation *fromOwnerObject(JSObject &obj);
|
||||
|
||||
bool isSized() const {
|
||||
return TypeDescr::isSized(kind());
|
||||
}
|
||||
|
||||
inline SizedTypeRepresentation *asSized();
|
||||
|
||||
bool isScalar() const {
|
||||
return kind() == TypeDescr::Scalar;
|
||||
}
|
||||
|
||||
inline ScalarTypeRepresentation *asScalar();
|
||||
|
||||
bool isReference() const {
|
||||
return kind() == TypeDescr::Reference;
|
||||
}
|
||||
|
||||
inline ReferenceTypeRepresentation *asReference();
|
||||
|
||||
bool isX4() const {
|
||||
return kind() == TypeDescr::X4;
|
||||
}
|
||||
|
||||
inline X4TypeRepresentation *asX4();
|
||||
|
||||
bool isSizedArray() const {
|
||||
return kind() == TypeDescr::SizedArray;
|
||||
}
|
||||
|
||||
inline SizedArrayTypeRepresentation *asSizedArray();
|
||||
|
||||
bool isUnsizedArray() const {
|
||||
return kind() == TypeDescr::UnsizedArray;
|
||||
}
|
||||
|
||||
inline UnsizedArrayTypeRepresentation *asUnsizedArray();
|
||||
|
||||
bool isAnyArray() const {
|
||||
return isSizedArray() || isUnsizedArray();
|
||||
}
|
||||
|
||||
bool isStruct() const {
|
||||
return kind() == TypeDescr::Struct;
|
||||
}
|
||||
|
||||
inline StructTypeRepresentation *asStruct();
|
||||
|
||||
void mark(JSTracer *tracer);
|
||||
};
|
||||
|
||||
class SizedTypeRepresentation : public TypeRepresentation {
|
||||
protected:
|
||||
SizedTypeRepresentation(TypeDescr::Kind kind, bool opaque, size_t size, size_t align);
|
||||
|
||||
size_t size_;
|
||||
|
||||
public:
|
||||
size_t size() const { return size_; }
|
||||
|
||||
// Initializes memory that contains `count` instances of this type.
|
||||
// `count` must be at least 1.
|
||||
void initInstance(const JSRuntime *rt, uint8_t *mem, size_t count);
|
||||
|
||||
// Traces memory that contains `count` instances of this type.
|
||||
void traceInstance(JSTracer *trace, uint8_t *mem, size_t count);
|
||||
};
|
||||
|
||||
class ScalarTypeRepresentation : public SizedTypeRepresentation {
|
||||
private:
|
||||
// in order to call constructor
|
||||
friend class TypeRepresentationHelper;
|
||||
|
||||
const ScalarTypeDescr::Type type_;
|
||||
|
||||
explicit ScalarTypeRepresentation(ScalarTypeDescr::Type type);
|
||||
|
||||
public:
|
||||
ScalarTypeDescr::Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
const char *typeName() const {
|
||||
return ScalarTypeDescr::typeName(type());
|
||||
}
|
||||
|
||||
static JSObject *Create(JSContext *cx, ScalarTypeDescr::Type type);
|
||||
};
|
||||
|
||||
class ReferenceTypeRepresentation : public SizedTypeRepresentation {
|
||||
private:
|
||||
ReferenceTypeDescr::Type type_;
|
||||
|
||||
explicit ReferenceTypeRepresentation(ReferenceTypeDescr::Type type);
|
||||
|
||||
public:
|
||||
ReferenceTypeDescr::Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
const char *typeName() const {
|
||||
return ReferenceTypeDescr::typeName(type());
|
||||
}
|
||||
|
||||
static JSObject *Create(JSContext *cx, ReferenceTypeDescr::Type type);
|
||||
};
|
||||
|
||||
class X4TypeRepresentation : public SizedTypeRepresentation {
|
||||
private:
|
||||
// in order to call constructor
|
||||
friend class TypeRepresentationHelper;
|
||||
|
||||
const X4TypeDescr::Type type_;
|
||||
|
||||
explicit X4TypeRepresentation(X4TypeDescr::Type type);
|
||||
|
||||
public:
|
||||
X4TypeDescr::Type type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
static JSObject *Create(JSContext *cx, X4TypeDescr::Type type);
|
||||
};
|
||||
|
||||
class UnsizedArrayTypeRepresentation : public TypeRepresentation {
|
||||
private:
|
||||
// so TypeRepresentation can call tracing routines
|
||||
friend class TypeRepresentation;
|
||||
|
||||
SizedTypeRepresentation *element_;
|
||||
|
||||
UnsizedArrayTypeRepresentation(SizedTypeRepresentation *element);
|
||||
|
||||
// See TypeRepresentation::traceFields()
|
||||
void traceUnsizedArrayFields(JSTracer *trace);
|
||||
|
||||
public:
|
||||
SizedTypeRepresentation *element() {
|
||||
return element_;
|
||||
}
|
||||
|
||||
static JSObject *Create(JSContext *cx,
|
||||
SizedTypeRepresentation *elementTypeRepr);
|
||||
};
|
||||
|
||||
class SizedArrayTypeRepresentation : public SizedTypeRepresentation {
|
||||
private:
|
||||
// so TypeRepresentation can call traceSizedArrayFields()
|
||||
friend class TypeRepresentation;
|
||||
|
||||
SizedTypeRepresentation *element_;
|
||||
size_t length_;
|
||||
|
||||
SizedArrayTypeRepresentation(SizedTypeRepresentation *element,
|
||||
size_t length);
|
||||
|
||||
// See TypeRepresentation::traceFields()
|
||||
void traceSizedArrayFields(JSTracer *trace);
|
||||
|
||||
public:
|
||||
SizedTypeRepresentation *element() {
|
||||
return element_;
|
||||
}
|
||||
|
||||
size_t length() {
|
||||
return length_;
|
||||
}
|
||||
|
||||
static JSObject *Create(JSContext *cx,
|
||||
SizedTypeRepresentation *elementTypeRepr,
|
||||
size_t length);
|
||||
};
|
||||
|
||||
struct StructField {
|
||||
size_t index;
|
||||
HeapPtrPropertyName propertyName;
|
||||
SizedTypeRepresentation *typeRepr;
|
||||
size_t offset;
|
||||
|
||||
explicit StructField(size_t index,
|
||||
PropertyName *propertyName,
|
||||
SizedTypeRepresentation *typeRepr,
|
||||
size_t offset);
|
||||
};
|
||||
|
||||
class StructTypeRepresentation : public SizedTypeRepresentation {
|
||||
private:
|
||||
// so TypeRepresentation can call traceStructFields() etc
|
||||
friend class TypeRepresentation;
|
||||
|
||||
size_t fieldCount_;
|
||||
|
||||
// StructTypeRepresentations are allocated with extra space to
|
||||
// store the contents of the fields array.
|
||||
StructField* fields() {
|
||||
return (StructField*) (this+1);
|
||||
}
|
||||
const StructField* fields() const {
|
||||
return (StructField*) (this+1);
|
||||
}
|
||||
|
||||
StructTypeRepresentation();
|
||||
bool init(JSContext *cx,
|
||||
AutoPropertyNameVector &names,
|
||||
AutoObjectVector &typeReprOwners);
|
||||
|
||||
// See TypeRepresentation::traceFields()
|
||||
void traceStructFields(JSTracer *trace);
|
||||
|
||||
public:
|
||||
size_t fieldCount() const {
|
||||
return fieldCount_;
|
||||
}
|
||||
|
||||
const StructField &field(size_t i) const {
|
||||
JS_ASSERT(i < fieldCount());
|
||||
return fields()[i];
|
||||
}
|
||||
|
||||
const StructField *fieldNamed(jsid id) const;
|
||||
|
||||
// Creates a struct type from two parallel arrays:
|
||||
// - `names`: the names of the struct type fields.
|
||||
// - `typeReprOwners`: the types of each field, which are assumed
|
||||
// to be the owner objects for sized type representations.
|
||||
static JSObject *Create(JSContext *cx,
|
||||
AutoPropertyNameVector &names,
|
||||
AutoObjectVector &typeReprOwners);
|
||||
};
|
||||
|
||||
// Definitions of the casting methods. These are pulled out of the
|
||||
// main class definition because both the super- and subtypes must be
|
||||
// defined for C++ to permit the static_cast.
|
||||
|
||||
SizedTypeRepresentation *
|
||||
TypeRepresentation::asSized() {
|
||||
JS_ASSERT(isSized());
|
||||
return static_cast<SizedTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
ScalarTypeRepresentation *
|
||||
TypeRepresentation::asScalar() {
|
||||
JS_ASSERT(isScalar());
|
||||
return static_cast<ScalarTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
ReferenceTypeRepresentation *
|
||||
TypeRepresentation::asReference() {
|
||||
JS_ASSERT(isReference());
|
||||
return static_cast<ReferenceTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
X4TypeRepresentation *
|
||||
TypeRepresentation::asX4() {
|
||||
JS_ASSERT(isX4());
|
||||
return static_cast<X4TypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
SizedArrayTypeRepresentation *
|
||||
TypeRepresentation::asSizedArray() {
|
||||
JS_ASSERT(isSizedArray());
|
||||
return static_cast<SizedArrayTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
UnsizedArrayTypeRepresentation *
|
||||
TypeRepresentation::asUnsizedArray() {
|
||||
JS_ASSERT(isUnsizedArray());
|
||||
return static_cast<UnsizedArrayTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
StructTypeRepresentation *
|
||||
TypeRepresentation::asStruct() {
|
||||
JS_ASSERT(isStruct());
|
||||
return static_cast<StructTypeRepresentation*>(this);
|
||||
}
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -106,12 +106,6 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
class TypeRepresentation;
|
||||
class ScalarTypeRepresentation;
|
||||
class ReferenceTypeRepresentation;
|
||||
class X4TypeRepresentation;
|
||||
class StructTypeDescr;
|
||||
|
||||
/*
|
||||
* Helper method for converting a double into other scalar
|
||||
* types in the same way that JavaScript would. In particular,
|
||||
@ -156,18 +150,24 @@ class TypeDescr : public JSObject
|
||||
return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
|
||||
}
|
||||
|
||||
JSObject &typeRepresentationOwnerObj() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_TYPE_REPR).toObject();
|
||||
JSAtom &stringRepr() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom();
|
||||
}
|
||||
|
||||
TypeRepresentation *typeRepresentation() const;
|
||||
TypeDescr::Kind kind() const {
|
||||
return (TypeDescr::Kind) getReservedSlot(JS_DESCR_SLOT_KIND).toInt32();
|
||||
}
|
||||
|
||||
TypeDescr::Kind kind() const;
|
||||
bool opaque() const {
|
||||
return getReservedSlot(JS_DESCR_SLOT_OPAQUE).toBoolean();
|
||||
}
|
||||
|
||||
bool opaque() const;
|
||||
bool transparent() const {
|
||||
return !opaque();
|
||||
}
|
||||
|
||||
size_t alignment() {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
|
||||
return (size_t) getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
|
||||
}
|
||||
};
|
||||
|
||||
@ -177,8 +177,11 @@ class SizedTypeDescr : public TypeDescr
|
||||
{
|
||||
public:
|
||||
size_t size() {
|
||||
return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
|
||||
return (size_t) getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
|
||||
}
|
||||
|
||||
void initInstances(const JSRuntime *rt, uint8_t *mem, size_t length);
|
||||
void traceInstances(JSTracer *trace, uint8_t *mem, size_t length);
|
||||
};
|
||||
|
||||
typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
|
||||
@ -213,13 +216,14 @@ class ScalarTypeDescr : public SimpleTypeDescr
|
||||
};
|
||||
static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
|
||||
|
||||
static size_t size(Type t);
|
||||
static size_t alignment(Type t);
|
||||
static const TypeDescr::Kind Kind = TypeDescr::Scalar;
|
||||
static const bool Opaque = false;
|
||||
static int32_t size(Type t);
|
||||
static int32_t alignment(Type t);
|
||||
static const char *typeName(Type type);
|
||||
|
||||
static const Class class_;
|
||||
static const JSFunctionSpec typeObjectMethods[];
|
||||
typedef ScalarTypeRepresentation TypeRepr;
|
||||
|
||||
ScalarTypeDescr::Type type() const {
|
||||
return (ScalarTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
|
||||
@ -261,14 +265,21 @@ class ReferenceTypeDescr : public SimpleTypeDescr
|
||||
static const int32_t TYPE_MAX = TYPE_STRING + 1;
|
||||
static const char *typeName(Type type);
|
||||
|
||||
static const TypeDescr::Kind Kind = TypeDescr::Reference;
|
||||
static const bool Opaque = true;
|
||||
static const Class class_;
|
||||
static int32_t size(Type t);
|
||||
static int32_t alignment(Type t);
|
||||
static const JSFunctionSpec typeObjectMethods[];
|
||||
typedef ReferenceTypeRepresentation TypeRepr;
|
||||
|
||||
ReferenceTypeDescr::Type type() const {
|
||||
return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
|
||||
}
|
||||
|
||||
const char *typeName() const {
|
||||
return typeName(type());
|
||||
}
|
||||
|
||||
static bool call(JSContext *cx, unsigned argc, Value *vp);
|
||||
};
|
||||
|
||||
@ -300,8 +311,11 @@ class X4TypeDescr : public ComplexTypeDescr
|
||||
TYPE_FLOAT32 = JS_X4TYPEREPR_FLOAT32,
|
||||
};
|
||||
|
||||
static const TypeDescr::Kind Kind = TypeDescr::X4;
|
||||
static const bool Opaque = false;
|
||||
static const Class class_;
|
||||
typedef X4TypeRepresentation TypeRepr;
|
||||
static int32_t size(Type t);
|
||||
static int32_t alignment(Type t);
|
||||
|
||||
X4TypeDescr::Type type() const {
|
||||
return (X4TypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
|
||||
@ -318,9 +332,7 @@ class X4TypeDescr : public ComplexTypeDescr
|
||||
bool IsTypedObjectClass(const Class *clasp); // Defined below
|
||||
bool IsTypedObjectArray(JSObject& obj);
|
||||
|
||||
bool InitializeCommonTypeDescriptorProperties(JSContext *cx,
|
||||
HandleTypeDescr obj,
|
||||
HandleObject typeReprOwnerObj);
|
||||
bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj);
|
||||
|
||||
/*
|
||||
* Properties and methods of the `ArrayType` meta type object. There
|
||||
@ -340,13 +352,15 @@ class ArrayMetaTypeDescr : public JSObject
|
||||
// either ArrayType.prototype or
|
||||
// unsizedArrayType.__proto__ depending on
|
||||
// whether this is a sized or unsized array
|
||||
// - `arrayTypeReprObj` - a type representation object for the array
|
||||
// - `elementType` - type object for the elements in the array
|
||||
// - `stringRepr` - canonical string representation for the array
|
||||
// - `size` - length of the array (0 if unsized)
|
||||
template<class T>
|
||||
static T *create(JSContext *cx,
|
||||
HandleObject arrayTypePrototype,
|
||||
HandleObject arrayTypeReprObj,
|
||||
HandleSizedTypeDescr elementType);
|
||||
HandleSizedTypeDescr elementType,
|
||||
HandleAtom stringRepr,
|
||||
int32_t size);
|
||||
|
||||
public:
|
||||
// Properties and methods to be installed on ArrayType.prototype,
|
||||
@ -376,6 +390,7 @@ class UnsizedArrayTypeDescr : public TypeDescr
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
static const TypeDescr::Kind Kind = TypeDescr::UnsizedArray;
|
||||
|
||||
// This is the sized method on unsized array type objects. It
|
||||
// produces a sized variant.
|
||||
@ -393,6 +408,7 @@ class SizedArrayTypeDescr : public ComplexTypeDescr
|
||||
{
|
||||
public:
|
||||
static const Class class_;
|
||||
static const TypeDescr::Kind Kind = TypeDescr::SizedArray;
|
||||
|
||||
SizedTypeDescr &elementType() {
|
||||
return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
|
||||
@ -414,14 +430,6 @@ class StructMetaTypeDescr : public JSObject
|
||||
static JSObject *create(JSContext *cx, HandleObject structTypeGlobal,
|
||||
HandleObject fields);
|
||||
|
||||
/*
|
||||
* Sets up structType slots based on calculated memory size
|
||||
* and alignment and stores fieldmap as well.
|
||||
*/
|
||||
static bool layout(JSContext *cx,
|
||||
Handle<StructTypeDescr*> structType,
|
||||
HandleObject fields);
|
||||
|
||||
public:
|
||||
// Properties and methods to be installed on StructType.prototype,
|
||||
// and hence inherited by all struct type objects:
|
||||
@ -443,10 +451,16 @@ class StructTypeDescr : public ComplexTypeDescr
|
||||
public:
|
||||
static const Class class_;
|
||||
|
||||
// Returns the number of fields defined in this struct.
|
||||
size_t fieldCount();
|
||||
|
||||
// Set `*out` to the index of the field named `id` and returns true,
|
||||
// or return false if no such field exists.
|
||||
bool fieldIndex(jsid id, size_t *out);
|
||||
|
||||
// Return the name of the field at index `index`.
|
||||
JSAtom &fieldName(size_t index);
|
||||
|
||||
// Return the type descr of the field at index `index`.
|
||||
SizedTypeDescr &fieldDescr(size_t index);
|
||||
|
||||
@ -630,10 +644,6 @@ class TypedObject : public ArrayBufferViewObject
|
||||
return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as<TypeDescr>();
|
||||
}
|
||||
|
||||
TypeRepresentation *typeRepresentation() const {
|
||||
return typeDescr().typeRepresentation();
|
||||
}
|
||||
|
||||
uint8_t *typedMem() const {
|
||||
return (uint8_t*) getPrivate();
|
||||
}
|
||||
|
@ -3,23 +3,24 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Getters and setters for various slots.
|
||||
|
||||
// Type repr slots
|
||||
|
||||
#define REPR_KIND(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_TYPEREPR_SLOT_KIND))
|
||||
|
||||
// Type object slots
|
||||
|
||||
#define DESCR_TYPE_REPR(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE_REPR)
|
||||
#define DESCR_KIND(obj) \
|
||||
REPR_KIND(DESCR_TYPE_REPR(obj))
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_KIND)
|
||||
#define DESCR_STRING_REPR(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRING_REPR)
|
||||
#define DESCR_ALIGNMENT(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ALIGNMENT)
|
||||
#define DESCR_SIZE(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZE)
|
||||
#define DESCR_SIZED_ARRAY_LENGTH(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH))
|
||||
#define DESCR_OPAQUE(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_OPAQUE)
|
||||
#define DESCR_TYPE(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_TYPE)
|
||||
#define DESCR_ARRAY_ELEMENT_TYPE(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_ARRAY_ELEM_TYPE))
|
||||
#define DESCR_SIZED_ARRAY_LENGTH(obj) \
|
||||
TO_INT32(UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_SIZED_ARRAY_LENGTH))
|
||||
#define DESCR_STRUCT_FIELD_NAMES(obj) \
|
||||
UnsafeGetReservedSlot(obj, JS_DESCR_SLOT_STRUCT_FIELD_NAMES)
|
||||
#define DESCR_STRUCT_FIELD_TYPES(obj) \
|
||||
@ -43,96 +44,11 @@
|
||||
#define HAS_PROPERTY(obj, prop) \
|
||||
callFunction(std_Object_hasOwnProperty, obj, prop)
|
||||
|
||||
function TYPEDOBJ_TYPE_REPR(obj) {
|
||||
// Eventually this will be a slot on typed objects
|
||||
return DESCR_TYPE_REPR(TYPEDOBJ_TYPE_DESCR(obj));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// DescrToSource
|
||||
//
|
||||
// Converts a type descriptor to a descriptive string
|
||||
|
||||
// toSource() for type descriptors.
|
||||
//
|
||||
// Warning: user exposed!
|
||||
function DescrToSourceMethod() {
|
||||
if (!IsObject(this) || !ObjectIsTypeDescr(this))
|
||||
ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Type", "toSource", "value");
|
||||
|
||||
return DescrToSource(this);
|
||||
}
|
||||
|
||||
function DescrToSource(descr) {
|
||||
assert(IsObject(descr) && ObjectIsTypeDescr(descr),
|
||||
"DescrToSource: not type descr");
|
||||
|
||||
switch (DESCR_KIND(descr)) {
|
||||
case JS_TYPEREPR_SCALAR_KIND:
|
||||
switch (DESCR_TYPE(descr)) {
|
||||
case JS_SCALARTYPEREPR_INT8: return "int8";
|
||||
case JS_SCALARTYPEREPR_UINT8: return "uint8";
|
||||
case JS_SCALARTYPEREPR_UINT8_CLAMPED: return "uint8Clamped";
|
||||
case JS_SCALARTYPEREPR_INT16: return "int16";
|
||||
case JS_SCALARTYPEREPR_UINT16: return "uint16";
|
||||
case JS_SCALARTYPEREPR_INT32: return "int32";
|
||||
case JS_SCALARTYPEREPR_UINT32: return "uint32";
|
||||
case JS_SCALARTYPEREPR_FLOAT32: return "float32";
|
||||
case JS_SCALARTYPEREPR_FLOAT64: return "float64";
|
||||
}
|
||||
assert(false, "Unhandled type: " + DESCR_TYPE(descr));
|
||||
return undefined;
|
||||
|
||||
case JS_TYPEREPR_REFERENCE_KIND:
|
||||
switch (DESCR_TYPE(descr)) {
|
||||
case JS_REFERENCETYPEREPR_ANY: return "any";
|
||||
case JS_REFERENCETYPEREPR_OBJECT: return "Object";
|
||||
case JS_REFERENCETYPEREPR_STRING: return "string";
|
||||
}
|
||||
assert(false, "Unhandled type: " + DESCR_TYPE(descr));
|
||||
return undefined;
|
||||
|
||||
case JS_TYPEREPR_X4_KIND:
|
||||
switch (DESCR_TYPE(descr)) {
|
||||
case JS_X4TYPEREPR_FLOAT32: return "float32x4";
|
||||
case JS_X4TYPEREPR_INT32: return "int32x4";
|
||||
}
|
||||
assert(false, "Unhandled type: " + DESCR_TYPE(descr));
|
||||
return undefined;
|
||||
|
||||
case JS_TYPEREPR_STRUCT_KIND:
|
||||
var result = "new StructType({";
|
||||
var fieldNames = DESCR_STRUCT_FIELD_NAMES(descr);
|
||||
var fieldTypes = DESCR_STRUCT_FIELD_TYPES(descr);
|
||||
for (var i = 0; i < fieldNames.length; i++) {
|
||||
if (i != 0)
|
||||
result += ", ";
|
||||
|
||||
result += fieldNames[i];
|
||||
result += ": ";
|
||||
result += DescrToSource(fieldTypes[i]);
|
||||
}
|
||||
result += "})";
|
||||
return result;
|
||||
|
||||
case JS_TYPEREPR_UNSIZED_ARRAY_KIND:
|
||||
return "new ArrayType(" + DescrToSource(descr.elementType) + ")";
|
||||
|
||||
case JS_TYPEREPR_SIZED_ARRAY_KIND:
|
||||
var result = ".array";
|
||||
var sep = "(";
|
||||
while (DESCR_KIND(descr) == JS_TYPEREPR_SIZED_ARRAY_KIND) {
|
||||
result += sep + DESCR_SIZED_ARRAY_LENGTH(descr);
|
||||
descr = descr.elementType;
|
||||
sep = ", ";
|
||||
}
|
||||
return DescrToSource(descr) + result + ")";
|
||||
}
|
||||
|
||||
assert(false, "Unhandled kind: " + DESCR_KIND(descr));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// TypedObjectPointer
|
||||
//
|
||||
@ -170,7 +86,7 @@ TypedObjectPointer.fromTypedObject = function(typed) {
|
||||
|
||||
#ifdef DEBUG
|
||||
TypedObjectPointer.prototype.toString = function() {
|
||||
return "Ptr(" + DescrToSource(this.descr) + " @ " + this.offset + ")";
|
||||
return "Ptr(" + DESCR_STRING_REPR(this.descr) + " @ " + this.offset + ")";
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -454,7 +370,7 @@ function SetTypedObjectValue(descr, typedObj, offset, fromValue) {
|
||||
}
|
||||
|
||||
// Writes `fromValue` into the memory pointed at by `this`, adapting
|
||||
// it to `typeRepr` as needed. This is the most general entry point
|
||||
// it to `this.descr` as needed. This is the most general entry point
|
||||
// and works for any type.
|
||||
TypedObjectPointer.prototype.set = function(fromValue) {
|
||||
assert(TypedObjectIsAttached(this.typedObj), "set() called with unattached typedObj");
|
||||
@ -463,8 +379,7 @@ TypedObjectPointer.prototype.set = function(fromValue) {
|
||||
// representation as the destination. In that case, we can just do a
|
||||
// memcpy.
|
||||
if (IsObject(fromValue) && ObjectIsTypedObject(fromValue)) {
|
||||
var typeRepr = DESCR_TYPE_REPR(this.descr);
|
||||
if (!this.descr.variable && TYPEDOBJ_TYPE_REPR(fromValue) === typeRepr) {
|
||||
if (!this.descr.variable && DescrsEquiv(this.descr, TYPEDOBJ_TYPE_DESCR(fromValue))) {
|
||||
if (!TypedObjectIsAttached(fromValue))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_HANDLE_UNATTACHED);
|
||||
|
||||
@ -513,7 +428,7 @@ TypedObjectPointer.prototype.set = function(fromValue) {
|
||||
|
||||
ThrowError(JSMSG_CANT_CONVERT_TO,
|
||||
typeof(fromValue),
|
||||
DescrToSource(this.descr));
|
||||
DESCR_STRING_REPR(this.descr));
|
||||
}
|
||||
|
||||
TypedObjectPointer.prototype.setArray = function(fromValue, length) {
|
||||
@ -609,7 +524,7 @@ TypedObjectPointer.prototype.setX4 = function(fromValue) {
|
||||
// to "adapt" fromValue, but there are no legal adaptions.
|
||||
ThrowError(JSMSG_CANT_CONVERT_TO,
|
||||
typeof(fromValue),
|
||||
DescrToSource(this.descr));
|
||||
DESCR_STRING_REPR(this.descr));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -679,7 +594,7 @@ function TypeDescrEquivalent(otherDescr) {
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
if (!IsObject(otherDescr) || !ObjectIsTypeDescr(otherDescr))
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
return DESCR_TYPE_REPR(this) === DESCR_TYPE_REPR(otherDescr);
|
||||
return DescrsEquiv(this, otherDescr);
|
||||
}
|
||||
|
||||
// TypedArray.redimension(newArrayType)
|
||||
@ -747,7 +662,7 @@ function TypedArrayRedimension(newArrayType) {
|
||||
}
|
||||
|
||||
// Check that the element types are equivalent.
|
||||
if (DESCR_TYPE_REPR(oldElementType) !== DESCR_TYPE_REPR(newElementType)) {
|
||||
if (!DescrsEquiv(oldElementType, newElementType)) {
|
||||
ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
|
||||
}
|
||||
|
||||
@ -790,6 +705,29 @@ function X4ToSource() {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Miscellaneous
|
||||
|
||||
function DescrsEquiv(descr1, descr2) {
|
||||
assert(IsObject(descr1) && ObjectIsTypeDescr(descr1), "descr1 not descr");
|
||||
assert(IsObject(descr2) && ObjectIsTypeDescr(descr2), "descr2 not descr");
|
||||
|
||||
// Potential optimization: these two strings are guaranteed to be
|
||||
// atoms, and hence this string comparison can just be a pointer
|
||||
// comparison. However, I don't think ion knows that. If this ever
|
||||
// becomes a bottleneck, we can add a intrinsic at some point that
|
||||
// is treated specially by Ion. (Bug 976688)
|
||||
|
||||
return DESCR_STRING_REPR(descr1) === DESCR_STRING_REPR(descr2);
|
||||
}
|
||||
|
||||
// toSource() for type descriptors.
|
||||
//
|
||||
// Warning: user exposed!
|
||||
function DescrToSource() {
|
||||
if (!IsObject(this) || !ObjectIsTypeDescr(this))
|
||||
ThrowError(JSMSG_INCOMPATIBLE_PROTO, "Type", "toSource", "value");
|
||||
|
||||
return DESCR_STRING_REPR(this);
|
||||
}
|
||||
|
||||
// Warning: user exposed!
|
||||
function ArrayShorthand(...dims) {
|
||||
if (!IsObject(this) || !ObjectIsTypeDescr(this))
|
||||
|
@ -18,50 +18,29 @@
|
||||
// working with, even though this is mildly wasteful.
|
||||
|
||||
// Slots on all type objects
|
||||
#define JS_DESCR_SLOT_TYPE_REPR 0 // Associated Type Representation
|
||||
#define JS_DESCR_SLOT_ALIGNMENT 1 // Alignment in bytes
|
||||
#define JS_DESCR_SLOT_SIZE 2 // Size in bytes, if sized, else 0
|
||||
#define JS_DESCR_SLOT_PROTO 3 // Prototype for instances, if any
|
||||
#define JS_DESCR_SLOT_KIND 0 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_STRING_REPR 1 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_ALIGNMENT 2 // Alignment in bytes
|
||||
#define JS_DESCR_SLOT_SIZE 3 // Size in bytes, if sized, else 0
|
||||
#define JS_DESCR_SLOT_OPAQUE 4 // Atomized string representation
|
||||
#define JS_DESCR_SLOT_PROTO 5 // Prototype for instances, if any
|
||||
|
||||
// Slots on scalars, references, and x4s
|
||||
#define JS_DESCR_SLOT_TYPE 4 // Type code
|
||||
#define JS_DESCR_SLOT_TYPE 6 // Type code
|
||||
|
||||
// Slots on all array descriptors
|
||||
#define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 4
|
||||
#define JS_DESCR_SLOT_ARRAY_ELEM_TYPE 6
|
||||
|
||||
// Slots on sized array descriptors
|
||||
#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 5
|
||||
#define JS_DESCR_SLOT_SIZED_ARRAY_LENGTH 7
|
||||
|
||||
// Slots on struct type objects
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 4
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 5
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 6
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_NAMES 6
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_TYPES 7
|
||||
#define JS_DESCR_SLOT_STRUCT_FIELD_OFFSETS 8
|
||||
|
||||
// Maximum number of slots for any descriptor
|
||||
#define JS_DESCR_SLOTS 7
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Slots for type representation objects
|
||||
//
|
||||
// Some slots apply to all type representations and some are specific
|
||||
// to particular kinds of type representations. Because all type
|
||||
// representations share the same class, however, they always have the
|
||||
// same number of slots, though not all of them will be initialized or
|
||||
// used in the same way.
|
||||
|
||||
// Slots on *all* type representations:
|
||||
#define JS_TYPEREPR_SLOT_KIND 0 // One of the `kind` constants below
|
||||
#define JS_TYPEREPR_SLOT_SIZE 1 // Size in bytes.
|
||||
#define JS_TYPEREPR_SLOT_ALIGNMENT 2 // Alignment in bytes.
|
||||
|
||||
// Slots on sized arrays:
|
||||
#define JS_TYPEREPR_SLOT_LENGTH 3 // Length of the array
|
||||
|
||||
// Slots on scalars, references, and X4s:
|
||||
#define JS_TYPEREPR_SLOT_TYPE 3 // One of the constants below
|
||||
|
||||
// Maximum number of slots for any type representation
|
||||
#define JS_TYPEREPR_SLOTS 4
|
||||
#define JS_DESCR_SLOTS 9
|
||||
|
||||
// These constants are for use exclusively in JS code. In C++ code,
|
||||
// prefer TypeRepresentation::Scalar etc, which allows you to
|
||||
|
@ -53,7 +53,6 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
|
||||
objectMetadataCallback(nullptr),
|
||||
lastAnimationTime(0),
|
||||
regExps(runtime_),
|
||||
typeReprs(runtime_),
|
||||
globalWriteBarriered(false),
|
||||
propertyTree(thisForCtor()),
|
||||
selfHostingScriptSource(nullptr),
|
||||
@ -110,9 +109,6 @@ JSCompartment::init(JSContext *cx)
|
||||
if (!regExps.init(cx))
|
||||
return false;
|
||||
|
||||
if (!typeReprs.init())
|
||||
return false;
|
||||
|
||||
enumerators = NativeIterator::allocateSentinel(cx);
|
||||
if (!enumerators)
|
||||
return false;
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "builtin/TypeRepresentation.h"
|
||||
#include "gc/Zone.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/PIC.h"
|
||||
@ -207,9 +206,6 @@ struct JSCompartment
|
||||
|
||||
js::RegExpCompartment regExps;
|
||||
|
||||
/* Set of all currently living type representations. */
|
||||
js::TypeRepresentationHash typeReprs;
|
||||
|
||||
/*
|
||||
* For generational GC, record whether a write barrier has added this
|
||||
* compartment's global to the store buffer since the last minor GC.
|
||||
|
@ -102,7 +102,6 @@ UNIFIED_SOURCES += [
|
||||
'builtin/SIMD.cpp',
|
||||
'builtin/TestingFunctions.cpp',
|
||||
'builtin/TypedObject.cpp',
|
||||
'builtin/TypeRepresentation.cpp',
|
||||
'devtools/sharkctl.cpp',
|
||||
'ds/LifoAlloc.cpp',
|
||||
'frontend/BytecodeCompiler.cpp',
|
||||
|
@ -33,7 +33,7 @@ function runTests() {
|
||||
assertEq(A.length, 10);
|
||||
assertEq(A.elementType, uint8);
|
||||
assertEq(A.byteLength, 10);
|
||||
assertEq(A.toSource(), "uint8.array(10)");
|
||||
assertEq(A.toSource(), "new ArrayType(uint8).dimension(10)");
|
||||
|
||||
assertEq(A.prototype.__proto__.__proto__, ArrayType.prototype.prototype);
|
||||
|
||||
|
@ -48,7 +48,6 @@
|
||||
macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
|
||||
macro(decodeURI, decodeURI, "decodeURI") \
|
||||
macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
|
||||
macro(DescrToSource, DescrToSource, "DescrToSource") \
|
||||
macro(default_, default_, "default") \
|
||||
macro(defineProperty, defineProperty, "defineProperty") \
|
||||
macro(defineGetter, defineGetter, "__defineGetter__") \
|
||||
|
Loading…
Reference in New Issue
Block a user