testPreserveJitCode.cpp (3228B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "mozilla/Utf8.h" // mozilla::Utf8Unit 6 7 #include "jit/Ion.h" // js::jit::IsIonEnabled 8 #include "js/CallAndConstruct.h" // JS::CallFunction 9 #include "js/CompilationAndEvaluation.h" // JS::CompileFunction 10 #include "js/EnvironmentChain.h" // JS::EnvironmentChain 11 #include "js/GlobalObject.h" // JS_NewGlobalObject 12 #include "js/SourceText.h" // JS::Source{Ownership,Text} 13 #include "jsapi-tests/tests.h" 14 #include "util/Text.h" 15 16 #include "vm/JSObject-inl.h" 17 #include "vm/JSScript-inl.h" 18 19 using namespace JS; 20 21 static void ScriptCallback(JSRuntime* rt, void* data, js::BaseScript* script, 22 const JS::AutoRequireNoGC& nogc) { 23 unsigned& count = *static_cast<unsigned*>(data); 24 if (script->asJSScript()->hasIonScript()) { 25 ++count; 26 } 27 } 28 29 BEGIN_TEST(test_PreserveJitCode) { 30 CHECK(testPreserveJitCode(false, 0)); 31 CHECK(testPreserveJitCode(true, 1)); 32 return true; 33 } 34 35 unsigned countIonScripts(JSObject* global) { 36 unsigned count = 0; 37 js::IterateScripts(cx, global->nonCCWRealm(), &count, ScriptCallback); 38 return count; 39 } 40 41 bool testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts) { 42 cx->runtime()->setOffthreadIonCompilationEnabled(false); 43 44 RootedObject global(cx, createTestGlobal(preserveJitCode)); 45 CHECK(global); 46 JSAutoRealm ar(cx, global); 47 48 // The Ion JIT may be unavailable due to --disable-jit or lack of support 49 // for this platform. 50 if (!js::jit::IsIonEnabled(cx)) { 51 knownFail = true; 52 } 53 54 CHECK_EQUAL(countIonScripts(global), 0u); 55 56 static constexpr char source[] = 57 "var i = 0;\n" 58 "var sum = 0;\n" 59 "while (i < 10) {\n" 60 " sum += i;\n" 61 " ++i;\n" 62 "}\n" 63 "return sum;\n"; 64 constexpr unsigned length = js_strlen(source); 65 66 JS::SourceText<mozilla::Utf8Unit> srcBuf; 67 CHECK(srcBuf.init(cx, source, length, JS::SourceOwnership::Borrowed)); 68 69 JS::CompileOptions options(cx); 70 options.setFileAndLine(__FILE__, 1); 71 72 JS::RootedFunction fun(cx); 73 JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No); 74 fun = 75 JS::CompileFunction(cx, emptyEnvChain, options, "f", 0, nullptr, srcBuf); 76 CHECK(fun); 77 78 RootedValue value(cx); 79 for (unsigned i = 0; i < 1500; ++i) { 80 CHECK(JS_CallFunction(cx, global, fun, JS::HandleValueArray::empty(), 81 &value)); 82 } 83 CHECK_EQUAL(value.toInt32(), 45); 84 CHECK_EQUAL(countIonScripts(global), 1u); 85 86 NonIncrementalGC(cx, JS::GCOptions::Normal, GCReason::API); 87 CHECK_EQUAL(countIonScripts(global), remainingIonScripts); 88 89 NonIncrementalGC(cx, JS::GCOptions::Shrink, GCReason::API); 90 CHECK_EQUAL(countIonScripts(global), 0u); 91 92 return true; 93 } 94 95 JSObject* createTestGlobal(bool preserveJitCode) { 96 JS::RealmOptions options; 97 options.creationOptions().setPreserveJitCode(preserveJitCode); 98 return JS_NewGlobalObject(cx, getGlobalClass(), nullptr, 99 JS::FireOnNewGlobalHook, options); 100 } 101 END_TEST(test_PreserveJitCode)