Bug 898356 Part 9 -- Move array buffers into their own file r=sfink

This commit is contained in:
Nicholas D. Matsakis 2014-02-19 14:10:43 -05:00
Родитель 557bc50fcd
Коммит 276c1cd4ed
9 изменённых файлов: 2158 добавлений и 2122 удалений

Просмотреть файл

@ -175,6 +175,212 @@ GetPrototype(JSContext *cx, HandleObject obj)
return &prototypeVal.toObject();
}
/***************************************************************************
* Type descriptors
*/
TypeRepresentation *
TypeDescr::typeRepresentation() const {
return TypeRepresentation::fromOwnerObject(typeRepresentationOwnerObj());
}
TypeDescr::Kind
TypeDescr::kind() const {
return typeRepresentation()->kind();
}
bool
TypeDescr::opaque() const {
return typeRepresentation()->opaque();
}
/***************************************************************************
* Scalar type objects
*
* Scalar type objects like `uint8`, `uint16`, are all instances of
* the ScalarTypeDescr class. Like all type objects, they have a reserved
* slot pointing to a TypeRepresentation object, which is used to
* distinguish which scalar type object this actually is.
*/
const Class js::ScalarTypeDescr::class_ = {
"Scalar",
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr,
ScalarTypeDescr::call,
nullptr,
nullptr,
nullptr
};
const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
{"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
JS_FS_END
};
static size_t ScalarSizes[] = {
#define SCALAR_SIZE(_kind, _type, _name) \
sizeof(_type),
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALAR_SIZE) 0
#undef SCALAR_SIZE
};
size_t
ScalarTypeDescr::size(Type t)
{
return ScalarSizes[t];
}
size_t
ScalarTypeDescr::alignment(Type t)
{
return ScalarSizes[t];
}
/*static*/ const char *
ScalarTypeDescr::typeName(Type type)
{
switch (type) {
#define NUMERIC_TYPE_TO_STRING(constant_, type_, name_) \
case constant_: return #name_;
JS_FOR_EACH_SCALAR_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
}
MOZ_ASSUME_UNREACHABLE("Invalid type");
}
bool
ScalarTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
args.callee().getClass()->name, "0", "s");
return false;
}
ScalarTypeRepresentation *typeRepr =
args.callee().as<ScalarTypeDescr>().typeRepresentation()->asScalar();
ScalarTypeDescr::Type type = typeRepr->type();
double number;
if (!ToNumber(cx, args[0], &number))
return false;
if (type == ScalarTypeDescr::TYPE_UINT8_CLAMPED)
number = ClampDoubleToUint8(number);
switch (type) {
#define SCALARTYPE_CALL(constant_, type_, name_) \
case constant_: { \
type_ converted = ConvertScalar<type_>(number); \
args.rval().setNumber((double) converted); \
return true; \
}
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALARTYPE_CALL)
#undef SCALARTYPE_CALL
}
return true;
}
/***************************************************************************
* Reference type objects
*
* Reference type objects like `Any` or `Object` basically work the
* same way that the scalar type objects do. There is one class with
* many instances, and each instance has a reserved slot with a
* TypeRepresentation object, which is used to distinguish which
* reference type object this actually is.
*/
const Class js::ReferenceTypeDescr::class_ = {
"Reference",
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr,
ReferenceTypeDescr::call,
nullptr,
nullptr,
nullptr
};
const JSFunctionSpec js::ReferenceTypeDescr::typeObjectMethods[] = {
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
{"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
JS_FS_END
};
/*static*/ const char *
ReferenceTypeDescr::typeName(Type type)
{
switch (type) {
#define NUMERIC_TYPE_TO_STRING(constant_, type_, name_) \
case constant_: return #name_;
JS_FOR_EACH_REFERENCE_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
}
MOZ_ASSUME_UNREACHABLE("Invalid type");
}
bool
js::ReferenceTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS_ASSERT(args.callee().is<ReferenceTypeDescr>());
ReferenceTypeRepresentation *typeRepr =
args.callee().as<ReferenceTypeDescr>().typeRepresentation()->asReference();
if (args.length() < 1) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
JSMSG_MORE_ARGS_NEEDED,
typeRepr->typeName(), "0", "s");
return false;
}
switch (typeRepr->type()) {
case ReferenceTypeDescr::TYPE_ANY:
args.rval().set(args[0]);
return true;
case ReferenceTypeDescr::TYPE_OBJECT:
{
RootedObject obj(cx, ToObject(cx, args[0]));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
}
case ReferenceTypeDescr::TYPE_STRING:
{
RootedString obj(cx, ToString<CanGC>(cx, args[0]));
if (!obj)
return false;
args.rval().setString(&*obj);
return true;
}
}
MOZ_ASSUME_UNREACHABLE("Unhandled Reference type");
}
/***************************************************************************
* ArrayMetaTypeDescr class
*/

Просмотреть файл

@ -10,8 +10,7 @@
#include "jsobj.h"
#include "builtin/TypedObjectConstants.h"
#include "builtin/TypedObjectSimple.h"
#include "vm/TypedArrayObject.h"
#include "vm/ArrayBufferObject.h"
/*
* -------------
@ -107,27 +106,197 @@
namespace js {
class TypeRepresentation;
class ScalarTypeRepresentation;
class ReferenceTypeRepresentation;
class X4TypeRepresentation;
class StructTypeDescr;
/*
* This object exists in order to encapsulate the typed object types
* somewhat, rather than sticking them all into the global object.
* Eventually it will go away and become a module.
* Helper method for converting a double into other scalar
* types in the same way that JavaScript would. In particular,
* simple C casting from double to int32_t gets things wrong
* for values like 0xF0000000.
*/
class TypedObjectModuleObject : public JSObject {
template <typename T>
static T ConvertScalar(double d)
{
if (TypeIsFloatingPoint<T>()) {
return T(d);
} else if (TypeIsUnsigned<T>()) {
uint32_t n = ToUint32(d);
return T(n);
} else {
int32_t n = ToInt32(d);
return T(n);
}
}
class TypeDescr : public JSObject
{
public:
enum Slot {
ArrayTypePrototype,
StructTypePrototype,
SlotCount
enum Kind {
Scalar = JS_TYPEREPR_SCALAR_KIND,
Reference = JS_TYPEREPR_REFERENCE_KIND,
X4 = JS_TYPEREPR_X4_KIND,
Struct = JS_TYPEREPR_STRUCT_KIND,
SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
};
static bool isSized(Kind kind) {
return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
}
JSObject &typeRepresentationOwnerObj() const {
return getReservedSlot(JS_DESCR_SLOT_TYPE_REPR).toObject();
}
TypeRepresentation *typeRepresentation() const;
TypeDescr::Kind kind() const;
bool opaque() const;
size_t alignment() {
return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
}
};
typedef Handle<TypeDescr*> HandleTypeDescr;
class SizedTypeDescr : public TypeDescr
{
public:
size_t size() {
return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
}
};
typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
class SimpleTypeDescr : public SizedTypeDescr
{
};
// Type for scalar type constructors like `uint8`. All such type
// constructors share a common js::Class and JSFunctionSpec. Scalar
// types are non-opaque (their storage is visible unless combined with
// an opaque reference type.)
class ScalarTypeDescr : public SimpleTypeDescr
{
public:
// Must match order of JS_FOR_EACH_SCALAR_TYPE_REPR below
enum Type {
TYPE_INT8 = JS_SCALARTYPEREPR_INT8,
TYPE_UINT8 = JS_SCALARTYPEREPR_UINT8,
TYPE_INT16 = JS_SCALARTYPEREPR_INT16,
TYPE_UINT16 = JS_SCALARTYPEREPR_UINT16,
TYPE_INT32 = JS_SCALARTYPEREPR_INT32,
TYPE_UINT32 = JS_SCALARTYPEREPR_UINT32,
TYPE_FLOAT32 = JS_SCALARTYPEREPR_FLOAT32,
TYPE_FLOAT64 = JS_SCALARTYPEREPR_FLOAT64,
/*
* Special type that's a uint8_t, but assignments are clamped to 0 .. 255.
* Treat the raw data type as a uint8_t.
*/
TYPE_UINT8_CLAMPED = JS_SCALARTYPEREPR_UINT8_CLAMPED,
};
static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
static size_t size(Type t);
static size_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();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
};
// Enumerates the cases of ScalarTypeDescr::Type which have
// unique C representation. In particular, omits Uint8Clamped since it
// is just a Uint8.
#define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
macro_(ScalarTypeDescr::TYPE_INT8, int8_t, int8) \
macro_(ScalarTypeDescr::TYPE_UINT8, uint8_t, uint8) \
macro_(ScalarTypeDescr::TYPE_INT16, int16_t, int16) \
macro_(ScalarTypeDescr::TYPE_UINT16, uint16_t, uint16) \
macro_(ScalarTypeDescr::TYPE_INT32, int32_t, int32) \
macro_(ScalarTypeDescr::TYPE_UINT32, uint32_t, uint32) \
macro_(ScalarTypeDescr::TYPE_FLOAT32, float, float32) \
macro_(ScalarTypeDescr::TYPE_FLOAT64, double, float64)
// Must be in same order as the enum ScalarTypeDescr::Type:
#define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_) \
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
macro_(ScalarTypeDescr::TYPE_UINT8_CLAMPED, uint8_t, uint8Clamped)
// Type for reference type constructors like `Any`, `String`, and
// `Object`. All such type constructors share a common js::Class and
// JSFunctionSpec. All these types are opaque.
class ReferenceTypeDescr : public SimpleTypeDescr
{
public:
// Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
enum Type {
TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
};
static const int32_t TYPE_MAX = TYPE_STRING + 1;
static const char *typeName(Type type);
static const Class class_;
static const JSFunctionSpec typeObjectMethods[];
typedef ReferenceTypeRepresentation TypeRepr;
ReferenceTypeDescr::Type type() const {
return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
};
#define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
macro_(ReferenceTypeDescr::TYPE_ANY, HeapValue, Any) \
macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \
macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string)
/*
* Type descriptors `float32x4` and `int32x4`
*/
class X4TypeDescr : public SizedTypeDescr
{
public:
enum Type {
TYPE_INT32 = JS_X4TYPEREPR_INT32,
TYPE_FLOAT32 = JS_X4TYPEREPR_FLOAT32,
};
static const Class class_;
typedef X4TypeRepresentation TypeRepr;
static bool getSuitableClaspAndProto(JSContext *cx,
TypeDescr::Kind kind,
const Class **clasp,
MutableHandleObject proto);
X4TypeDescr::Type type() const {
return (X4TypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
static bool is(const Value &v);
};
#define JS_FOR_EACH_X4_TYPE_REPR(macro_) \
macro_(X4TypeDescr::TYPE_INT32, int32_t, int32) \
macro_(X4TypeDescr::TYPE_FLOAT32, float, float32)
bool IsTypedObjectClass(const Class *clasp); // Defined in TypedArrayObject.h
bool InitializeCommonTypeDescriptorProperties(JSContext *cx,
HandleTypeDescr obj,
HandleObject typeReprOwnerObj);
@ -260,6 +429,27 @@ class StructTypeDescr : public SizedTypeDescr {
typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
/*
* This object exists in order to encapsulate the typed object types
* somewhat, rather than sticking them all into the global object.
* Eventually it will go away and become a module.
*/
class TypedObjectModuleObject : public JSObject {
public:
enum Slot {
ArrayTypePrototype,
StructTypePrototype,
SlotCount
};
static const Class class_;
static bool getSuitableClaspAndProto(JSContext *cx,
TypeDescr::Kind kind,
const Class **clasp,
MutableHandleObject proto);
};
/*
* Base type for typed objects and handles. Basically any type whose
* contents consist of typed memory.

Просмотреть файл

@ -1,217 +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/TypedObjectSimple.h"
using mozilla::DebugOnly;
using namespace js;
/***************************************************************************
* Type descriptors
*/
TypeRepresentation *
TypeDescr::typeRepresentation() const {
return TypeRepresentation::fromOwnerObject(typeRepresentationOwnerObj());
}
TypeDescr::Kind
TypeDescr::kind() const {
return typeRepresentation()->kind();
}
bool
TypeDescr::opaque() const {
return typeRepresentation()->opaque();
}
/***************************************************************************
* Scalar type objects
*
* Scalar type objects like `uint8`, `uint16`, are all instances of
* the ScalarTypeDescr class. Like all type objects, they have a reserved
* slot pointing to a TypeRepresentation object, which is used to
* distinguish which scalar type object this actually is.
*/
const Class js::ScalarTypeDescr::class_ = {
"Scalar",
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr,
ScalarTypeDescr::call,
nullptr,
nullptr,
nullptr
};
const JSFunctionSpec js::ScalarTypeDescr::typeObjectMethods[] = {
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
{"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
JS_FS_END
};
static size_t ScalarSizes[] = {
#define SCALAR_SIZE(_kind, _type, _name) \
sizeof(_type),
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALAR_SIZE) 0
#undef SCALAR_SIZE
};
size_t
ScalarTypeDescr::size(Type t)
{
return ScalarSizes[t];
}
size_t
ScalarTypeDescr::alignment(Type t)
{
return ScalarSizes[t];
}
/*static*/ const char *
ScalarTypeDescr::typeName(Type type)
{
switch (type) {
#define NUMERIC_TYPE_TO_STRING(constant_, type_, name_) \
case constant_: return #name_;
JS_FOR_EACH_SCALAR_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
}
MOZ_ASSUME_UNREACHABLE("Invalid type");
}
bool
ScalarTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
args.callee().getClass()->name, "0", "s");
return false;
}
ScalarTypeRepresentation *typeRepr =
args.callee().as<ScalarTypeDescr>().typeRepresentation()->asScalar();
ScalarTypeDescr::Type type = typeRepr->type();
double number;
if (!ToNumber(cx, args[0], &number))
return false;
if (type == ScalarTypeDescr::TYPE_UINT8_CLAMPED)
number = ClampDoubleToUint8(number);
switch (type) {
#define SCALARTYPE_CALL(constant_, type_, name_) \
case constant_: { \
type_ converted = ConvertScalar<type_>(number); \
args.rval().setNumber((double) converted); \
return true; \
}
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALARTYPE_CALL)
#undef SCALARTYPE_CALL
}
return true;
}
/***************************************************************************
* Reference type objects
*
* Reference type objects like `Any` or `Object` basically work the
* same way that the scalar type objects do. There is one class with
* many instances, and each instance has a reserved slot with a
* TypeRepresentation object, which is used to distinguish which
* reference type object this actually is.
*/
const Class js::ReferenceTypeDescr::class_ = {
"Reference",
JSCLASS_HAS_RESERVED_SLOTS(JS_DESCR_SLOTS),
JS_PropertyStub, /* addProperty */
JS_DeletePropertyStub, /* delProperty */
JS_PropertyStub, /* getProperty */
JS_StrictPropertyStub, /* setProperty */
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
nullptr,
ReferenceTypeDescr::call,
nullptr,
nullptr,
nullptr
};
const JSFunctionSpec js::ReferenceTypeDescr::typeObjectMethods[] = {
JS_SELF_HOSTED_FN("toSource", "DescrToSourceMethod", 0, 0),
{"array", {nullptr, nullptr}, 1, 0, "ArrayShorthand"},
{"equivalent", {nullptr, nullptr}, 1, 0, "TypeDescrEquivalent"},
JS_FS_END
};
/*static*/ const char *
ReferenceTypeDescr::typeName(Type type)
{
switch (type) {
#define NUMERIC_TYPE_TO_STRING(constant_, type_, name_) \
case constant_: return #name_;
JS_FOR_EACH_REFERENCE_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
}
MOZ_ASSUME_UNREACHABLE("Invalid type");
}
bool
js::ReferenceTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
JS_ASSERT(args.callee().is<ReferenceTypeDescr>());
ReferenceTypeRepresentation *typeRepr =
args.callee().as<ReferenceTypeDescr>().typeRepresentation()->asReference();
if (args.length() < 1) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
JSMSG_MORE_ARGS_NEEDED,
typeRepr->typeName(), "0", "s");
return false;
}
switch (typeRepr->type()) {
case ReferenceTypeDescr::TYPE_ANY:
args.rval().set(args[0]);
return true;
case ReferenceTypeDescr::TYPE_OBJECT:
{
RootedObject obj(cx, ToObject(cx, args[0]));
if (!obj)
return false;
args.rval().setObject(*obj);
return true;
}
case ReferenceTypeDescr::TYPE_STRING:
{
RootedString obj(cx, ToString<CanGC>(cx, args[0]));
if (!obj)
return false;
args.rval().setString(&*obj);
return true;
}
}
MOZ_ASSUME_UNREACHABLE("Unhandled Reference type");
}

Просмотреть файл

@ -1,220 +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_TypedObjectSimple_h
#define builtin_TypedObjectSimple_h
#include "jsobj.h"
#include "builtin/TypedObjectConstants.h"
/*
* Simple Typed Objects
* --------------------
*
* Contains definitions for the "simple" type descriptors like scalar
* and reference types. These are pulled apart from the rest of the
* typed object primarily so that this file can be included from
* TypedArrayObject.h, but it also helps to reduce the monolithic
* nature of TypedObject.h.
*/
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,
* simple C casting from double to int32_t gets things wrong
* for values like 0xF0000000.
*/
template <typename T>
static T ConvertScalar(double d)
{
if (TypeIsFloatingPoint<T>()) {
return T(d);
} else if (TypeIsUnsigned<T>()) {
uint32_t n = ToUint32(d);
return T(n);
} else {
int32_t n = ToInt32(d);
return T(n);
}
}
class TypeDescr : public JSObject
{
public:
enum Kind {
Scalar = JS_TYPEREPR_SCALAR_KIND,
Reference = JS_TYPEREPR_REFERENCE_KIND,
X4 = JS_TYPEREPR_X4_KIND,
Struct = JS_TYPEREPR_STRUCT_KIND,
SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
};
static bool isSized(Kind kind) {
return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
}
JSObject &typeRepresentationOwnerObj() const {
return getReservedSlot(JS_DESCR_SLOT_TYPE_REPR).toObject();
}
TypeRepresentation *typeRepresentation() const;
TypeDescr::Kind kind() const;
bool opaque() const;
size_t alignment() {
return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
}
};
typedef Handle<TypeDescr*> HandleTypeDescr;
class SizedTypeDescr : public TypeDescr
{
public:
size_t size() {
return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
}
};
typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
class SimpleTypeDescr : public SizedTypeDescr
{
};
// Type for scalar type constructors like `uint8`. All such type
// constructors share a common js::Class and JSFunctionSpec. Scalar
// types are non-opaque (their storage is visible unless combined with
// an opaque reference type.)
class ScalarTypeDescr : public SimpleTypeDescr
{
public:
// Must match order of JS_FOR_EACH_SCALAR_TYPE_REPR below
enum Type {
TYPE_INT8 = JS_SCALARTYPEREPR_INT8,
TYPE_UINT8 = JS_SCALARTYPEREPR_UINT8,
TYPE_INT16 = JS_SCALARTYPEREPR_INT16,
TYPE_UINT16 = JS_SCALARTYPEREPR_UINT16,
TYPE_INT32 = JS_SCALARTYPEREPR_INT32,
TYPE_UINT32 = JS_SCALARTYPEREPR_UINT32,
TYPE_FLOAT32 = JS_SCALARTYPEREPR_FLOAT32,
TYPE_FLOAT64 = JS_SCALARTYPEREPR_FLOAT64,
/*
* Special type that's a uint8_t, but assignments are clamped to 0 .. 255.
* Treat the raw data type as a uint8_t.
*/
TYPE_UINT8_CLAMPED = JS_SCALARTYPEREPR_UINT8_CLAMPED,
};
static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
static size_t size(Type t);
static size_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();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
};
// Enumerates the cases of ScalarTypeDescr::Type which have
// unique C representation. In particular, omits Uint8Clamped since it
// is just a Uint8.
#define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
macro_(ScalarTypeDescr::TYPE_INT8, int8_t, int8) \
macro_(ScalarTypeDescr::TYPE_UINT8, uint8_t, uint8) \
macro_(ScalarTypeDescr::TYPE_INT16, int16_t, int16) \
macro_(ScalarTypeDescr::TYPE_UINT16, uint16_t, uint16) \
macro_(ScalarTypeDescr::TYPE_INT32, int32_t, int32) \
macro_(ScalarTypeDescr::TYPE_UINT32, uint32_t, uint32) \
macro_(ScalarTypeDescr::TYPE_FLOAT32, float, float32) \
macro_(ScalarTypeDescr::TYPE_FLOAT64, double, float64)
// Must be in same order as the enum ScalarTypeDescr::Type:
#define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_) \
JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
macro_(ScalarTypeDescr::TYPE_UINT8_CLAMPED, uint8_t, uint8Clamped)
// Type for reference type constructors like `Any`, `String`, and
// `Object`. All such type constructors share a common js::Class and
// JSFunctionSpec. All these types are opaque.
class ReferenceTypeDescr : public SimpleTypeDescr
{
public:
// Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
enum Type {
TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
};
static const int32_t TYPE_MAX = TYPE_STRING + 1;
static const char *typeName(Type type);
static const Class class_;
static const JSFunctionSpec typeObjectMethods[];
typedef ReferenceTypeRepresentation TypeRepr;
ReferenceTypeDescr::Type type() const {
return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
};
#define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
macro_(ReferenceTypeDescr::TYPE_ANY, HeapValue, Any) \
macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \
macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string)
/*
* Type descriptors `float32x4` and `int32x4`
*/
class X4TypeDescr : public SizedTypeDescr
{
public:
enum Type {
TYPE_INT32 = JS_X4TYPEREPR_INT32,
TYPE_FLOAT32 = JS_X4TYPEREPR_FLOAT32,
};
static const Class class_;
typedef X4TypeRepresentation TypeRepr;
X4TypeDescr::Type type() const {
return (X4TypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
}
static bool call(JSContext *cx, unsigned argc, Value *vp);
static bool is(const Value &v);
};
#define JS_FOR_EACH_X4_TYPE_REPR(macro_) \
macro_(X4TypeDescr::TYPE_INT32, int32_t, int32) \
macro_(X4TypeDescr::TYPE_FLOAT32, float, float32)
bool IsTypedObjectClass(const Class *clasp); // Defined in TypedArrayObject.h
} // namespace js
#endif

Просмотреть файл

@ -100,7 +100,6 @@ UNIFIED_SOURCES += [
'builtin/SIMD.cpp',
'builtin/TestingFunctions.cpp',
'builtin/TypedObject.cpp',
'builtin/TypedObjectSimple.cpp',
'builtin/TypeRepresentation.cpp',
'devtools/sharkctl.cpp',
'ds/LifoAlloc.cpp',
@ -156,6 +155,7 @@ UNIFIED_SOURCES += [
'perf/jsperf.cpp',
'prmjtime.cpp',
'vm/ArgumentsObject.cpp',
'vm/ArrayBufferObject.cpp',
'vm/CallNonGenericMethod.cpp',
'vm/CharacterEncoding.cpp',
'vm/Compression.cpp',

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,317 @@
/* -*- 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 vm_ArrayBufferObject_h
#define vm_ArrayBufferObject_h
#include "jsobj.h"
#include "builtin/TypedObjectConstants.h"
#include "vm/Runtime.h"
typedef struct JSProperty JSProperty;
namespace js {
class ArrayBufferViewObject;
// The inheritance hierarchy for the various classes relating to typed arrays
// is as follows.
//
// - JSObject
// - ArrayBufferObject
// - ArrayBufferViewObject
// - DataViewObject
// - TypedArrayObject (declared in vm/TypedArrayObject.h)
// - TypedArrayObjectTemplate
// - Int8ArrayObject
// - Uint8ArrayObject
// - ...
// - TypedObject (declared in builtin/TypedObject.h)
//
// Note that |TypedArrayObjectTemplate| is just an implementation
// detail that makes implementing its various subclasses easier.
typedef Vector<ArrayBufferObject *, 0, SystemAllocPolicy> ArrayBufferVector;
/*
* ArrayBufferObject
*
* This class holds the underlying raw buffer that the various
* ArrayBufferViewObject subclasses (DataViewObject and the TypedArrays)
* access. It can be created explicitly and passed to an ArrayBufferViewObject
* subclass, or can be created implicitly by constructing a TypedArrayObject
* with a size.
*/
class ArrayBufferObject : public JSObject
{
static bool byteLengthGetterImpl(JSContext *cx, CallArgs args);
static bool fun_slice_impl(JSContext *cx, CallArgs args);
public:
static const Class class_;
static const Class protoClass;
static const JSFunctionSpec jsfuncs[];
static const JSFunctionSpec jsstaticfuncs[];
static bool byteLengthGetter(JSContext *cx, unsigned argc, Value *vp);
static bool fun_slice(JSContext *cx, unsigned argc, Value *vp);
static bool fun_isView(JSContext *cx, unsigned argc, Value *vp);
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, bool clear = true);
static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
uint32_t begin, uint32_t end);
static bool createDataViewForThisImpl(JSContext *cx, CallArgs args);
static bool createDataViewForThis(JSContext *cx, unsigned argc, Value *vp);
template<typename T>
static bool createTypedArrayFromBufferImpl(JSContext *cx, CallArgs args);
template<typename T>
static bool createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Value *vp);
static void obj_trace(JSTracer *trc, JSObject *obj);
static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineProperty(JSContext *cx, HandleObject obj,
HandlePropertyName name, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineSpecial(JSContext *cx, HandleObject obj,
HandleSpecialId sid, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp);
static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandlePropertyName name, MutableHandleValue vp);
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp);
static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleSpecialId sid, MutableHandleValue vp);
static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, bool strict);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleValue vp, bool strict);
static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleValue vp, bool strict);
static bool obj_setSpecial(JSContext *cx, HandleObject obj,
HandleSpecialId sid, MutableHandleValue vp, bool strict);
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded);
static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
bool *succeeded);
static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
bool *succeeded);
static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
MutableHandleValue statep, MutableHandleId idp);
static void sweep(JSCompartment *rt);
static void resetArrayBufferList(JSCompartment *rt);
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
static void restoreArrayBufferLists(ArrayBufferVector &vector);
static bool stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
uint8_t **data);
static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->initializedLength = bytes;
// NB: one or both of these fields is clobbered by GetViewList to store
// the 'views' link. Set them to 0 to effectively initialize 'views'
// to nullptr.
header->length = 0;
header->capacity = 0;
}
static void initElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->flags = 0;
updateElementsHeader(header, bytes);
}
static uint32_t headerInitializedLength(const js::ObjectElements *header) {
return header->initializedLength;
}
void addView(ArrayBufferViewObject *view);
void changeContents(JSContext *cx, ObjectElements *newHeader);
/*
* Ensure data is not stored inline in the object. Used when handing back a
* GC-safe pointer.
*/
static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
uint32_t byteLength() const {
return getElementsHeader()->initializedLength;
}
/*
* Neuter all views of an ArrayBuffer.
*/
static bool neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer);
inline uint8_t * dataPointer() const {
return (uint8_t *) elements;
}
/*
* Discard the ArrayBuffer contents. For asm.js buffers, at least, should
* be called after neuterViews().
*/
void neuter(JSContext *cx);
/*
* Check if the arrayBuffer contains any data. This will return false for
* ArrayBuffer.prototype and neutered ArrayBuffers.
*/
bool hasData() const {
return getClass() == &class_;
}
bool isAsmJSArrayBuffer() const {
return getElementsHeader()->isAsmJSArrayBuffer();
}
bool isNeutered() const {
return getElementsHeader()->isNeuteredBuffer();
}
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
static bool neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer);
static void releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj);
};
/*
* ArrayBufferViewObject
*
* Common definitions shared by all ArrayBufferViews.
*/
class ArrayBufferViewObject : public JSObject
{
protected:
/* Offset of view in underlying ArrayBufferObject */
static const size_t BYTEOFFSET_SLOT = JS_TYPEDOBJ_SLOT_BYTEOFFSET;
/* Byte length of view */
static const size_t BYTELENGTH_SLOT = JS_TYPEDOBJ_SLOT_BYTELENGTH;
/* Underlying ArrayBufferObject */
static const size_t BUFFER_SLOT = JS_TYPEDOBJ_SLOT_OWNER;
/* ArrayBufferObjects point to a linked list of views, chained through this slot */
static const size_t NEXT_VIEW_SLOT = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
/*
* When ArrayBufferObjects are traced during GC, they construct a linked
* list of ArrayBufferObjects with more than one view, chained through this
* slot of the first view of each ArrayBufferObject.
*/
static const size_t NEXT_BUFFER_SLOT = JS_TYPEDOBJ_SLOT_NEXT_BUFFER;
public:
JSObject *bufferObject() const {
return &getFixedSlot(BUFFER_SLOT).toObject();
}
ArrayBufferObject *bufferLink() {
return static_cast<ArrayBufferObject*>(getFixedSlot(NEXT_BUFFER_SLOT).toPrivate());
}
inline void setBufferLink(ArrayBufferObject *buffer);
ArrayBufferViewObject *nextView() const {
return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
}
inline void setNextView(ArrayBufferViewObject *view);
void prependToViews(ArrayBufferViewObject *viewsHead);
void neuter(JSContext *cx);
static void trace(JSTracer *trc, JSObject *obj);
};
bool
ToClampedIndex(JSContext *cx, HandleValue v, uint32_t length, uint32_t *out);
inline void
PostBarrierTypedArrayObject(JSObject *obj)
{
#ifdef JSGC_GENERATIONAL
JS_ASSERT(obj);
JSRuntime *rt = obj->runtimeFromMainThread();
if (!rt->isHeapBusy() && !IsInsideNursery(rt, obj))
rt->gcStoreBuffer.putWholeCell(obj);
#endif
}
inline void
InitArrayBufferViewDataPointer(ArrayBufferViewObject *obj, ArrayBufferObject *buffer, size_t byteOffset)
{
/*
* N.B. The base of the array's data is stored in the object's
* private data rather than a slot to avoid alignment restrictions
* on private Values.
*/
obj->initPrivate(buffer->dataPointer() + byteOffset);
PostBarrierTypedArrayObject(obj);
}
MOZ_ALWAYS_INLINE bool
IsArrayBuffer(HandleValue v)
{
return v.isObject() && v.toObject().is<ArrayBufferObject>();
}
inline void
ArrayBufferViewObject::setBufferLink(ArrayBufferObject *buffer)
{
setFixedSlot(NEXT_BUFFER_SLOT, PrivateValue(buffer));
PostBarrierTypedArrayObject(this);
}
inline void
ArrayBufferViewObject::setNextView(ArrayBufferViewObject *view)
{
setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(view));
PostBarrierTypedArrayObject(this);
}
} // namespace js
#endif // vm_ArrayBufferObject_h

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,263 +9,15 @@
#include "jsobj.h"
#include "builtin/TypedObjectSimple.h"
#include "builtin/TypedObject.h"
#include "gc/Barrier.h"
#include "js/Class.h"
#include "vm/ArrayBufferObject.h"
typedef struct JSProperty JSProperty;
namespace js {
typedef Vector<ArrayBufferObject *, 0, SystemAllocPolicy> ArrayBufferVector;
// The inheritance hierarchy for the various classes relating to typed arrays
// is as follows.
//
// - JSObject
// - ArrayBufferObject
// - ArrayBufferViewObject
// - DataViewObject
// - TypedArrayObject
// - TypedArrayObjectTemplate
// - Int8ArrayObject
// - Uint8ArrayObject
// - ...
//
// Note that |TypedArrayObjectTemplate| is just an implementation detail that
// makes implementing its various subclasses easier.
class ArrayBufferViewObject;
/*
* ArrayBufferObject
*
* This class holds the underlying raw buffer that the various
* ArrayBufferViewObject subclasses (DataViewObject and the TypedArrays)
* access. It can be created explicitly and passed to an ArrayBufferViewObject
* subclass, or can be created implicitly by constructing a TypedArrayObject
* with a size.
*/
class ArrayBufferObject : public JSObject
{
static bool byteLengthGetterImpl(JSContext *cx, CallArgs args);
static bool fun_slice_impl(JSContext *cx, CallArgs args);
public:
static const Class class_;
static const Class protoClass;
static const JSFunctionSpec jsfuncs[];
static const JSFunctionSpec jsstaticfuncs[];
static bool byteLengthGetter(JSContext *cx, unsigned argc, Value *vp);
static bool fun_slice(JSContext *cx, unsigned argc, Value *vp);
static bool fun_isView(JSContext *cx, unsigned argc, Value *vp);
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, bool clear = true);
static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
uint32_t begin, uint32_t end);
static bool createDataViewForThisImpl(JSContext *cx, CallArgs args);
static bool createDataViewForThis(JSContext *cx, unsigned argc, Value *vp);
template<typename T>
static bool createTypedArrayFromBufferImpl(JSContext *cx, CallArgs args);
template<typename T>
static bool createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Value *vp);
static void obj_trace(JSTracer *trc, JSObject *obj);
static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_lookupSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineProperty(JSContext *cx, HandleObject obj,
HandlePropertyName name, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_defineSpecial(JSContext *cx, HandleObject obj,
HandleSpecialId sid, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp);
static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandlePropertyName name, MutableHandleValue vp);
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp);
static bool obj_getSpecial(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleSpecialId sid, MutableHandleValue vp);
static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, bool strict);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
MutableHandleValue vp, bool strict);
static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleValue vp, bool strict);
static bool obj_setSpecial(JSContext *cx, HandleObject obj,
HandleSpecialId sid, MutableHandleValue vp, bool strict);
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
HandleId id, unsigned *attrsp);
static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
bool *succeeded);
static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
bool *succeeded);
static bool obj_deleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid,
bool *succeeded);
static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
MutableHandleValue statep, MutableHandleId idp);
static void sweep(JSCompartment *rt);
static void resetArrayBufferList(JSCompartment *rt);
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
static void restoreArrayBufferLists(ArrayBufferVector &vector);
static bool stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
uint8_t **data);
static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->initializedLength = bytes;
// NB: one or both of these fields is clobbered by GetViewList to store
// the 'views' link. Set them to 0 to effectively initialize 'views'
// to nullptr.
header->length = 0;
header->capacity = 0;
}
static void initElementsHeader(js::ObjectElements *header, uint32_t bytes) {
header->flags = 0;
updateElementsHeader(header, bytes);
}
static uint32_t headerInitializedLength(const js::ObjectElements *header) {
return header->initializedLength;
}
void addView(ArrayBufferViewObject *view);
void changeContents(JSContext *cx, ObjectElements *newHeader);
/*
* Ensure data is not stored inline in the object. Used when handing back a
* GC-safe pointer.
*/
static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
uint32_t byteLength() const {
return getElementsHeader()->initializedLength;
}
/*
* Neuter all views of an ArrayBuffer.
*/
static bool neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer);
inline uint8_t * dataPointer() const {
return (uint8_t *) elements;
}
/*
* Discard the ArrayBuffer contents. For asm.js buffers, at least, should
* be called after neuterViews().
*/
void neuter(JSContext *cx);
/*
* Check if the arrayBuffer contains any data. This will return false for
* ArrayBuffer.prototype and neutered ArrayBuffers.
*/
bool hasData() const {
return getClass() == &class_;
}
bool isAsmJSArrayBuffer() const {
return getElementsHeader()->isAsmJSArrayBuffer();
}
bool isNeutered() const {
return getElementsHeader()->isNeuteredBuffer();
}
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
static bool neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer);
static void releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj);
};
/*
* ArrayBufferViewObject
*
* Common definitions shared by all ArrayBufferViews.
*/
class ArrayBufferViewObject : public JSObject
{
protected:
/* Offset of view in underlying ArrayBufferObject */
static const size_t BYTEOFFSET_SLOT = JS_TYPEDOBJ_SLOT_BYTEOFFSET;
/* Byte length of view */
static const size_t BYTELENGTH_SLOT = JS_TYPEDOBJ_SLOT_BYTELENGTH;
/* Underlying ArrayBufferObject */
static const size_t BUFFER_SLOT = JS_TYPEDOBJ_SLOT_OWNER;
/* ArrayBufferObjects point to a linked list of views, chained through this slot */
static const size_t NEXT_VIEW_SLOT = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
/*
* When ArrayBufferObjects are traced during GC, they construct a linked
* list of ArrayBufferObjects with more than one view, chained through this
* slot of the first view of each ArrayBufferObject.
*/
static const size_t NEXT_BUFFER_SLOT = JS_TYPEDOBJ_SLOT_NEXT_BUFFER;
public:
JSObject *bufferObject() const {
return &getFixedSlot(BUFFER_SLOT).toObject();
}
ArrayBufferObject *bufferLink() {
return static_cast<ArrayBufferObject*>(getFixedSlot(NEXT_BUFFER_SLOT).toPrivate());
}
inline void setBufferLink(ArrayBufferObject *buffer);
ArrayBufferViewObject *nextView() const {
return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
}
inline void setNextView(ArrayBufferViewObject *view);
void prependToViews(ArrayBufferViewObject *viewsHead);
void neuter(JSContext *cx);
static void trace(JSTracer *trc, JSObject *obj);
};
/*
* TypedArrayObject
*