js/src/vm/TypedArrayObject.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef vm_TypedArrayObject_h
michael@0 8 #define vm_TypedArrayObject_h
michael@0 9
michael@0 10 #include "jsobj.h"
michael@0 11
michael@0 12 #include "builtin/TypedObject.h"
michael@0 13 #include "gc/Barrier.h"
michael@0 14 #include "js/Class.h"
michael@0 15 #include "vm/ArrayBufferObject.h"
michael@0 16
michael@0 17 typedef struct JSProperty JSProperty;
michael@0 18
michael@0 19 namespace js {
michael@0 20
michael@0 21 /*
michael@0 22 * TypedArrayObject
michael@0 23 *
michael@0 24 * The non-templated base class for the specific typed implementations.
michael@0 25 * This class holds all the member variables that are used by
michael@0 26 * the subclasses.
michael@0 27 */
michael@0 28
michael@0 29 class TypedArrayObject : public ArrayBufferViewObject
michael@0 30 {
michael@0 31 protected:
michael@0 32 // Typed array properties stored in slots, beyond those shared by all
michael@0 33 // ArrayBufferViews.
michael@0 34 static const size_t LENGTH_SLOT = JS_TYPEDOBJ_SLOT_LENGTH;
michael@0 35 static const size_t TYPE_SLOT = JS_TYPEDOBJ_SLOT_TYPE_DESCR;
michael@0 36 static const size_t RESERVED_SLOTS = JS_TYPEDOBJ_SLOTS;
michael@0 37 static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA;
michael@0 38
michael@0 39 static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
michael@0 40 "bad inlined constant in jsfriendapi.h");
michael@0 41
michael@0 42 public:
michael@0 43 static const Class classes[ScalarTypeDescr::TYPE_MAX];
michael@0 44 static const Class protoClasses[ScalarTypeDescr::TYPE_MAX];
michael@0 45
michael@0 46 static const size_t FIXED_DATA_START = DATA_SLOT + 1;
michael@0 47
michael@0 48 // For typed arrays which can store their data inline, the array buffer
michael@0 49 // object is created lazily.
michael@0 50 static const uint32_t INLINE_BUFFER_LIMIT =
michael@0 51 (JSObject::MAX_FIXED_SLOTS - FIXED_DATA_START) * sizeof(Value);
michael@0 52
michael@0 53 static gc::AllocKind
michael@0 54 AllocKindForLazyBuffer(size_t nbytes)
michael@0 55 {
michael@0 56 JS_ASSERT(nbytes <= INLINE_BUFFER_LIMIT);
michael@0 57 /* For GGC we need at least one slot in which to store a forwarding pointer. */
michael@0 58 size_t dataSlots = Max(size_t(1), AlignBytes(nbytes, sizeof(Value)) / sizeof(Value));
michael@0 59 JS_ASSERT(nbytes <= dataSlots * sizeof(Value));
michael@0 60 return gc::GetGCObjectKind(FIXED_DATA_START + dataSlots);
michael@0 61 }
michael@0 62
michael@0 63 static Value bufferValue(TypedArrayObject *tarr) {
michael@0 64 return tarr->getFixedSlot(BUFFER_SLOT);
michael@0 65 }
michael@0 66 static Value byteOffsetValue(TypedArrayObject *tarr) {
michael@0 67 return tarr->getFixedSlot(BYTEOFFSET_SLOT);
michael@0 68 }
michael@0 69 static Value byteLengthValue(TypedArrayObject *tarr) {
michael@0 70 return tarr->getFixedSlot(BYTELENGTH_SLOT);
michael@0 71 }
michael@0 72 static Value lengthValue(TypedArrayObject *tarr) {
michael@0 73 return tarr->getFixedSlot(LENGTH_SLOT);
michael@0 74 }
michael@0 75
michael@0 76 static bool
michael@0 77 ensureHasBuffer(JSContext *cx, Handle<TypedArrayObject *> tarray);
michael@0 78
michael@0 79 ArrayBufferObject *sharedBuffer() const;
michael@0 80 ArrayBufferObject *buffer() const {
michael@0 81 JSObject *obj = bufferValue(const_cast<TypedArrayObject*>(this)).toObjectOrNull();
michael@0 82 if (!obj)
michael@0 83 return nullptr;
michael@0 84 if (obj->is<ArrayBufferObject>())
michael@0 85 return &obj->as<ArrayBufferObject>();
michael@0 86 return sharedBuffer();
michael@0 87 }
michael@0 88 uint32_t byteOffset() const {
michael@0 89 return byteOffsetValue(const_cast<TypedArrayObject*>(this)).toInt32();
michael@0 90 }
michael@0 91 uint32_t byteLength() const {
michael@0 92 return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
michael@0 93 }
michael@0 94 uint32_t length() const {
michael@0 95 return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
michael@0 96 }
michael@0 97
michael@0 98 uint32_t type() const {
michael@0 99 return getFixedSlot(TYPE_SLOT).toInt32();
michael@0 100 }
michael@0 101 void *viewData() const {
michael@0 102 // Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
michael@0 103 return static_cast<void*>(getPrivate(DATA_SLOT));
michael@0 104 }
michael@0 105
michael@0 106 Value getElement(uint32_t index);
michael@0 107 static void setElement(TypedArrayObject &obj, uint32_t index, double d);
michael@0 108
michael@0 109 void neuter(void *newData);
michael@0 110
michael@0 111 static uint32_t slotWidth(int atype) {
michael@0 112 switch (atype) {
michael@0 113 case ScalarTypeDescr::TYPE_INT8:
michael@0 114 case ScalarTypeDescr::TYPE_UINT8:
michael@0 115 case ScalarTypeDescr::TYPE_UINT8_CLAMPED:
michael@0 116 return 1;
michael@0 117 case ScalarTypeDescr::TYPE_INT16:
michael@0 118 case ScalarTypeDescr::TYPE_UINT16:
michael@0 119 return 2;
michael@0 120 case ScalarTypeDescr::TYPE_INT32:
michael@0 121 case ScalarTypeDescr::TYPE_UINT32:
michael@0 122 case ScalarTypeDescr::TYPE_FLOAT32:
michael@0 123 return 4;
michael@0 124 case ScalarTypeDescr::TYPE_FLOAT64:
michael@0 125 return 8;
michael@0 126 default:
michael@0 127 MOZ_ASSUME_UNREACHABLE("invalid typed array type");
michael@0 128 }
michael@0 129 }
michael@0 130
michael@0 131 int slotWidth() {
michael@0 132 return slotWidth(type());
michael@0 133 }
michael@0 134
michael@0 135 /*
michael@0 136 * Byte length above which created typed arrays and data views will have
michael@0 137 * singleton types regardless of the context in which they are created.
michael@0 138 */
michael@0 139 static const uint32_t SINGLETON_TYPE_BYTE_LENGTH = 1024 * 1024 * 10;
michael@0 140
michael@0 141 static int lengthOffset();
michael@0 142 static int dataOffset();
michael@0 143 };
michael@0 144
michael@0 145 inline bool
michael@0 146 IsTypedArrayClass(const Class *clasp)
michael@0 147 {
michael@0 148 return &TypedArrayObject::classes[0] <= clasp &&
michael@0 149 clasp < &TypedArrayObject::classes[ScalarTypeDescr::TYPE_MAX];
michael@0 150 }
michael@0 151
michael@0 152 inline bool
michael@0 153 IsTypedArrayProtoClass(const Class *clasp)
michael@0 154 {
michael@0 155 return &TypedArrayObject::protoClasses[0] <= clasp &&
michael@0 156 clasp < &TypedArrayObject::protoClasses[ScalarTypeDescr::TYPE_MAX];
michael@0 157 }
michael@0 158
michael@0 159 bool
michael@0 160 IsTypedArrayConstructor(HandleValue v, uint32_t type);
michael@0 161
michael@0 162 bool
michael@0 163 IsTypedArrayBuffer(HandleValue v);
michael@0 164
michael@0 165 ArrayBufferObject &
michael@0 166 AsTypedArrayBuffer(HandleValue v);
michael@0 167
michael@0 168 // Return value is whether the string is some integer. If the string is an
michael@0 169 // integer which is not representable as a uint64_t, the return value is true
michael@0 170 // and the resulting index is UINT64_MAX.
michael@0 171 bool
michael@0 172 StringIsTypedArrayIndex(JSLinearString *str, uint64_t *indexp);
michael@0 173
michael@0 174 inline bool
michael@0 175 IsTypedArrayIndex(jsid id, uint64_t *indexp)
michael@0 176 {
michael@0 177 if (JSID_IS_INT(id)) {
michael@0 178 int32_t i = JSID_TO_INT(id);
michael@0 179 JS_ASSERT(i >= 0);
michael@0 180 *indexp = (double)i;
michael@0 181 return true;
michael@0 182 }
michael@0 183
michael@0 184 if (MOZ_UNLIKELY(!JSID_IS_STRING(id)))
michael@0 185 return false;
michael@0 186
michael@0 187 JSAtom *atom = JSID_TO_ATOM(id);
michael@0 188
michael@0 189 jschar c = atom->chars()[0];
michael@0 190 if (!JS7_ISDEC(c) && c != '-')
michael@0 191 return false;
michael@0 192
michael@0 193 return StringIsTypedArrayIndex(atom, indexp);
michael@0 194 }
michael@0 195
michael@0 196 static inline unsigned
michael@0 197 TypedArrayShift(ArrayBufferView::ViewType viewType)
michael@0 198 {
michael@0 199 switch (viewType) {
michael@0 200 case ArrayBufferView::TYPE_INT8:
michael@0 201 case ArrayBufferView::TYPE_UINT8:
michael@0 202 case ArrayBufferView::TYPE_UINT8_CLAMPED:
michael@0 203 return 0;
michael@0 204 case ArrayBufferView::TYPE_INT16:
michael@0 205 case ArrayBufferView::TYPE_UINT16:
michael@0 206 return 1;
michael@0 207 case ArrayBufferView::TYPE_INT32:
michael@0 208 case ArrayBufferView::TYPE_UINT32:
michael@0 209 case ArrayBufferView::TYPE_FLOAT32:
michael@0 210 return 2;
michael@0 211 case ArrayBufferView::TYPE_FLOAT64:
michael@0 212 return 3;
michael@0 213 default:;
michael@0 214 }
michael@0 215 MOZ_ASSUME_UNREACHABLE("Unexpected array type");
michael@0 216 }
michael@0 217
michael@0 218 class DataViewObject : public ArrayBufferViewObject
michael@0 219 {
michael@0 220 static const size_t RESERVED_SLOTS = JS_DATAVIEW_SLOTS;
michael@0 221 static const size_t DATA_SLOT = JS_TYPEDOBJ_SLOT_DATA;
michael@0 222
michael@0 223 private:
michael@0 224 static const Class protoClass;
michael@0 225
michael@0 226 static bool is(HandleValue v) {
michael@0 227 return v.isObject() && v.toObject().hasClass(&class_);
michael@0 228 }
michael@0 229
michael@0 230 template <typename NativeType>
michael@0 231 static uint8_t *
michael@0 232 getDataPointer(JSContext *cx, Handle<DataViewObject*> obj, uint32_t offset);
michael@0 233
michael@0 234 template<Value ValueGetter(DataViewObject *view)>
michael@0 235 static bool
michael@0 236 getterImpl(JSContext *cx, CallArgs args);
michael@0 237
michael@0 238 template<Value ValueGetter(DataViewObject *view)>
michael@0 239 static bool
michael@0 240 getter(JSContext *cx, unsigned argc, Value *vp);
michael@0 241
michael@0 242 template<Value ValueGetter(DataViewObject *view)>
michael@0 243 static bool
michael@0 244 defineGetter(JSContext *cx, PropertyName *name, HandleObject proto);
michael@0 245
michael@0 246 public:
michael@0 247 static const Class class_;
michael@0 248
michael@0 249 static Value byteOffsetValue(DataViewObject *view) {
michael@0 250 Value v = view->getReservedSlot(BYTEOFFSET_SLOT);
michael@0 251 JS_ASSERT(v.toInt32() >= 0);
michael@0 252 return v;
michael@0 253 }
michael@0 254
michael@0 255 static Value byteLengthValue(DataViewObject *view) {
michael@0 256 Value v = view->getReservedSlot(BYTELENGTH_SLOT);
michael@0 257 JS_ASSERT(v.toInt32() >= 0);
michael@0 258 return v;
michael@0 259 }
michael@0 260
michael@0 261 static Value bufferValue(DataViewObject *view) {
michael@0 262 return view->getReservedSlot(BUFFER_SLOT);
michael@0 263 }
michael@0 264
michael@0 265 uint32_t byteOffset() const {
michael@0 266 return byteOffsetValue(const_cast<DataViewObject*>(this)).toInt32();
michael@0 267 }
michael@0 268
michael@0 269 uint32_t byteLength() const {
michael@0 270 return byteLengthValue(const_cast<DataViewObject*>(this)).toInt32();
michael@0 271 }
michael@0 272
michael@0 273 ArrayBufferObject &arrayBuffer() const {
michael@0 274 return bufferValue(const_cast<DataViewObject*>(this)).toObject().as<ArrayBufferObject>();
michael@0 275 }
michael@0 276
michael@0 277 void *dataPointer() const {
michael@0 278 return getPrivate();
michael@0 279 }
michael@0 280
michael@0 281 static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
michael@0 282 static bool constructWithProto(JSContext *cx, unsigned argc, Value *vp);
michael@0 283 static bool construct(JSContext *cx, JSObject *bufobj, const CallArgs &args,
michael@0 284 HandleObject proto);
michael@0 285
michael@0 286 static inline DataViewObject *
michael@0 287 create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
michael@0 288 Handle<ArrayBufferObject*> arrayBuffer, JSObject *proto);
michael@0 289
michael@0 290 static bool getInt8Impl(JSContext *cx, CallArgs args);
michael@0 291 static bool fun_getInt8(JSContext *cx, unsigned argc, Value *vp);
michael@0 292
michael@0 293 static bool getUint8Impl(JSContext *cx, CallArgs args);
michael@0 294 static bool fun_getUint8(JSContext *cx, unsigned argc, Value *vp);
michael@0 295
michael@0 296 static bool getInt16Impl(JSContext *cx, CallArgs args);
michael@0 297 static bool fun_getInt16(JSContext *cx, unsigned argc, Value *vp);
michael@0 298
michael@0 299 static bool getUint16Impl(JSContext *cx, CallArgs args);
michael@0 300 static bool fun_getUint16(JSContext *cx, unsigned argc, Value *vp);
michael@0 301
michael@0 302 static bool getInt32Impl(JSContext *cx, CallArgs args);
michael@0 303 static bool fun_getInt32(JSContext *cx, unsigned argc, Value *vp);
michael@0 304
michael@0 305 static bool getUint32Impl(JSContext *cx, CallArgs args);
michael@0 306 static bool fun_getUint32(JSContext *cx, unsigned argc, Value *vp);
michael@0 307
michael@0 308 static bool getFloat32Impl(JSContext *cx, CallArgs args);
michael@0 309 static bool fun_getFloat32(JSContext *cx, unsigned argc, Value *vp);
michael@0 310
michael@0 311 static bool getFloat64Impl(JSContext *cx, CallArgs args);
michael@0 312 static bool fun_getFloat64(JSContext *cx, unsigned argc, Value *vp);
michael@0 313
michael@0 314 static bool setInt8Impl(JSContext *cx, CallArgs args);
michael@0 315 static bool fun_setInt8(JSContext *cx, unsigned argc, Value *vp);
michael@0 316
michael@0 317 static bool setUint8Impl(JSContext *cx, CallArgs args);
michael@0 318 static bool fun_setUint8(JSContext *cx, unsigned argc, Value *vp);
michael@0 319
michael@0 320 static bool setInt16Impl(JSContext *cx, CallArgs args);
michael@0 321 static bool fun_setInt16(JSContext *cx, unsigned argc, Value *vp);
michael@0 322
michael@0 323 static bool setUint16Impl(JSContext *cx, CallArgs args);
michael@0 324 static bool fun_setUint16(JSContext *cx, unsigned argc, Value *vp);
michael@0 325
michael@0 326 static bool setInt32Impl(JSContext *cx, CallArgs args);
michael@0 327 static bool fun_setInt32(JSContext *cx, unsigned argc, Value *vp);
michael@0 328
michael@0 329 static bool setUint32Impl(JSContext *cx, CallArgs args);
michael@0 330 static bool fun_setUint32(JSContext *cx, unsigned argc, Value *vp);
michael@0 331
michael@0 332 static bool setFloat32Impl(JSContext *cx, CallArgs args);
michael@0 333 static bool fun_setFloat32(JSContext *cx, unsigned argc, Value *vp);
michael@0 334
michael@0 335 static bool setFloat64Impl(JSContext *cx, CallArgs args);
michael@0 336 static bool fun_setFloat64(JSContext *cx, unsigned argc, Value *vp);
michael@0 337
michael@0 338 static bool initClass(JSContext *cx);
michael@0 339 static void neuter(JSObject *view);
michael@0 340 template<typename NativeType>
michael@0 341 static bool read(JSContext *cx, Handle<DataViewObject*> obj,
michael@0 342 CallArgs &args, NativeType *val, const char *method);
michael@0 343 template<typename NativeType>
michael@0 344 static bool write(JSContext *cx, Handle<DataViewObject*> obj,
michael@0 345 CallArgs &args, const char *method);
michael@0 346
michael@0 347 void neuter(void *newData);
michael@0 348
michael@0 349 private:
michael@0 350 static const JSFunctionSpec jsfuncs[];
michael@0 351 };
michael@0 352
michael@0 353 static inline int32_t
michael@0 354 ClampIntForUint8Array(int32_t x)
michael@0 355 {
michael@0 356 if (x < 0)
michael@0 357 return 0;
michael@0 358 if (x > 255)
michael@0 359 return 255;
michael@0 360 return x;
michael@0 361 }
michael@0 362
michael@0 363 } // namespace js
michael@0 364
michael@0 365 template <>
michael@0 366 inline bool
michael@0 367 JSObject::is<js::TypedArrayObject>() const
michael@0 368 {
michael@0 369 return js::IsTypedArrayClass(getClass());
michael@0 370 }
michael@0 371
michael@0 372 template <>
michael@0 373 inline bool
michael@0 374 JSObject::is<js::ArrayBufferViewObject>() const
michael@0 375 {
michael@0 376 return is<js::DataViewObject>() || is<js::TypedArrayObject>() ||
michael@0 377 IsTypedObjectClass(getClass());
michael@0 378 }
michael@0 379
michael@0 380 #endif /* vm_TypedArrayObject_h */

mercurial