/* 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/. */ // For js::jit::IsIonEnabled(). #include "jit/Ion.h" #include "jsapi-tests/tests.h" using namespace JS; static void ScriptCallback(JSRuntime* rt, void* data, JSScript* script) { unsigned& count = *static_cast<unsigned*>(data); if (script->hasIonScript()) ++count; } BEGIN_TEST(test_PreserveJitCode) { CHECK(testPreserveJitCode(false, 0)); CHECK(testPreserveJitCode(true, 1)); return true; } unsigned countIonScripts(JSObject* global) { unsigned count = 0; js::IterateScripts(cx, global->compartment(), &count, ScriptCallback); return count; } bool testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts) { cx->options().setBaseline(true); cx->options().setIon(true); cx->setOffthreadIonCompilationEnabled(false); RootedObject global(cx, createTestGlobal(preserveJitCode)); CHECK(global); JSAutoCompartment ac(cx, global); #ifdef JS_CODEGEN_ARM64 // The ARM64 Ion JIT is not yet enabled, so this test will fail with // countIonScripts(global) == 0. Once Ion is enabled for ARM64, this test // should be passing again, and this code can be deleted. // Bug 1208526 - ARM64: Reenable jsapi-tests/testPreserveJitCode once Ion is enabled if (!js::jit::IsIonEnabled(cx)) knownFail = true; #endif CHECK_EQUAL(countIonScripts(global), 0u); const char* source = "var i = 0;\n" "var sum = 0;\n" "while (i < 10) {\n" " sum += i;\n" " ++i;\n" "}\n" "return sum;\n"; unsigned length = strlen(source); JS::RootedFunction fun(cx); JS::CompileOptions options(cx); options.setFileAndLine(__FILE__, 1); JS::AutoObjectVector emptyScopeChain(cx); CHECK(JS::CompileFunction(cx, emptyScopeChain, options, "f", 0, nullptr, source, length, &fun)); RootedValue value(cx); for (unsigned i = 0; i < 1500; ++i) CHECK(JS_CallFunction(cx, global, fun, JS::HandleValueArray::empty(), &value)); CHECK_EQUAL(value.toInt32(), 45); CHECK_EQUAL(countIonScripts(global), 1u); GCForReason(cx, GC_NORMAL, gcreason::API); CHECK_EQUAL(countIonScripts(global), remainingIonScripts); GCForReason(cx, GC_SHRINK, gcreason::API); CHECK_EQUAL(countIonScripts(global), 0u); return true; } JSObject* createTestGlobal(bool preserveJitCode) { JS::CompartmentOptions options; options.creationOptions().setPreserveJitCode(preserveJitCode); options.behaviors().setVersion(JSVERSION_LATEST); return JS_NewGlobalObject(cx, getGlobalClass(), nullptr, JS::FireOnNewGlobalHook, options); } END_TEST(test_PreserveJitCode)