From 485ed1e9d2b8885b17c4f8cef50c3d77ea858542 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 28 Mar 2014 17:33:33 -0700 Subject: [PATCH] Bug 988476 - Create Debugger.Memory, a place to expose our memory tools to JS; r=jimb --- js/src/jit-test/tests/debug/Memory-01.js | 6 +++ js/src/moz.build | 1 + js/src/vm/Debugger.cpp | 40 +++++++++++++------- js/src/vm/Debugger.h | 7 ++-- js/src/vm/DebuggerMemory.cpp | 47 ++++++++++++++++++++++++ js/src/vm/DebuggerMemory.h | 34 +++++++++++++++++ 6 files changed, 119 insertions(+), 16 deletions(-) create mode 100644 js/src/jit-test/tests/debug/Memory-01.js create mode 100644 js/src/vm/DebuggerMemory.cpp create mode 100644 js/src/vm/DebuggerMemory.h diff --git a/js/src/jit-test/tests/debug/Memory-01.js b/js/src/jit-test/tests/debug/Memory-01.js new file mode 100644 index 00000000000..7dc00b9ee8c --- /dev/null +++ b/js/src/jit-test/tests/debug/Memory-01.js @@ -0,0 +1,6 @@ +assertEq(typeof Debugger.Memory, "function"); +let dbg = new Debugger; +assertEq(dbg.memory instanceof Debugger.Memory, true); + +load(libdir + "asserts.js"); +assertThrowsInstanceOf(() => new Debugger.Memory, TypeError); diff --git a/js/src/moz.build b/js/src/moz.build index 5561034f49e..97cb1430839 100644 --- a/js/src/moz.build +++ b/js/src/moz.build @@ -163,6 +163,7 @@ UNIFIED_SOURCES += [ 'vm/Compression.cpp', 'vm/DateTime.cpp', 'vm/Debugger.cpp', + 'vm/DebuggerMemory.cpp', 'vm/ErrorObject.cpp', 'vm/ForkJoin.cpp', 'vm/GlobalObject.cpp', diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 74dafced438..19c54dbc3b9 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -12,19 +12,17 @@ #include "jsnum.h" #include "jsobj.h" #include "jswrapper.h" - #include "frontend/BytecodeCompiler.h" #include "gc/Marking.h" #include "jit/BaselineJIT.h" #include "js/Vector.h" #include "vm/ArgumentsObject.h" +#include "vm/DebuggerMemory.h" #include "vm/WrapperObject.h" - #include "jsgcinlines.h" #include "jsobjinlines.h" #include "jsopcodeinlines.h" #include "jsscriptinlines.h" - #include "vm/ObjectImpl-inl.h" #include "vm/Stack-inl.h" @@ -1929,11 +1927,17 @@ Debugger::setUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp) "uncaughtExceptionHook"); return false; } - dbg->uncaughtExceptionHook = args[0].toObjectOrNull(); args.rval().setUndefined(); return true; } +bool +Debugger::getMemory(JSContext *cx, unsigned argc, Value *vp) +{ + THIS_DEBUGGER(cx, argc, vp, "get memory", args, dbg); + args.rval().set(dbg->object->getReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE)); + return true; +} GlobalObject * Debugger::unwrapDebuggeeArgument(JSContext *cx, const Value &v) @@ -2135,17 +2139,24 @@ Debugger::construct(JSContext *cx, unsigned argc, Value *vp) return false; RootedObject proto(cx, &v.toObject()); JS_ASSERT(proto->getClass() == &Debugger::jsclass); - /* * Make the new Debugger object. Each one has a reference to - * Debugger.{Frame,Object,Script}.prototype in reserved slots. The rest of - * the reserved slots are for hooks; they default to undefined. + * Debugger.{Frame,Object,Script,Memory}.prototype in reserved slots. The + * rest of the reserved slots are for hooks; they default to undefined. */ RootedObject obj(cx, NewObjectWithGivenProto(cx, &Debugger::jsclass, proto, nullptr)); if (!obj) return false; for (unsigned slot = JSSLOT_DEBUG_PROTO_START; slot < JSSLOT_DEBUG_PROTO_STOP; slot++) obj->setReservedSlot(slot, proto->getReservedSlot(slot)); + /* Create the Debugger.Memory instance accessible by the + * |Debugger.prototype.memory| getter. */ + Value memoryProto = obj->getReservedSlot(JSSLOT_DEBUG_MEMORY_PROTO); + RootedObject memory(cx, NewObjectWithGivenProto(cx, &DebuggerMemory::class_, + &memoryProto.toObject(), nullptr)); + if (!memory) + return false; + obj->setReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE, ObjectValue(*memory)); /* Construct the underlying C++ object. */ Debugger *dbg = cx->new_(cx, obj.get()); @@ -2814,9 +2825,9 @@ const JSPropertySpec Debugger::properties[] = { JS_PSGS("onNewGlobalObject", Debugger::getOnNewGlobalObject, Debugger::setOnNewGlobalObject, 0), JS_PSGS("uncaughtExceptionHook", Debugger::getUncaughtExceptionHook, Debugger::setUncaughtExceptionHook, 0), + JS_PSG("memory", Debugger::getMemory, 0), JS_PS_END }; - const JSFunctionSpec Debugger::methods[] = { JS_FN("addDebuggee", Debugger::addDebuggee, 1, 0), JS_FN("addAllGlobalsAsDebuggees", Debugger::addAllGlobalsAsDebuggees, 0, 0), @@ -5905,13 +5916,11 @@ JS_DefineDebuggerObject(JSContext *cx, HandleObject obj) scriptProto(cx), sourceProto(cx), objectProto(cx), - envProto(cx); - + envProto(cx), + memoryProto(cx); objProto = obj->as().getOrCreateObjectPrototype(cx); if (!objProto) return false; - - debugProto = js_InitClass(cx, obj, objProto, &Debugger::jsclass, Debugger::construct, 1, Debugger::properties, Debugger::methods, nullptr, nullptr, @@ -5946,18 +5955,23 @@ JS_DefineDebuggerObject(JSContext *cx, HandleObject obj) nullptr, nullptr); if (!objectProto) return false; - envProto = js_InitClass(cx, debugCtor, objProto, &DebuggerEnv_class, DebuggerEnv_construct, 0, DebuggerEnv_properties, DebuggerEnv_methods, nullptr, nullptr); if (!envProto) return false; + memoryProto = js_InitClass(cx, debugCtor, objProto, &DebuggerMemory::class_, + DebuggerMemory::construct, 0, DebuggerMemory::properties, + DebuggerMemory::methods, nullptr, nullptr); + if (!memoryProto) + return false; debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_FRAME_PROTO, ObjectValue(*frameProto)); debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_OBJECT_PROTO, ObjectValue(*objectProto)); debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_SCRIPT_PROTO, ObjectValue(*scriptProto)); debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_SOURCE_PROTO, ObjectValue(*sourceProto)); debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_ENV_PROTO, ObjectValue(*envProto)); + debugProto->setReservedSlot(Debugger::JSSLOT_DEBUG_MEMORY_PROTO, ObjectValue(*memoryProto)); return true; } diff --git a/js/src/vm/Debugger.h b/js/src/vm/Debugger.h index 5d8c61b46dd..699d099c720 100644 --- a/js/src/vm/Debugger.h +++ b/js/src/vm/Debugger.h @@ -170,7 +170,6 @@ class Debugger : private mozilla::LinkedListElement OnNewGlobalObject, HookCount }; - enum { JSSLOT_DEBUG_PROTO_START, JSSLOT_DEBUG_FRAME_PROTO = JSSLOT_DEBUG_PROTO_START, @@ -178,12 +177,13 @@ class Debugger : private mozilla::LinkedListElement JSSLOT_DEBUG_OBJECT_PROTO, JSSLOT_DEBUG_SCRIPT_PROTO, JSSLOT_DEBUG_SOURCE_PROTO, + JSSLOT_DEBUG_MEMORY_PROTO, JSSLOT_DEBUG_PROTO_STOP, JSSLOT_DEBUG_HOOK_START = JSSLOT_DEBUG_PROTO_STOP, JSSLOT_DEBUG_HOOK_STOP = JSSLOT_DEBUG_HOOK_START + HookCount, - JSSLOT_DEBUG_COUNT = JSSLOT_DEBUG_HOOK_STOP + JSSLOT_DEBUG_MEMORY_INSTANCE = JSSLOT_DEBUG_HOOK_STOP, + JSSLOT_DEBUG_COUNT }; - private: HeapPtrObject object; /* The Debugger object. Strong reference. */ GlobalObjectSet debuggees; /* Debuggee globals. Cross-compartment weak references. */ @@ -321,6 +321,7 @@ class Debugger : private mozilla::LinkedListElement static bool setOnNewGlobalObject(JSContext *cx, unsigned argc, Value *vp); static bool getUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp); static bool setUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp); + static bool getMemory(JSContext *cx, unsigned argc, Value *vp); static bool addDebuggee(JSContext *cx, unsigned argc, Value *vp); static bool addAllGlobalsAsDebuggees(JSContext *cx, unsigned argc, Value *vp); static bool removeDebuggee(JSContext *cx, unsigned argc, Value *vp); diff --git a/js/src/vm/DebuggerMemory.cpp b/js/src/vm/DebuggerMemory.cpp new file mode 100644 index 00000000000..f3fb055df4b --- /dev/null +++ b/js/src/vm/DebuggerMemory.cpp @@ -0,0 +1,47 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 "vm/DebuggerMemory.h" + +namespace js { + +/* static */ bool +DebuggerMemory::construct(JSContext *cx, unsigned argc, Value *vp) +{ + JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR, + "Debugger.Memory"); + return false; +} + +/* static */ const Class DebuggerMemory::class_ = { + "Memory", + JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | + JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGGER_MEMORY_COUNT), + + JS_PropertyStub, // addProperty + JS_DeletePropertyStub, // delProperty + JS_PropertyStub, // getProperty + JS_StrictPropertyStub, // setProperty + JS_EnumerateStub, // enumerate + JS_ResolveStub, // resolve + JS_ConvertStub, // convert + + nullptr, // finalize + nullptr, // call + nullptr, // hasInstance + nullptr, // construct + nullptr // trace +}; + +/* static */ const JSPropertySpec DebuggerMemory::properties[] = { + JS_PS_END +}; + +/* static */ const JSFunctionSpec DebuggerMemory::methods[] = { + JS_FS_END +}; + +} /* namespace js */ diff --git a/js/src/vm/DebuggerMemory.h b/js/src/vm/DebuggerMemory.h new file mode 100644 index 00000000000..0ae171fd0a5 --- /dev/null +++ b/js/src/vm/DebuggerMemory.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * 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 vm_DebuggerMemory_h +#define vm_DebuggerMemory_h + +#include "jsapi.h" +#include "jscntxt.h" +#include "jsobj.h" +#include "js/Class.h" +#include "js/Value.h" + +namespace js { + +class DebuggerMemory : public JSObject { + enum { + JSSLOT_DEBUGGER_MEMORY_COUNT + }; + +public: + + static bool construct(JSContext *cx, unsigned argc, Value *vp); + + static const Class class_; + static const JSPropertySpec properties[]; + static const JSFunctionSpec methods[]; +}; + +} /* namespace js */ + +#endif /* vm_DebuggerMemory_h */