# HG changeset patch # Parent 3098b9949017274321ae45edad078075b66397db # 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 @@ -65,16 +65,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 @@ -19,16 +19,17 @@ #include #include "jstypes.h" #include "jsutil.h" #include "jsclist.h" #include "jsprf.h" #include "jsapi.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" @@ -1851,16 +1852,24 @@ static JSStdName standard_class_names[] {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Float64Array), TYPED_ARRAY_CLASP(TYPE_FLOAT64)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(Uint8ClampedArray), TYPED_ARRAY_CLASP(TYPE_UINT8_CLAMPED)}, {js_InitTypedArrayClasses, EAGER_CLASS_ATOM(DataView), &DataViewClass}, {js_InitWeakMapClass, EAGER_ATOM_AND_CLASP(WeakMap)}, {js_InitProxyClass, EAGER_ATOM_AND_CLASP(Proxy)}, + {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} }; static JSStdName object_prototype_names[] = { /* Object.prototype properties (global delegates to Object.prototype). */ {js_InitObjectClass, EAGER_ATOM(proto), CLASP(Object)}, #if JS_HAS_TOSOURCE {js_InitObjectClass, EAGER_ATOM(toSource), CLASP(Object)}, 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, jsval *vp) +{ + return ReportIsNotFunction(cx, vp); +} + +JSBool DataThrowError(JSContext *cx, unsigned argc, jsval *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 + jsval TypeVal; + if (!JS_GetProperty(cx, global, "Type", &TypeVal)) + return NULL; + + JSObject *TypeFunObj; + if (!JSVAL_IS_PRIMITIVE(TypeVal)) + TypeFunObj = JSVAL_TO_OBJECT(TypeVal); + 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 (!JSVAL_IS_PRIMITIVE(DataVal)) + DataFunObj = JSVAL_TO_OBJECT(DataVal); + 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,\ + JS_PropertyStub,\ + JS_PropertyStub,\ + JS_StrictPropertyStub,\ + 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_PropertyStub, + JS_PropertyStub, + JS_StrictPropertyStub, + JS_EnumerateStub, + JS_ResolveStub, + JS_ConvertStub +}; + +static Class StructTypeClass = { + "StructType", + JSCLASS_HAS_CACHED_PROTO(JSProto_StructType), + JS_PropertyStub, + JS_PropertyStub, + 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 @@ -55,10 +55,24 @@ macro(Uint8ClampedArray, 33, js_InitTypedArrayClasses) \ macro(Proxy, 34, js_InitProxyClass) \ macro(AnyName, 35, js_InitNullClass) \ macro(WeakMap, 36, js_InitWeakMapClass) \ macro(Map, 37, js_InitMapClass) \ macro(Set, 38, js_InitSetClass) \ macro(DataView, 39, js_InitTypedArrayClasses) \ macro(ParallelArray, 40, js_InitParallelArrayClass) \ + macro(Type, 41, js_InitBinaryDataClasses) \ + macro(Data, 42, js_InitBinaryDataClasses) \ + macro(uint8, 43, js_InitBinaryDataClasses) \ + macro(uint16, 44, js_InitBinaryDataClasses) \ + macro(uint32, 45, js_InitBinaryDataClasses) \ + macro(uint64, 46, js_InitBinaryDataClasses) \ + macro(int8, 47, js_InitBinaryDataClasses) \ + macro(int16, 48, js_InitBinaryDataClasses) \ + macro(int32, 49, js_InitBinaryDataClasses) \ + macro(int64, 50, js_InitBinaryDataClasses) \ + macro(float32, 51, js_InitBinaryDataClasses) \ + macro(float64, 52, js_InitBinaryDataClasses) \ + macro(ArrayType, 53, js_InitBinaryDataClasses) \ + macro(StructType, 54, 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)