# HG changeset patch # Parent 7130e5134a6e34cc4873c60b9c0eb2af03dee490 # User Nikhil Marathe Bug 578700 - Binary Data initialize architecture. diff --git a/js/src/Makefile.in b/js/src/Makefile.in --- a/js/src/Makefile.in +++ b/js/src/Makefile.in @@ -52,16 +52,17 @@ VPATH += \ $(NULL) CPPSRCS = \ jsalloc.cpp \ jsanalyze.cpp \ jsapi.cpp \ jsarray.cpp \ jsatom.cpp \ + jsbinarydata.cpp \ jsbool.cpp \ jsclone.cpp \ jscntxt.cpp \ jscompartment.cpp \ jsdate.cpp \ jsdbgapi.cpp \ jsdhash.cpp \ jsdtoa.cpp \ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -22,16 +22,17 @@ #include #include "jstypes.h" #include "jsutil.h" #include "jsclist.h" #include "jsprf.h" #include "jsarray.h" #include "jsatom.h" +#include "jsbinarydata.h" #include "jsbool.h" #include "jsclone.h" #include "jscntxt.h" #include "jsversion.h" #include "jsdate.h" #include "jsdtoa.h" #include "jsexn.h" #include "jsfun.h" @@ -1848,16 +1849,24 @@ static JSStdName standard_class_atoms[] {js_InitSetClass, EAGER_CLASS_ATOM(Set), &js::SetObject::class_}, #ifdef ENABLE_PARALLEL_JS {js_InitParallelArrayClass, EAGER_CLASS_ATOM(ParallelArray), &js::ParallelArrayObject::class_}, #endif {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)}, #if ENABLE_INTL_API {js_InitIntlClass, EAGER_ATOM_AND_CLASP(Intl)}, #endif + {js_InitBinaryDataClasses, EAGER_CLASS_ATOM(Type), CLASP(Type)}, + {js_InitBinaryDataClasses, EAGER_CLASS_ATOM(Data), CLASP(Data)}, +#define BINARYDATA_NUMERIC_NAMES(type_)\ + {js_InitBinaryDataClasses, EAGER_CLASS_ATOM(type_), CLASP(type_##Block)}, + BINARYDATA_FOR_EACH_NUMERIC_TYPES(BINARYDATA_NUMERIC_NAMES) +#undef BINARYDATA_NUMERIC_NAMES + {js_InitBinaryDataClasses, EAGER_CLASS_ATOM(ArrayType), CLASP(ArrayType)}, + {js_InitBinaryDataClasses, EAGER_CLASS_ATOM(StructType), CLASP(StructType)}, {NULL, 0, NULL} }; /* * Table of top-level function and constant names and their init functions. * If you add a "standard" global function or property, remember to update * this table. */ diff --git a/js/src/jsbinarydata.cpp b/js/src/jsbinarydata.cpp new file mode 100644 --- /dev/null +++ b/js/src/jsbinarydata.cpp @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ +/* 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 "jsbinarydata.h" + +#include "jscompartment.h" +#include "jsobj.h" +#include "jsinterp.h" + +#include "vm/GlobalObject.h" + +using namespace js; + +JSBool TypeThrowError(JSContext *cx, unsigned argc, Value *vp) +{ + return ReportIsNotFunction(cx, *vp); +} + +JSBool DataThrowError(JSContext *cx, unsigned argc, Value *vp) +{ + return ReportIsNotFunction(cx, *vp); +} + +// FIXME will actually require knowing function name +JSBool createNumericBlock(JSContext *cx, unsigned argc, jsval *vp) +{ + return false; +} + +JSBool createArrayType(JSContext *cx, unsigned argc, jsval *vp) +{ + return false; +} + +JSBool createStructType(JSContext *cx, unsigned argc, jsval *vp) +{ + return false; +} + +JSBool DataInstanceUpdate(JSContext *cx, unsigned argc, jsval *vp) +{ + return false; +} + +JSBool +ArrayTypeObject::repeat(JSContext *cx, unsigned int argc, jsval *vp) +{ + return false; +} + +static JSObject * +InitBaseClasses(JSContext *cx, HandleObject obj) +{ + JSFunction *TypeFun = JS_DefineFunction(cx, obj, "Type", TypeThrowError, 0, 0); + if (!TypeFun) + return NULL; + + JSFunction *DataFun = JS_DefineFunction(cx, obj, "Data", DataThrowError, 0, 0); + if (!DataFun) + return NULL; + + RootedObject DataPrototype(cx, JS_NewObject(cx, NULL, NULL, obj)); + if (!JS_DefineFunction(cx, DataPrototype, "update", DataInstanceUpdate, 1, 0)) + return NULL; + + if (!LinkConstructorAndPrototype(cx, DataFun, DataPrototype)) + return NULL; + + if (!LinkConstructorAndPrototype(cx, TypeFun, DataFun)) + return NULL; + + return obj; +} + +static JSObject * +SetupComplexHeirarchy(JSContext *cx, HandleObject global, HandleObject complexObject) +{ + // get the 'Type' function + Value TypeVal; + if (!JS_GetProperty(cx, global, "Type", &TypeVal)) + return NULL; + + RootedObject TypeFunObj(cx); + if (!TypeVal.isPrimitive()) + TypeFunObj = TypeVal.toObjectOrNull(); + else + return NULL; + + // Set complexObject.__proto__ = Type + if (!JS_SetPrototype(cx, complexObject, TypeFunObj)) + return NULL; + + // get the 'Data' function + jsval DataVal; + if (!JS_GetProperty(cx, global, "Data", &DataVal)) + return NULL; + + RootedObject DataFunObj(cx); + if (!DataVal.isPrimitive()) + DataFunObj = DataVal.toObjectOrNull(); + else + return NULL; + + // Set complexObject.prototype.__proto__ = Data + RootedObject prototypeObj(cx, JS_NewObject(cx, NULL, NULL, global)); + if (!LinkConstructorAndPrototype(cx, complexObject, prototypeObj)) + return NULL; + + if (!JS_SetPrototype(cx, prototypeObj, DataFunObj)) + return NULL; + + // Set complexObject.prototype.prototype.__proto__ = Data.prototype + // TODO does this have to actually be a Class so we can set accessor properties etc? + RootedObject prototypePrototypeObj(cx, JS_NewObject(cx, NULL, NULL, global)); + if (!LinkConstructorAndPrototype(cx, prototypeObj, prototypePrototypeObj)) + return NULL; + + RootedValue DataPrototypeVal(cx); + if (!JSObject::getProperty(cx, DataFunObj, DataFunObj, cx->names().classPrototype, &DataPrototypeVal)) + return NULL; + + if (!JS_SetPrototype(cx, prototypePrototypeObj, DataPrototypeVal.toObjectOrNull())) + return NULL; + + return complexObject; +} + +static JSObject * +InitComplexClasses(JSContext *cx, HandleObject obj) +{ + // TODO FIXME use DefineConstructorAndPrototype and other + // utilities + RootedFunction ArrayTypeFun(cx, JS_DefineFunction(cx, obj, "ArrayType", createArrayType, 1, 0)); + if (!ArrayTypeFun) + return NULL; + + if (!SetupComplexHeirarchy(cx, obj, ArrayTypeFun)) + return NULL; + + // ArrayType.prototype.repeat + RootedValue ArrayTypePrototypeVal(cx); + if (!JSObject::getProperty(cx, ArrayTypeFun, ArrayTypeFun, cx->names().classPrototype, &ArrayTypePrototypeVal)) + return NULL; + + if (!JS_DefineFunction(cx, ArrayTypePrototypeVal.toObjectOrNull(), "repeat", ArrayTypeObject::repeat, 1, 0)) + return NULL; + + RootedFunction StructTypeFun(cx, JS_DefineFunction(cx, obj, "StructType", createStructType, 1, 0)); + if (!StructTypeFun) + return NULL; + + if (!SetupComplexHeirarchy(cx, obj, StructTypeFun)) + return NULL; + + return obj; +} + +JSObject * +js_InitBinaryDataClasses(JSContext *cx, JSHandleObject obj) +{ + if (!InitBaseClasses(cx, obj)) + return NULL; + +typedef float_t float32_t; +typedef double_t float64_t; +#define BINARYDATA_NUMERIC_DEFINE(type_)\ + do {\ + JSFunction *numFun = JS_DefineFunction(cx, obj, #type_, createNumericBlock, 1, 0);\ + if (!numFun)\ + return NULL;\ +\ + if (!JS_DefineProperty(cx, numFun, "bytes", INT_TO_JSVAL(sizeof(type_##_t)), JS_PropertyStub, JS_StrictPropertyStub, 0))\ + return NULL;\ + } while(0); + BINARYDATA_FOR_EACH_NUMERIC_TYPES(BINARYDATA_NUMERIC_DEFINE) +#undef BINARYDATA_NUMERIC_DEFINE + + if (!InitComplexClasses(cx, obj)) + return NULL; + return obj; +} diff --git a/js/src/jsbinarydata.h b/js/src/jsbinarydata.h new file mode 100644 --- /dev/null +++ b/js/src/jsbinarydata.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ +/* 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 jsbinarydata_h +#define jsbinarydata_h + +#include "jsapi.h" +#include "jsobj.h" +#include "jsfriendapi.h" +#include "gc/Heap.h" + +namespace js { +class Block : public gc::Cell +{ +}; +static Class DataClass; +static Class TypeClass; + +#define BINARYDATA_FOR_EACH_NUMERIC_TYPES(macro_)\ + macro_(uint8)\ + macro_(uint16)\ + macro_(uint32)\ + macro_(uint64)\ + macro_(int8)\ + macro_(int16)\ + macro_(int32)\ + macro_(int64)\ + macro_(float32)\ + macro_(float64) + +#define BINARYDATA_NUMERIC_CLASSES(type_)\ +static Class type_##BlockClass = {\ + #type_,\ + JSCLASS_HAS_CACHED_PROTO(JSProto_##type_),\ + JS_PropertyStub, /* addProperty */\ + JS_DeletePropertyStub, /* delProperty */\ + JS_PropertyStub, /* getProperty */\ + JS_StrictPropertyStub, /* setProperty */\ + JS_EnumerateStub,\ + JS_ResolveStub,\ + JS_ConvertStub\ +}; + +BINARYDATA_FOR_EACH_NUMERIC_TYPES(BINARYDATA_NUMERIC_CLASSES) + +static Class ArrayTypeClass = { + "ArrayType", + JSCLASS_HAS_CACHED_PROTO(JSProto_ArrayType), + JS_PropertyStub, + JS_DeletePropertyStub, + JS_PropertyStub, + JS_StrictPropertyStub, + JS_EnumerateStub, + JS_ResolveStub, + JS_ConvertStub +}; + +static Class StructTypeClass = { + "StructType", + JSCLASS_HAS_CACHED_PROTO(JSProto_StructType), + JS_PropertyStub, + JS_DeletePropertyStub, + JS_PropertyStub, + JS_StrictPropertyStub, + JS_EnumerateStub, + JS_ResolveStub, + JS_ConvertStub +}; + +class ArrayTypeObject : public JSObject +{ + public: + static JSBool repeat(JSContext *cx, unsigned int argc, jsval *vp); +}; +} + +extern JS_FRIEND_API(JSObject *) +js_InitBinaryDataClasses(JSContext *cx, JSHandleObject obj); + +#endif /* jsbinarydata_h */ diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h --- a/js/src/jsprototypes.h +++ b/js/src/jsprototypes.h @@ -51,10 +51,24 @@ macro(Uint8ClampedArray, 30, js_InitTypedArrayClasses) \ macro(Proxy, 31, js_InitProxyClass) \ macro(WeakMap, 32, js_InitWeakMapClass) \ macro(Map, 33, js_InitMapClass) \ macro(Set, 34, js_InitSetClass) \ macro(DataView, 35, js_InitTypedArrayClasses) \ macro(ParallelArray, 36, js_InitParallelArrayClass) \ macro(Intl, 37, js_InitIntlClass) \ + macro(Type, 38, js_InitBinaryDataClasses) \ + macro(Data, 39, js_InitBinaryDataClasses) \ + macro(uint8, 40, js_InitBinaryDataClasses) \ + macro(uint16, 41, js_InitBinaryDataClasses) \ + macro(uint32, 42, js_InitBinaryDataClasses) \ + macro(uint64, 43, js_InitBinaryDataClasses) \ + macro(int8, 44, js_InitBinaryDataClasses) \ + macro(int16, 45, js_InitBinaryDataClasses) \ + macro(int32, 46, js_InitBinaryDataClasses) \ + macro(int64, 47, js_InitBinaryDataClasses) \ + macro(float32, 48, js_InitBinaryDataClasses) \ + macro(float64, 49, js_InitBinaryDataClasses) \ + macro(ArrayType, 50, js_InitBinaryDataClasses) \ + macro(StructType, 51, js_InitBinaryDataClasses) \ #endif /* jsprototypes_h___ */ diff --git a/js/src/tests/ecma_6/BinaryData/architecture.js b/js/src/tests/ecma_6/BinaryData/architecture.js new file mode 100644 --- /dev/null +++ b/js/src/tests/ecma_6/BinaryData/architecture.js @@ -0,0 +1,32 @@ +var BUGNUMBER = 578700; +var summary = 'Test class diagram'; + +print(BUGNUMBER + ": " + summary); + +assertEq(Type.__proto__, Function.prototype); +assertEq(Type.prototype, Data); + +assertEq(Data.__proto__, Function.prototype); +assertEq(Data.prototype.__proto__, Object.prototype); +assertEq(Data.prototype.constructor, Data); +assertEq(typeof Data.prototype.update === "function", true); + +var sizes = [1, 2, 4, 8, 1, 2, 4, 8, 4, 8]; +[uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64].forEach(function(numType, i) { + assertEq(numType.__proto__, Function.prototype); + assertEq(numType.bytes, sizes[i]); +}); + +assertEq(ArrayType.__proto__, Type); +assertEq(ArrayType.prototype.__proto__, Type.prototype); +assertEq(typeof ArrayType.prototype.repeat === "function", true); + +assertEq(ArrayType.prototype.prototype.__proto__, Data.prototype); + +assertEq(StructType.__proto__, Type); +assertEq(StructType.prototype.__proto__, Type.prototype); +assertEq(StructType.prototype.prototype.__proto__, Data.prototype); + +if (typeof reportCompare === "function") + reportCompare(true, true); +print("Tests complete"); diff --git a/js/src/tests/ecma_6/BinaryData/shell.js b/js/src/tests/ecma_6/BinaryData/shell.js new file mode 100644 diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -25,16 +25,19 @@ extern JSObject * js_InitObjectClass(JSContext *cx, js::HandleObject obj); extern JSObject * js_InitFunctionClass(JSContext *cx, js::HandleObject obj); extern JSObject * js_InitTypedArrayClasses(JSContext *cx, js::HandleObject obj); +extern JSObject * +js_InitBinaryDataClasses(JSContext *cx, js::HandleObject obj); + namespace js { class Debugger; /* * Global object slots are reserved as follows: * * [0, JSProto_LIMIT)