Skip to content

Commit 4c06013

Browse files
authored
Merge pull request #3107 from cloudflare/yagiz/enable-compile-cache
enable built-in compile cache behind autogate
2 parents 3f81de0 + 23cce68 commit 4c06013

File tree

8 files changed

+51
-37
lines changed

8 files changed

+51
-37
lines changed

src/workerd/jsg/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ wd_cc_library(
6262
":observer",
6363
":url",
6464
"//src/workerd/util",
65+
"//src/workerd/util:autogate",
6566
"//src/workerd/util:sentry",
6667
"//src/workerd/util:thread-scopes",
6768
"//src/workerd/util:uuid",

src/workerd/jsg/jsg-test.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class Evaluator {
4646
auto modules = ModuleRegistryImpl<IsolateType_TypeWrapper>::from(js);
4747
auto p = kj::Path::parse("main");
4848
modules->add(p,
49-
jsg::ModuleRegistry::ModuleInfo(
50-
lock, "main", code, ModuleInfoCompileOption::BUNDLE, observer));
49+
jsg::ModuleRegistry::ModuleInfo(lock, "main", code, nullptr /* compile cache */,
50+
ModuleInfoCompileOption::BUNDLE, observer));
5151

5252
// Instantiate the module
5353
auto& moduleInfo = KJ_REQUIRE_NONNULL(modules->resolve(js, p));

src/workerd/jsg/modules.c++

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "jsg.h"
77
#include "setup.h"
88

9+
#include <workerd/util/autogate.h>
10+
911
#include <kj/mutex.h>
1012

1113
#include <set>
@@ -365,53 +367,46 @@ static CompilationObserver::Option convertOption(ModuleInfoCompileOption option)
365367
v8::Local<v8::Module> compileEsmModule(jsg::Lock& js,
366368
kj::StringPtr name,
367369
kj::ArrayPtr<const char> content,
370+
kj::ArrayPtr<const kj::byte> compileCache,
368371
ModuleInfoCompileOption option,
369372
const CompilationObserver& observer) {
370373
// destroy the observer after compilation finished to indicate the end of the process.
371374
auto compilationObserver =
372375
observer.onEsmCompilationStart(js.v8Isolate, name, convertOption(option));
373376

374377
// Must pass true for `is_module`, but we can skip everything else.
375-
const int resourceLineOffset = 0;
376-
const int resourceColumnOffset = 0;
377-
const bool resourceIsSharedCrossOrigin = false;
378-
const int scriptId = -1;
379-
const bool resourceIsOpaque = false;
380-
const bool isWasm = false;
381-
const bool isModule = true;
378+
constexpr int resourceLineOffset = 0;
379+
constexpr int resourceColumnOffset = 0;
380+
constexpr bool resourceIsSharedCrossOrigin = false;
381+
constexpr int scriptId = -1;
382+
constexpr bool resourceIsOpaque = false;
383+
constexpr bool isWasm = false;
384+
constexpr bool isModule = true;
382385
v8::ScriptOrigin origin(v8StrIntern(js.v8Isolate, name), resourceLineOffset, resourceColumnOffset,
383386
resourceIsSharedCrossOrigin, scriptId, {}, resourceIsOpaque, isWasm, isModule);
384387
v8::Local<v8::String> contentStr;
385-
v8::ScriptCompiler::CachedData* existingCacheData = nullptr;
386-
auto compileOptions = v8::ScriptCompiler::kNoCompileOptions;
387-
const auto& compileCache = CompileCache::get();
388388

389389
if (option == ModuleInfoCompileOption::BUILTIN) {
390390
// TODO(later): Use of newExternalOneByteString here limits our built-in source
391391
// modules (for which this path is used) to only the latin1 character set. We
392392
// may need to revisit that to import built-ins as UTF-16 (two-byte).
393393
contentStr = jsg::newExternalOneByteString(js, content);
394-
395-
// We only enable compile cache for built-in modules for now.
396-
KJ_IF_SOME(cached, compileCache.find(name)) {
397-
compileOptions = v8::ScriptCompiler::kConsumeCodeCache;
398-
existingCacheData = cached.AsCachedData().release();
399-
}
400394
} else {
401395
contentStr = jsg::v8Str(js.v8Isolate, content);
402396
}
403397

404-
v8::ScriptCompiler::Source source(contentStr, origin, existingCacheData);
405-
auto module =
406-
jsg::check(v8::ScriptCompiler::CompileModule(js.v8Isolate, &source, compileOptions));
407-
408-
if (existingCacheData == nullptr) {
409-
auto cachedData = std::shared_ptr<v8::ScriptCompiler::CachedData>(
410-
v8::ScriptCompiler::CreateCodeCache(module->GetUnboundModuleScript()));
411-
compileCache.add(name, kj::mv(cachedData));
398+
if (util::Autogate::isEnabled(util::AutogateKey::COMPILE_CACHE_FOR_BUILTINS)) {
399+
if (compileCache.size() > 0 && compileCache.begin() != nullptr) {
400+
auto cached = std::make_unique<v8::ScriptCompiler::CachedData>(
401+
compileCache.begin(), compileCache.size());
402+
v8::ScriptCompiler::Source source(contentStr, origin, cached.release());
403+
return jsg::check(v8::ScriptCompiler::CompileModule(
404+
js.v8Isolate, &source, v8::ScriptCompiler::kConsumeCodeCache));
405+
}
412406
}
413407

414-
return module;
408+
v8::ScriptCompiler::Source source(contentStr, origin);
409+
return jsg::check(v8::ScriptCompiler::CompileModule(js.v8Isolate, &source));
415410
}
416411

417412
v8::Local<v8::Module> createSyntheticModule(
@@ -438,9 +433,10 @@ ModuleRegistry::ModuleInfo::ModuleInfo(
438433
ModuleRegistry::ModuleInfo::ModuleInfo(jsg::Lock& js,
439434
kj::StringPtr name,
440435
kj::ArrayPtr<const char> content,
436+
kj::ArrayPtr<const kj::byte> compileCache,
441437
ModuleInfoCompileOption flags,
442438
const CompilationObserver& observer)
443-
: ModuleInfo(js, compileEsmModule(js, name, content, flags, observer)) {}
439+
: ModuleInfo(js, compileEsmModule(js, name, content, compileCache, flags, observer)) {}
444440

445441
ModuleRegistry::ModuleInfo::ModuleInfo(jsg::Lock& js,
446442
kj::StringPtr name,

src/workerd/jsg/modules.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ class ModuleRegistry {
352352
ModuleInfo(jsg::Lock& js,
353353
kj::StringPtr name,
354354
kj::ArrayPtr<const char> content,
355+
kj::ArrayPtr<const kj::byte> compileCache,
355356
ModuleInfoCompileOption flags,
356357
const CompilationObserver& observer);
357358

@@ -506,7 +507,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {
506507
}
507508
}
508509
// TODO: asChars() might be wrong for wide characters
509-
addBuiltinModule(module.getName(), module.getSrc().asChars(), module.getType());
510+
addBuiltinModule(module.getName(), module.getSrc().asChars(), module.getType(),
511+
module.getCompileCache().asBytes());
510512
}
511513

512514
void addBuiltinBundle(Bundle::Reader bundle, kj::Maybe<Type> maybeFilter = kj::none) {
@@ -521,11 +523,13 @@ class ModuleRegistryImpl final: public ModuleRegistry {
521523
// sourceCode has to exist while this ModuleRegistry exists.
522524
// The expectation is for this method to be called during the assembly of worker global context
523525
// after registering all user modules.
524-
void addBuiltinModule(
525-
kj::StringPtr specifier, kj::ArrayPtr<const char> sourceCode, Type type = Type::BUILTIN) {
526+
void addBuiltinModule(kj::StringPtr specifier,
527+
kj::ArrayPtr<const char> sourceCode,
528+
Type type = Type::BUILTIN,
529+
kj::ArrayPtr<const kj::byte> compileCache = {}) {
526530
KJ_ASSERT(type != Type::BUNDLE);
527531
auto path = kj::Path::parse(specifier);
528-
entries.insert(kj::heap<Entry>(path, type, sourceCode));
532+
entries.insert(kj::heap<Entry>(path, type, sourceCode, compileCache));
529533
}
530534

531535
void addBuiltinModule(
@@ -728,15 +732,22 @@ class ModuleRegistryImpl final: public ModuleRegistry {
728732
// Either instantiated module or module source code.
729733
Info info;
730734

735+
// Optional compileCache.
736+
kj::ArrayPtr<const kj::byte> compileCache;
737+
731738
Entry(const kj::Path& specifier, Type type, ModuleInfo info)
732739
: specifier(specifier.clone()),
733740
type(type),
734741
info(kj::mv(info)) {}
735742

736-
Entry(const kj::Path& specifier, Type type, kj::ArrayPtr<const char> src)
743+
Entry(const kj::Path& specifier,
744+
Type type,
745+
kj::ArrayPtr<const char> src,
746+
kj::ArrayPtr<const kj::byte> compileCache)
737747
: specifier(specifier.clone()),
738748
type(type),
739-
info(src) {}
749+
info(src),
750+
compileCache(compileCache) {}
740751

741752
Entry(const kj::Path& specifier, Type type, ModuleCallback factory)
742753
: specifier(specifier.clone()),
@@ -756,8 +767,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {
756767
return kj::Maybe<ModuleInfo&>(moduleInfo);
757768
}
758769
KJ_CASE_ONEOF(src, kj::ArrayPtr<const char>) {
759-
info =
760-
ModuleInfo(js, specifier.toString(), src, ModuleInfoCompileOption::BUILTIN, observer);
770+
info = ModuleInfo(js, specifier.toString(), src, compileCache,
771+
ModuleInfoCompileOption::BUILTIN, observer);
761772
return info.tryGet<ModuleInfo>();
762773
}
763774
KJ_CASE_ONEOF(src, ModuleCallback) {

src/workerd/jsg/resource-test.c++

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "jsg-test.h"
66

77
#include <workerd/jsg/resource-test.capnp.h>
8+
#include <workerd/util/autogate.h>
89

910
namespace workerd::jsg::test {
1011
namespace {
@@ -590,6 +591,7 @@ struct JsBundleContext: public ContextGlobalObject {
590591
JSG_DECLARE_ISOLATE_TYPE(JsBundleIsolate, JsBundleContext);
591592

592593
KJ_TEST("expectEvalModule function works") {
594+
util::Autogate::initAutogate({});
593595
Evaluator<JsBundleContext, JsBundleIsolate, decltype(nullptr), JsBundleIsolate_TypeWrapper> e(
594596
v8System);
595597
e.expectEvalModule("export function run() { return 123; }", "number", "123");

src/workerd/server/workerd-api.c++

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,8 +398,9 @@ kj::Maybe<jsg::ModuleRegistry::ModuleInfo> WorkerdApi::tryCompileModule(jsg::Loc
398398
lock, Impl::compileJsonGlobal(lock, module.getJson())));
399399
}
400400
case config::Worker::Module::ES_MODULE: {
401+
// TODO(soon): Make sure passing nullptr to compile cache is desired.
401402
return jsg::ModuleRegistry::ModuleInfo(lock, module.getName(), module.getEsModule(),
402-
jsg::ModuleInfoCompileOption::BUNDLE, observer);
403+
nullptr /* compile cache */, jsg::ModuleInfoCompileOption::BUNDLE, observer);
403404
}
404405
case config::Worker::Module::COMMON_JS_MODULE: {
405406
kj::Maybe<kj::Array<kj::StringPtr>> named = kj::none;

src/workerd/util/autogate.c++

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ kj::StringPtr KJ_STRINGIFY(AutogateKey key) {
1919
return "test-workerd"_kj;
2020
case AutogateKey::PYTHON_EXTERNAL_BUNDLE:
2121
return "python-external-bundle"_kj;
22+
case AutogateKey::COMPILE_CACHE_FOR_BUILTINS:
23+
return "compile-cache-for-builtins"_kj;
2224
case AutogateKey::NumOfKeys:
2325
KJ_FAIL_ASSERT("NumOfKeys should not be used in getName");
2426
}

src/workerd/util/autogate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace workerd::util {
1515
enum class AutogateKey {
1616
TEST_WORKERD,
1717
PYTHON_EXTERNAL_BUNDLE,
18+
COMPILE_CACHE_FOR_BUILTINS,
1819
NumOfKeys // Reserved for iteration.
1920
};
2021

0 commit comments

Comments
 (0)