Bug 578700 - Binary Data: initialize architecture. r=nmatsakis
authorNikhil Marathe <nsm.nikhil@gmail.com>
Thu, 25 Jul 2013 17:57:04 -0700
changeset 152364 5dd7854c9474f0a997233430072f7a6b239677a7
parent 152363 631b3d5d54f46823f660ff5ad5ae298356309b10
child 152365 2aa4435cd79882c98217991bad72c65633269430
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnmatsakis
bugs578700
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 578700 - Binary Data: initialize architecture. r=nmatsakis
js/src/Makefile.in
js/src/builtin/BinaryData.cpp
js/src/builtin/BinaryData.h
js/src/builtin/TestingFunctions.cpp
js/src/jsapi.cpp
js/src/jsprototypes.h
js/src/moz.build
js/src/tests/ecma_6/BinaryData/architecture.js
js/src/tests/ecma_6/BinaryData/shell.js
js/src/vm/GlobalObject.h
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -67,16 +67,20 @@ VPATH		+= \
 
 ###############################################
 # BEGIN enable non-releasable features
 #
 ifdef NIGHTLY_BUILD
 DEFINES += -DENABLE_PARALLEL_JS
 endif
 
+ifdef NIGHTLY_BUILD
+DEFINES += -DENABLE_BINARYDATA
+endif
+
 # Ion
 ifdef ENABLE_ION
 VPATH +=	$(srcdir)/ion
 VPATH +=	$(srcdir)/ion/shared
 
 ifeq (86, $(findstring 86,$(TARGET_CPU)))
 ifeq (x86_64, $(TARGET_CPU))
 VPATH +=	$(srcdir)/ion/x64
new file mode 100644
--- /dev/null
+++ b/js/src/builtin/BinaryData.cpp
@@ -0,0 +1,201 @@
+/* -*- 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 "builtin/BinaryData.h"
+
+#include "jscompartment.h"
+#include "jsobj.h"
+
+#include "jsatominlines.h"
+#include "jsobjinlines.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;
+}
+
+bool
+GlobalObject::initDataObject(JSContext *cx, Handle<GlobalObject *> global)
+{
+    RootedObject DataProto(cx);
+    DataProto = NewObjectWithGivenProto(cx, &DataClass, global->getOrCreateObjectPrototype(cx), global, SingletonObject);
+    if (!DataProto)
+        return false;
+
+    RootedAtom DataName(cx, ClassName(JSProto_Data, cx));
+    RootedFunction DataCtor(cx, global->createConstructor(cx, DataThrowError, DataName, 1, JSFunction::ExtendedFinalizeKind));
+    if (!DataCtor)
+        return false;
+
+    if (!JS_DefineFunction(cx, DataProto, "update", DataInstanceUpdate, 1, 0))
+        return false;
+
+    if (!LinkConstructorAndPrototype(cx, DataCtor, DataProto))
+        return false;
+
+    if (!DefineConstructorAndPrototype(cx, global, JSProto_Data, DataCtor, DataProto))
+        return false;
+
+    global->setReservedSlot(JSProto_Data, ObjectValue(*DataCtor));
+    return true;
+}
+
+bool
+GlobalObject::initTypeObject(JSContext *cx, Handle<GlobalObject *> global)
+{
+    RootedObject TypeProto(cx, global->getOrCreateDataObject(cx));
+    if (!TypeProto)
+        return false;
+
+    RootedAtom TypeName(cx, ClassName(JSProto_Type, cx));
+    RootedFunction TypeCtor(cx, global->createConstructor(cx, TypeThrowError, TypeName, 1, JSFunction::ExtendedFinalizeKind));
+    if (!TypeCtor)
+        return false;
+
+    if (!LinkConstructorAndPrototype(cx, TypeCtor, TypeProto))
+        return false;
+
+    if (!DefineConstructorAndPrototype(cx, global, JSProto_Type, TypeCtor, TypeProto))
+        return false;
+
+    global->setReservedSlot(JSProto_Type, ObjectValue(*TypeCtor));
+    return true;
+}
+
+static JSObject *
+SetupComplexHeirarchy(JSContext *cx, Handle<GlobalObject *> global, HandleObject complexObject)
+{
+    // get the 'Type' constructor
+    RootedObject TypeObject(cx, global->getOrCreateTypeObject(cx));
+    if (!TypeObject)
+        return NULL;
+
+    // Set complexObject.__proto__ = Type
+    if (!JS_SetPrototype(cx, complexObject, TypeObject))
+        return NULL;
+
+    RootedObject DataObject(cx, global->getOrCreateDataObject(cx));
+    if (!DataObject)
+        return NULL;
+
+    RootedValue DataProtoVal(cx);
+    if (!JSObject::getProperty(cx, DataObject, DataObject, cx->names().classPrototype, &DataProtoVal))
+        return NULL;
+
+    RootedObject DataProto(cx, DataProtoVal.toObjectOrNull());
+    if (!DataProto)
+        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, DataObject))
+        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;
+
+    if (!JS_SetPrototype(cx, prototypePrototypeObj, DataProto))
+        return NULL;
+
+    return complexObject;
+}
+
+static JSObject *
+InitComplexClasses(JSContext *cx, Handle<GlobalObject *> global)
+{
+    // TODO FIXME use DefineConstructorAndPrototype and other
+    // utilities
+    RootedFunction ArrayTypeFun(cx, JS_DefineFunction(cx, global, "ArrayType", createArrayType, 1, 0));
+    if (!ArrayTypeFun)
+        return NULL;
+
+    if (!SetupComplexHeirarchy(cx, global, 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, global, "StructType", createStructType, 1, 0));
+    if (!StructTypeFun)
+        return NULL;
+
+    if (!SetupComplexHeirarchy(cx, global, StructTypeFun))
+        return NULL;
+
+    return global;
+}
+
+JSObject *
+js_InitBinaryDataClasses(JSContext *cx, HandleObject obj)
+{
+    JS_ASSERT(obj->is<GlobalObject>());
+    Rooted<GlobalObject *> global(cx, &obj->as<GlobalObject>());
+
+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, global))
+        return NULL;
+    return global;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/builtin/BinaryData.h
@@ -0,0 +1,103 @@
+/* -*- 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 builtin_BinaryData_h
+#define builtin_BinaryData_h
+
+#include "jsapi.h"
+#include "jsobj.h"
+#include "jsfriendapi.h"
+#include "gc/Heap.h"
+
+namespace js {
+class Block : public gc::Cell
+{
+};
+
+static Class DataClass = {
+    "Data",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Data),
+    JS_PropertyStub,
+    JS_DeletePropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub
+};
+
+static Class TypeClass = {
+    "Type",
+    JSCLASS_HAS_CACHED_PROTO(JSProto_Type),
+    JS_PropertyStub,
+    JS_DeletePropertyStub,
+    JS_PropertyStub,
+    JS_StrictPropertyStub,
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub
+};
+
+
+#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);
+};
+}
+
+#endif /* builtin_BinaryData_h */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -172,16 +172,24 @@ GetBuildConfiguration(JSContext *cx, uns
 #ifdef ENABLE_PARALLEL_JS
     value = BooleanValue(true);
 #else
     value = BooleanValue(false);
 #endif
     if (!JS_SetProperty(cx, info, "parallelJS", &value))
         return false;
 
+#ifdef ENABLE_BINARYDATA
+    value = BooleanValue(true);
+#else
+    value = BooleanValue(false);
+#endif
+    if (!JS_SetProperty(cx, info, "binary-data", &value))
+        return false;
+
     *vp = ObjectValue(*info);
     return true;
 }
 
 static JSBool
 GC(JSContext *cx, unsigned argc, jsval *vp)
 {
     /*
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -48,16 +48,17 @@
 #include "jsworkers.h"
 #endif
 #include "jswrapper.h"
 #include "prmjtime.h"
 
 #if ENABLE_YARR_JIT
 #include "assembler/jit/ExecutableAllocator.h"
 #endif
+#include "builtin/BinaryData.h"
 #include "builtin/Eval.h"
 #include "builtin/Intl.h"
 #include "builtin/MapObject.h"
 #include "builtin/ParallelArray.h"
 #include "builtin/RegExp.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/FullParseHandler.h"  // for JS_BufferIsCompileableUnit
 #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
@@ -1845,16 +1846,19 @@ static const JSStdName standard_class_at
     {js_InitSetClass,                   EAGER_ATOM_AND_OCLASP(Set)},
 #ifdef ENABLE_PARALLEL_JS
     {js_InitParallelArrayClass,         EAGER_ATOM_AND_OCLASP(ParallelArray)},
 #endif
     {js_InitProxyClass,                 EAGER_CLASS_ATOM(Proxy), OCLASP(ObjectProxy)},
 #if ENABLE_INTL_API
     {js_InitIntlClass,                  EAGER_ATOM_AND_CLASP(Intl)},
 #endif
+#ifdef ENABLE_BINARYDATA
+    {js_InitBinaryDataClasses,          EAGER_ATOM_AND_CLASP(Type)},
+#endif
     {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.
  */
@@ -1901,16 +1905,27 @@ static const JSStdName standard_class_na
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Int32Array),   TYPED_ARRAY_CLASP(TYPE_INT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Uint32Array),  TYPED_ARRAY_CLASP(TYPE_UINT32)},
     {js_InitTypedArrayClasses,  EAGER_CLASS_ATOM(Float32Array), TYPED_ARRAY_CLASP(TYPE_FLOAT32)},
     {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),     &DataViewObject::class_},
 
+    /* Binary Data */
+#ifdef ENABLE_BINARYDATA
+    {js_InitBinaryDataClasses,          EAGER_ATOM_AND_CLASP(Type)},
+    {js_InitBinaryDataClasses,          EAGER_ATOM_AND_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_ATOM_AND_CLASP(ArrayType)},
+    {js_InitBinaryDataClasses,          EAGER_ATOM_AND_CLASP(StructType)},
+#endif
     {NULL,                      0, NULL}
 };
 
 static const JSStdName object_prototype_names[] = {
     /* Object.prototype properties (global delegates to Object.prototype). */
     {js_InitObjectClass,        EAGER_ATOM(proto), &JSObject::class_},
 #if JS_HAS_TOSOURCE
     {js_InitObjectClass,        EAGER_ATOM(toSource), &JSObject::class_},
--- 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 */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -75,16 +75,17 @@ EXPORTS.js += [
     '../public/RootingAPI.h',
     '../public/Utility.h',
     '../public/Value.h',
     '../public/Vector.h',
 ]
 
 CPP_SOURCES += [
     'ArgumentsObject.cpp',
+    'BinaryData.cpp',
     'BytecodeCompiler.cpp',
     'BytecodeEmitter.cpp',
     'CharacterEncoding.cpp',
     'DateTime.cpp',
     'Debugger.cpp',
     'Eval.cpp',
     'ExecutableAllocator.cpp',
     'FoldConstants.cpp',
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/BinaryData/architecture.js
@@ -0,0 +1,66 @@
+// |reftest| skip-if(!this.hasOwnProperty("Type"))
+var BUGNUMBER = 578700;
+var summary = 'Binary Data class diagram';
+
+function assertNotEq(a, b) {
+    var ok = false;
+    try {
+        assertEq(a, b);
+    } catch(exc) {
+        ok = true;
+    }
+  
+    if (!ok)
+        throw new TypeError("Assertion failed: assertNotEq(" + a + " " + b + ")");
+}
+
+function runTests() {
+    print(BUGNUMBER + ": " + summary);
+  
+    assertEq(Data.__proto__, Function.prototype);
+    assertEq(Data.prototype.__proto__, Object.prototype);
+    assertEq(Data.prototype.constructor, Data);
+    assertEq(typeof Data.prototype.update === "function", true);
+  
+    assertEq(Type.__proto__, Function.prototype);
+    assertEq(Type.prototype, Data);
+  
+    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);
+  
+    // Change global 'Type' and see if things stay sane.
+    Type = function() {
+        return 42;
+    }
+  
+    Data = function() {
+        return 43;
+    }
+  
+    assertNotEq(ArrayType.prototype.__proto__, Type.prototype);
+    assertNotEq(ArrayType.prototype.prototype.__proto__, Data.prototype);
+  
+    assertNotEq(StructType.prototype.__proto__, Type.prototype);
+    assertNotEq(StructType.prototype.prototype.__proto__, Data.prototype);
+  
+    if (typeof reportCompare === "function")
+        reportCompare(true, true);
+    print("Tests complete");
+}
+
+runTests();
new file mode 100644
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -22,16 +22,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)
@@ -322,16 +325,24 @@ class GlobalObject : public JSObject
     JSObject *getOrCreateDateTimeFormatPrototype(JSContext *cx) {
         return getOrCreateObject(cx, DATE_TIME_FORMAT_PROTO, initDateTimeFormatProto);
     }
 
     JSObject *getIteratorPrototype() {
         return &getPrototype(JSProto_Iterator).toObject();
     }
 
+    JSObject *getOrCreateDataObject(JSContext *cx) {
+        return getOrCreateObject(cx, JSProto_Data, initDataObject);
+    }
+
+    JSObject *getOrCreateTypeObject(JSContext *cx) {
+        return getOrCreateObject(cx, JSProto_Type, initTypeObject);
+    }
+
   private:
     typedef bool (*ObjectInitOp)(JSContext *cx, Handle<GlobalObject*> global);
 
     JSObject *getOrCreateObject(JSContext *cx, unsigned slot, ObjectInitOp init) {
         Value v = getSlotRef(slot);
         if (v.isObject())
             return &v.toObject();
         Rooted<GlobalObject*> self(cx, this);
@@ -424,16 +435,20 @@ class GlobalObject : public JSObject
     static bool initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global);
 
     // Implemented in Intl.cpp.
     static bool initIntlObject(JSContext *cx, Handle<GlobalObject*> global);
     static bool initCollatorProto(JSContext *cx, Handle<GlobalObject*> global);
     static bool initNumberFormatProto(JSContext *cx, Handle<GlobalObject*> global);
     static bool initDateTimeFormatProto(JSContext *cx, Handle<GlobalObject*> global);
 
+    // Implemented in builtin/BinaryData.cpp
+    static bool initTypeObject(JSContext *cx, Handle<GlobalObject*> global);
+    static bool initDataObject(JSContext *cx, Handle<GlobalObject*> global);
+
     static bool initStandardClasses(JSContext *cx, Handle<GlobalObject*> global);
 
     typedef js::Vector<js::Debugger *, 0, js::SystemAllocPolicy> DebuggerVector;
 
     /*
      * The collection of Debugger objects debugging this global. If this global
      * is not a debuggee, this returns either NULL or an empty vector.
      */