js/src/jsapi-tests/testProfileStrings.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 *
michael@0 4 * Tests the stack-based instrumentation profiler on a JSRuntime
michael@0 5 */
michael@0 6 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 7 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 9
michael@0 10 #include "jscntxt.h"
michael@0 11
michael@0 12 #include "jsapi-tests/tests.h"
michael@0 13
michael@0 14 static js::ProfileEntry pstack[10];
michael@0 15 static uint32_t psize = 0;
michael@0 16 static uint32_t max_stack = 0;
michael@0 17
michael@0 18 static void
michael@0 19 reset(JSContext *cx)
michael@0 20 {
michael@0 21 psize = max_stack = 0;
michael@0 22 memset(pstack, 0, sizeof(pstack));
michael@0 23 cx->runtime()->spsProfiler.stringsReset();
michael@0 24 cx->runtime()->spsProfiler.enableSlowAssertions(true);
michael@0 25 js::EnableRuntimeProfilingStack(cx->runtime(), true);
michael@0 26 }
michael@0 27
michael@0 28 static const JSClass ptestClass = {
michael@0 29 "Prof", 0, JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub,
michael@0 30 JS_StrictPropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
michael@0 31 };
michael@0 32
michael@0 33 static bool
michael@0 34 test_fn(JSContext *cx, unsigned argc, jsval *vp)
michael@0 35 {
michael@0 36 max_stack = psize;
michael@0 37 return true;
michael@0 38 }
michael@0 39
michael@0 40 static bool
michael@0 41 test_fn2(JSContext *cx, unsigned argc, jsval *vp)
michael@0 42 {
michael@0 43 JS::RootedValue r(cx);
michael@0 44 JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
michael@0 45 return JS_CallFunctionName(cx, global, "d", JS::HandleValueArray::empty(), &r);
michael@0 46 }
michael@0 47
michael@0 48 static bool
michael@0 49 enable(JSContext *cx, unsigned argc, jsval *vp)
michael@0 50 {
michael@0 51 js::EnableRuntimeProfilingStack(cx->runtime(), true);
michael@0 52 return true;
michael@0 53 }
michael@0 54
michael@0 55 static bool
michael@0 56 disable(JSContext *cx, unsigned argc, jsval *vp)
michael@0 57 {
michael@0 58 js::EnableRuntimeProfilingStack(cx->runtime(), false);
michael@0 59 return true;
michael@0 60 }
michael@0 61
michael@0 62 static bool
michael@0 63 Prof(JSContext* cx, unsigned argc, jsval *vp)
michael@0 64 {
michael@0 65 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
michael@0 66 JSObject *obj = JS_NewObjectForConstructor(cx, &ptestClass, args);
michael@0 67 if (!obj)
michael@0 68 return false;
michael@0 69 args.rval().setObject(*obj);
michael@0 70 return true;
michael@0 71 }
michael@0 72
michael@0 73 static const JSFunctionSpec ptestFunctions[] = {
michael@0 74 JS_FS("test_fn", test_fn, 0, 0),
michael@0 75 JS_FS("test_fn2", test_fn2, 0, 0),
michael@0 76 JS_FS("enable", enable, 0, 0),
michael@0 77 JS_FS("disable", disable, 0, 0),
michael@0 78 JS_FS_END
michael@0 79 };
michael@0 80
michael@0 81 static JSObject*
michael@0 82 initialize(JSContext *cx)
michael@0 83 {
michael@0 84 js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 10);
michael@0 85 JS::RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
michael@0 86 return JS_InitClass(cx, global, js::NullPtr(), &ptestClass, Prof, 0,
michael@0 87 nullptr, ptestFunctions, nullptr, nullptr);
michael@0 88 }
michael@0 89
michael@0 90 BEGIN_TEST(testProfileStrings_isCalledWithInterpreter)
michael@0 91 {
michael@0 92 CHECK(initialize(cx));
michael@0 93
michael@0 94 EXEC("function g() { var p = new Prof(); p.test_fn(); }");
michael@0 95 EXEC("function f() { g(); }");
michael@0 96 EXEC("function e() { f(); }");
michael@0 97 EXEC("function d() { e(); }");
michael@0 98 EXEC("function c() { d(); }");
michael@0 99 EXEC("function b() { c(); }");
michael@0 100 EXEC("function a() { b(); }");
michael@0 101 EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
michael@0 102 EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
michael@0 103
michael@0 104 reset(cx);
michael@0 105 {
michael@0 106 JS::RootedValue rval(cx);
michael@0 107 /* Make sure the stack resets and we have an entry for each stack */
michael@0 108 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 109 &rval));
michael@0 110 CHECK(psize == 0);
michael@0 111 CHECK(max_stack >= 8);
michael@0 112 CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
michael@0 113 /* Make sure the stack resets and we added no new entries */
michael@0 114 max_stack = 0;
michael@0 115 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 116 &rval));
michael@0 117 CHECK(psize == 0);
michael@0 118 CHECK(max_stack >= 8);
michael@0 119 CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
michael@0 120 }
michael@0 121 reset(cx);
michael@0 122 {
michael@0 123 JS::RootedValue rval(cx);
michael@0 124 CHECK(JS_CallFunctionName(cx, global, "check2", JS::HandleValueArray::empty(),
michael@0 125 &rval));
michael@0 126 CHECK(cx->runtime()->spsProfiler.stringsCount() == 5);
michael@0 127 CHECK(max_stack >= 6);
michael@0 128 CHECK(psize == 0);
michael@0 129 }
michael@0 130 js::EnableRuntimeProfilingStack(cx->runtime(), false);
michael@0 131 js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 3);
michael@0 132 reset(cx);
michael@0 133 {
michael@0 134 JS::RootedValue rval(cx);
michael@0 135 pstack[3].setLabel((char*) 1234);
michael@0 136 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 137 &rval));
michael@0 138 CHECK((size_t) pstack[3].label() == 1234);
michael@0 139 CHECK(max_stack >= 8);
michael@0 140 CHECK(psize == 0);
michael@0 141 }
michael@0 142 return true;
michael@0 143 }
michael@0 144 END_TEST(testProfileStrings_isCalledWithInterpreter)
michael@0 145
michael@0 146 BEGIN_TEST(testProfileStrings_isCalledWithJIT)
michael@0 147 {
michael@0 148 CHECK(initialize(cx));
michael@0 149 JS::RuntimeOptionsRef(cx).setBaseline(true)
michael@0 150 .setIon(true);
michael@0 151
michael@0 152 EXEC("function g() { var p = new Prof(); p.test_fn(); }");
michael@0 153 EXEC("function f() { g(); }");
michael@0 154 EXEC("function e() { f(); }");
michael@0 155 EXEC("function d() { e(); }");
michael@0 156 EXEC("function c() { d(); }");
michael@0 157 EXEC("function b() { c(); }");
michael@0 158 EXEC("function a() { b(); }");
michael@0 159 EXEC("function check() { var p = new Prof(); p.test_fn(); a(); }");
michael@0 160 EXEC("function check2() { var p = new Prof(); p.test_fn2(); }");
michael@0 161
michael@0 162 reset(cx);
michael@0 163 {
michael@0 164 JS::RootedValue rval(cx);
michael@0 165 /* Make sure the stack resets and we have an entry for each stack */
michael@0 166 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 167 &rval));
michael@0 168 CHECK(psize == 0);
michael@0 169 CHECK(max_stack >= 8);
michael@0 170
michael@0 171 /* Make sure the stack resets and we added no new entries */
michael@0 172 uint32_t cnt = cx->runtime()->spsProfiler.stringsCount();
michael@0 173 max_stack = 0;
michael@0 174 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 175 &rval));
michael@0 176 CHECK(psize == 0);
michael@0 177 CHECK(cx->runtime()->spsProfiler.stringsCount() == cnt);
michael@0 178 CHECK(max_stack >= 8);
michael@0 179 }
michael@0 180
michael@0 181 js::EnableRuntimeProfilingStack(cx->runtime(), false);
michael@0 182 js::SetRuntimeProfilingStack(cx->runtime(), pstack, &psize, 3);
michael@0 183 reset(cx);
michael@0 184 {
michael@0 185 /* Limit the size of the stack and make sure we don't overflow */
michael@0 186 JS::RootedValue rval(cx);
michael@0 187 pstack[3].setLabel((char*) 1234);
michael@0 188 CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
michael@0 189 &rval));
michael@0 190 CHECK(psize == 0);
michael@0 191 CHECK(max_stack >= 8);
michael@0 192 CHECK((size_t) pstack[3].label() == 1234);
michael@0 193 }
michael@0 194 return true;
michael@0 195 }
michael@0 196 END_TEST(testProfileStrings_isCalledWithJIT)
michael@0 197
michael@0 198 BEGIN_TEST(testProfileStrings_isCalledWhenError)
michael@0 199 {
michael@0 200 CHECK(initialize(cx));
michael@0 201 JS::RuntimeOptionsRef(cx).setBaseline(true)
michael@0 202 .setIon(true);
michael@0 203
michael@0 204 EXEC("function check2() { throw 'a'; }");
michael@0 205
michael@0 206 reset(cx);
michael@0 207 JS::ContextOptionsRef(cx).setDontReportUncaught(true);
michael@0 208 {
michael@0 209 JS::RootedValue rval(cx);
michael@0 210 /* Make sure the stack resets and we have an entry for each stack */
michael@0 211 bool ok = JS_CallFunctionName(cx, global, "check2", JS::HandleValueArray::empty(),
michael@0 212 &rval);
michael@0 213 CHECK(!ok);
michael@0 214 CHECK(psize == 0);
michael@0 215 CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
michael@0 216
michael@0 217 JS_ClearPendingException(cx);
michael@0 218 }
michael@0 219 return true;
michael@0 220 }
michael@0 221 END_TEST(testProfileStrings_isCalledWhenError)
michael@0 222
michael@0 223 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
michael@0 224 {
michael@0 225 CHECK(initialize(cx));
michael@0 226 JS::RuntimeOptionsRef(cx).setBaseline(true)
michael@0 227 .setIon(true);
michael@0 228
michael@0 229 EXEC("function b(p) { p.test_fn(); }");
michael@0 230 EXEC("function a() { var p = new Prof(); p.enable(); b(p); }");
michael@0 231 reset(cx);
michael@0 232 js::EnableRuntimeProfilingStack(cx->runtime(), false);
michael@0 233 {
michael@0 234 /* enable it in the middle of JS and make sure things check out */
michael@0 235 JS::RootedValue rval(cx);
michael@0 236 JS_CallFunctionName(cx, global, "a", JS::HandleValueArray::empty(), &rval);
michael@0 237 CHECK(psize == 0);
michael@0 238 CHECK(max_stack >= 1);
michael@0 239 CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
michael@0 240 }
michael@0 241
michael@0 242 EXEC("function d(p) { p.disable(); }");
michael@0 243 EXEC("function c() { var p = new Prof(); d(p); }");
michael@0 244 reset(cx);
michael@0 245 {
michael@0 246 /* now disable in the middle of js */
michael@0 247 JS::RootedValue rval(cx);
michael@0 248 JS_CallFunctionName(cx, global, "c", JS::HandleValueArray::empty(), &rval);
michael@0 249 CHECK(psize == 0);
michael@0 250 }
michael@0 251
michael@0 252 EXEC("function e() { var p = new Prof(); d(p); p.enable(); b(p); }");
michael@0 253 reset(cx);
michael@0 254 {
michael@0 255 /* now disable in the middle of js, but re-enable before final exit */
michael@0 256 JS::RootedValue rval(cx);
michael@0 257 JS_CallFunctionName(cx, global, "e", JS::HandleValueArray::empty(), &rval);
michael@0 258 CHECK(psize == 0);
michael@0 259 CHECK(max_stack >= 3);
michael@0 260 }
michael@0 261
michael@0 262 EXEC("function h() { }");
michael@0 263 EXEC("function g(p) { p.disable(); for (var i = 0; i < 100; i++) i++; }");
michael@0 264 EXEC("function f() { g(new Prof()); }");
michael@0 265 reset(cx);
michael@0 266 cx->runtime()->spsProfiler.enableSlowAssertions(false);
michael@0 267 {
michael@0 268 JS::RootedValue rval(cx);
michael@0 269 /* disable, and make sure that if we try to re-enter the JIT the pop
michael@0 270 * will still happen */
michael@0 271 JS_CallFunctionName(cx, global, "f", JS::HandleValueArray::empty(), &rval);
michael@0 272 CHECK(psize == 0);
michael@0 273 }
michael@0 274 return true;
michael@0 275 }
michael@0 276 END_TEST(testProfileStrings_worksWhenEnabledOnTheFly)

mercurial