зеркало из https://github.com/mozilla/gecko-dev.git
Bug 898356 Part 9 -- Move array buffers into their own file r=sfink
This commit is contained in:
Родитель
557bc50fcd
Коммит
276c1cd4ed
|
@ -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
|
||||
*
|
||||
|
|
Загрузка…
Ссылка в новой задаче