#include "gdb-tests.h" #include "jsapi.h" // sundry symbols not moved to more-specific headers yet #include "jsfriendapi.h" // JSFunctionSpecWithHelp #include "jit/JitOptions.h" // js::jit::JitOptions #include "js/CallArgs.h" // JS::CallArgs, JS::CallArgsFromVp #include "js/CompilationAndEvaluation.h" // JS::Evaluate #include "js/CompileOptions.h" // JS::CompileOptions #include "js/RootingAPI.h" // JS::Rooted #include "js/SourceText.h" // JS::Source{Ownership,Text} #include "js/Value.h" // JS::Value #include "mozilla/Utf8.h" // mozilla::Utf8Unit #include // uint32_t #include // strlen static bool Something(JSContext* cx, unsigned argc, JS::Value* vp) { JS::CallArgs args = JS::CallArgsFromVp(argc, vp); args.rval().setInt32(23); breakpoint(); return true; } // clang-format off static const JSFunctionSpecWithHelp unwind_functions[] = { JS_FN_HELP("something", Something, 0, 0, "something()", " Test function for test-unwind."), JS_FS_HELP_END }; // clang-format on FRAGMENT(unwind, simple) { using namespace JS; JS::Rooted global(cx, JS::CurrentGlobalOrNull(cx)); if (!JS_DefineFunctionsWithHelp(cx, global, unwind_functions)) { return; } // Define an itercount property and use it to ensure Baseline compilation. uint32_t threshold = js::jit::JitOptions.baselineJitWarmUpThreshold; RootedValue val(cx, Int32Value(threshold + 10)); if (!JS_DefineProperty(cx, global, "itercount", val, 0)) { return; } int line0 = __LINE__; const char* bytes = "\n" "function unwindFunctionInner() {\n" " for (var i = 0; i < itercount; i++) {}\n" " return something();\n" "}\n" "\n" "function unwindFunctionOuter() {\n" " for (var i = 0; i < itercount; i++) {}\n" " return unwindFunctionInner();\n" "}\n" "\n" "unwindFunctionOuter();\n"; JS::CompileOptions opts(cx); opts.setFileAndLine(__FILE__, line0 + 1); JS::SourceText srcBuf; if (!srcBuf.init(cx, bytes, strlen(bytes), JS::SourceOwnership::Borrowed)) { return; } JS::Rooted rval(cx); JS::Evaluate(cx, opts, srcBuf, &rval); }