From a3de3d6a60e10c1da9a535580401b8d4cb680968 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 30 Jul 2014 17:14:19 -0700 Subject: [PATCH] Bug 1038316: Add support for ES6 Symbols to ubi::Node. r=sfink --- js/public/UbiNode.h | 11 ++++---- js/src/builtin/TestingFunctions.cpp | 27 ++++++++++--------- .../jit-test/tests/heap-analysis/findPath.js | 5 ++++ js/src/vm/UbiNode.cpp | 7 +++++ 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/js/public/UbiNode.h b/js/public/UbiNode.h index d2acc2e24289..11fdb3f212bf 100644 --- a/js/public/UbiNode.h +++ b/js/public/UbiNode.h @@ -23,7 +23,7 @@ // JS::ubi::Node is a pointer-like type designed for internal use by heap // analysis tools. A ubi::Node can refer to: // -// - a JS value, like a string or object; +// - a JS value, like a string, object, or symbol; // - an internal SpiderMonkey structure, like a shape or a scope chain object // - an instance of some embedding-provided type: in Firefox, an XPCOM // object, or an internal DOM node class instance @@ -315,10 +315,10 @@ class Node { return is() ? static_cast(base()->ptr) : nullptr; } - // If this node refers to something that can be represented as a - // JavaScript value that is safe to expose to JavaScript code, return that - // value. Otherwise return UndefinedValue(). JSStrings and some (but not - // all!) JSObjects can be exposed. + // If this node refers to something that can be represented as a JavaScript + // value that is safe to expose to JavaScript code, return that value. + // Otherwise return UndefinedValue(). JSStrings, JS::Symbols, and some (but + // not all!) JSObjects can be exposed. JS::Value exposeToJS() const; const jschar *typeName() const { return base()->typeName(); } @@ -427,6 +427,7 @@ class TracerConcrete : public Base { template<> struct Concrete : TracerConcrete { }; template<> struct Concrete : TracerConcrete { }; +template<> struct Concrete : TracerConcrete { }; template<> struct Concrete : TracerConcrete { }; template<> struct Concrete : TracerConcrete { }; template<> struct Concrete : TracerConcrete { }; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 036424b361cf..4917c5ac261c 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -1790,21 +1790,20 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp) return false; } - // We don't ToString non-objects given as 'start' or 'target'. We can't - // see edges to non-string primitive values, and it doesn't make much - // sense to ask for paths to or from a freshly allocated string, so - // if a non-string primitive appears here it's probably a mistake. - if (!args[0].isObject() && !args[0].isString()) { + // We don't ToString non-objects given as 'start' or 'target', because this + // test is all about object identity, and ToString doesn't preserve that. + // Non-GCThing endpoints don't make much sense. + if (!args[0].isObject() && !args[0].isString() && !args[0].isSymbol()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, args[0], JS::NullPtr(), - "neither an object nor a string", NULL); + "not an object, string, or symbol", NULL); return false; } - if (!args[1].isObject() && !args[1].isString()) { + if (!args[1].isObject() && !args[1].isString() && !args[1].isSymbol()) { js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_UNEXPECTED_TYPE, JSDVG_SEARCH_STACK, args[0], JS::NullPtr(), - "neither an object nor a string", NULL); + "not an object, string, or symbol", NULL); return false; } @@ -1837,10 +1836,13 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp) // Construct a JavaScript array describing the path from the start to the // target. Each element has the form: // - // { node: , edge: } + // { + // node: , + // edge: + // } // - // or, if the node is some internal thing, that isn't a proper - // JavaScript value: + // or, if the node is some internal thing that isn't a proper JavaScript + // value: // // { node: undefined, edge: } size_t length = nodes.length(); @@ -1868,8 +1870,7 @@ FindPath(JSContext *cx, unsigned argc, jsval *vp) return false; edgeName.release(); // edgeStr acquired ownership - if (!JS_DefineProperty(cx, obj, "edge", edgeStr, - JSPROP_ENUMERATE, nullptr, nullptr)) + if (!JS_DefineProperty(cx, obj, "edge", edgeStr, JSPROP_ENUMERATE, nullptr, nullptr)) return false; result->setDenseElement(length - i - 1, ObjectValue(*obj)); diff --git a/js/src/jit-test/tests/heap-analysis/findPath.js b/js/src/jit-test/tests/heap-analysis/findPath.js index ede2363e8d58..82222b4e06e6 100644 --- a/js/src/jit-test/tests/heap-analysis/findPath.js +++ b/js/src/jit-test/tests/heap-analysis/findPath.js @@ -42,3 +42,8 @@ Match.Pattern([{node: {}, edge: "shape"}, .assert(findPath(o, o)); print(findPath(o, o).map((e) => e.edge).toString()); +// Check that we can generate ubi::Nodes for Symbols. +var so = { sym: Symbol() }; +Match.Pattern([{node: {}, edge: "sym" }]) + .assert(findPath(so, so.sym)); +print(findPath(so, so.sym).map((e) => e.edge).toString()); diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index c825501423bd..4c307ffd1940 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -37,6 +37,7 @@ Node::Node(JSGCTraceKind kind, void *ptr) switch (kind) { case JSTRACE_OBJECT: construct(static_cast(ptr)); break; case JSTRACE_STRING: construct(static_cast(ptr)); break; + case JSTRACE_SYMBOL: construct(static_cast(ptr)); break; case JSTRACE_SCRIPT: construct(static_cast(ptr)); break; case JSTRACE_LAZY_SCRIPT: construct(static_cast(ptr)); break; case JSTRACE_JITCODE: construct(static_cast(ptr)); break; @@ -55,6 +56,8 @@ Node::Node(Value value) construct(&value.toObject()); else if (value.isString()) construct(value.toString()); + else if (value.isSymbol()) + construct(value.toSymbol()); else construct(nullptr); } @@ -75,6 +78,8 @@ Node::exposeToJS() const } } else if (is()) { v.setString(as()); + } else if (is()) { + v.setSymbol(as()); } else { v.setUndefined(); } @@ -210,6 +215,8 @@ template<> const jschar TracerConcrete::concreteTypeName[] = MOZ_UTF16("JSObject"); template<> const jschar TracerConcrete::concreteTypeName[] = MOZ_UTF16("JSString"); +template<> const jschar TracerConcrete::concreteTypeName[] = + MOZ_UTF16("JS::Symbol"); template<> const jschar TracerConcrete::concreteTypeName[] = MOZ_UTF16("JSScript"); template<> const jschar TracerConcrete::concreteTypeName[] =